forked from I2P_Developers/i2p.i2p
Ratchet: Updates
- Prep for prop. 154 with SingleTagSet - Variable timeout for tagsets - Start cleaner sooner - Make key optional in next key block - HTML debug output improvement - log tweaks and javadocs
This commit is contained in:
@ -772,14 +772,14 @@ public final class ECIESAEADEngine {
|
|||||||
* - 16 byte MAC
|
* - 16 byte MAC
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param target unused, this is AEAD encrypt only using the session key and tag
|
* @param target only used if callback is non-null to register it
|
||||||
* @param replyDI non-null to request an ack, or null
|
* @param replyDI non-null to request an ack, or null
|
||||||
* @return encrypted data or null on failure
|
* @return encrypted data or null on failure
|
||||||
*/
|
*/
|
||||||
private byte[] encryptExistingSession(CloveSet cloves, PublicKey target, RatchetEntry re,
|
private byte[] encryptExistingSession(CloveSet cloves, PublicKey target, RatchetEntry re,
|
||||||
DeliveryInstructions replyDI, ReplyCallback callback,
|
DeliveryInstructions replyDI, ReplyCallback callback,
|
||||||
RatchetSKM keyManager) {
|
RatchetSKM keyManager) {
|
||||||
//
|
// TODO remove DI, just make it a boolean
|
||||||
if (ACKREQ_IN_ES && replyDI == null)
|
if (ACKREQ_IN_ES && replyDI == null)
|
||||||
replyDI = new DeliveryInstructions();
|
replyDI = new DeliveryInstructions();
|
||||||
byte rawTag[] = re.tag.getData();
|
byte rawTag[] = re.tag.getData();
|
||||||
@ -794,6 +794,31 @@ public final class ECIESAEADEngine {
|
|||||||
return encr;
|
return encr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an Existing Session Message to an anonymous target
|
||||||
|
* using the given session key and tag, for netdb DSM/DSRM replies.
|
||||||
|
* Called from MessageWrapper.
|
||||||
|
*
|
||||||
|
* No datetime, no next key, no acks, no ack requests.
|
||||||
|
* n=0, ad=null.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* - 8 byte SessionTag
|
||||||
|
* - payload
|
||||||
|
* - 16 byte MAC
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @return encrypted data or null on failure
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public byte[] encrypt(CloveSet cloves, SessionKey key, RatchetSessionTag tag) {
|
||||||
|
byte rawTag[] = tag.getData();
|
||||||
|
byte[] payload = createPayload(cloves, 0, null, null, null);
|
||||||
|
byte encr[] = encryptAEADBlock(rawTag, payload, key, 0);
|
||||||
|
System.arraycopy(rawTag, 0, encr, 0, TAGLEN);
|
||||||
|
return encr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* No ad
|
* No ad
|
||||||
*/
|
*/
|
||||||
|
@ -48,12 +48,12 @@ final class MuxedEngine {
|
|||||||
try {
|
try {
|
||||||
rv = _context.garlicMessageParser().readCloveSet(dec, 0);
|
rv = _context.garlicMessageParser().readCloveSet(dec, 0);
|
||||||
} catch (DataFormatException dfe) {
|
} catch (DataFormatException dfe) {
|
||||||
if (_log.shouldWarn())
|
if (_log.shouldInfo())
|
||||||
_log.warn("ElG decrypt failed, trying ECIES", dfe);
|
_log.info("ElG decrypt failed, trying ECIES", dfe);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_log.shouldWarn())
|
//if (_log.shouldDebug())
|
||||||
_log.warn("ElG decrypt failed, trying ECIES");
|
// _log.debug("ElG decrypt failed, trying ECIES");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rv == null) {
|
if (rv == null) {
|
||||||
|
@ -12,6 +12,9 @@ class NextSessionKey extends PublicKey {
|
|||||||
private final int _id;
|
private final int _id;
|
||||||
private final boolean _isReverse, _isRequest;
|
private final boolean _isReverse, _isRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data may be null
|
||||||
|
*/
|
||||||
public NextSessionKey(byte[] data, int id, boolean isReverse, boolean isRequest) {
|
public NextSessionKey(byte[] data, int id, boolean isReverse, boolean isRequest) {
|
||||||
super(EncType.ECIES_X25519, data);
|
super(EncType.ECIES_X25519, data);
|
||||||
_id = id;
|
_id = id;
|
||||||
|
@ -136,13 +136,19 @@ class RatchetPayload {
|
|||||||
|
|
||||||
case BLOCK_NEXTKEY:
|
case BLOCK_NEXTKEY:
|
||||||
{
|
{
|
||||||
if (len != 35)
|
if (len != 3 && len != 35)
|
||||||
throw new IOException("Bad length for NEXTKEY: " + len);
|
throw new IOException("Bad length for NEXTKEY: " + len);
|
||||||
boolean isReverse = (payload[i] & 0x01) != 0;
|
boolean hasKey = (payload[i] & 0x01) != 0;
|
||||||
boolean isRequest = (payload[i] & 0x02) != 0;
|
boolean isReverse = (payload[i] & 0x02) != 0;
|
||||||
|
boolean isRequest = (payload[i] & 0x04) != 0;
|
||||||
int id = (int) DataHelper.fromLong(payload, i + 1, 2);
|
int id = (int) DataHelper.fromLong(payload, i + 1, 2);
|
||||||
byte[] data = new byte[32];
|
byte[] data;
|
||||||
System.arraycopy(payload, i + 3, data, 0, 32);
|
if (hasKey) {
|
||||||
|
data = new byte[32];
|
||||||
|
System.arraycopy(payload, i + 3, data, 0, 32);
|
||||||
|
} else {
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
NextSessionKey nsk = new NextSessionKey(data, id, isReverse, isRequest);
|
NextSessionKey nsk = new NextSessionKey(data, id, isReverse, isRequest);
|
||||||
cb.gotNextKey(nsk);
|
cb.gotNextKey(nsk);
|
||||||
}
|
}
|
||||||
@ -352,17 +358,22 @@ class RatchetPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getDataLength() {
|
public int getDataLength() {
|
||||||
return 35;
|
return next.getData() != null ? 35 : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int writeData(byte[] tgt, int off) {
|
public int writeData(byte[] tgt, int off) {
|
||||||
if (next.isReverse())
|
if (next.getData() != null)
|
||||||
tgt[off] = 0x01;
|
tgt[off] = 0x01;
|
||||||
if (next.isRequest())
|
if (next.isReverse())
|
||||||
tgt[off] |= 0x02;
|
tgt[off] |= 0x02;
|
||||||
|
if (next.isRequest())
|
||||||
|
tgt[off] |= 0x04;
|
||||||
DataHelper.toLong(tgt, off + 1, 2, next.getID());
|
DataHelper.toLong(tgt, off + 1, 2, next.getID());
|
||||||
System.arraycopy(next.getData(), 0, tgt, off + 3, 32);
|
if (next.getData() != null) {
|
||||||
return off + 35;
|
System.arraycopy(next.getData(), 0, tgt, off + 3, 32);
|
||||||
|
return off + 35;
|
||||||
|
}
|
||||||
|
return off + 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
* Let outbound session tags sit around for this long before expiring them.
|
* Let outbound session tags sit around for this long before expiring them.
|
||||||
* Inbound tag expiration is set by SESSION_LIFETIME_MAX_MS
|
* Inbound tag expiration is set by SESSION_LIFETIME_MAX_MS
|
||||||
*/
|
*/
|
||||||
private final static long SESSION_TAG_DURATION_MS = 12 * 60 * 1000;
|
final static long SESSION_TAG_DURATION_MS = 12 * 60 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep unused inbound session tags around for this long (a few minutes longer than
|
* Keep unused inbound session tags around for this long (a few minutes longer than
|
||||||
@ -63,9 +63,9 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
*
|
*
|
||||||
* This is also the max idle time for an outbound session.
|
* This is also the max idle time for an outbound session.
|
||||||
*/
|
*/
|
||||||
private final static long SESSION_LIFETIME_MAX_MS = SESSION_TAG_DURATION_MS + 3 * 60 * 1000;
|
final static long SESSION_LIFETIME_MAX_MS = SESSION_TAG_DURATION_MS + 3 * 60 * 1000;
|
||||||
|
|
||||||
private final static long SESSION_PENDING_DURATION_MS = 5 * 60 * 1000;
|
final static long SESSION_PENDING_DURATION_MS = 5 * 60 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time to send more if we are this close to expiration
|
* Time to send more if we are this close to expiration
|
||||||
@ -110,8 +110,8 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
|
|
||||||
private class CleanupEvent extends SimpleTimer2.TimedEvent {
|
private class CleanupEvent extends SimpleTimer2.TimedEvent {
|
||||||
public CleanupEvent() {
|
public CleanupEvent() {
|
||||||
// wait until outbound expiration time to start
|
// wait until first expiration time to start
|
||||||
super(_context.simpleTimer2(), SESSION_TAG_DURATION_MS);
|
super(_context.simpleTimer2(), SESSION_PENDING_DURATION_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void timeReached() {
|
public void timeReached() {
|
||||||
@ -491,6 +491,14 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One time session
|
||||||
|
* @param expire time from now
|
||||||
|
*/
|
||||||
|
public void tagsReceived(SessionKey key, RatchetSessionTag tag, long expire) {
|
||||||
|
new SingleTagSet(this, key, tag, _context.clock().now(), expire);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove a bunch of arbitrarily selected tags, then drop all of
|
* remove a bunch of arbitrarily selected tags, then drop all of
|
||||||
* the associated tag sets. this is very time consuming - iterating
|
* the associated tag sets. this is very time consuming - iterating
|
||||||
@ -543,13 +551,15 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if (state == null) {
|
if (state == null) {
|
||||||
// TODO this should really be after decrypt...
|
// TODO this should really be after decrypt...
|
||||||
PublicKey pk = tagSet.getRemoteKey();
|
PublicKey pk = tagSet.getRemoteKey();
|
||||||
OutboundSession sess = getSession(pk);
|
if (pk != null) {
|
||||||
if (sess != null) {
|
OutboundSession sess = getSession(pk);
|
||||||
sess.firstTagConsumed(tagSet);
|
if (sess != null) {
|
||||||
} else {
|
sess.firstTagConsumed(tagSet);
|
||||||
if (_log.shouldDebug())
|
} else {
|
||||||
_log.debug("First tag consumed but session is gone");
|
if (_log.shouldDebug())
|
||||||
}
|
_log.debug("First tag consumed but session is gone");
|
||||||
|
}
|
||||||
|
} // else null for SingleTagSets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_log.shouldDebug()) {
|
if (_log.shouldDebug()) {
|
||||||
@ -611,13 +621,12 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
*/
|
*/
|
||||||
private int aggressiveExpire() {
|
private int aggressiveExpire() {
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
long exp = now - SESSION_LIFETIME_MAX_MS;
|
|
||||||
|
|
||||||
// inbound
|
// inbound
|
||||||
int removed = 0;
|
int removed = 0;
|
||||||
for (Iterator<RatchetTagSet> iter = _inboundTagSets.values().iterator(); iter.hasNext();) {
|
for (Iterator<RatchetTagSet> iter = _inboundTagSets.values().iterator(); iter.hasNext();) {
|
||||||
RatchetTagSet ts = iter.next();
|
RatchetTagSet ts = iter.next();
|
||||||
if (ts.getDate() < exp) {
|
if (ts.getExpiration() < now) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
removed++;
|
removed++;
|
||||||
}
|
}
|
||||||
@ -626,7 +635,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
// outbound
|
// outbound
|
||||||
int oremoved = 0;
|
int oremoved = 0;
|
||||||
int cremoved = 0;
|
int cremoved = 0;
|
||||||
exp = now - (SESSION_LIFETIME_MAX_MS / 2);
|
long exp = now - (SESSION_LIFETIME_MAX_MS / 2);
|
||||||
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext();) {
|
for (Iterator<OutboundSession> iter = _outboundSessions.values().iterator(); iter.hasNext();) {
|
||||||
OutboundSession sess = iter.next();
|
OutboundSession sess = iter.next();
|
||||||
oremoved += sess.expireTags(now);
|
oremoved += sess.expireTags(now);
|
||||||
@ -753,7 +762,6 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
int total = 0;
|
int total = 0;
|
||||||
int totalSets = 0;
|
int totalSets = 0;
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
long exp = now - SESSION_LIFETIME_MAX_MS;
|
|
||||||
Set<RatchetTagSet> sets = new TreeSet<RatchetTagSet>(new RatchetTagSetComparator());
|
Set<RatchetTagSet> sets = new TreeSet<RatchetTagSet>(new RatchetTagSetComparator());
|
||||||
for (Map.Entry<SessionKey, Set<RatchetTagSet>> e : inboundSets.entrySet()) {
|
for (Map.Entry<SessionKey, Set<RatchetTagSet>> e : inboundSets.entrySet()) {
|
||||||
SessionKey skey = e.getKey();
|
SessionKey skey = e.getKey();
|
||||||
@ -767,8 +775,9 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
int size = ts.size();
|
int size = ts.size();
|
||||||
total += size;
|
total += size;
|
||||||
buf.append("<li><b>ID: ").append(ts.getID());
|
buf.append("<li><b>ID: ").append(ts.getID());
|
||||||
buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()));
|
buf.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
||||||
long expires = ts.getDate() - exp;
|
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
||||||
|
long expires = ts.getExpiration() - now;
|
||||||
if (expires > 0)
|
if (expires > 0)
|
||||||
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
||||||
else
|
else
|
||||||
@ -789,7 +798,6 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
|
|
||||||
// outbound
|
// outbound
|
||||||
totalSets = 0;
|
totalSets = 0;
|
||||||
exp = now - SESSION_TAG_DURATION_MS;
|
|
||||||
Set<OutboundSession> outbound = getOutboundSessions();
|
Set<OutboundSession> outbound = getOutboundSessions();
|
||||||
for (OutboundSession sess : outbound) {
|
for (OutboundSession sess : outbound) {
|
||||||
sets.clear();
|
sets.clear();
|
||||||
@ -808,8 +816,9 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
for (RatchetTagSet ts : sets) {
|
for (RatchetTagSet ts : sets) {
|
||||||
int size = ts.remaining();
|
int size = ts.remaining();
|
||||||
buf.append("<li><b>ID: ").append(ts.getID())
|
buf.append("<li><b>ID: ").append(ts.getID())
|
||||||
.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()));
|
.append(" created:</b> ").append(DataHelper.formatTime(ts.getCreated()))
|
||||||
long expires = ts.getDate() - exp;
|
.append(" <b>last use:</b> ").append(DataHelper.formatTime(ts.getDate()));
|
||||||
|
long expires = ts.getExpiration() - now;
|
||||||
if (expires > 0)
|
if (expires > 0)
|
||||||
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
buf.append(" <b>expires in:</b> ").append(DataHelper.formatDuration2(expires)).append(" with ");
|
||||||
else
|
else
|
||||||
@ -1130,7 +1139,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
synchronized (_tagSets) {
|
synchronized (_tagSets) {
|
||||||
for (Iterator<RatchetTagSet> iter = _tagSets.iterator(); iter.hasNext(); ) {
|
for (Iterator<RatchetTagSet> iter = _tagSets.iterator(); iter.hasNext(); ) {
|
||||||
RatchetTagSet set = iter.next();
|
RatchetTagSet set = iter.next();
|
||||||
if (set.getDate() + SESSION_TAG_DURATION_MS <= now) {
|
if (set.getExpiration() <= now) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
removed++;
|
removed++;
|
||||||
}
|
}
|
||||||
@ -1139,7 +1148,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
if ((now & 0x0f) == 0) {
|
if ((now & 0x0f) == 0) {
|
||||||
for (Iterator<RatchetTagSet> iter = _unackedTagSets.iterator(); iter.hasNext(); ) {
|
for (Iterator<RatchetTagSet> iter = _unackedTagSets.iterator(); iter.hasNext(); ) {
|
||||||
RatchetTagSet set = iter.next();
|
RatchetTagSet set = iter.next();
|
||||||
if (set.getDate() + SESSION_TAG_DURATION_MS <= now) {
|
if (set.getExpiration() <= now) {
|
||||||
iter.remove();
|
iter.remove();
|
||||||
removed++;
|
removed++;
|
||||||
}
|
}
|
||||||
@ -1156,7 +1165,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
while (!_tagSets.isEmpty()) {
|
while (!_tagSets.isEmpty()) {
|
||||||
RatchetTagSet set = _tagSets.get(0);
|
RatchetTagSet set = _tagSets.get(0);
|
||||||
synchronized(set) {
|
synchronized(set) {
|
||||||
if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
|
if (set.getExpiration() > now) {
|
||||||
RatchetSessionTag tag = set.consumeNext();
|
RatchetSessionTag tag = set.consumeNext();
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
set.setDate(now);
|
set.setDate(now);
|
||||||
@ -1186,7 +1195,7 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
RatchetTagSet set = _tagSets.get(i);
|
RatchetTagSet set = _tagSets.get(i);
|
||||||
if (!set.getAcked())
|
if (!set.getAcked())
|
||||||
continue;
|
continue;
|
||||||
if (set.getDate() + SESSION_TAG_DURATION_MS > now) {
|
if (set.getExpiration() > now) {
|
||||||
// or just add fixed number?
|
// or just add fixed number?
|
||||||
int sz = set.remaining();
|
int sz = set.remaining();
|
||||||
tags += sz;
|
tags += sz;
|
||||||
@ -1205,12 +1214,13 @@ public class RatchetSKM extends SessionKeyManager implements SessionTagListener
|
|||||||
long last = 0;
|
long last = 0;
|
||||||
synchronized (_tagSets) {
|
synchronized (_tagSets) {
|
||||||
for (RatchetTagSet set : _tagSets) {
|
for (RatchetTagSet set : _tagSets) {
|
||||||
if (set.getDate() > last && set.remaining() > 0)
|
long exp = set.getExpiration();
|
||||||
last = set.getDate();
|
if (exp > last && set.remaining() > 0)
|
||||||
|
last = exp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (last > 0)
|
if (last > 0)
|
||||||
return last + SESSION_TAG_DURATION_MS;
|
return last;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ import net.i2p.util.Log;
|
|||||||
class RatchetTagSet implements TagSetHandle {
|
class RatchetTagSet implements TagSetHandle {
|
||||||
private final SessionTagListener _lsnr;
|
private final SessionTagListener _lsnr;
|
||||||
private final PublicKey _remoteKey;
|
private final PublicKey _remoteKey;
|
||||||
private final SessionKey _key;
|
protected final SessionKey _key;
|
||||||
private final HandshakeState _state;
|
private final HandshakeState _state;
|
||||||
// inbound only, else null
|
// inbound only, else null
|
||||||
// We use object for tags because we must do indexOfValueByValue()
|
// We use object for tags because we must do indexOfValueByValue()
|
||||||
@ -48,6 +48,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
private final SparseArray<byte[]> _sessionKeys;
|
private final SparseArray<byte[]> _sessionKeys;
|
||||||
private final HKDF hkdf;
|
private final HKDF hkdf;
|
||||||
private final long _created;
|
private final long _created;
|
||||||
|
private final long _timeout;
|
||||||
private long _date;
|
private long _date;
|
||||||
private final int _id;
|
private final int _id;
|
||||||
private final int _originalSize;
|
private final int _originalSize;
|
||||||
@ -84,7 +85,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, HandshakeState state, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, HandshakeState state, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id) {
|
long date, int id) {
|
||||||
this(hkdf, null, state, null, rootKey, data, date, id, false, 0, 0);
|
this(hkdf, null, state, null, rootKey, data, date, RatchetSKM.SESSION_PENDING_DURATION_MS, id, false, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,7 +95,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id) {
|
long date, int id) {
|
||||||
this(hkdf, null, null, null, rootKey, data, date, id, false, 0, 0);
|
this(hkdf, null, null, null, rootKey, data, date, RatchetSKM.SESSION_TAG_DURATION_MS, id, false, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,7 +105,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, int minSize, int maxSize) {
|
long date, int id, int minSize, int maxSize) {
|
||||||
this(hkdf, lsnr, state, null, rootKey, data, date, id, true, minSize, maxSize);
|
this(hkdf, lsnr, state, null, rootKey, data, date, RatchetSKM.SESSION_PENDING_DURATION_MS, id, true, minSize, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,7 +116,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr,
|
public RatchetTagSet(HKDF hkdf, SessionTagListener lsnr,
|
||||||
PublicKey remoteKey, SessionKey rootKey, SessionKey data,
|
PublicKey remoteKey, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, int minSize, int maxSize) {
|
long date, int id, int minSize, int maxSize) {
|
||||||
this(hkdf, lsnr, null, remoteKey, rootKey, data, date, id, true, minSize, maxSize);
|
this(hkdf, lsnr, null, remoteKey, rootKey, data, date, RatchetSKM.SESSION_LIFETIME_MAX_MS, id, true, minSize, maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,12 +125,13 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
*/
|
*/
|
||||||
private RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state,
|
private RatchetTagSet(HKDF hkdf, SessionTagListener lsnr, HandshakeState state,
|
||||||
PublicKey remoteKey, SessionKey rootKey, SessionKey data,
|
PublicKey remoteKey, SessionKey rootKey, SessionKey data,
|
||||||
long date, int id, boolean isInbound, int minSize, int maxSize) {
|
long date, long timeout, int id, boolean isInbound, int minSize, int maxSize) {
|
||||||
_lsnr = lsnr;
|
_lsnr = lsnr;
|
||||||
_state = state;
|
_state = state;
|
||||||
_remoteKey = remoteKey;
|
_remoteKey = remoteKey;
|
||||||
_key = rootKey;
|
_key = rootKey;
|
||||||
_created = date;
|
_created = date;
|
||||||
|
_timeout = timeout;
|
||||||
_date = date;
|
_date = date;
|
||||||
_id = id;
|
_id = id;
|
||||||
_originalSize = minSize;
|
_originalSize = minSize;
|
||||||
@ -159,6 +161,31 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For SingleTagSet
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
protected RatchetTagSet(SessionTagListener lsnr, SessionKey rootKey, long date, long timeout) {
|
||||||
|
_lsnr = lsnr;
|
||||||
|
_state = null;
|
||||||
|
_remoteKey = null;
|
||||||
|
_key = rootKey;
|
||||||
|
_created = date;
|
||||||
|
_timeout = timeout;
|
||||||
|
_date = date;
|
||||||
|
_id = 0x10003;
|
||||||
|
_originalSize = 1;
|
||||||
|
_maxSize = 1;
|
||||||
|
_nextRootKey = null;
|
||||||
|
_sesstag_ck = null;
|
||||||
|
_sesstag_constant = null;
|
||||||
|
_symmkey_ck = null;
|
||||||
|
_symmkey_constant = null;
|
||||||
|
hkdf = null;
|
||||||
|
_sessionTags = null;
|
||||||
|
_sessionKeys = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
if (_sessionTags != null)
|
if (_sessionTags != null)
|
||||||
_sessionTags.clear();
|
_sessionTags.clear();
|
||||||
@ -201,6 +228,7 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* For inbound and outbound: last used time
|
* For inbound and outbound: last used time
|
||||||
|
* Expiration is getDate() + getTimeout().
|
||||||
*/
|
*/
|
||||||
public long getDate() {
|
public long getDate() {
|
||||||
return _date;
|
return _date;
|
||||||
@ -214,12 +242,30 @@ class RatchetTagSet implements TagSetHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For inbound and outbound: creation time
|
* For inbound and outbound: creation time, for debugging only
|
||||||
*/
|
*/
|
||||||
public long getCreated() {
|
public long getCreated() {
|
||||||
return _created;
|
return _created;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For inbound and outbound: Idle timeout interval.
|
||||||
|
* Expiration is getDate() + getTimeout().
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public long getTimeout() {
|
||||||
|
return _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For inbound and outbound: Expiration.
|
||||||
|
* Expiration is getDate() + getTimeout().
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
public synchronized long getExpiration() {
|
||||||
|
return _date + _timeout;
|
||||||
|
}
|
||||||
|
|
||||||
/** for debugging */
|
/** for debugging */
|
||||||
public int getOriginalSize() {
|
public int getOriginalSize() {
|
||||||
return _originalSize;
|
return _originalSize;
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
package net.i2p.router.crypto.ratchet;
|
||||||
|
|
||||||
|
import net.i2p.data.SessionKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inbound ES tagset with a single tag and key.
|
||||||
|
* Nonce is 0.
|
||||||
|
* For receiving DSM/DSRM replies.
|
||||||
|
*
|
||||||
|
* @since 0.9.46
|
||||||
|
*/
|
||||||
|
class SingleTagSet extends RatchetTagSet {
|
||||||
|
|
||||||
|
private final RatchetSessionTag _tag;
|
||||||
|
private boolean _isUsed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For outbound Existing Session
|
||||||
|
*/
|
||||||
|
public SingleTagSet(SessionTagListener lsnr, SessionKey key, RatchetSessionTag tag, long date, long timeout) {
|
||||||
|
super(lsnr, key, date, timeout);
|
||||||
|
_tag = tag;
|
||||||
|
lsnr.addTag(tag, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return _isUsed ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int remaining() {
|
||||||
|
return _isUsed ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionKeyAndNonce consume(RatchetSessionTag tag) {
|
||||||
|
if (_isUsed || !tag.equals(_tag))
|
||||||
|
return null;
|
||||||
|
_isUsed = true;
|
||||||
|
return new SessionKeyAndNonce(_key.getData(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder buf = new StringBuilder(64);
|
||||||
|
buf.append("[SingleTagSet: 0 ");
|
||||||
|
buf.append(_tag.toBase64());
|
||||||
|
buf.append(' ').append(_key.toBase64());
|
||||||
|
buf.append(']');
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user