Changeset 7cbb43a


Ignore:
Timestamp:
Mar 2, 2019 7:53:16 PM (21 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
54d9a29
Parents:
335736b
Message:

I2CP: Encrypted LS2 handling fixes, log tweaks (WIP)
Add number of privkeys field to CreateLeaseSet2 message
Check all privkeys, not just the first, on router side

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java

    r335736b r7cbb43a  
    269269        } else {
    270270            leaseSet.setEncryptionKey(li.getPublicKey());
    271         }
    272         leaseSet.setSigningKey(li.getSigningPublicKey());
     271            // revocation key
     272            leaseSet.setSigningKey(li.getSigningPublicKey());
     273        }
    273274        // SubSession options aren't updated via the gui, so use the primary options
    274275        Properties opts;
  • core/java/src/net/i2p/data/EncryptedLeaseSet.java

    r335736b r7cbb43a  
    66import java.io.InputStream;
    77import java.io.OutputStream;
     8import java.util.List;
    89
    910import net.i2p.I2PAppContext;
     
    6970    @Override
    7071    public int getLeaseCount() {
    71         // TODO attempt decryption
    7272        return _decryptedLS2 != null ? _decryptedLS2.getLeaseCount() : 0;
    7373    }
     
    7878    @Override
    7979    public Lease getLease(int index) {
    80         // TODO attempt decryption
    8180        return _decryptedLS2 != null ? _decryptedLS2.getLease(index) : null;
     81    }
     82
     83    /**
     84     *  @return null if not decrypted.
     85     *  @since 0.9.39
     86     */
     87    public List<PublicKey> getEncryptionKeys() {
     88        if (_decryptedLS2 != null)
     89            return _decryptedLS2.getEncryptionKeys();
     90        return super.getEncryptionKeys();
    8291    }
    8392
     
    106115            _signingKey = bpk;
    107116        else if (!_signingKey.equals(bpk))
    108             throw new IllegalArgumentException("blinded pubkey mismatch");
     117            throw new IllegalArgumentException("blinded pubkey mismatch:" +
     118                                               "\nas received:   " + _signingKey +
     119                                               "\nas calculated: " + bpk);
    109120    }
    110121
     
    122133        else
    123134            _alpha = Blinding.generateAlpha(ctx, _destination, null, _published);
    124         return Blinding.blind(spk, _alpha);
     135        SigningPublicKey rv = Blinding.blind(spk, _alpha);
     136        if (_log.shouldDebug())
     137            _log.debug("Blind:" +
     138                       "\norig:    " + spk +
     139                       "\nalpha:   " + _alpha +
     140                       "\nblinded: " + rv);
     141        return rv;
    125142    }
    126143
     
    349366        ciphertext = new byte[SALT_LEN + plaintext.length];
    350367        System.arraycopy(salt, 0, ciphertext, 0, SALT_LEN);
     368        if (_log.shouldDebug()) {
     369            _log.debug("Encrypt: chacha20 key:\n" + net.i2p.util.HexDump.dump(key));
     370            _log.debug("Encrypt: chacha20 IV:\n" + net.i2p.util.HexDump.dump(iv));
     371        }
    351372        ChaCha20.encrypt(key, iv, plaintext, 0, ciphertext, SALT_LEN, plaintext.length);
    352373        if (_log.shouldDebug())
     
    378399        // first 32 bytes of ciphertext are the salt
    379400        hkdf.calculate(ciphertext, input, ELS2L1K, key, iv, 0);
     401        if (_log.shouldDebug()) {
     402            _log.debug("Decrypt: chacha20 key:\n" + net.i2p.util.HexDump.dump(key));
     403            _log.debug("Decrypt: chacha20 IV:\n" + net.i2p.util.HexDump.dump(iv));
     404        }
    380405        ChaCha20.decrypt(key, iv, ciphertext, SALT_LEN, plaintext, 0, plaintext.length);
    381406        if (_log.shouldDebug()) {
     
    478503        if (_log.shouldDebug()) {
    479504            _log.debug("Sign inner with key: " + key.getType() + ' ' + key.toBase64());
    480             _log.debug("Corresponding pubkey: " + key.toPublic().toBase64());
    481             _log.debug("Sign inner: " + _signature.getType() + ' ' + _signature.toBase64());
     505            _log.debug("Corresponding pubkey: " + key.toPublic());
     506            _log.debug("Inner sig: " + _signature.getType() + ' ' + _signature.toBase64());
    482507        }
    483508        encrypt(null);
     
    499524        if (_log.shouldDebug()) {
    500525            _log.debug("Sign outer with key: " + bkey.getType() + ' ' + bkey.toBase64());
    501             _log.debug("Corresponding pubkey: " + bkey.toPublic().toBase64());
    502             _log.debug("Sign outer: " + _signature.getType() + ' ' + _signature.toBase64());
     526            _log.debug("Corresponding pubkey: " + bkey.toPublic());
     527            _log.debug("Outer sig: " + _signature.getType() + ' ' + _signature.toBase64());
    503528        }
    504529    }
     
    515540        if (_log.shouldDebug()) {
    516541            _log.debug("Sig verify outer with key: " + _signingKey.getType() + ' ' + _signingKey.toBase64());
    517             _log.debug("Sig verify outer: " + _signature.getType() + ' ' + _signature.toBase64());
     542            _log.debug("Outer sig: " + _signature.getType() + ' ' + _signature.toBase64());
    518543        }
    519544        if (!super.verifySignature()) {
     
    538563            _log.debug("Decrypted inner LS2:\n" + _decryptedLS2);
    539564            _log.debug("Sig verify inner with key: " + _decryptedLS2.getDestination().getSigningPublicKey().getType() + ' ' + _decryptedLS2.getDestination().getSigningPublicKey().toBase64());
    540             _log.debug("Sig verify inner: " + _decryptedLS2.getSignature().getType() + ' ' + _decryptedLS2.getSignature().toBase64());
     565            _log.debug("Inner sig: " + _decryptedLS2.getSignature().getType() + ' ' + _decryptedLS2.getSignature().toBase64());
    541566        }
    542567        boolean rv = _decryptedLS2.verifySignature();
  • core/java/src/net/i2p/data/LeaseSet2.java

    r335736b r7cbb43a  
    1717import net.i2p.crypto.SigType;
    1818import net.i2p.util.Clock;
     19import net.i2p.util.Log;
    1920import net.i2p.util.OrderedProperties;
    2021
     
    255256    public int getType() {
    256257        return KEY_TYPE_LS2;
     258    }
     259
     260    /**
     261     *  The revocation key. Overridden to do nothing,
     262     *  as we're using the _signingKey field for the blinded key in Enc LS2.
     263     *
     264     * @since 0.9.39
     265     */
     266    @Override
     267    public void setSigningKey(SigningPublicKey key) {
     268        Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet2.class);
     269        if (log.shouldWarn())
     270            log.warn("Don't set revocation key in ls2", new Exception("I did it"));
    257271    }
    258272
  • core/java/src/net/i2p/data/i2cp/CreateLeaseSet2Message.java

    r335736b r7cbb43a  
    116116                    LeaseSet2 ls2 = (LeaseSet2) _leaseSet;
    117117                    // get one PrivateKey for each PublicKey
    118                     // TODO decrypt an encrypted LS so we can get the keys
    119118                    List<PublicKey> pks = ls2.getEncryptionKeys();
    120                     if (pks == null)
    121                         throw new I2CPMessageException("TODO decrypt");
    122                     for (PublicKey pk : pks) {
    123                         EncType etype = pk.getType();
    124                         if (etype == null)
    125                             throw new I2CPMessageException("Unsupported encryption type");
     119                    int numkeys = in.read();
     120                    // pks is null for encrypted LS2
     121                    if (pks != null && numkeys != pks.size())
     122                        throw new I2CPMessageException("Wrong number of privkeys");
     123                    for (int i = 0; i < numkeys; i++) {
    126124                        int encType = (int) DataHelper.readLong(in, 2);
    127125                        int encLen = (int) DataHelper.readLong(in, 2);
    128                         if (encType != etype.getCode() || encLen != etype.getPrivkeyLen())
    129                             throw new I2CPMessageException("Enc type mismatch");
     126                        EncType etype;
     127                        if (pks != null) {
     128                            // standard LS2
     129                            etype = pks.get(i).getType();
     130                            if (etype == null)
     131                                throw new I2CPMessageException("Unsupported encryption type: " + encType);
     132                            if (encType != etype.getCode())
     133                                throw new I2CPMessageException("Enc type mismatch");
     134                            if (encLen != etype.getPrivkeyLen())
     135                                throw new I2CPMessageException("Enc type bad length");
     136                        } else {
     137                            // encrypted LS2
     138                            etype = EncType.getByCode(encType);
     139                            if (etype == null)
     140                                throw new I2CPMessageException("Unsupported encryption type: " + encType);
     141                            if (encLen != etype.getPrivkeyLen())
     142                                throw new I2CPMessageException("Enc type bad length");
     143                        }
    130144                        PrivateKey priv = new PrivateKey(etype);
    131145                        priv.readBytes(in);
     
    165179            _leaseSet.writeBytes(os);
    166180            if (type != DatabaseEntry.KEY_TYPE_META_LS2) {
    167                 for (PrivateKey pk : getPrivateKeys()) {
     181                List<PrivateKey> pks = getPrivateKeys();
     182                os.write(pks.size());
     183                for (PrivateKey pk : pks) {
    168184                    EncType etype = pk.getType();
    169185                    DataHelper.writeLong(os, 2, etype.getCode());
     
    188204        buf.append("[CreateLeaseSet2Message: ");
    189205        buf.append("\n\tLeaseSet: ").append(_leaseSet);
    190         if (_leaseSet.getType() != DatabaseEntry.KEY_TYPE_META_LS2) {
     206        int type = _leaseSet.getType();
     207        if (type != DatabaseEntry.KEY_TYPE_META_LS2 &&
     208            type != DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
    191209            for (PrivateKey pk : getPrivateKeys()) {
    192210                buf.append("\n\tPrivateKey: ").append(pk);
  • router/java/src/net/i2p/router/client/ClientMessageEventListener.java

    r335736b r7cbb43a  
    2020import net.i2p.data.Hash;
    2121import net.i2p.data.LeaseSet;
     22import net.i2p.data.LeaseSet2;
    2223import net.i2p.data.Payload;
     24import net.i2p.data.PrivateKey;
    2325import net.i2p.data.PublicKey;
    2426import net.i2p.data.i2cp.BandwidthLimitsMessage;
     
    291293        }
    292294        String lsType = props.getProperty("i2cp.leaseSetType");
    293         if ("7".equals(lsType)) {
     295        if ("5".equals(lsType)) {
     296            SigType stype = dest.getSigningPublicKey().getType();
     297            if (stype != SigType.EdDSA_SHA512_Ed25519 &&
     298                stype != SigType.RedDSA_SHA512_Ed25519) {
     299                _runner.disconnectClient("Invalid sig type for encrypted LS");
     300                return;
     301            }
     302        } else if ("7".equals(lsType)) {
    294303            // Prevent tunnel builds for Meta LS
    295304            // more TODO
     
    513522        }
    514523        int type = ls.getType();
    515         if (type != DatabaseEntry.KEY_TYPE_META_LS2 && message.getPrivateKey() == null) {
     524        if (type != DatabaseEntry.KEY_TYPE_META_LS2 &&
     525            type != DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2 &&
     526            message.getPrivateKey() == null) {
    516527            if (_log.shouldLog(Log.ERROR))
    517528                _log.error("Null private keys: " + message);
     
    537548        }
    538549        Destination dest = cfg.getDestination();
    539         Destination ndest = ls.getDestination();
    540         if (!dest.equals(ndest)) {
    541             if (_log.shouldLog(Log.ERROR))
    542                 _log.error("Different destination in LS");
    543             _runner.disconnectClient("Different destination in LS");
    544             return;
     550        if (type == DatabaseEntry.KEY_TYPE_ENCRYPTED_LS2) {
     551            // so we can decrypt it
     552            try {
     553                ls.setDestination(dest);
     554            } catch (RuntimeException re) {
     555                if (_log.shouldError())
     556                    _log.error("Error decrypting leaseset from client", re);
     557                _runner.disconnectClient(re.toString());
     558                return;
     559            }
     560            // we have to do this before checking encryption keys below
     561            if (!ls.verifySignature()) {
     562                if (_log.shouldError())
     563                    _log.error("Error decrypting leaseset from client");
     564                _runner.disconnectClient("Error decrypting leaseset from client");
     565                return;
     566            }
     567        } else {
     568            Destination ndest = ls.getDestination();
     569            if (!dest.equals(ndest)) {
     570                if (_log.shouldLog(Log.ERROR))
     571                    _log.error("Different destination in LS");
     572                _runner.disconnectClient("Different destination in LS");
     573                return;
     574            }
    545575        }
    546576        if (type != DatabaseEntry.KEY_TYPE_META_LS2) {
     
    551581                // Private crypto key should never change, and if it does,
    552582                // one of the checks below will fail
    553                 PublicKey pk;
    554                 try {
    555                     pk = message.getPrivateKey().toPublic();
    556                 } catch (IllegalArgumentException iae) {
    557                     if (_log.shouldLog(Log.ERROR))
    558                         _log.error("Bad private key in LS");
    559                     _runner.disconnectClient("Bad private key in LS");
    560                     return;
    561                 }
    562                 if (!pk.equals(ls.getEncryptionKey())) {
    563                     if (_log.shouldLog(Log.ERROR))
    564                         _log.error("Private/public crypto key mismatch in LS");
    565                     _runner.disconnectClient("Private/public crypto key mismatch in LS");
    566                     return;
     583                if (type == DatabaseEntry.KEY_TYPE_LEASESET) {
     584                    // LS1
     585                    PublicKey pk;
     586                    try {
     587                        pk = message.getPrivateKey().toPublic();
     588                    } catch (IllegalArgumentException iae) {
     589                        if (_log.shouldLog(Log.ERROR))
     590                            _log.error("Bad private key in LS");
     591                        _runner.disconnectClient("Bad private key in LS");
     592                        return;
     593                    }
     594                    if (!pk.equals(ls.getEncryptionKey())) {
     595                        if (_log.shouldLog(Log.ERROR))
     596                            _log.error("Private/public crypto key mismatch in LS");
     597                        _runner.disconnectClient("Private/public crypto key mismatch in LS");
     598                        return;
     599                    }
     600                } else {
     601                    // LS2
     602                    LeaseSet2 ls2 = (LeaseSet2) ls;
     603                    CreateLeaseSet2Message msg2 = (CreateLeaseSet2Message) message;
     604                    List<PublicKey> eks = ls2.getEncryptionKeys();
     605                    List<PrivateKey> pks = msg2.getPrivateKeys();
     606                    for (int i = 0; i < eks.size(); i++) {
     607                        PublicKey ek = eks.get(i);
     608                        PublicKey pk;
     609                        try {
     610                            pk = pks.get(i).toPublic();
     611                        } catch (IllegalArgumentException iae) {
     612                            if (_log.shouldLog(Log.ERROR))
     613                                _log.error("Bad private key in LS: " + i);
     614                            _runner.disconnectClient("Bad private key in LS: " + i);
     615                            return;
     616                        }
     617                        if (!pk.equals(ek)) {
     618                            if (_log.shouldLog(Log.ERROR))
     619                                _log.error("Private/public crypto key mismatch in LS for key: " + i);
     620                            _runner.disconnectClient("Private/public crypto key mismatch in LS for key: " + i);
     621                            return;
     622                        }
     623                    }
    567624                }
    568625                // just register new SPK, don't verify, unused
Note: See TracChangeset for help on using the changeset viewer.