Changeset da81046 for router


Ignore:
Timestamp:
Jun 26, 2018 4:06:18 PM (2 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
49221ad
Parents:
70f018eb
Message:

NTCP2: Noise library changes:
Use key factory for key pair generation
Hardcode Noise name and compute first hash in advance
Expose mixHash method so we can process message 1 and 2 padding
Add method to get chaining key and hash for siphash key generation
Remove unused patterns, methods, code
Debug and speed test code
Finals

Location:
router/java/src/com/southernstorm/noise
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • router/java/src/com/southernstorm/noise/crypto/Curve25519.java

    r70f018eb rda81046  
    4141        private static final int NUM_LIMBS_255BIT = 10;
    4242        private static final int NUM_LIMBS_510BIT = 20;
    43         private int[] x_1;
    44         private int[] x_2;
    45         private int[] x_3;
    46         private int[] z_2;
    47         private int[] z_3;
    48         private int[] A;
    49         private int[] B;
    50         private int[] C;
    51         private int[] D;
    52         private int[] E;
    53         private int[] AA;
    54         private int[] BB;
    55         private int[] DA;
    56         private int[] CB;
    57         private long[] t1;
    58         private int[] t2;
     43        private final int[] x_1;
     44        private final int[] x_2;
     45        private final int[] x_3;
     46        private final int[] z_2;
     47        private final int[] z_3;
     48        private final int[] A;
     49        private final int[] B;
     50        private final int[] C;
     51        private final int[] D;
     52        private final int[] E;
     53        private final int[] AA;
     54        private final int[] BB;
     55        private final int[] DA;
     56        private final int[] CB;
     57        private final long[] t1;
     58        private final int[] t2;
    5959
    6060        /**
     
    189189
    190190                // At this point "x" will either be the answer or it will be the
    191             // answer plus (2^255 - 19).  Perform a trial subtraction to
     191                // answer plus (2^255 - 19).  Perform a trial subtraction to
    192192                // complete the reduction process.
    193193                reduceQuick(result);
  • router/java/src/com/southernstorm/noise/crypto/Poly1305.java

    r70f018eb rda81046  
    3333
    3434        // The 130-bit intermediate values are broken up into five 26-bit words.
    35         private byte[] nonce;
    36         private byte[] block;
    37         private int[] h;
    38         private int[] r;
    39         private int[] c;
    40         private long[] t;
     35        private final byte[] nonce;
     36        private final byte[] block;
     37        private final int[] h;
     38        private final int[] r;
     39        private final int[] c;
     40        private final long[] t;
    4141        private int posn;
    4242
     
    320320                Arrays.fill(nonce, (byte)0);
    321321                Arrays.fill(block, (byte)0);
    322                 Arrays.fill(h, (int)0);
    323                 Arrays.fill(r, (int)0);
    324                 Arrays.fill(c, (int)0);
     322                Arrays.fill(h, 0);
     323                Arrays.fill(r, 0);
     324                Arrays.fill(c, 0);
    325325                Arrays.fill(t, (long)0);
    326326        }
  • router/java/src/com/southernstorm/noise/protocol/ChaChaPolyCipherState.java

    r70f018eb rda81046  
    3434 * Implements the ChaChaPoly cipher for Noise.
    3535 */
    36 class ChaChaPolyCipherState implements CipherState {
    37 
    38         private Poly1305 poly;
    39         private int[] input;
    40         private int[] output;
    41         private byte[] polyKey;
    42         long n;
     36public class ChaChaPolyCipherState implements CipherState {
     37
     38        private final Poly1305 poly;
     39        private final int[] input;
     40        private final int[] output;
     41        private final byte[] polyKey;
     42        private long n;
    4343        private boolean haskey;
     44        // I2P debug to be removed
     45        private byte[] initialKey;
    4446       
    4547        /**
     
    8183        @Override
    8284        public void initializeKey(byte[] key, int offset) {
     85                // I2P debug to be removed
     86                initialKey = new byte[32];
     87                System.arraycopy(key, 0, initialKey, 0, 32);
    8388                ChaChaCore.initKey256(input, key, offset);
    8489                n = 0;
     
    288293                n = nonce;
    289294        }
     295
     296        /**
     297         *  I2P debug to be removed
     298         *  @return null if none yet
     299         */
     300        public byte[] getKey() {
     301                if (!haskey)
     302                        return null;
     303                return initialKey;
     304        }
     305
     306        /**
     307         *  I2P debug
     308         */
     309        @Override
     310        public String toString() {
     311                StringBuilder buf = new StringBuilder();
     312                buf.append("  Cipher State:\n" +
     313                           "    nonce: ");
     314                buf.append(n);
     315                buf.append("\n" +
     316                           "    init key: ");
     317                // I2P debug to be removed
     318                if (haskey)
     319                        buf.append(net.i2p.data.Base64.encode(initialKey));
     320                else
     321                        buf.append("null");
     322                buf.append("\n    poly key: ");
     323                if (haskey)
     324                        buf.append(net.i2p.data.Base64.encode(polyKey));
     325                else
     326                        buf.append("null");
     327                buf.append('\n');
     328                return buf.toString();
     329        }
    290330}
  • router/java/src/com/southernstorm/noise/protocol/CipherState.java

    r70f018eb rda81046  
    156156         */
    157157        void setNonce(long nonce);
     158
     159        /**
     160         *  I2P debug to be removed
     161         */
     162        public byte[] getKey();
    158163}
  • router/java/src/com/southernstorm/noise/protocol/CipherStatePair.java

    r70f018eb rda81046  
    7070        public void senderOnly()
    7171        {
    72                 if (recv != null) {
    73                         recv.destroy();
    74                         recv = null;
    75                 }
     72                recv.destroy();
    7673        }
    7774       
     
    8380        public void receiverOnly()
    8481        {
    85                 if (send != null) {
    86                         send.destroy();
    87                         send = null;
    88                 }
     82                send.destroy();
    8983        }
    9084       
  • router/java/src/com/southernstorm/noise/protocol/Curve25519DHState.java

    r70f018eb rda81046  
    2323package com.southernstorm.noise.protocol;
    2424
     25import java.security.KeyPair;
    2526import java.util.Arrays;
    2627
    2728import com.southernstorm.noise.crypto.Curve25519;
     29
     30import net.i2p.router.transport.crypto.X25519KeyFactory;
    2831
    2932/**
     
    3235class Curve25519DHState implements DHState {
    3336
    34         private byte[] publicKey;
    35         private byte[] privateKey;
     37        private final byte[] publicKey;
     38        private final byte[] privateKey;
    3639        private int mode;
     40        private final X25519KeyFactory _xdh;
    3741
    3842        /**
    3943         * Constructs a new Diffie-Hellman object for Curve25519.
    4044         */
    41         public Curve25519DHState()
     45        public Curve25519DHState(X25519KeyFactory xdh)
    4246        {
    4347                publicKey = new byte [32];
    4448                privateKey = new byte [32];
    4549                mode = 0;
     50                _xdh = xdh;
    4651        }
    4752
     
    7378        @Override
    7479        public void generateKeyPair() {
    75                 Noise.random(privateKey);
    76                 Curve25519.eval(publicKey, 0, privateKey, null);
     80                KeyPair kp = _xdh.getKeys();
     81                System.arraycopy(kp.getPrivate().getEncoded(), 0, privateKey, 0, 32);
     82                System.arraycopy(kp.getPublic().getEncoded(), 0, publicKey, 0, 32);
    7783                mode = 0x03;
    7884        }
  • router/java/src/com/southernstorm/noise/protocol/HandshakeState.java

    r70f018eb rda81046  
    2929import javax.crypto.ShortBufferException;
    3030
     31import net.i2p.router.transport.crypto.X25519KeyFactory;
     32
    3133/**
    3234 * Interface to a Noise handshake.
     
    3436public class HandshakeState implements Destroyable {
    3537
    36         private SymmetricState symmetric;
    37         private boolean isInitiator;
     38        private final SymmetricState symmetric;
     39        private final boolean isInitiator;
    3840        private DHState localKeyPair;
    3941        private DHState localEphemeral;
     
    4547        private DHState fixedHybrid;
    4648        private int action;
    47         private int requirements;
    48         private short[] pattern;
     49        private final int requirements;
    4950        private int patternIndex;
    50         private byte[] preSharedKey;
    51         private byte[] prologue;
     51        // not supported
     52        private static final byte[] preSharedKey = null;
     53        // not supported
     54        private static final byte[] prologue = null;
    5255
    5356        /**
     
    133136        private static final int FALLBACK_POSSIBLE = 0x40;
    134137
    135         /**
    136          * Creates a new Noise handshake.
    137          *
    138          * @param protocolName The name of the Noise protocol.
    139          * @param role The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER.
    140          *
    141          * @throws IllegalArgumentException The protocolName is not
    142          * formatted correctly, or the role is not recognized.
    143          *
    144          * @throws NoSuchAlgorithmException One of the cryptographic algorithms
    145          * that is specified in the protocolName is not supported.
    146          */
    147         public HandshakeState(String protocolName, int role) throws NoSuchAlgorithmException
    148         {
     138        public static final String protocolName = "Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256";
     139        private static final String prefix;
     140        private static final String patternId;
     141        private static String dh;
     142        private static final String cipher;
     143        private static final String hash;
     144        private static final short[] pattern;
     145
     146        static {
    149147                // Parse the protocol name into its components.
    150148                String[] components = protocolName.split("_");
    151149                if (components.length != 5)
    152150                        throw new IllegalArgumentException("Protocol name must have 5 components");
    153                 String prefix = components[0];
    154                 String patternId = components[1];
    155                 String dh = components[2];
    156                 String hybrid = null;
    157                 String cipher = components[3];
    158                 String hash = components[4];
     151                prefix = components[0];
     152                patternId = components[1].substring(0, 2);
     153                dh = components[2];
     154                cipher = components[3];
     155                hash = components[4];
    159156                if (!prefix.equals("Noise") && !prefix.equals("NoisePSK"))
    160157                        throw new IllegalArgumentException("Prefix must be Noise or NoisePSK");
     
    162159                if (pattern == null)
    163160                        throw new IllegalArgumentException("Handshake pattern is not recognized");
     161                if (!dh.equals("25519"))
     162                        throw new IllegalArgumentException("Unknown Noise DH algorithm name: " + dh);
     163        }
     164
     165        /**
     166         * Creates a new Noise handshake.
     167         * Noise protocol name is hardcoded.
     168         *
     169         * @param role The role, HandshakeState.INITIATOR or HandshakeState.RESPONDER.
     170         * @param xdh The key pair factory for ephemeral keys
     171         *
     172         * @throws IllegalArgumentException The protocolName is not
     173         * formatted correctly, or the role is not recognized.
     174         *
     175         * @throws NoSuchAlgorithmException One of the cryptographic algorithms
     176         * that is specified in the protocolName is not supported.
     177         */
     178        public HandshakeState(int role, X25519KeyFactory xdh) throws NoSuchAlgorithmException
     179        {
    164180                short flags = pattern[0];
    165181                int extraReqs = 0;
     
    170186                        flags = Pattern.reverseFlags(flags);
    171187                }
    172                 int index = dh.indexOf('+');
    173                 if (index != -1) {
    174                         // The DH name has two components: regular and hybrid.
    175                         hybrid = dh.substring(index + 1);
    176                         dh = dh.substring(0, index);
    177                         if ((flags & Pattern.FLAG_LOCAL_HYBRID) == 0 || (flags & Pattern.FLAG_REMOTE_HYBRID) == 0)
    178                                 throw new IllegalArgumentException("Hybrid function specified for non-hybrid pattern");
    179                 } else {
    180                         if ((flags & Pattern.FLAG_LOCAL_HYBRID) != 0 || (flags & Pattern.FLAG_REMOTE_HYBRID) != 0)
    181                                 throw new IllegalArgumentException("Hybrid function not specified for hybrid pattern");
    182                 }
    183188
    184189                // Check that the role is correctly specified.
     
    187192
    188193                // Initialize this object.  This will also create the cipher and hash objects.
    189                 symmetric = new SymmetricState(protocolName, cipher, hash);
     194                symmetric = new SymmetricState(cipher, hash);
    190195                isInitiator = (role == INITIATOR);
    191196                action = NO_ACTION;
     
    195200                // Create the DH objects that we will need later.
    196201                if ((flags & Pattern.FLAG_LOCAL_STATIC) != 0)
    197                         localKeyPair = Noise.createDH(dh);
     202                        localKeyPair = new Curve25519DHState(xdh);
    198203                if ((flags & Pattern.FLAG_LOCAL_EPHEMERAL) != 0)
    199                         localEphemeral = Noise.createDH(dh);
    200                 if ((flags & Pattern.FLAG_LOCAL_HYBRID) != 0)
    201                         localHybrid = Noise.createDH(hybrid);
     204                        localEphemeral = new Curve25519DHState(xdh);
    202205                if ((flags & Pattern.FLAG_REMOTE_STATIC) != 0)
    203                         remotePublicKey = Noise.createDH(dh);
     206                        remotePublicKey = new Curve25519DHState(xdh);
    204207                if ((flags & Pattern.FLAG_REMOTE_EPHEMERAL) != 0)
    205                         remoteEphemeral = Noise.createDH(dh);
    206                 if ((flags & Pattern.FLAG_REMOTE_HYBRID) != 0)
    207                         remoteHybrid = Noise.createDH(hybrid);
     208                        remoteEphemeral = new Curve25519DHState(xdh);
    208209               
    209                 // We cannot use hybrid algorithms like New Hope for ephemeral or static keys,
    210                 // as the unbalanced nature of the algorithm only works with "f" and "ff" tokens.
    211                 if (localKeyPair instanceof DHStateHybrid)
    212                         throw new NoSuchAlgorithmException("Cannot use '" + localKeyPair.getDHName() + "' for static keys");
    213                 if (localEphemeral instanceof DHStateHybrid)
    214                         throw new NoSuchAlgorithmException("Cannot use '" + localEphemeral.getDHName() + "' for ephemeral keys");
    215                 if (remotePublicKey instanceof DHStateHybrid)
    216                         throw new NoSuchAlgorithmException("Cannot use '" + remotePublicKey.getDHName() + "' for static keys");
    217                 if (remoteEphemeral instanceof DHStateHybrid)
    218                         throw new NoSuchAlgorithmException("Cannot use '" + remoteEphemeral.getDHName() + "' for ephemeral keys");
    219210        }
    220211
     
    237228        {
    238229                return isInitiator ? INITIATOR : RESPONDER;
    239         }
    240 
    241         /**
    242          * Determine if this handshake needs a pre-shared key value
    243          * and one has not been configured yet.
    244          *
    245          * @return true if a pre-shared key is needed; false if not.
    246          */
    247         public boolean needsPreSharedKey()
    248         {
    249                 if (preSharedKey != null)
    250                         return false;
    251                 else
    252                         return (requirements & PSK_REQUIRED) != 0;
    253         }
    254        
    255         /**
    256          * Determine if this object has already been configured with a
    257          * pre-shared key.
    258          *
    259          * @return true if the pre-shared key has already been configured;
    260          * false if one is not needed or it has not been configured yet.
    261          */
    262         public boolean hasPreSharedKey()
    263         {
    264                 return preSharedKey != null;
    265         }
    266 
    267         /**
    268          * Sets the pre-shared key for this handshake.
    269          *
    270          * @param key Buffer containing the pre-shared key value.
    271          * @param offset Offset into the buffer of the first byte of the key.
    272          * @param length The length of the pre-shared key, which must be 32.
    273          *
    274          * @throws IllegalArgumentException The length is not 32.
    275          *
    276          * @throws UnsupportedOperationException Pre-shared keys are not
    277          * supported for this handshake type.
    278          *
    279          * @throws IllegalStateException The handshake has already started,
    280          * so the pre-shared key can no longer be set.
    281          */
    282         public void setPreSharedKey(byte[] key, int offset, int length)
    283         {
    284                 if (length != 32) {
    285                         throw new IllegalArgumentException
    286                                 ("Pre-shared keys must be 32 bytes in length");
    287                 }
    288                 if ((requirements & PSK_REQUIRED) == 0) {
    289                         throw new UnsupportedOperationException
    290                                 ("Pre-shared keys are not supported for this handshake");
    291                 }
    292                 if (action != NO_ACTION) {
    293                         throw new IllegalStateException
    294                                 ("Handshake has already started; cannot set pre-shared key");
    295                 }
    296                 if (preSharedKey != null) {
    297                         Noise.destroy(preSharedKey);
    298                         preSharedKey = null;
    299                 }
    300                 preSharedKey = Noise.copySubArray(key, offset, length);
    301         }
    302        
    303         /**
    304          * Sets the prologue for this handshake.
    305          *
    306          * @param prologue Buffer containing the prologue value.
    307          * @param offset Offset into the buffer of the first byte of the prologue.
    308          * @param length The length of the prologue in bytes.
    309          *
    310          * @throws IllegalStateException The handshake has already started,
    311          * so the prologue can no longer be set.
    312          */
    313         public void setPrologue(byte[] prologue, int offset, int length)
    314         {
    315                 if (action != NO_ACTION) {
    316                         throw new IllegalStateException
    317                                 ("Handshake has already started; cannot set prologue");
    318                 }
    319                 if (this.prologue != null) {
    320                         Noise.destroy(this.prologue);
    321                         this.prologue = null;
    322                 }
    323                 this.prologue = Noise.copySubArray(prologue, offset, length);
    324230        }
    325231       
     
    407313        }
    408314
    409         /**
    410          * Gets the DHState object containing a fixed local ephemeral
    411          * key value for this handshake.
    412          *
    413          * @return The fixed ephemeral key object, or null if a local
    414          * ephemeral key is not required by this handshake.
    415          *
    416          * This function is intended for testing only.  It can be used
    417          * to establish a fixed ephemeral key for test vectors.  This
    418          * function should not be used in real applications.
    419          */
    420         public DHState getFixedEphemeralKey()
    421         {
    422                 if (fixedEphemeral != null)
    423                         return fixedEphemeral;
    424                 if (localEphemeral == null)
    425                         return null;
    426                 try {
    427                         fixedEphemeral = Noise.createDH(localEphemeral.getDHName());
    428                 } catch (NoSuchAlgorithmException e) {
    429                         // This shouldn't happen - the local ephemeral key would
    430                         // have already been created with the same name!
    431                         fixedEphemeral = null;
    432                 }
    433                 return fixedEphemeral;
    434         }
    435 
    436         /**
    437          * Gets the DHState object containing a fixed local hybrid
    438          * key value for this handshake.
    439          *
    440          * @return The fixed hybrid key object, or null if a local
    441          * hybrid key is not required by this handshake.
    442          *
    443          * This function is intended for testing only.  It can be used
    444          * to establish a fixed hybrid key for test vectors.  This
    445          * function should not be used in real applications.
    446          */
    447         public DHState getFixedHybridKey()
    448         {
    449                 if (fixedHybrid != null)
    450                         return fixedHybrid;
    451                 if (localHybrid == null)
    452                         return null;
    453                 try {
    454                         fixedHybrid = Noise.createDH(localHybrid.getDHName());
    455                 } catch (NoSuchAlgorithmException e) {
    456                         // This shouldn't happen - the local hybrid key would
    457                         // have already been created with the same name!
    458                         fixedHybrid = null;
    459                 }
    460                 return fixedHybrid;
    461         }
    462 
    463315        // Empty value for when the prologue is not supplied.
    464316        private static final byte[] emptyPrologue = new byte [0];
     
    482334         * @see #writeMessage(byte[], int, byte[], int, int)
    483335         * @see #readMessage(byte[], int, int, byte[], int)
    484          * @see #fallback()
     336         * see #fallback()
    485337         */
    486338        public void start()
     
    504356                        if (remotePublicKey == null || !remotePublicKey.hasPublicKey())
    505357                                throw new IllegalStateException("Remote static key required");
    506                 }
    507                 if ((requirements & PSK_REQUIRED) != 0) {
    508                         if (preSharedKey == null)
    509                                 throw new IllegalStateException("Pre-shared key required");
    510358                }
    511359               
     
    515363                else
    516364                        symmetric.mixHash(emptyPrologue, 0, 0);
    517                
    518                 // Hash the pre-shared key into the chaining key and handshake hash.
    519                 if (preSharedKey != null)
    520                         symmetric.mixPreSharedKey(preSharedKey);
    521365               
    522366                // Mix the pre-supplied public keys into the handshake hash.
     
    555399
    556400        /**
    557          * Falls back to the "XXfallback" handshake pattern.
    558          *
    559          * This function is intended used to help implement the "Noise Pipes" protocol.
    560          * It resets a HandshakeState object with the original handshake pattern
    561          * (usually "IK"), converting it into an object with the handshake pattern
    562          * "XXfallback".  Information from the previous session such as the local
    563          * keypair, the initiator's ephemeral key, the prologue value, and the
    564          * pre-shared key, are passed to the new session.
    565          *
    566          * Once the fallback has been initiated, the application can set
    567          * new values for the handshake parameters if the values from the
    568          * previous session do not apply.  For example, the application may
    569          * use a different prologue for the fallback than for the original
    570          * session.
    571          *
    572          * After setting any new parameters, the application calls start()
    573          * again to restart the handshake from where it left off before the fallback.
    574          *
    575          * Note that this function reverses the roles of initiator and responder.
    576          *
    577          * @throws UnsupportedOperationException The current handshake pattern
    578          * is not compatible with "XXfallback".
    579          *
    580          * @throws IllegalStateException The previous protocol has not started
    581          * or it has not reached the fallback position yet.
    582          *
    583          * @throws NoSuchAlgorithmException One of the cryptographic algorithms
    584          * that is specified in the new protocolName is not supported.
    585          *
    586          * @see #start()
    587          */
    588         public void fallback() throws NoSuchAlgorithmException
    589         {
    590                 fallback("XXfallback");
    591         }
    592 
    593         /**
    594          * Falls back to another handshake pattern.
    595          *
    596          * @param patternName The name of the pattern to fall back to;
    597          * e.g. "XXfallback", "NXfallback", etc.
    598          *
    599          * This function resets a HandshakeState object with the original
    600          * handshake pattern, and converts it into an object with the new handshake
    601          * patternName.  Information from the previous session such as the local
    602          * keypair, the initiator's ephemeral key, the prologue value, and the
    603          * pre-shared key, are passed to the new session.
    604          *
    605          * Once the fallback has been initiated, the application can set
    606          * new values for the handshake parameters if the values from the
    607          * previous session do not apply.  For example, the application may
    608          * use a different prologue for the fallback than for the original
    609          * session.
    610          *
    611          * After setting any new parameters, the application calls start()
    612          * again to restart the handshake from where it left off before the fallback.
    613          *
    614          * The new pattern may have greater key requirements than the original;
    615          * for example changing from "NK" from "XXfallback" requires that the
    616          * initiator's static public key be set.  The application is responsible for
    617          * setting any extra keys before calling start().
    618          *
    619          * Note that this function reverses the roles of initiator and responder.
    620          *
    621          * @throws UnsupportedOperationException The current handshake pattern
    622          * is not compatible with the patternName, or patternName is not a
    623          * fallback pattern.
    624          *
    625          * @throws IllegalStateException The previous protocol has not started
    626          * or it has not reached the fallback position yet.
    627          *
    628          * @throws NoSuchAlgorithmException One of the cryptographic algorithms
    629          * that is specified in the new protocolName is not supported.
    630          *
    631          * @see #start()
    632          */
    633         public void fallback(String patternName) throws NoSuchAlgorithmException
    634         {
    635                 // The original pattern must end in "K" for fallback to be possible.
    636                 if ((requirements & FALLBACK_POSSIBLE) == 0)
    637                         throw new UnsupportedOperationException("Previous handshake pattern does not support fallback");
    638 
    639                 // Check that "patternName" supports fallback.
    640                 short[] newPattern = Pattern.lookup(patternName);
    641                 if (newPattern == null || (newPattern[0] & Pattern.FLAG_REMOTE_EPHEM_REQ) == 0)
    642                         throw new UnsupportedOperationException("New pattern is not a fallback pattern");
    643 
    644             // The initiator should be waiting for a return message from the
    645             // responder, and the responder should have failed on the first
    646             // handshake message from the initiator.  We also allow the
    647             // responder to fallback after processing the first message
    648             // successfully; it decides to always fall back anyway.
    649                 if (isInitiator) {
    650                         if ((action != FAILED && action != READ_MESSAGE) || !localEphemeral.hasPublicKey())
    651                                 throw new IllegalStateException("Initiator cannot fall back from this state");
    652                 } else {
    653                         if ((action != FAILED && action != WRITE_MESSAGE) || !remoteEphemeral.hasPublicKey())
    654                                 throw new IllegalStateException("Responder cannot fall back from this state");
    655                 }
    656                
    657                 // Format a new protocol name for the fallback variant
    658                 // and recreate the SymmetricState object.
    659                 String[] components = symmetric.getProtocolName().split("_");
    660                 components[1] = patternName;
    661                 StringBuilder builder = new StringBuilder();
    662                 builder.append(components[0]);
    663                 for (int index = 1; index < components.length; ++index) {
    664                         builder.append('_');
    665                         builder.append(components[index]);
    666                 }
    667                 String name = builder.toString();
    668                 SymmetricState newSymmetric = new SymmetricState(name, components[3], components[4]);
    669                 symmetric.destroy();
    670                 symmetric = newSymmetric;
    671                
    672                 // Convert the HandshakeState to the "XXfallback" pattern.
    673                 if (isInitiator) {
    674                         if (remoteEphemeral != null)
    675                                 remoteEphemeral.clearKey();
    676                         if (remoteHybrid != null)
    677                                 remoteHybrid.clearKey();
    678                         if (remotePublicKey != null)
    679                                 remotePublicKey.clearKey();
    680                         isInitiator = false;
    681                 } else {
    682                         if (localEphemeral != null)
    683                                 localEphemeral.clearKey();
    684                         if (localHybrid != null)
    685                                 localHybrid.clearKey();
    686                         if ((newPattern[0] & Pattern.FLAG_REMOTE_REQUIRED) == 0 && remotePublicKey != null)
    687                                 remotePublicKey.clearKey();
    688                         isInitiator = true;
    689                 }
    690                 action = NO_ACTION;
    691                 pattern = newPattern;
    692                 patternIndex = 1;
    693                 short flags = pattern[0];
    694                 if (!isInitiator) {
    695                         // Reverse the pattern flags so that the responder is "local".
    696                         flags = Pattern.reverseFlags(flags);
    697                 }
    698                 requirements = computeRequirements(flags, components[0], isInitiator ? INITIATOR : RESPONDER, true);
    699         }
    700 
    701         /**
    702401         * Gets the next action that the application should perform for
    703402         * the handshake part of the protocol.
     
    796495                                        case Pattern.E:
    797496                                        {
    798                                     // Generate a local ephemeral keypair and add the public
    799                                     // key to the message.  If we are running fixed vector tests,
    800                                     // then the ephemeral key may have already been provided.
     497                                                // Generate a local ephemeral keypair and add the public
     498                                                // key to the message.  If we are running fixed vector tests,
     499                                                // then the ephemeral key may have already been provided.
    801500                                                if (localEphemeral == null)
    802501                                                        throw new IllegalStateException("Pattern definition error");
     
    812511
    813512                                                // If the protocol is using pre-shared keys, then also mix
    814                                     // the local ephemeral key into the chaining key.
     513                                                // the local ephemeral key into the chaining key.
    815514                                                if (preSharedKey != null)
    816515                                                        symmetric.mixKey(message, messagePosn, len);
     
    821520                                        case Pattern.S:
    822521                                        {
    823                                     // Encrypt the local static public key and add it to the message.
     522                                                // Encrypt the local static public key and add it to the message.
    824523                                                if (localKeyPair == null)
    825524                                                        throw new IllegalStateException("Pattern definition error");
     
    857556                                                else
    858557                                                        mixDH(localEphemeral, remotePublicKey);
    859                                         }
    860                                         break;
    861 
    862                                         case Pattern.SS:
    863                                         {
    864                                                 // DH operation with initiator and responder static keys.
    865                                                 mixDH(localKeyPair, remotePublicKey);
    866                                         }
    867                                         break;
    868                                        
    869                                         case Pattern.F:
    870                                         {
    871                                     // Generate a local hybrid keypair and add the public
    872                                     // key to the message.  If we are running fixed vector tests,
    873                                     // then a fixed hybrid key may have already been provided.
    874                                                 if (localHybrid == null)
    875                                                         throw new IllegalStateException("Pattern definition error");
    876                                                 if (localHybrid instanceof DHStateHybrid) {
    877                                                         // The DH object is something like New Hope which needs to
    878                                                         // generate keys relative to the other party's public key.
    879                                                         DHStateHybrid hybrid = (DHStateHybrid)localHybrid;
    880                                                         if (fixedHybrid == null)
    881                                                                 hybrid.generateKeyPair(remoteHybrid);
    882                                                         else
    883                                                                 hybrid.copyFrom(fixedHybrid, remoteHybrid);
    884                                                 } else {
    885                                                         if (fixedHybrid == null)
    886                                                                 localHybrid.generateKeyPair();
    887                                                         else
    888                                                                 localHybrid.copyFrom(fixedHybrid);
    889                                                 }
    890                                                 len = localHybrid.getPublicKeyLength();
    891                                                 if (space < len)
    892                                                         throw new ShortBufferException();
    893                                                 macLen = symmetric.getMACLength();
    894                                                 if (space < (len + macLen))
    895                                                         throw new ShortBufferException();
    896                                                 localHybrid.getPublicKey(message, messagePosn);
    897                                                 messagePosn += symmetric.encryptAndHash(message, messagePosn, message, messagePosn, len);
    898                                         }
    899                                         break;
    900                                        
    901                                         case Pattern.FF:
    902                                         {
    903                                                 // DH operation with initiator and responder hybrid keys.
    904                                                 mixDH(localHybrid, remoteHybrid);
    905558                                        }
    906559                                        break;
     
    994647                                        case Pattern.E:
    995648                                        {
    996                                     // Save the remote ephemeral key and hash it.
     649                                                // Save the remote ephemeral key and hash it.
    997650                                                if (remoteEphemeral == null)
    998651                                                        throw new IllegalStateException("Pattern definition error");
     
    1003656                                                remoteEphemeral.setPublicKey(message, messageOffset);
    1004657                                                if (remoteEphemeral.isNullPublicKey()) {
    1005                                         // The remote ephemeral key is null, which means that it is
    1006                                         // not contributing anything to the security of the session
    1007                                         // and is in fact downgrading the security to "none at all"
    1008                                         // in some of the message patterns.  Reject all such keys.
     658                                                        // The remote ephemeral key is null, which means that it is
     659                                                        // not contributing anything to the security of the session
     660                                                        // and is in fact downgrading the security to "none at all"
     661                                                        // in some of the message patterns.  Reject all such keys.
    1009662                                                        throw new BadPaddingException("Null remote public key");
    1010663                                                }
    1011664
    1012665                                                // If the protocol is using pre-shared keys, then also mix
    1013                                     // the remote ephemeral key into the chaining key.
     666                                                // the remote ephemeral key into the chaining key.
    1014667                                                if (preSharedKey != null)
    1015668                                                        symmetric.mixKey(message, messageOffset, len);
     
    1066719                                        break;
    1067720       
    1068                                         case Pattern.SS:
    1069                                         {
    1070                                                 // DH operation with initiator and responder static keys.
    1071                                                 mixDH(localKeyPair, remotePublicKey);
    1072                                         }
    1073                                         break;
    1074                                        
    1075                                         case Pattern.F:
    1076                                         {
    1077                                                 // Decrypt and read the remote hybrid ephemeral key.
    1078                                                 if (remoteHybrid == null)
    1079                                                         throw new IllegalStateException("Pattern definition error");
    1080                                                 if (remoteHybrid instanceof DHStateHybrid) {
    1081                                                         // The DH object is something like New Hope.  The public key
    1082                                                         // length may need to change based on whether we already have
    1083                                                         // generated a local hybrid keypair or not.
    1084                                                         ((DHStateHybrid)remoteHybrid).specifyPeer(localHybrid);
    1085                                                 }
    1086                                                 len = remoteHybrid.getPublicKeyLength();
    1087                                                 macLen = symmetric.getMACLength();
    1088                                                 if (space < (len + macLen))
    1089                                                         throw new ShortBufferException();
    1090                                                 byte[] temp = new byte [len];
    1091                                                 try {
    1092                                                         if (symmetric.decryptAndHash(message, messageOffset, temp, 0, len + macLen) != len)
    1093                                                                 throw new ShortBufferException();
    1094                                                         remoteHybrid.setPublicKey(temp, 0);
    1095                                                 } finally {
    1096                                                         Noise.destroy(temp);
    1097                                                 }
    1098                                                 messageOffset += len + macLen;
    1099                                         }
    1100                                         break;
    1101        
    1102                                         case Pattern.FF:
    1103                                         {
    1104                                                 // DH operation with initiator and responder hybrid keys.
    1105                                                 mixDH(localHybrid, remoteHybrid);
    1106                                         }
    1107                                         break;
    1108 
    1109721                                        default:
    1110722                                        {
     
    1236848        private static int computeRequirements(short flags, String prefix, int role, boolean isFallback)
    1237849        {
    1238                 int requirements = 0;
     850            int requirements = 0;
    1239851            if ((flags & Pattern.FLAG_LOCAL_STATIC) != 0) {
    1240852                requirements |= LOCAL_REQUIRED;
     
    1253865                    requirements |= FALLBACK_PREMSG;
    1254866            }
    1255             if (prefix.equals("NoisePSK")) {
    1256                 requirements |= PSK_REQUIRED;
    1257             }
    1258867            return requirements;
    1259868        }
     869
     870        /**
     871         *  I2P for mixing in padding in messages 1 and 2
     872         */
     873        public void mixHash(byte[] data, int offset, int length) {
     874                symmetric.mixHash(data, offset, length);
     875        }
     876
     877        /**
     878         *  I2P for getting chaining key for siphash calc
     879         *  @return a copy
     880         */
     881        public byte[] getChainingKey() {
     882                return symmetric.getChainingKey();
     883        }
     884
     885        /**
     886         *  I2P for getting current hash for siphash calculation
     887         *  @return NOT a copy, do not modify
     888         */
     889        public byte[] getHash() {
     890                return symmetric.getHandshakeHash();
     891        }
     892
     893        /**
     894         *  I2P debug
     895         */
     896        @Override
     897        public String toString() {
     898                StringBuilder buf = new StringBuilder();
     899                buf.append("Handshake State:\n");
     900                buf.append(symmetric.toString());
     901
     902                byte[] tmp = new byte[32];
     903
     904                DHState dh = localKeyPair;
     905                buf.append("Local static public key (s) :      ");
     906                if (dh != null && dh.hasPublicKey()) {
     907                        dh.getPublicKey(tmp, 0);
     908                        buf.append(net.i2p.data.Base64.encode(tmp));
     909                } else {
     910                        buf.append("null");
     911                }
     912                buf.append('\n');
     913
     914                dh = remotePublicKey;
     915                buf.append("Remote static public key (rs) :    ");
     916                if (dh != null && dh.hasPublicKey()) {
     917                        dh.getPublicKey(tmp, 0);
     918                        buf.append(net.i2p.data.Base64.encode(tmp));
     919                } else {
     920                        buf.append("null");
     921                }
     922                buf.append('\n');
     923
     924                dh = localEphemeral;
     925                buf.append("Local ephemeral public key (e) :   ");
     926                if (dh != null && dh.hasPublicKey()) {
     927                        dh.getPublicKey(tmp, 0);
     928                        buf.append(net.i2p.data.Base64.encode(tmp));
     929                } else {
     930                        buf.append("null");
     931                }
     932                buf.append('\n');
     933
     934                dh = remoteEphemeral;
     935                buf.append("Remote ephemeral public key (re) : ");
     936                if (dh != null && dh.hasPublicKey()) {
     937                        dh.getPublicKey(tmp, 0);
     938                        buf.append(net.i2p.data.Base64.encode(tmp));
     939                } else {
     940                        buf.append("null");
     941                }
     942                buf.append('\n');
     943
     944                return buf.toString();
     945        }
    1260946}
  • router/java/src/com/southernstorm/noise/protocol/Noise.java

    r70f018eb rda81046  
    3030import javax.crypto.BadPaddingException;
    3131
    32 import com.southernstorm.noise.crypto.Blake2bMessageDigest;
    33 import com.southernstorm.noise.crypto.Blake2sMessageDigest;
    34 import com.southernstorm.noise.crypto.SHA256MessageDigest;
    35 import com.southernstorm.noise.crypto.SHA512MessageDigest;
    36 
    3732/**
    3833 * Utility functions for the Noise protocol library.
     
    4540        public static final int MAX_PACKET_LEN = 65535;
    4641       
    47         private static SecureRandom random = new SecureRandom();
    48        
    49         /**
    50          * Generates random data using the system random number generator.
    51          *
    52          * @param data The data buffer to fill with random data.
    53          */
    54         public static void random(byte[] data)
    55         {
    56                 random.nextBytes(data);
    57         }
    58 
    59         private static boolean forceFallbacks = false;
    60        
    61         /**
    62          * Force the use of plain Java fallback crypto implementations.
    63          *
    64          * @param force Set to true for force fallbacks, false to
    65          * try to use the system implementation before falling back.
    66          *
    67          * This function is intended for testing purposes to toggle between
    68          * the system JCA/JCE implementations and the plain Java fallback
    69          * reference implementations.
    70          */
    71         public static void setForceFallbacks(boolean force)
    72         {
    73                 forceFallbacks = force;
    74         }
    75 
    76         /**
    77          * Creates a Diffie-Hellman object from its Noise protocol name.
    78          *
    79          * @param name The name of the DH algorithm; e.g. "25519", "448", etc.
    80          *
    81          * @return The Diffie-Hellman object if the name is recognized.
    82          *
    83          * @throws NoSuchAlgorithmException The name is not recognized as a
    84          * valid Noise protocol name, or there is no cryptography provider
    85          * in the system that implements the algorithm.
    86          */
    87         public static DHState createDH(String name) throws NoSuchAlgorithmException
    88         {
    89                 if (name.equals("25519"))
    90                         return new Curve25519DHState();
    91                 if (name.equals("448"))
    92                         return new Curve448DHState();
    93                 if (name.equals("NewHope"))
    94                         return new NewHopeDHState();
    95                 throw new NoSuchAlgorithmException("Unknown Noise DH algorithm name: " + name);
    96         }
    97 
    9842        /**
    9943         * Creates a cipher object from its Noise protocol name.
     
    10953        public static CipherState createCipher(String name) throws NoSuchAlgorithmException
    11054        {
    111                 if (name.equals("AESGCM")) {
    112                         if (forceFallbacks)
    113                                 return new AESGCMFallbackCipherState();
    114                         // "AES/GCM/NoPadding" exists in some recent JDK's but it is flaky
    115                         // to use and not easily back-portable to older Android versions.
    116                         // We instead emulate AESGCM on top of "AES/CTR/NoPadding".
    117                         try {
    118                                 return new AESGCMOnCtrCipherState();
    119                         } catch (NoSuchAlgorithmException e1) {
    120                                 // Could not find anything useful in the JCA/JCE so
    121                                 // use the pure Java fallback implementation instead.
    122                                 return new AESGCMFallbackCipherState();
    123                         }
    124                 } else if (name.equals("ChaChaPoly")) {
     55                if (name.equals("ChaChaPoly")) {
    12556                        return new ChaChaPolyCipherState();
    12657                }
     
    14677                // JDK is "SHA-256", although "SHA-512" is fairly common as well.
    14778                if (name.equals("SHA256")) {
    148                         if (forceFallbacks)
    149                                 return new SHA256MessageDigest();
    15079                        try {
    15180                                return MessageDigest.getInstance("SHA-256");
    15281                        } catch (NoSuchAlgorithmException e) {
    153                                 return new SHA256MessageDigest();
    154                         }
    155                 } else if (name.equals("SHA512")) {
    156                         if (forceFallbacks)
    157                                 return new SHA512MessageDigest();
    158                         try {
    159                                 return MessageDigest.getInstance("SHA-512");
    160                         } catch (NoSuchAlgorithmException e) {
    161                                 return new SHA512MessageDigest();
    162                         }
    163                 } else if (name.equals("BLAKE2b")) {
    164                         // Bouncy Castle registers the BLAKE2b variant we
    165                         // want under the name "BLAKE2B-512".
    166                         if (forceFallbacks)
    167                                 return new Blake2bMessageDigest();
    168                         try {
    169                                 return MessageDigest.getInstance("BLAKE2B-512");
    170                         } catch (NoSuchAlgorithmException e) {
    171                                 return new Blake2bMessageDigest();
    172                         }
    173                 } else if (name.equals("BLAKE2s")) {
    174                         // Bouncy Castle doesn't currently (June 2016) have an
    175                         // implementation of BLAKE2s, but look for the most
    176                         // obvious provider name in case one is added in the future.
    177                         if (forceFallbacks)
    178                                 return new Blake2sMessageDigest();
    179                         try {
    180                                 return MessageDigest.getInstance("BLAKE2S-256");
    181                         } catch (NoSuchAlgorithmException e) {
    182                                 return new Blake2sMessageDigest();
    18382                        }
    18483                }
  • router/java/src/com/southernstorm/noise/protocol/Pattern.java

    r70f018eb rda81046  
    5555        public static final short FLAG_REMOTE_HYBRID_REQ = 0x2000;
    5656
    57         private static final short[] noise_pattern_N = {
    58             FLAG_LOCAL_EPHEMERAL |
    59             FLAG_REMOTE_STATIC |
    60             FLAG_REMOTE_REQUIRED,
    61 
    62             E,
    63             ES
    64         };
    65 
    66         private static final short[] noise_pattern_K = {
    67             FLAG_LOCAL_STATIC |
    68             FLAG_LOCAL_EPHEMERAL |
    69             FLAG_LOCAL_REQUIRED |
    70             FLAG_REMOTE_STATIC |
    71             FLAG_REMOTE_REQUIRED,
    72 
    73             E,
    74             ES,
    75             SS
    76         };
    77 
    78         private static final short[] noise_pattern_X = {
    79             FLAG_LOCAL_STATIC |
    80             FLAG_LOCAL_EPHEMERAL |
    81             FLAG_REMOTE_STATIC |
    82             FLAG_REMOTE_REQUIRED,
    83 
    84             E,
    85             ES,
    86             S,
    87             SS
    88         };
    89 
    90         private static final short[] noise_pattern_NN = {
    91             FLAG_LOCAL_EPHEMERAL |
    92             FLAG_REMOTE_EPHEMERAL,
    93 
    94             E,
    95             FLIP_DIR,
    96             E,
    97             EE
    98         };
    99 
    100         private static final short[] noise_pattern_NK = {
    101             FLAG_LOCAL_EPHEMERAL |
    102             FLAG_REMOTE_STATIC |
    103             FLAG_REMOTE_EPHEMERAL |
    104             FLAG_REMOTE_REQUIRED,
    105 
    106             E,
    107             ES,
    108             FLIP_DIR,
    109             E,
    110             EE
    111         };
    112 
    113         private static final short[] noise_pattern_NX = {
    114             FLAG_LOCAL_EPHEMERAL |
    115             FLAG_REMOTE_STATIC |
    116             FLAG_REMOTE_EPHEMERAL,
    117 
    118             E,
    119             FLIP_DIR,
    120             E,
    121             EE,
    122             S,
    123             ES
    124         };
    125 
    126         private static final short[] noise_pattern_XN = {
    127             FLAG_LOCAL_STATIC |
    128             FLAG_LOCAL_EPHEMERAL |
    129             FLAG_REMOTE_EPHEMERAL,
    130 
    131             E,
    132             FLIP_DIR,
    133             E,
    134             EE,
    135             FLIP_DIR,
    136             S,
    137             SE
    138         };
    139 
    14057        private static final short[] noise_pattern_XK = {
    14158            FLAG_LOCAL_STATIC |
     
    15572        };
    15673
    157         private static final short[] noise_pattern_XX = {
    158             FLAG_LOCAL_STATIC |
    159             FLAG_LOCAL_EPHEMERAL |
    160             FLAG_REMOTE_STATIC |
    161             FLAG_REMOTE_EPHEMERAL,
    162 
    163             E,
    164             FLIP_DIR,
    165             E,
    166             EE,
    167             S,
    168             ES,
    169             FLIP_DIR,
    170             S,
    171             SE
    172         };
    173 
    174         private static final short[] noise_pattern_KN = {
    175             FLAG_LOCAL_STATIC |
    176             FLAG_LOCAL_EPHEMERAL |
    177             FLAG_LOCAL_REQUIRED |
    178             FLAG_REMOTE_EPHEMERAL,
    179 
    180             E,
    181             FLIP_DIR,
    182             E,
    183             EE,
    184             SE
    185         };
    186 
    187         private static final short[] noise_pattern_KK = {
    188             FLAG_LOCAL_STATIC |
    189             FLAG_LOCAL_EPHEMERAL |
    190             FLAG_LOCAL_REQUIRED |
    191             FLAG_REMOTE_STATIC |
    192             FLAG_REMOTE_EPHEMERAL |
    193             FLAG_REMOTE_REQUIRED,
    194 
    195             E,
    196             ES,
    197             SS,
    198             FLIP_DIR,
    199             E,
    200             EE,
    201             SE
    202         };
    203 
    204         private static final short[] noise_pattern_KX = {
    205             FLAG_LOCAL_STATIC |
    206             FLAG_LOCAL_EPHEMERAL |
    207             FLAG_LOCAL_REQUIRED |
    208             FLAG_REMOTE_STATIC |
    209             FLAG_REMOTE_EPHEMERAL,
    210 
    211             E,
    212             FLIP_DIR,
    213             E,
    214             EE,
    215             SE,
    216             S,
    217             ES
    218         };
    219 
    220         private static final short[] noise_pattern_IN = {
    221             FLAG_LOCAL_STATIC |
    222             FLAG_LOCAL_EPHEMERAL |
    223             FLAG_REMOTE_EPHEMERAL,
    224 
    225             E,
    226             S,
    227             FLIP_DIR,
    228             E,
    229             EE,
    230             SE
    231         };
    232 
    233         private static final short[] noise_pattern_IK = {
    234             FLAG_LOCAL_STATIC |
    235             FLAG_LOCAL_EPHEMERAL |
    236             FLAG_REMOTE_STATIC |
    237             FLAG_REMOTE_EPHEMERAL |
    238             FLAG_REMOTE_REQUIRED,
    239 
    240             E,
    241             ES,
    242             S,
    243             SS,
    244             FLIP_DIR,
    245             E,
    246             EE,
    247             SE
    248         };
    249 
    250         private static final short[] noise_pattern_IX = {
    251             FLAG_LOCAL_STATIC |
    252             FLAG_LOCAL_EPHEMERAL |
    253             FLAG_REMOTE_STATIC |
    254             FLAG_REMOTE_EPHEMERAL,
    255 
    256             E,
    257             S,
    258             FLIP_DIR,
    259             E,
    260             EE,
    261             SE,
    262             S,
    263             ES
    264         };
    265 
    266         private static final short[] noise_pattern_XXfallback = {
    267             FLAG_LOCAL_STATIC |
    268             FLAG_LOCAL_EPHEMERAL |
    269             FLAG_REMOTE_STATIC |
    270             FLAG_REMOTE_EPHEMERAL |
    271             FLAG_REMOTE_EPHEM_REQ,
    272 
    273             E,
    274             EE,
    275             S,
    276             SE,
    277             FLIP_DIR,
    278             S,
    279             ES
    280         };
    281 
    282         private static final short[] noise_pattern_Xnoidh = {
    283             FLAG_LOCAL_STATIC |
    284             FLAG_LOCAL_EPHEMERAL |
    285             FLAG_REMOTE_STATIC |
    286             FLAG_REMOTE_REQUIRED,
    287 
    288             E,
    289             S,
    290             ES,
    291             SS
    292         };
    293 
    294         private static final short[] noise_pattern_NXnoidh = {
    295             FLAG_LOCAL_EPHEMERAL |
    296             FLAG_REMOTE_STATIC |
    297             FLAG_REMOTE_EPHEMERAL,
    298 
    299             E,
    300             FLIP_DIR,
    301             E,
    302             S,
    303             EE,
    304             ES
    305         };
    306 
    307         private static final short[] noise_pattern_XXnoidh = {
    308             FLAG_LOCAL_STATIC |
    309             FLAG_LOCAL_EPHEMERAL |
    310             FLAG_REMOTE_STATIC |
    311             FLAG_REMOTE_EPHEMERAL,
    312 
    313             E,
    314             FLIP_DIR,
    315             E,
    316             S,
    317             EE,
    318             ES,
    319             FLIP_DIR,
    320             S,
    321             SE
    322         };
    323 
    324         private static final short[] noise_pattern_KXnoidh = {
    325             FLAG_LOCAL_STATIC |
    326             FLAG_LOCAL_EPHEMERAL |
    327             FLAG_LOCAL_REQUIRED |
    328             FLAG_REMOTE_STATIC |
    329             FLAG_REMOTE_EPHEMERAL,
    330 
    331             E,
    332             FLIP_DIR,
    333             E,
    334             S,
    335             EE,
    336             SE,
    337             ES
    338         };
    339 
    340         private static final short[] noise_pattern_IKnoidh = {
    341             FLAG_LOCAL_STATIC |
    342             FLAG_LOCAL_EPHEMERAL |
    343             FLAG_REMOTE_STATIC |
    344             FLAG_REMOTE_EPHEMERAL |
    345             FLAG_REMOTE_REQUIRED,
    346 
    347             E,
    348             S,
    349             ES,
    350             SS,
    351             FLIP_DIR,
    352             E,
    353             EE,
    354             SE
    355         };
    356 
    357         private static final short[] noise_pattern_IXnoidh = {
    358             FLAG_LOCAL_STATIC |
    359             FLAG_LOCAL_EPHEMERAL |
    360             FLAG_REMOTE_STATIC |
    361             FLAG_REMOTE_EPHEMERAL,
    362 
    363             E,
    364             S,
    365             FLIP_DIR,
    366             E,
    367             S,
    368             EE,
    369             SE,
    370             ES
    371         };
    372 
    373         private static final short[] noise_pattern_NNhfs = {
    374             FLAG_LOCAL_EPHEMERAL |
    375             FLAG_LOCAL_HYBRID |
    376             FLAG_REMOTE_EPHEMERAL |
    377             FLAG_REMOTE_HYBRID,
    378 
    379             E,
    380             F,
    381             FLIP_DIR,
    382             E,
    383             F,
    384             EE,
    385             FF
    386         };
    387 
    388         private static final short[] noise_pattern_NKhfs = {
    389             FLAG_LOCAL_EPHEMERAL |
    390             FLAG_LOCAL_HYBRID |
    391             FLAG_REMOTE_STATIC |
    392             FLAG_REMOTE_EPHEMERAL |
    393             FLAG_REMOTE_HYBRID |
    394             FLAG_REMOTE_REQUIRED,
    395 
    396             E,
    397             F,
    398             ES,
    399             FLIP_DIR,
    400             E,
    401             F,
    402             EE,
    403             FF
    404         };
    405 
    406         private static final short[] noise_pattern_NXhfs = {
    407             FLAG_LOCAL_EPHEMERAL |
    408             FLAG_LOCAL_HYBRID |
    409             FLAG_REMOTE_STATIC |
    410             FLAG_REMOTE_EPHEMERAL |
    411             FLAG_REMOTE_HYBRID,
    412 
    413             E,
    414             F,
    415             FLIP_DIR,
    416             E,
    417             F,
    418             EE,
    419             FF,
    420             S,
    421             ES
    422         };
    423 
    424         private static final short[] noise_pattern_XNhfs = {
    425             FLAG_LOCAL_STATIC |
    426             FLAG_LOCAL_EPHEMERAL |
    427             FLAG_LOCAL_HYBRID |
    428             FLAG_REMOTE_EPHEMERAL |
    429             FLAG_REMOTE_HYBRID,
    430 
    431             E,
    432             F,
    433             FLIP_DIR,
    434             E,
    435             F,
    436             EE,
    437             FF,
    438             FLIP_DIR,
    439             S,
    440             SE
    441         };
    442 
    443         private static final short[] noise_pattern_XKhfs = {
    444             FLAG_LOCAL_STATIC |
    445             FLAG_LOCAL_EPHEMERAL |
    446             FLAG_LOCAL_HYBRID |
    447             FLAG_REMOTE_STATIC |
    448             FLAG_REMOTE_EPHEMERAL |
    449             FLAG_REMOTE_HYBRID |
    450             FLAG_REMOTE_REQUIRED,
    451 
    452             E,
    453             F,
    454             ES,
    455             FLIP_DIR,
    456             E,
    457             F,
    458             EE,
    459             FF,
    460             FLIP_DIR,
    461             S,
    462             SE
    463         };
    464 
    465         private static final short[] noise_pattern_XXhfs = {
    466             FLAG_LOCAL_STATIC |
    467             FLAG_LOCAL_EPHEMERAL |
    468             FLAG_LOCAL_HYBRID |
    469             FLAG_REMOTE_STATIC |
    470             FLAG_REMOTE_EPHEMERAL |
    471             FLAG_REMOTE_HYBRID,
    472 
    473             E,
    474             F,
    475             FLIP_DIR,
    476             E,
    477             F,
    478             EE,
    479             FF,
    480             S,
    481             ES,
    482             FLIP_DIR,
    483             S,
    484             SE
    485         };
    486 
    487         private static final short[] noise_pattern_KNhfs = {
    488             FLAG_LOCAL_STATIC |
    489             FLAG_LOCAL_EPHEMERAL |
    490             FLAG_LOCAL_REQUIRED |
    491             FLAG_LOCAL_HYBRID |
    492             FLAG_REMOTE_EPHEMERAL |
    493             FLAG_REMOTE_HYBRID,
    494 
    495             E,
    496             F,
    497             FLIP_DIR,
    498             E,
    499             F,
    500             EE,
    501             FF,
    502             SE
    503         };
    504 
    505         private static final short[] noise_pattern_KKhfs = {
    506             FLAG_LOCAL_STATIC |
    507             FLAG_LOCAL_EPHEMERAL |
    508             FLAG_LOCAL_REQUIRED |
    509             FLAG_LOCAL_HYBRID |
    510             FLAG_REMOTE_STATIC |
    511             FLAG_REMOTE_EPHEMERAL |
    512             FLAG_REMOTE_HYBRID |
    513             FLAG_REMOTE_REQUIRED,
    514 
    515             E,
    516             F,
    517             ES,
    518             SS,
    519             FLIP_DIR,
    520             E,
    521             F,
    522             EE,
    523             FF,
    524             SE
    525         };
    526 
    527         private static final short[] noise_pattern_KXhfs = {
    528             FLAG_LOCAL_STATIC |
    529             FLAG_LOCAL_EPHEMERAL |
    530             FLAG_LOCAL_REQUIRED |
    531             FLAG_LOCAL_HYBRID |
    532             FLAG_REMOTE_STATIC |
    533             FLAG_REMOTE_EPHEMERAL |
    534             FLAG_REMOTE_HYBRID,
    535 
    536             E,
    537             F,
    538             FLIP_DIR,
    539             E,
    540             F,
    541             EE,
    542             FF,
    543             SE,
    544             S,
    545             ES
    546         };
    547 
    548         private static final short[] noise_pattern_INhfs = {
    549             FLAG_LOCAL_STATIC |
    550             FLAG_LOCAL_EPHEMERAL |
    551             FLAG_LOCAL_HYBRID |
    552             FLAG_REMOTE_EPHEMERAL |
    553             FLAG_REMOTE_HYBRID,
    554 
    555             E,
    556             F,
    557             S,
    558             FLIP_DIR,
    559             E,
    560             F,
    561             EE,
    562             FF,
    563             SE
    564         };
    565 
    566         private static final short[] noise_pattern_IKhfs = {
    567             FLAG_LOCAL_STATIC |
    568             FLAG_LOCAL_EPHEMERAL |
    569             FLAG_LOCAL_HYBRID |
    570             FLAG_REMOTE_STATIC |
    571             FLAG_REMOTE_EPHEMERAL |
    572             FLAG_REMOTE_HYBRID |
    573             FLAG_REMOTE_REQUIRED,
    574 
    575             E,
    576             F,
    577             ES,
    578             S,
    579             SS,
    580             FLIP_DIR,
    581             E,
    582             F,
    583             EE,
    584             FF,
    585             SE
    586         };
    587 
    588         private static final short[] noise_pattern_IXhfs = {
    589             FLAG_LOCAL_STATIC |
    590             FLAG_LOCAL_EPHEMERAL |
    591             FLAG_LOCAL_HYBRID |
    592             FLAG_REMOTE_STATIC |
    593             FLAG_REMOTE_EPHEMERAL |
    594             FLAG_REMOTE_HYBRID,
    595 
    596             E,
    597             F,
    598             S,
    599             FLIP_DIR,
    600             E,
    601             F,
    602             EE,
    603             FF,
    604             SE,
    605             S,
    606             ES
    607         };
    608 
    609         private static final short[] noise_pattern_XXfallback_hfs = {
    610             FLAG_LOCAL_STATIC |
    611             FLAG_LOCAL_EPHEMERAL |
    612             FLAG_LOCAL_HYBRID |
    613             FLAG_REMOTE_STATIC |
    614             FLAG_REMOTE_EPHEMERAL |
    615             FLAG_REMOTE_EPHEM_REQ |
    616             FLAG_REMOTE_HYBRID |
    617             FLAG_REMOTE_HYBRID_REQ,
    618 
    619             E,
    620             F,
    621             EE,
    622             FF,
    623             S,
    624             SE,
    625             FLIP_DIR,
    626             S,
    627             ES
    628         };
    629 
    630         private static final short[] noise_pattern_NXnoidh_hfs = {
    631             FLAG_LOCAL_EPHEMERAL |
    632             FLAG_LOCAL_HYBRID |
    633             FLAG_REMOTE_STATIC |
    634             FLAG_REMOTE_EPHEMERAL |
    635             FLAG_REMOTE_HYBRID,
    636 
    637             E,
    638             F,
    639             FLIP_DIR,
    640             E,
    641             F,
    642             S,
    643             EE,
    644             FF,
    645             ES
    646         };
    647 
    648         private static final short[] noise_pattern_XXnoidh_hfs = {
    649             FLAG_LOCAL_STATIC |
    650             FLAG_LOCAL_EPHEMERAL |
    651             FLAG_LOCAL_HYBRID |
    652             FLAG_REMOTE_STATIC |
    653             FLAG_REMOTE_EPHEMERAL |
    654             FLAG_REMOTE_HYBRID,
    655 
    656             E,
    657             F,
    658             FLIP_DIR,
    659             E,
    660             F,
    661             S,
    662             EE,
    663             FF,
    664             ES,
    665             FLIP_DIR,
    666             S,
    667             SE
    668         };
    669 
    670         private static final short[] noise_pattern_KXnoidh_hfs = {
    671             FLAG_LOCAL_STATIC |
    672             FLAG_LOCAL_EPHEMERAL |
    673             FLAG_LOCAL_REQUIRED |
    674             FLAG_LOCAL_HYBRID |
    675             FLAG_REMOTE_STATIC |
    676             FLAG_REMOTE_EPHEMERAL |
    677             FLAG_REMOTE_HYBRID,
    678 
    679             E,
    680             F,
    681             FLIP_DIR,
    682             E,
    683             F,
    684             S,
    685             EE,
    686             FF,
    687             SE,
    688             ES
    689         };
    690 
    691         private static final short[] noise_pattern_IKnoidh_hfs = {
    692             FLAG_LOCAL_STATIC |
    693             FLAG_LOCAL_EPHEMERAL |
    694             FLAG_LOCAL_HYBRID |
    695             FLAG_REMOTE_STATIC |
    696             FLAG_REMOTE_EPHEMERAL |
    697             FLAG_REMOTE_EPHEMERAL |
    698             FLAG_REMOTE_HYBRID,
    699 
    700             E,
    701             F,
    702             S,
    703             ES,
    704             SS,
    705             FLIP_DIR,
    706             E,
    707             F,
    708             EE,
    709             FF,
    710             SE
    711         };
    712 
    713         private static final short[] noise_pattern_IXnoidh_hfs = {
    714             FLAG_LOCAL_STATIC |
    715             FLAG_LOCAL_EPHEMERAL |
    716             FLAG_LOCAL_HYBRID |
    717             FLAG_REMOTE_STATIC |
    718             FLAG_REMOTE_EPHEMERAL |
    719             FLAG_REMOTE_HYBRID,
    720 
    721             E,
    722             F,
    723             S,
    724             FLIP_DIR,
    725             E,
    726             F,
    727             S,
    728             EE,
    729             FF,
    730             SE,
    731             ES
    732         };
    733 
    73474        /**
    73575         * Look up the description information for a pattern.
     
    74080        public static short[] lookup(String name)
    74181        {
    742                 if (name.equals("N"))
    743                         return noise_pattern_N;
    744                 else if (name.equals("K"))
    745                         return noise_pattern_K;
    746                 else if (name.equals("X"))
    747                         return noise_pattern_X;
    748                 else if (name.equals("NN"))
    749                         return noise_pattern_NN;
    750                 else if (name.equals("NK"))
    751                         return noise_pattern_NK;
    752                 else if (name.equals("NX"))
    753                         return noise_pattern_NX;
    754                 else if (name.equals("XN"))
    755                         return noise_pattern_XN;
    756                 else if (name.equals("XK"))
     82                if (name.equals("XK"))
    75783                        return noise_pattern_XK;
    758                 else if (name.equals("XX"))
    759                         return noise_pattern_XX;
    760                 else if (name.equals("KN"))
    761                         return noise_pattern_KN;
    762                 else if (name.equals("KK"))
    763                         return noise_pattern_KK;
    764                 else if (name.equals("KX"))
    765                         return noise_pattern_KX;
    766                 else if (name.equals("IN"))
    767                         return noise_pattern_IN;
    768                 else if (name.equals("IK"))
    769                         return noise_pattern_IK;
    770                 else if (name.equals("IX"))
    771                         return noise_pattern_IX;
    772                 else if (name.equals("XXfallback"))
    773                         return noise_pattern_XXfallback;
    774                 else if (name.equals("Xnoidh"))
    775                         return noise_pattern_Xnoidh;
    776                 else if (name.equals("NXnoidh"))
    777                         return noise_pattern_NXnoidh;
    778                 else if (name.equals("XXnoidh"))
    779                         return noise_pattern_XXnoidh;
    780                 else if (name.equals("KXnoidh"))
    781                         return noise_pattern_KXnoidh;
    782                 else if (name.equals("IKnoidh"))
    783                         return noise_pattern_IKnoidh;
    784                 else if (name.equals("IXnoidh"))
    785                         return noise_pattern_IXnoidh;
    786                 else if (name.equals("NNhfs"))
    787                         return noise_pattern_NNhfs;
    788                 else if (name.equals("NKhfs"))
    789                         return noise_pattern_NKhfs;
    790                 else if (name.equals("NXhfs"))
    791                         return noise_pattern_NXhfs;
    792                 else if (name.equals("XNhfs"))
    793                         return noise_pattern_XNhfs;
    794                 else if (name.equals("XKhfs"))
    795                         return noise_pattern_XKhfs;
    796                 else if (name.equals("XXhfs"))
    797                         return noise_pattern_XXhfs;
    798                 else if (name.equals("KNhfs"))
    799                         return noise_pattern_KNhfs;
    800                 else if (name.equals("KKhfs"))
    801                         return noise_pattern_KKhfs;
    802                 else if (name.equals("KXhfs"))
    803                         return noise_pattern_KXhfs;
    804                 else if (name.equals("INhfs"))
    805                         return noise_pattern_INhfs;
    806                 else if (name.equals("IKhfs"))
    807                         return noise_pattern_IKhfs;
    808                 else if (name.equals("IXhfs"))
    809                         return noise_pattern_IXhfs;
    810                 else if (name.equals("XXfallback+hfs"))
    811                         return noise_pattern_XXfallback_hfs;
    812                 else if (name.equals("NXnoidh+hfs"))
    813                         return noise_pattern_NXnoidh_hfs;
    814                 else if (name.equals("XXnoidh+hfs"))
    815                         return noise_pattern_XXnoidh_hfs;
    816                 else if (name.equals("KXnoidh+hfs"))
    817                         return noise_pattern_KXnoidh_hfs;
    818                 else if (name.equals("IKnoidh+hfs"))
    819                         return noise_pattern_IKnoidh_hfs;
    820                 else if (name.equals("IXnoidh+hfs"))
    821                         return noise_pattern_IXnoidh_hfs;
    82284                return null;
    82385        }
  • router/java/src/com/southernstorm/noise/protocol/SymmetricState.java

    r70f018eb rda81046  
    3737class SymmetricState implements Destroyable {
    3838       
    39         private String name;
    40         private CipherState cipher;
    41         private MessageDigest hash;
    42         private byte[] ck;
    43         private byte[] h;
    44         private byte[] prev_h;
     39        // precalculated hash of the Noise name
     40        private static final byte[] INIT_HASH;
     41
     42        static {
     43                byte[] protocolNameBytes;
     44                try {
     45                        protocolNameBytes = HandshakeState.protocolName.getBytes("UTF-8");
     46                } catch (UnsupportedEncodingException e) {
     47                        // If UTF-8 is not supported, then we are definitely in trouble!
     48                        throw new UnsupportedOperationException("UTF-8 encoding is not supported");
     49                }
     50                INIT_HASH = new byte[32];
     51                if (protocolNameBytes.length <= 32) {
     52                        System.arraycopy(protocolNameBytes, 0, INIT_HASH, 0, protocolNameBytes.length);
     53                        Arrays.fill(INIT_HASH, protocolNameBytes.length, 32, (byte)0);
     54                } else {
     55                        try {
     56                                MessageDigest hash = Noise.createHash("SHA256");
     57                                hash.update(protocolNameBytes, 0, protocolNameBytes.length);
     58                                hash.digest(INIT_HASH, 0, 32);
     59                        } catch (Exception e) {
     60                                throw new IllegalStateException(e);
     61                        }
     62                }
     63        }
     64
     65        private final CipherState cipher;
     66        private final MessageDigest hash;
     67        private final byte[] ck;
     68        private final byte[] h;
     69        private final byte[] prev_h;
    4570
    4671        /**
    4772         * Constructs a new symmetric state object.
     73         * Noise protocol name is hardcoded.
    4874         *
    4975         * @param protocolName The name of the Noise protocol, which is assumed to be valid.
     
    5480         * protocol name is not supported.
    5581         */
    56         public SymmetricState(String protocolName, String cipherName, String hashName) throws NoSuchAlgorithmException
    57         {
    58                 name = protocolName;
     82        public SymmetricState(String cipherName, String hashName) throws NoSuchAlgorithmException
     83        {
    5984                cipher = Noise.createCipher(cipherName);
    6085                hash = Noise.createHash(hashName);
     
    6489                prev_h = new byte [hashLength];
    6590               
    66                 byte[] protocolNameBytes;
    67                 try {
    68                         protocolNameBytes = protocolName.getBytes("UTF-8");
    69                 } catch (UnsupportedEncodingException e) {
    70                         // If UTF-8 is not supported, then we are definitely in trouble!
    71                         throw new UnsupportedOperationException("UTF-8 encoding is not supported");
    72                 }
    73                
    74                 if (protocolNameBytes.length <= hashLength) {
    75                         System.arraycopy(protocolNameBytes, 0, h, 0, protocolNameBytes.length);
    76                         Arrays.fill(h, protocolNameBytes.length, h.length, (byte)0);
    77                 } else {
    78                         hashOne(protocolNameBytes, 0, protocolNameBytes.length, h, 0, h.length);
    79                 }
    80                
     91                System.arraycopy(INIT_HASH, 0, h, 0, hashLength);
    8192                System.arraycopy(h, 0, ck, 0, hashLength);
    8293        }
     
    89100        public String getProtocolName()
    90101        {
    91                 return name;
     102                return HandshakeState.protocolName;
    92103        }
    93104       
     
    312323        @Override
    313324        public void destroy() {
    314                 if (cipher != null) {
    315                         cipher.destroy();
    316                         cipher = null;
    317                 }
    318                 if (hash != null) {
    319                         // The built-in fallback implementations are destroyable.
    320                         // JCA/JCE implementations aren't, so try reset() instead.
    321                         if (hash instanceof Destroyable)
    322                                 ((Destroyable)hash).destroy();
    323                         else
    324                                 hash.reset();
    325                         hash = null;
    326                 }
    327                 if (ck != null) {
    328                         Noise.destroy(ck);
    329                         ck = null;
    330                 }
    331                 if (h != null) {
    332                         Noise.destroy(h);
    333                         h = null;
    334                 }
    335                 if (prev_h != null) {
    336                         Noise.destroy(prev_h);
    337                         prev_h = null;
    338                 }
     325                cipher.destroy();
     326                hash.reset();
     327                Noise.destroy(ck);
     328                Noise.destroy(h);
     329                Noise.destroy(prev_h);
    339330        }
    340331
     
    482473                }
    483474        }
     475
     476        /**
     477         *  I2P for getting chaining key for siphash calculation
     478         *  @return a copy
     479         */
     480        public byte[] getChainingKey() {
     481                byte[] rv = new byte[ck.length];
     482                System.arraycopy(ck, 0, rv, 0, ck.length);
     483                return rv;
     484        }
     485
     486        /**
     487         *  I2P debug
     488         */
     489        @Override
     490        public String toString() {
     491                StringBuilder buf = new StringBuilder();
     492                buf.append("  Symmetric State:\n" +
     493                           "    ck: ");
     494                buf.append(net.i2p.data.Base64.encode(ck));
     495                buf.append("\n" +
     496                           "    h:  ");
     497                buf.append(net.i2p.data.Base64.encode(h));
     498                buf.append('\n');
     499                buf.append(cipher.toString());
     500                return buf.toString();
     501        }
     502
     503/****
     504    private static final int LENGTH = 33;
     505
     506    public static void main(String args[]) throws Exception {
     507        net.i2p.I2PAppContext ctx = net.i2p.I2PAppContext.getGlobalContext();
     508        byte[] rand = new byte[32];
     509        byte[] data = new byte[LENGTH];
     510        byte[] out = new byte[32];
     511        System.out.println("Warmup");
     512        int RUNS = 25000;
     513        SymmetricState ss = new SymmetricState("ChaChaPoly", "SHA256");
     514        for (int i = 0; i < RUNS; i++) {
     515            ctx.random().nextBytes(rand);
     516            ctx.random().nextBytes(data);
     517            ss.hmac(rand, 0, 32, data, 0, LENGTH, out, 0, 32);
     518        }
     519        System.out.println("Start");
     520        RUNS = 500000;
     521        long start = System.currentTimeMillis();
     522        for (int i = 0; i < RUNS; i++) {
     523            ss.hmac(rand, 0, 32, data, 0, LENGTH, out, 0, 32);
     524        }
     525        long time = System.currentTimeMillis() - start;
     526        System.out.println("Time for " + RUNS + " HMAC-SHA256 computations:");
     527        System.out.println("Noise time (ms): " + time);
     528    }
     529****/
    484530}
Note: See TracChangeset for help on using the changeset viewer.