use of net.i2p.data.i2np.GarlicMessage in project i2p.i2p by i2p.
the class TestJob method sendTest.
private void sendTest(I2NPMessage m) {
// garlic route that DeliveryStatusMessage to ourselves so the endpoints and gateways
// can't tell its a test. to simplify this, we encrypt it with a random key and tag,
// remembering that key+tag so that we can decrypt it later. this means we can do the
// garlic encryption without any ElGamal (yay)
PayloadGarlicConfig payload = new PayloadGarlicConfig();
payload.setCertificate(Certificate.NULL_CERT);
payload.setId(getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE));
payload.setPayload(m);
payload.setRecipient(getContext().router().getRouterInfo());
payload.setDeliveryInstructions(DeliveryInstructions.LOCAL);
payload.setExpiration(m.getMessageExpiration());
SessionKey encryptKey = getContext().keyGenerator().generateSessionKey();
SessionTag encryptTag = new SessionTag(true);
_encryptTag = encryptTag;
SessionKey sentKey = new SessionKey();
Set<SessionTag> sentTags = null;
GarlicMessage msg = GarlicMessageBuilder.buildMessage(getContext(), payload, sentKey, sentTags, getContext().keyManager().getPublicKey(), encryptKey, encryptTag);
if (msg == null) {
// overloaded / unknown peers / etc
scheduleRetest();
return;
}
Set<SessionTag> encryptTags = new RemovableSingletonSet<SessionTag>(encryptTag);
// Register the single tag with the appropriate SKM
if (_cfg.isInbound() && !_pool.getSettings().isExploratory()) {
SessionKeyManager skm = getContext().clientManager().getClientSessionKeyManager(_pool.getSettings().getDestination());
if (skm != null)
skm.tagsReceived(encryptKey, encryptTags);
} else {
getContext().sessionKeyManager().tagsReceived(encryptKey, encryptTags);
}
if (_log.shouldLog(Log.DEBUG))
_log.debug("Sending garlic test of " + _outTunnel + " / " + _replyTunnel);
getContext().tunnelDispatcher().dispatchOutbound(msg, _outTunnel.getSendTunnelId(0), _replyTunnel.getReceiveTunnelId(0), _replyTunnel.getPeer(0));
}
use of net.i2p.data.i2np.GarlicMessage in project i2p.i2p by i2p.
the class GarlicMessageBuilder method buildClove.
/**
* UNUSED
*
* The Garlic Message we are building contains another garlic message,
* as specified by a GarlicConfig (NOT a PayloadGarlicConfig).
*
* So this calls back to the top, to buildMessage(ctx, config),
* which uses the router's SKM, i.e. the wrong one.
* Unfortunately we've lost the reference to the SessionKeyManager way down here,
* so we can't call buildMessage(ctx, config, key, tags, skm).
*
* If we do ever end up constructing a garlic message that contains a garlic message,
* we'll have to fix this by passing the skm through the last buildMessage,
* through buildCloveSet, to here.
*/
private static byte[] buildClove(RouterContext ctx, GarlicConfig config) throws DataFormatException, IOException {
GarlicClove clove = new GarlicClove(ctx);
GarlicMessage msg = buildMessage(ctx, config);
if (msg == null)
throw new DataFormatException("Unable to build message from clove config");
clove.setData(msg);
return buildCommonClove(clove, config);
}
use of net.i2p.data.i2np.GarlicMessage in project i2p.i2p by i2p.
the class GarlicMessageBuilder method buildMessage.
/**
* used by TestJob and directly above
* and for encrypting DatabaseLookupMessages
*
* @param ctx scope
* @param config how/what to wrap
* @param wrappedKey unused - why??
* @param wrappedTags New tags to be sent along with the message.
* 200 max enforced at receiver; null OK
* @param target public key of the location being garlic routed to (may be null if we
* know the encryptKey and encryptTag)
* @param encryptKey sessionKey used to encrypt the current message, non-null
* @param encryptTag sessionTag used to encrypt the current message, null to force ElG
* @throws IllegalArgumentException on error
*/
public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set<SessionTag> wrappedTags, PublicKey target, SessionKey encryptKey, SessionTag encryptTag) {
Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
if (config == null)
throw new IllegalArgumentException("Null config specified");
GarlicMessage msg = new GarlicMessage(ctx);
// noteWrap(ctx, msg, config);
byte[] cloveSet = buildCloveSet(ctx, config);
// TODO - 128 is the minimum padded size - should it be more? less? random?
byte[] encData = ctx.elGamalAESEngine().encrypt(cloveSet, target, encryptKey, wrappedTags, encryptTag, 128);
msg.setData(encData);
msg.setMessageExpiration(config.getExpiration());
long timeFromNow = config.getExpiration() - ctx.clock().now();
if (timeFromNow < 1 * 1000) {
if (log.shouldLog(Log.DEBUG))
log.debug("Building a message expiring in " + timeFromNow + "ms: " + config, new Exception("created by"));
return null;
}
if (log.shouldLog(Log.DEBUG))
log.debug("CloveSet (" + config.getCloveCount() + " cloves) for message " + msg.getUniqueId() + " is " + cloveSet.length + " bytes and encrypted message data is " + encData.length + " bytes");
return msg;
}
use of net.i2p.data.i2np.GarlicMessage in project i2p.i2p by i2p.
the class OutboundClientMessageJobHelper method buildAckClove.
/**
* Build a clove that sends a DeliveryStatusMessage to us.
* As of 0.9.12, the DSM is wrapped in a GarlicMessage.
* @param skm encrypt dsm with this skm non-null
* @return null on error
*/
private static PayloadGarlicConfig buildAckClove(RouterContext ctx, Hash from, TunnelInfo replyToTunnel, long replyToken, long expiration, SessionKeyManager skm) {
Log log = ctx.logManager().getLog(OutboundClientMessageJobHelper.class);
if (replyToTunnel == null) {
if (log.shouldLog(Log.WARN))
log.warn("Unable to send client message from " + from.toBase64() + ", as there are no inbound tunnels available");
return null;
}
// tunnel id on that gateway
TunnelId replyToTunnelId = replyToTunnel.getReceiveTunnelId(0);
// inbound tunnel gateway
Hash replyToTunnelRouter = replyToTunnel.getPeer(0);
if (log.shouldLog(Log.DEBUG))
log.debug("Ack for the data message will come back along tunnel " + replyToTunnelId + ": " + replyToTunnel);
DeliveryInstructions ackInstructions = new DeliveryInstructions();
ackInstructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_TUNNEL);
ackInstructions.setRouter(replyToTunnelRouter);
ackInstructions.setTunnelId(replyToTunnelId);
// defaults
// ackInstructions.setDelayRequested(false);
// ackInstructions.setDelaySeconds(0);
// ackInstructions.setEncrypted(false);
PayloadGarlicConfig ackClove = new PayloadGarlicConfig();
ackClove.setCertificate(Certificate.NULL_CERT);
ackClove.setDeliveryInstructions(ackInstructions);
ackClove.setExpiration(expiration);
ackClove.setId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
DeliveryStatusMessage dsm = buildDSM(ctx, replyToken);
GarlicMessage msg = wrapDSM(ctx, skm, dsm);
if (msg == null) {
if (log.shouldLog(Log.WARN))
log.warn("Failed to wrap ack clove");
return null;
}
ackClove.setPayload(msg);
return ackClove;
}
use of net.i2p.data.i2np.GarlicMessage in project i2p.i2p by i2p.
the class OutboundClientMessageJobHelper method createGarlicMessage.
/**
* Build a garlic message that will be delivered to the router on which the target is located.
* Inside the message are two cloves: one containing the payload with instructions for
* delivery to the (now local) destination, and the other containing a DeliveryStatusMessage with
* instructions for delivery to an inbound tunnel of this router.
*
* How the DeliveryStatusMessage is wrapped can vary - it can be simply sent to a tunnel (as above),
* wrapped in a GarlicMessage and source routed a few hops before being tunneled, source routed the
* entire way back, or not wrapped at all - in which case the payload clove contains a SourceRouteBlock
* and a request for a reply.
*
* For now, its just a tunneled DeliveryStatusMessage
*
* Unused?
*
* @param wrappedKey output parameter that will be filled with the sessionKey used
* @param wrappedTags output parameter that will be filled with the sessionTags used
* @param bundledReplyLeaseSet if specified, the given LeaseSet will be packaged with the message (allowing
* much faster replies, since their netDb search will return almost instantly)
* @param replyTunnel non-null if requireAck is true or bundledReplyLeaseSet is non-null
* @param requireAck if true, bundle replyToken in an ack clove
* @return garlic, or null if no tunnels were found (or other errors)
*/
/**
**
* static GarlicMessage createGarlicMessage(RouterContext ctx, long replyToken, long expiration, PublicKey recipientPK,
* Payload data, Hash from, Destination dest, TunnelInfo replyTunnel,
* SessionKey wrappedKey, Set<SessionTag> wrappedTags,
* boolean requireAck, LeaseSet bundledReplyLeaseSet) {
* PayloadGarlicConfig dataClove = buildDataClove(ctx, data, dest, expiration);
* return createGarlicMessage(ctx, replyToken, expiration, recipientPK, dataClove, from, dest, replyTunnel,
* 0, 0, wrappedKey, wrappedTags, requireAck, bundledReplyLeaseSet);
* }
***
*/
/**
* Allow the app to specify the data clove directly, which enables OutboundClientMessage to resend the
* same payload (including expiration and unique id) in different garlics (down different tunnels)
*
* This is called from OCMOSJ
*
* @param tagsToSendOverride if > 0, use this instead of skm's default
* @param lowTagsOverride if > 0, use this instead of skm's default
* @param wrappedKey output parameter that will be filled with the sessionKey used
* @param wrappedTags output parameter that will be filled with the sessionTags used
* @param replyTunnel non-null if requireAck is true or bundledReplyLeaseSet is non-null
* @param requireAck if true, bundle replyToken in an ack clove
* @param bundledReplyLeaseSet may be null; if non-null, put it in a clove
* @return garlic, or null if no tunnels were found (or other errors)
*/
static GarlicMessage createGarlicMessage(RouterContext ctx, long replyToken, long expiration, PublicKey recipientPK, PayloadGarlicConfig dataClove, Hash from, Destination dest, TunnelInfo replyTunnel, int tagsToSendOverride, int lowTagsOverride, SessionKey wrappedKey, Set<SessionTag> wrappedTags, boolean requireAck, LeaseSet bundledReplyLeaseSet) {
SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(from);
if (skm == null)
return null;
GarlicConfig config = createGarlicConfig(ctx, replyToken, expiration, recipientPK, dataClove, from, dest, replyTunnel, requireAck, bundledReplyLeaseSet, skm);
if (config == null)
return null;
// no use sending tags unless we have a reply token set up already
int tagsToSend = replyToken >= 0 ? (tagsToSendOverride > 0 ? tagsToSendOverride : skm.getTagsToSend()) : 0;
int lowThreshold = lowTagsOverride > 0 ? lowTagsOverride : skm.getLowThreshold();
GarlicMessage msg = GarlicMessageBuilder.buildMessage(ctx, config, wrappedKey, wrappedTags, tagsToSend, lowThreshold, skm);
return msg;
}
Aggregations