Search in sources :

Example 16 with SigType

use of net.i2p.crypto.SigType in project i2p.i2p by i2p.

the class GeneralHelper method getSigType.

/**
 *  @param newTunnelType used if tunnel < 0
 *  @return the current type if we have a destination already,
 *          else the default for that type of tunnel
 */
public int getSigType(int tunnel, String newTunnelType) {
    SigType type;
    String ttype;
    boolean isShared;
    if (tunnel >= 0) {
        Destination d = getDestination(tunnel);
        if (d != null) {
            type = d.getSigType();
            if (type != null)
                return type.getCode();
        }
        String stype = getProperty(tunnel, I2PClient.PROP_SIGTYPE, null);
        type = stype != null ? SigType.parseSigType(stype) : null;
        ttype = getTunnelType(tunnel);
        isShared = isSharedClient(tunnel);
    } else {
        type = null;
        ttype = newTunnelType;
        isShared = false;
    }
    if (type == null) {
        // same default logic as in TunnelController.setConfig()
        if (!TunnelController.isClient(ttype) || TunnelController.TYPE_IRC_CLIENT.equals(ttype) || TunnelController.TYPE_SOCKS_IRC.equals(ttype) || TunnelController.TYPE_SOCKS.equals(ttype) || TunnelController.TYPE_STREAMR_CLIENT.equals(ttype) || TunnelController.TYPE_STD_CLIENT.equals(ttype) || (TunnelController.TYPE_HTTP_CLIENT.equals(ttype) && isShared))
            type = TunnelController.PREFERRED_SIGTYPE;
        else
            type = SigType.DSA_SHA1;
    }
    return type.getCode();
}
Also used : Destination(net.i2p.data.Destination) SigType(net.i2p.crypto.SigType)

Example 17 with SigType

use of net.i2p.crypto.SigType in project i2p.i2p by i2p.

the class RouterPrivateKeyFile method getRouterIdentity.

/**
 *  Read it in from the file.
 *  Also sets the local privKey and signingPrivKey.
 */
public RouterIdentity getRouterIdentity() throws IOException, DataFormatException {
    InputStream in = null;
    try {
        in = new BufferedInputStream(new FileInputStream(this.file));
        RouterIdentity ri = new RouterIdentity();
        ri.readBytes(in);
        privKey = new PrivateKey();
        privKey.readBytes(in);
        SigType type = ri.getSigningPublicKey().getType();
        if (type == null)
            throw new DataFormatException("Unknown sig type");
        signingPrivKey = new SigningPrivateKey(type);
        signingPrivKey.readBytes(in);
        // set it a Destination, so we may call validateKeyPairs()
        // or other methods
        dest = new Destination();
        dest.setPublicKey(ri.getPublicKey());
        dest.setSigningPublicKey(ri.getSigningPublicKey());
        dest.setCertificate(ri.getCertificate());
        dest.setPadding(ri.getPadding());
        return ri;
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (IOException ioe) {
            }
        }
    }
}
Also used : SigningPrivateKey(net.i2p.data.SigningPrivateKey) Destination(net.i2p.data.Destination) SigningPrivateKey(net.i2p.data.SigningPrivateKey) PrivateKey(net.i2p.data.PrivateKey) DataFormatException(net.i2p.data.DataFormatException) BufferedInputStream(java.io.BufferedInputStream) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) SigType(net.i2p.crypto.SigType)

Example 18 with SigType

use of net.i2p.crypto.SigType in project i2p.i2p by i2p.

the class InboundEstablishState method receiveSessionConfirmed.

/**
 *  Note that while a SessionConfirmed could in theory be fragmented,
 *  in practice a RouterIdentity is 387 bytes and a single fragment is 512 bytes max,
 *  so it will never be fragmented.
 */
public synchronized void receiveSessionConfirmed(UDPPacketReader.SessionConfirmedReader conf) {
    if (_receivedIdentity == null)
        _receivedIdentity = new byte[conf.readTotalFragmentNum()][];
    int cur = conf.readCurrentFragmentNum();
    if (cur >= _receivedIdentity.length) {
        // avoid AIOOBE
        // should do more than this, but what? disconnect?
        fail();
        packetReceived();
        return;
    }
    if (_receivedIdentity[cur] == null) {
        byte[] fragment = new byte[conf.readCurrentFragmentSize()];
        conf.readFragmentData(fragment, 0);
        _receivedIdentity[cur] = fragment;
    }
    if (cur == _receivedIdentity.length - 1) {
        _receivedSignedOnTime = conf.readFinalFragmentSignedOnTime();
        // TODO verify time to prevent replay attacks
        buildIdentity();
        if (_receivedUnconfirmedIdentity != null) {
            SigType type = _receivedUnconfirmedIdentity.getSigningPublicKey().getType();
            if (type != null) {
                int sigLen = type.getSigLen();
                if (_receivedSignature == null)
                    _receivedSignature = new byte[sigLen];
                conf.readFinalSignature(_receivedSignature, 0, sigLen);
            } else {
                if (_log.shouldLog(Log.WARN))
                    _log.warn("Unsupported sig type from: " + toString());
                // _x() in UDPTransport
                _context.banlist().banlistRouterForever(_receivedUnconfirmedIdentity.calculateHash(), "Unsupported signature type");
                fail();
            }
        } else {
            if (_log.shouldLog(Log.WARN))
                _log.warn("Bad ident from: " + toString());
            fail();
        }
    }
    if ((_currentState == InboundState.IB_STATE_UNKNOWN) || (_currentState == InboundState.IB_STATE_REQUEST_RECEIVED) || (_currentState == InboundState.IB_STATE_CREATED_SENT)) {
        if (confirmedFullyReceived())
            _currentState = InboundState.IB_STATE_CONFIRMED_COMPLETELY;
        else
            _currentState = InboundState.IB_STATE_CONFIRMED_PARTIALLY;
    }
    packetReceived();
}
Also used : SigType(net.i2p.crypto.SigType)

Example 19 with SigType

use of net.i2p.crypto.SigType in project i2p.i2p by i2p.

the class EstablishState method receiveOutbound.

/**
 *  We are Alice, so receive these bytes as part of an outbound connection.
 *  This method receives messages 2 and 4, and sends message 3.
 *
 *  All data must be copied out of the buffer as Reader.processRead()
 *  will return it to the pool.
 *
 *  Caller must synch.
 *
 *  FIXME none of the _state comparisons use _stateLock, but whole thing
 *  is synchronized, should be OK. See isComplete()
 */
private void receiveOutbound(ByteBuffer src) {
    // Read in Y, which is the first part of message #2
    while (_state == State.OB_SENT_X && src.hasRemaining()) {
        byte c = src.get();
        _Y[_received++] = c;
        // if (_log.shouldLog(Log.DEBUG)) _log.debug("recv x" + (int)c + " received=" + _received);
        if (_received >= XY_SIZE) {
            try {
                _dh.setPeerPublicValue(_Y);
                // force the calc
                _dh.getSessionKey();
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug(prefix() + "DH session key calculated (" + _dh.getSessionKey().toBase64() + ")");
                changeState(State.OB_GOT_Y);
            } catch (DHSessionKeyBuilder.InvalidPublicParameterException e) {
                _context.statManager().addRateData("ntcp.invalidDH", 1);
                fail("Invalid X", e);
                return;
            }
        }
    }
    // Read in the rest of message #2
    while (_state == State.OB_GOT_Y && src.hasRemaining()) {
        int i = _received - XY_SIZE;
        _received++;
        byte c = src.get();
        _e_hXY_tsB[i] = c;
        // _log.debug(prefix() + "recv _e_hXY_tsB " + (int)c + " received=" + _received);
        if (i + 1 >= HXY_TSB_PAD_SIZE) {
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "received _e_hXY_tsB fully");
            byte[] hXY_tsB = new byte[HXY_TSB_PAD_SIZE];
            _context.aes().decrypt(_e_hXY_tsB, 0, hXY_tsB, 0, _dh.getSessionKey(), _Y, XY_SIZE - AES_SIZE, HXY_TSB_PAD_SIZE);
            byte[] XY = new byte[XY_SIZE + XY_SIZE];
            System.arraycopy(_X, 0, XY, 0, XY_SIZE);
            System.arraycopy(_Y, 0, XY, XY_SIZE, XY_SIZE);
            byte[] h = SimpleByteCache.acquire(HXY_SIZE);
            _context.sha().calculateHash(XY, 0, XY_SIZE + XY_SIZE, h, 0);
            // _log.debug(prefix() + "h(XY)=" + h.toBase64());
            if (!DataHelper.eq(h, 0, hXY_tsB, 0, HXY_SIZE)) {
                SimpleByteCache.release(h);
                _context.statManager().addRateData("ntcp.invalidHXY", 1);
                fail("Invalid H(X+Y) - mitm attack attempted?");
                return;
            }
            SimpleByteCache.release(h);
            changeState(State.OB_GOT_HXY);
            // their (Bob's) timestamp in seconds
            _tsB = DataHelper.fromLong(hXY_tsB, HXY_SIZE, 4);
            long now = _context.clock().now();
            // rtt from sending #1 to receiving #2
            long rtt = now - _con.getCreated();
            // our (Alice's) timestamp in seconds
            _tsA = (now + 500) / 1000;
            _peerSkew = (now - (_tsB * 1000) - (rtt / 2) + 500) / 1000;
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "h(X+Y) is correct, skew = " + _peerSkew);
            // the skew is not authenticated yet, but it is certainly fatal to
            // the establishment, so fail hard if appropriate
            long diff = 1000 * Math.abs(_peerSkew);
            if (!_context.clock().getUpdatedSuccessfully()) {
                // Adjust the clock one time in desperation
                // We are Alice, he is Bob, adjust to match Bob
                _context.clock().setOffset(1000 * (0 - _peerSkew), true);
                _peerSkew = 0;
                if (diff != 0)
                    _log.logAlways(Log.WARN, "NTP failure, NTCP adjusting clock by " + DataHelper.formatDuration(diff));
            } else if (diff >= Router.CLOCK_FUDGE_FACTOR) {
                _context.statManager().addRateData("ntcp.invalidOutboundSkew", diff);
                _transport.markReachable(_con.getRemotePeer().calculateHash(), false);
                // Only banlist if we know what time it is
                _context.banlist().banlistRouter(DataHelper.formatDuration(diff), _con.getRemotePeer().calculateHash(), _x("Excessive clock skew: {0}"));
                _transport.setLastBadSkew(_peerSkew);
                fail("Clocks too skewed (" + diff + " ms)", null, true);
                return;
            } else if (_log.shouldLog(Log.DEBUG)) {
                _log.debug(prefix() + "Clock skew: " + diff + " ms");
            }
            // now prepare and send our response
            // send E(#+Alice.identity+tsA+padding+S(X+Y+Bob.identHash+tsA+tsB), sk, hX_xor_Bob.identHash[16:31])
            // +12;
            int sigSize = XY_SIZE + XY_SIZE + HXY_SIZE + 4 + 4;
            byte[] preSign = new byte[sigSize];
            System.arraycopy(_X, 0, preSign, 0, XY_SIZE);
            System.arraycopy(_Y, 0, preSign, XY_SIZE, XY_SIZE);
            System.arraycopy(_con.getRemotePeer().calculateHash().getData(), 0, preSign, XY_SIZE + XY_SIZE, HXY_SIZE);
            DataHelper.toLong(preSign, XY_SIZE + XY_SIZE + HXY_SIZE, 4, _tsA);
            DataHelper.toLong(preSign, XY_SIZE + XY_SIZE + HXY_SIZE + 4, 4, _tsB);
            // hXY_tsB has 12 bytes of padding (size=48, tsB=4 + hXY=32)
            // System.arraycopy(hXY_tsB, hXY_tsB.length-12, preSign, _X.length+_Y.length+Hash.HASH_LENGTH+4+4, 12);
            // byte sigPad[] = new byte[padSig];
            // _context.random().nextBytes(sigPad);
            // System.arraycopy(sigPad, 0, preSign, _X.length+_Y.length+Hash.HASH_LENGTH+4+4, padSig);
            Signature sig = _context.dsa().sign(preSign, _context.keyManager().getSigningPrivateKey());
            // if (_log.shouldLog(Log.DEBUG)) {
            // _log.debug(prefix()+"signing " + Base64.encode(preSign));
            // }
            byte[] ident = _context.router().getRouterInfo().getIdentity().toByteArray();
            // handle variable signature size
            int min = 2 + ident.length + 4 + sig.length();
            int rem = min % AES_SIZE;
            int padding = 0;
            if (rem > 0)
                padding = AES_SIZE - rem;
            byte[] preEncrypt = new byte[min + padding];
            DataHelper.toLong(preEncrypt, 0, 2, ident.length);
            System.arraycopy(ident, 0, preEncrypt, 2, ident.length);
            DataHelper.toLong(preEncrypt, 2 + ident.length, 4, _tsA);
            if (padding > 0)
                _context.random().nextBytes(preEncrypt, 2 + ident.length + 4, padding);
            System.arraycopy(sig.getData(), 0, preEncrypt, 2 + ident.length + 4 + padding, sig.length());
            _prevEncrypted = new byte[preEncrypt.length];
            _context.aes().encrypt(preEncrypt, 0, _prevEncrypted, 0, _dh.getSessionKey(), _hX_xor_bobIdentHash, _hX_xor_bobIdentHash.length - AES_SIZE, preEncrypt.length);
            // if (_log.shouldLog(Log.DEBUG)) {
            // _log.debug(prefix() + "unencrypted response to Bob: " + Base64.encode(preEncrypt));
            // _log.debug(prefix() + "encrypted response to Bob: " + Base64.encode(_prevEncrypted));
            // }
            // send 'er off (when the bw limiter says, etc)
            changeState(State.OB_SENT_RI);
            _transport.getPumper().wantsWrite(_con, _prevEncrypted);
        }
    }
    // Read in message #4
    if (_state == State.OB_SENT_RI && src.hasRemaining()) {
        // we are receiving their confirmation
        // recv E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev)
        int off = 0;
        if (_e_bobSig == null) {
            // handle variable signature size
            int siglen = _con.getRemotePeer().getSigningPublicKey().getType().getSigLen();
            int rem = siglen % AES_SIZE;
            int padding;
            if (rem > 0)
                padding = AES_SIZE - rem;
            else
                padding = 0;
            _e_bobSig = new byte[siglen + padding];
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "receiving E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev) (remaining? " + src.hasRemaining() + ")");
        } else {
            off = _received - XY_SIZE - HXY_TSB_PAD_SIZE;
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "continuing to receive E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev) (remaining? " + src.hasRemaining() + " off=" + off + " recv=" + _received + ")");
        }
        while (_state == State.OB_SENT_RI && src.hasRemaining()) {
            // if (_log.shouldLog(Log.DEBUG)) _log.debug(prefix()+"recv bobSig received=" + _received);
            _e_bobSig[off++] = src.get();
            _received++;
            if (off >= _e_bobSig.length) {
                changeState(State.OB_GOT_SIG);
                // if (_log.shouldLog(Log.DEBUG))
                // _log.debug(prefix() + "received E(S(X+Y+Alice.identHash+tsA+tsB)+padding, sk, prev): " + Base64.encode(_e_bobSig));
                byte[] bobSig = new byte[_e_bobSig.length];
                _context.aes().decrypt(_e_bobSig, 0, bobSig, 0, _dh.getSessionKey(), _e_hXY_tsB, HXY_TSB_PAD_SIZE - AES_SIZE, _e_bobSig.length);
                // ignore the padding
                // handle variable signature size
                SigType type = _con.getRemotePeer().getSigningPublicKey().getType();
                int siglen = type.getSigLen();
                byte[] bobSigData = new byte[siglen];
                System.arraycopy(bobSig, 0, bobSigData, 0, siglen);
                Signature sig = new Signature(type, bobSigData);
                byte[] toVerify = new byte[XY_SIZE + XY_SIZE + HXY_SIZE + 4 + 4];
                int voff = 0;
                System.arraycopy(_X, 0, toVerify, voff, XY_SIZE);
                voff += XY_SIZE;
                System.arraycopy(_Y, 0, toVerify, voff, XY_SIZE);
                voff += XY_SIZE;
                System.arraycopy(_context.routerHash().getData(), 0, toVerify, voff, HXY_SIZE);
                voff += HXY_SIZE;
                DataHelper.toLong(toVerify, voff, 4, _tsA);
                voff += 4;
                DataHelper.toLong(toVerify, voff, 4, _tsB);
                voff += 4;
                boolean ok = _context.dsa().verifySignature(sig, toVerify, _con.getRemotePeer().getSigningPublicKey());
                if (!ok) {
                    _context.statManager().addRateData("ntcp.invalidSignature", 1);
                    fail("Signature was invalid - attempt to spoof " + _con.getRemotePeer().calculateHash().toBase64() + "?");
                } else {
                    if (_log.shouldLog(Log.DEBUG))
                        _log.debug(prefix() + "signature verified from Bob.  done!");
                    prepareExtra(src);
                    // reuse buf
                    byte[] nextWriteIV = _curEncrypted;
                    System.arraycopy(_prevEncrypted, _prevEncrypted.length - AES_SIZE, nextWriteIV, 0, AES_SIZE);
                    // this does not copy the nextWriteIV, do not release to cache
                    // We are Alice, he is Bob, clock skew is Bob - Alice
                    // skew in seconds
                    _con.finishOutboundEstablishment(_dh.getSessionKey(), _peerSkew, nextWriteIV, _e_bobSig);
                    releaseBufs(true);
                    // if socket gets closed this will be null - prevent NPE
                    InetAddress ia = _con.getChannel().socket().getInetAddress();
                    if (ia != null)
                        _transport.setIP(_con.getRemotePeer().calculateHash(), ia.getAddress());
                    changeState(State.VERIFIED);
                }
                return;
            }
        }
    }
}
Also used : Signature(net.i2p.data.Signature) DHSessionKeyBuilder(net.i2p.router.transport.crypto.DHSessionKeyBuilder) InetAddress(java.net.InetAddress) SigType(net.i2p.crypto.SigType)

Example 20 with SigType

use of net.i2p.crypto.SigType in project i2p.i2p by i2p.

the class EstablishState method receiveInbound.

/**
 *  we are Bob, so receive these bytes as part of an inbound connection
 *  This method receives messages 1 and 3, and sends messages 2 and 4.
 *
 *  All data must be copied out of the buffer as Reader.processRead()
 *  will return it to the pool.
 *
 *  Caller must synch.
 *
 *  FIXME none of the _state comparisons use _stateLock, but whole thing
 *  is synchronized, should be OK. See isComplete()
 */
private void receiveInbound(ByteBuffer src) {
    while (_state == State.IB_INIT && src.hasRemaining()) {
        byte c = src.get();
        _X[_received++] = c;
        // }
        if (_received >= XY_SIZE)
            changeState(State.IB_GOT_X);
    }
    while (_state == State.IB_GOT_X && src.hasRemaining()) {
        int i = _received - XY_SIZE;
        _received++;
        byte c = src.get();
        _hX_xor_bobIdentHash[i] = c;
        // if (_log.shouldLog(Log.DEBUG)) _log.debug("recv bih" + (int)c + " received=" + _received);
        if (i >= HXY_SIZE - 1)
            changeState(State.IB_GOT_HX);
    }
    if (_state == State.IB_GOT_HX) {
        if (_log.shouldLog(Log.DEBUG))
            _log.debug(prefix() + "Enough data for a DH received");
        // first verify that Alice knows who she is trying to talk with and that the X
        // isn't corrupt
        byte[] realXor = SimpleByteCache.acquire(HXY_SIZE);
        _context.sha().calculateHash(_X, 0, XY_SIZE, realXor, 0);
        xor32(_context.routerHash().getData(), realXor);
        // }
        if (!DataHelper.eq(realXor, _hX_xor_bobIdentHash)) {
            SimpleByteCache.release(realXor);
            _context.statManager().addRateData("ntcp.invalidHXxorBIH", 1);
            fail("Invalid hX_xor");
            return;
        }
        SimpleByteCache.release(realXor);
        if (!_transport.isHXHIValid(_hX_xor_bobIdentHash)) {
            // blocklist source? but spoofed IPs could DoS us
            _context.statManager().addRateData("ntcp.replayHXxorBIH", 1);
            fail("Replay hX_xor");
            return;
        }
        try {
            // ok, they're actually trying to talk to us, and we got their (unauthenticated) X
            _dh.setPeerPublicValue(_X);
            // force the calc
            _dh.getSessionKey();
            System.arraycopy(_hX_xor_bobIdentHash, AES_SIZE, _prevEncrypted, 0, AES_SIZE);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "DH session key calculated (" + _dh.getSessionKey().toBase64() + ")");
            // now prepare our response: Y+E(H(X+Y)+tsB+padding, sk, Y[239:255])
            byte[] xy = new byte[XY_SIZE + XY_SIZE];
            System.arraycopy(_X, 0, xy, 0, XY_SIZE);
            System.arraycopy(_Y, 0, xy, XY_SIZE, XY_SIZE);
            byte[] hxy = SimpleByteCache.acquire(HXY_SIZE);
            _context.sha().calculateHash(xy, 0, XY_SIZE + XY_SIZE, hxy, 0);
            // our (Bob's) timestamp in seconds
            _tsB = (_context.clock().now() + 500) / 1000l;
            // 48
            byte[] toEncrypt = new byte[HXY_TSB_PAD_SIZE];
            System.arraycopy(hxy, 0, toEncrypt, 0, HXY_SIZE);
            byte[] tsB = DataHelper.toLong(4, _tsB);
            System.arraycopy(tsB, 0, toEncrypt, HXY_SIZE, tsB.length);
            // DataHelper.toLong(toEncrypt, hxy.getData().length, 4, _tsB);
            _context.random().nextBytes(toEncrypt, HXY_SIZE + 4, 12);
            if (_log.shouldLog(Log.DEBUG)) {
                // _log.debug(prefix()+"Y="+Base64.encode(_Y));
                // _log.debug(prefix()+"x+y="+Base64.encode(xy));
                _log.debug(prefix() + "h(x+y)=" + Base64.encode(hxy));
                _log.debug(prefix() + "tsb = " + _tsB);
                _log.debug(prefix() + "unencrypted H(X+Y)+tsB+padding: " + Base64.encode(toEncrypt));
                _log.debug(prefix() + "encryption iv= " + Base64.encode(_Y, XY_SIZE - AES_SIZE, AES_SIZE));
                _log.debug(prefix() + "encryption key= " + _dh.getSessionKey().toBase64());
            }
            SimpleByteCache.release(hxy);
            _context.aes().encrypt(toEncrypt, 0, _e_hXY_tsB, 0, _dh.getSessionKey(), _Y, XY_SIZE - AES_SIZE, HXY_TSB_PAD_SIZE);
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "encrypted H(X+Y)+tsB+padding: " + Base64.encode(_e_hXY_tsB));
            byte[] write = new byte[XY_SIZE + HXY_TSB_PAD_SIZE];
            System.arraycopy(_Y, 0, write, 0, XY_SIZE);
            System.arraycopy(_e_hXY_tsB, 0, write, XY_SIZE, HXY_TSB_PAD_SIZE);
            // ok, now that is prepared, we want to actually send it, so make sure we are up for writing
            changeState(State.IB_SENT_Y);
            _transport.getPumper().wantsWrite(_con, write);
            if (!src.hasRemaining())
                return;
        } catch (DHSessionKeyBuilder.InvalidPublicParameterException e) {
            _context.statManager().addRateData("ntcp.invalidDH", 1);
            fail("Invalid X", e);
            return;
        }
    }
    // ok, we are onto the encrypted area, i.e. Message #3
    while ((_state == State.IB_SENT_Y || _state == State.IB_GOT_RI_SIZE || _state == State.IB_GOT_RI) && src.hasRemaining()) {
        // Collect a 16-byte block
        while (_curEncryptedOffset < AES_SIZE && src.hasRemaining()) {
            _curEncrypted[_curEncryptedOffset++] = src.get();
            _received++;
        }
        // Decrypt the 16-byte block
        if (_curEncryptedOffset >= AES_SIZE) {
            _context.aes().decrypt(_curEncrypted, 0, _curDecrypted, 0, _dh.getSessionKey(), _prevEncrypted, 0, AES_SIZE);
            // if (_log.shouldLog(Log.DEBUG))
            // _log.debug(prefix() + "full block read and decrypted: ");
            byte[] swap = _prevEncrypted;
            _prevEncrypted = _curEncrypted;
            _curEncrypted = swap;
            _curEncryptedOffset = 0;
            if (_state == State.IB_SENT_Y) {
                // we are on the first decrypted block
                int sz = (int) DataHelper.fromLong(_curDecrypted, 0, 2);
                if (sz < MIN_RI_SIZE || sz > MAX_RI_SIZE) {
                    _context.statManager().addRateData("ntcp.invalidInboundSize", sz);
                    fail("size is invalid", new Exception("size is " + sz));
                    return;
                }
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug(prefix() + "got the RI size: " + sz);
                _aliceIdentSize = sz;
                changeState(State.IB_GOT_RI_SIZE);
            // We must defer the calculations for total size of the message until
            // we get the full alice ident so
            // we can determine how long the signature is.
            // See below
            }
            try {
                _sz_aliceIdent_tsA_padding_aliceSig.write(_curDecrypted);
            } catch (IOException ioe) {
                if (_log.shouldLog(Log.ERROR))
                    _log.error(prefix() + "Error writing to the baos?", ioe);
            }
            if (_state == State.IB_GOT_RI_SIZE && _sz_aliceIdent_tsA_padding_aliceSig.size() >= 2 + _aliceIdentSize) {
                // we have enough to get Alice's RI and determine the sig+padding length
                readAliceRouterIdentity();
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug(prefix() + "got the RI");
                if (_aliceIdent == null) {
                    // readAliceRouterIdentity already called fail
                    return;
                }
                SigType type = _aliceIdent.getSigningPublicKey().getType();
                if (type == null) {
                    fail("Unsupported sig type");
                    return;
                }
                changeState(State.IB_GOT_RI);
                // handle variable signature size
                _sz_aliceIdent_tsA_padding_aliceSigSize = 2 + _aliceIdentSize + 4 + type.getSigLen();
                int rem = (_sz_aliceIdent_tsA_padding_aliceSigSize % AES_SIZE);
                int padding = 0;
                if (rem > 0)
                    padding = AES_SIZE - rem;
                _sz_aliceIdent_tsA_padding_aliceSigSize += padding;
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug(prefix() + "alice ident size decrypted as " + _aliceIdentSize + ", making the padding at " + padding + " and total size at " + _sz_aliceIdent_tsA_padding_aliceSigSize);
            }
            if (_state == State.IB_GOT_RI && _sz_aliceIdent_tsA_padding_aliceSig.size() >= _sz_aliceIdent_tsA_padding_aliceSigSize) {
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug(prefix() + "got the sig");
                verifyInbound();
                if (_state == State.VERIFIED && src.hasRemaining())
                    prepareExtra(src);
                if (_log.shouldLog(Log.DEBUG))
                    _log.debug(prefix() + "verifying size (sz=" + _sz_aliceIdent_tsA_padding_aliceSig.size() + " expected=" + _sz_aliceIdent_tsA_padding_aliceSigSize + ' ' + _state + " extra=" + (_extra != null ? _extra.length : 0) + ")");
                return;
            }
        } else {
            // block was read, so we can't decrypt it.
            if (_log.shouldLog(Log.DEBUG))
                _log.debug(prefix() + "end of available data with only a partial block read (" + _curEncryptedOffset + ", " + _received + ")");
        }
    }
    if (_log.shouldLog(Log.DEBUG))
        _log.debug(prefix() + "done with the data, not yet complete or corrupt");
}
Also used : IOException(java.io.IOException) DHSessionKeyBuilder(net.i2p.router.transport.crypto.DHSessionKeyBuilder) DataFormatException(net.i2p.data.DataFormatException) IOException(java.io.IOException) UnknownHostException(java.net.UnknownHostException) SigType(net.i2p.crypto.SigType)

Aggregations

SigType (net.i2p.crypto.SigType)44 IOException (java.io.IOException)18 DataFormatException (net.i2p.data.DataFormatException)15 Signature (net.i2p.data.Signature)14 Destination (net.i2p.data.Destination)12 SigningPublicKey (net.i2p.data.SigningPublicKey)11 File (java.io.File)6 GeneralSecurityException (java.security.GeneralSecurityException)6 Properties (java.util.Properties)6 Hash (net.i2p.data.Hash)6 PrivateKey (net.i2p.data.PrivateKey)6 SigningPrivateKey (net.i2p.data.SigningPrivateKey)6 PublicKey (net.i2p.data.PublicKey)5 SimpleDataStructure (net.i2p.data.SimpleDataStructure)5 RouterInfo (net.i2p.data.router.RouterInfo)5 ByteArrayOutputStream (java.io.ByteArrayOutputStream)4 I2PException (net.i2p.I2PException)4 RouterIdentity (net.i2p.data.router.RouterIdentity)4 Log (net.i2p.util.Log)4 ByteArrayInputStream (java.io.ByteArrayInputStream)3