Search in sources :

Example 11 with SessionKey

use of net.i2p.data.SessionKey in project i2p.i2p by i2p.

the class IntroductionManager method receiveRelayRequest.

/**
 *  We are Bob and we got this from Alice.
 *  Send a RelayIntro to Charlie and a RelayResponse to Alice.
 *  We should already have a session with Charlie, but not necessarily with Alice.
 */
void receiveRelayRequest(RemoteHostId alice, UDPPacketReader reader) {
    if (_context.router().isHidden())
        return;
    UDPPacketReader.RelayRequestReader rrReader = reader.getRelayRequestReader();
    long tag = rrReader.readTag();
    int ipSize = rrReader.readIPSize();
    int port = rrReader.readPort();
    // ip/port inside message should be 0:0, as it's unimplemented on send -
    // see PacketBuilder.buildRelayRequest()
    // and we don't read it here.
    // FIXME implement for getting Alice's IPv4 in RelayRequest sent over IPv6?
    // or is that just too easy to spoof?
    byte[] aliceIP = alice.getIP();
    int alicePort = alice.getPort();
    if (!isValid(alice.getIP(), alice.getPort())) {
        if (_log.shouldWarn())
            _log.warn("Bad relay req from " + alice + " for " + Addresses.toString(aliceIP, alicePort));
        _context.statManager().addRateData("udp.relayBadIP", 1);
        return;
    }
    // TODO relay request over IPv6
    if (ipSize != 0) {
        byte[] ip = new byte[ipSize];
        rrReader.readIP(ip, 0);
        if (!Arrays.equals(aliceIP, ip)) {
            if (_log.shouldWarn())
                _log.warn("Bad relay req from " + alice + " for " + Addresses.toString(ip, port));
            _context.statManager().addRateData("udp.relayBadIP", 1);
            return;
        }
    }
    // TODO relay request over IPv6
    if (port != 0 && port != alicePort) {
        if (_log.shouldWarn())
            _log.warn("Bad relay req from " + alice + " for " + Addresses.toString(aliceIP, port));
        _context.statManager().addRateData("udp.relayBadIP", 1);
        return;
    }
    PeerState charlie = get(tag);
    if (charlie == null) {
        if (_log.shouldLog(Log.INFO))
            _log.info("Receive relay request from " + alice + " with unknown tag");
        _context.statManager().addRateData("udp.receiveRelayRequestBadTag", 1);
        return;
    }
    if (_log.shouldLog(Log.INFO))
        _log.info("Receive relay request from " + alice + " for tag " + tag + " and relaying with " + charlie);
    // TODO throttle based on alice identity and/or intro tag?
    _context.statManager().addRateData("udp.receiveRelayRequest", 1);
    // send that peer an introduction for alice
    _transport.send(_builder.buildRelayIntro(alice, charlie, reader.getRelayRequestReader()));
    // send alice back charlie's info
    // lookup session so we can use session key if available
    SessionKey cipherKey = null;
    SessionKey macKey = null;
    PeerState aliceState = _transport.getPeerState(alice);
    if (aliceState != null) {
        // established session (since 0.9.12)
        cipherKey = aliceState.getCurrentCipherKey();
        macKey = aliceState.getCurrentMACKey();
    }
    if (cipherKey == null || macKey == null) {
        // no session, use intro key (was only way before 0.9.12)
        byte[] key = new byte[SessionKey.KEYSIZE_BYTES];
        reader.getRelayRequestReader().readAliceIntroKey(key, 0);
        cipherKey = new SessionKey(key);
        macKey = cipherKey;
        if (_log.shouldLog(Log.INFO))
            _log.info("Sending relay response (w/ intro key) to " + alice);
    } else {
        if (_log.shouldLog(Log.INFO))
            _log.info("Sending relay response (in-session) to " + alice);
    }
    _transport.send(_builder.buildRelayResponse(alice, charlie, reader.getRelayRequestReader().readNonce(), cipherKey, macKey));
}
Also used : SessionKey(net.i2p.data.SessionKey)

Example 12 with SessionKey

use of net.i2p.data.SessionKey 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));
}
Also used : PayloadGarlicConfig(net.i2p.router.message.PayloadGarlicConfig) SessionKey(net.i2p.data.SessionKey) RemovableSingletonSet(net.i2p.router.util.RemovableSingletonSet) GarlicMessage(net.i2p.data.i2np.GarlicMessage) SessionKeyManager(net.i2p.crypto.SessionKeyManager) SessionTag(net.i2p.data.SessionTag)

Example 13 with SessionKey

use of net.i2p.data.SessionKey in project i2p.i2p by i2p.

the class PacketBuilder method buildRelayRequest.

/**
 *  build intro packets for each of the published introducers
 *  @return empty list on failure
 */
public List<UDPPacket> buildRelayRequest(UDPTransport transport, OutboundEstablishState state, SessionKey ourIntroKey) {
    UDPAddress addr = state.getRemoteAddress();
    int count = addr.getIntroducerCount();
    List<UDPPacket> rv = new ArrayList<UDPPacket>(count);
    long cutoff = _context.clock().now() + 5 * 60 * 1000L;
    for (int i = 0; i < count; i++) {
        InetAddress iaddr = addr.getIntroducerHost(i);
        int iport = addr.getIntroducerPort(i);
        byte[] ikey = addr.getIntroducerKey(i);
        long tag = addr.getIntroducerTag(i);
        long exp = addr.getIntroducerExpiration(i);
        // let's not use an introducer on a privileged port, sounds like trouble
        if (ikey == null || !TransportUtil.isValidPort(iport) || iaddr == null || tag <= 0 || // must be IPv4 for now as we don't send Alice IP/port, see below
        iaddr.getAddress().length != 4 || (!_transport.isValid(iaddr.getAddress())) || (exp > 0 && exp < cutoff) || (Arrays.equals(iaddr.getAddress(), _transport.getExternalIP()) && !_transport.allowLocal())) {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Cannot build a relay request to " + state.getRemoteIdentity().calculateHash() + ", as their UDP address is invalid: addr=" + addr + " index=" + i);
            // TODO implement some sort of introducer banlist
            continue;
        }
        // lookup session so we can use session key if available
        SessionKey cipherKey = null;
        SessionKey macKey = null;
        // first look up by ikey, it is equal to router hash for now
        PeerState bobState = null;
        if (ikey.length == Hash.HASH_LENGTH) {
            bobState = transport.getPeerState(new Hash(ikey));
        }
        if (bobState == null) {
            RemoteHostId rhid = new RemoteHostId(iaddr.getAddress(), iport);
            bobState = transport.getPeerState(rhid);
        }
        if (bobState != null) {
            // established session (since 0.9.12)
            cipherKey = bobState.getCurrentCipherKey();
            macKey = bobState.getCurrentMACKey();
        }
        if (cipherKey == null || macKey == null) {
            // no session, use intro key (was only way before 0.9.12)
            cipherKey = new SessionKey(ikey);
            macKey = cipherKey;
            if (_log.shouldLog(Log.INFO))
                _log.info("Sending relay request (w/ intro key) to " + iaddr + ":" + iport);
        } else {
            if (_log.shouldLog(Log.INFO))
                _log.info("Sending relay request (in-session) to " + iaddr + ":" + iport);
        }
        rv.add(buildRelayRequest(iaddr, iport, cipherKey, macKey, tag, ourIntroKey, state.getIntroNonce()));
    }
    return rv;
}
Also used : SessionKey(net.i2p.data.SessionKey) ArrayList(java.util.ArrayList) Hash(net.i2p.data.Hash) InetAddress(java.net.InetAddress)

Example 14 with SessionKey

use of net.i2p.data.SessionKey in project i2p.i2p by i2p.

the class GarlicMessageBuilder method needsTags.

/**
 *  @param local non-null; do not use this method for the router's SessionKeyManager
 *  @param minTagOverride 0 for no override, &gt; 0 to override SKM's settings
 */
static boolean needsTags(RouterContext ctx, PublicKey key, Hash local, int minTagOverride) {
    SessionKeyManager skm = ctx.clientManager().getClientSessionKeyManager(local);
    if (skm == null)
        return true;
    SessionKey curKey = skm.getCurrentKey(key);
    if (curKey == null)
        return true;
    if (minTagOverride > 0)
        return skm.shouldSendTags(key, curKey, minTagOverride);
    return skm.shouldSendTags(key, curKey);
}
Also used : SessionKey(net.i2p.data.SessionKey) SessionKeyManager(net.i2p.crypto.SessionKeyManager)

Example 15 with SessionKey

use of net.i2p.data.SessionKey in project i2p.i2p by i2p.

the class GarlicMessageBuilder method buildMessage.

/**
 * called by netdb and above
 *
 * @param ctx scope
 * @param config how/what to wrap
 * @param wrappedKey output parameter that will be filled with the sessionKey used
 * @param wrappedTags Output parameter that will be filled with the sessionTags used.
 *                          If non-empty on return you must call skm.tagsDelivered() when sent
 *                          and then call skm.tagsAcked() or skm.failTags() later.
 * @param numTagsToDeliver only if the estimated available tags are below the threshold.
 *                               Set to zero to disable tag delivery. You must set to zero if you are not
 *                               equipped to confirm delivery and call skm.tagsAcked() or failTags() later.
 *                               If this is always 0, it forces ElGamal every time.
 * @param lowTagsThreshold the threshold
 * @param skm non-null
 * @throws IllegalArgumentException on error
 */
public static GarlicMessage buildMessage(RouterContext ctx, GarlicConfig config, SessionKey wrappedKey, Set<SessionTag> wrappedTags, int numTagsToDeliver, int lowTagsThreshold, SessionKeyManager skm) {
    Log log = ctx.logManager().getLog(GarlicMessageBuilder.class);
    PublicKey key = config.getRecipientPublicKey();
    if (key == null) {
        if (config.getRecipient() == null) {
            throw new IllegalArgumentException("Null recipient specified");
        } else if (config.getRecipient().getIdentity() == null) {
            throw new IllegalArgumentException("Null recipient.identity specified");
        } else if (config.getRecipient().getIdentity().getPublicKey() == null) {
            throw new IllegalArgumentException("Null recipient.identity.publicKey specified");
        } else
            key = config.getRecipient().getIdentity().getPublicKey();
    }
    if (log.shouldLog(Log.INFO))
        log.info("Encrypted with public key to expire on " + new Date(config.getExpiration()));
    SessionKey curKey = skm.getCurrentOrNewKey(key);
    SessionTag curTag = null;
    curTag = skm.consumeNextAvailableTag(key, curKey);
    if (log.shouldLog(Log.DEBUG)) {
        int availTags = skm.getAvailableTags(key, curKey);
        log.debug("Available tags for encryption: " + availTags + " low threshold: " + lowTagsThreshold);
    }
    if (numTagsToDeliver > 0 && skm.shouldSendTags(key, curKey, lowTagsThreshold)) {
        for (int i = 0; i < numTagsToDeliver; i++) wrappedTags.add(new SessionTag(true));
        if (log.shouldLog(Log.INFO))
            log.info("Too few tags available so we're including " + numTagsToDeliver);
    }
    wrappedKey.setData(curKey.getData());
    return buildMessage(ctx, config, wrappedKey, wrappedTags, key, curKey, curTag);
}
Also used : Log(net.i2p.util.Log) PublicKey(net.i2p.data.PublicKey) SessionKey(net.i2p.data.SessionKey) SessionTag(net.i2p.data.SessionTag) Date(java.util.Date)

Aggregations

SessionKey (net.i2p.data.SessionKey)69 SessionTag (net.i2p.data.SessionTag)15 PublicKey (net.i2p.data.PublicKey)14 I2PAppContext (net.i2p.I2PAppContext)13 HashSet (java.util.HashSet)11 Hash (net.i2p.data.Hash)11 SessionKeyManager (net.i2p.crypto.SessionKeyManager)10 PrivateKey (net.i2p.data.PrivateKey)10 InetAddress (java.net.InetAddress)9 DataFormatException (net.i2p.data.DataFormatException)9 UnknownHostException (java.net.UnknownHostException)7 TagSetHandle (net.i2p.crypto.TagSetHandle)5 Map (java.util.Map)4 GarlicMessage (net.i2p.data.i2np.GarlicMessage)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 Set (java.util.Set)3 EncryptedBuildRecord (net.i2p.data.i2np.EncryptedBuildRecord)3 BigInteger (java.math.BigInteger)2