forked from I2P_Developers/i2p.i2p
Router: Checks for new enc types
- Prevent encrypted lookups or stores - Prevent participting in our tunnels - Handle padding - Checks in crypto classes
This commit is contained in:
@ -17,6 +17,7 @@ import java.util.Set;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.AESEngine;
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -97,6 +98,8 @@ public final class ElGamalAESEngine {
|
||||
_log.error("Data is less than the minimum size (" + data.length + " < " + MIN_ENCRYPTED_SIZE + ")");
|
||||
return null;
|
||||
}
|
||||
if (targetPrivateKey.getType() != EncType.ELGAMAL_2048)
|
||||
return null;
|
||||
|
||||
byte tag[] = new byte[32];
|
||||
System.arraycopy(data, 0, tag, 0, 32);
|
||||
@ -399,7 +402,8 @@ public final class ElGamalAESEngine {
|
||||
* no less than the paddedSize parameter, but may be more. This method uses the
|
||||
* ElGamal+AES algorithm in the data structure spec.
|
||||
*
|
||||
* @param target public key to which the data should be encrypted.
|
||||
* @param target public key to which the data should be encrypted, must be ELGAMAL_2048.
|
||||
* May be null if key and currentTag are non-null.
|
||||
* @param key session key to use during encryption
|
||||
* @param tagsForDelivery session tags to be associated with the key (or newKey if specified), or null;
|
||||
* 200 max enforced at receiver
|
||||
@ -407,11 +411,17 @@ public final class ElGamalAESEngine {
|
||||
* @param newKey key to be delivered to the target, with which the tagsForDelivery should be associated, or null
|
||||
* @param paddedSize minimum size in bytes of the body after padding it (if less than the
|
||||
* body's real size, no bytes are appended but the body is not truncated)
|
||||
* @throws IllegalArgumentException on bad target EncType
|
||||
*
|
||||
* Unused externally, only called by below (i.e. newKey is always null)
|
||||
*/
|
||||
public byte[] encrypt(byte data[], PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery,
|
||||
SessionTag currentTag, SessionKey newKey, long paddedSize) {
|
||||
if (target != null) {
|
||||
EncType type = target.getType();
|
||||
if (type != EncType.ELGAMAL_2048)
|
||||
throw new IllegalArgumentException("Bad public key type " + type);
|
||||
}
|
||||
if (currentTag == null) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Current tag is null, encrypting as new session");
|
||||
@ -420,8 +430,9 @@ public final class ElGamalAESEngine {
|
||||
}
|
||||
//if (_log.shouldLog(Log.INFO))
|
||||
// _log.info("Current tag is NOT null, encrypting as existing session");
|
||||
// target unused, using key and tag only
|
||||
_context.statManager().updateFrequency("crypto.elGamalAES.encryptExistingSession");
|
||||
byte rv[] = encryptExistingSession(data, target, key, tagsForDelivery, currentTag, newKey, paddedSize);
|
||||
byte rv[] = encryptExistingSession(data, key, tagsForDelivery, currentTag, newKey, paddedSize);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Existing session encrypted with tag: " + currentTag.toString() + ": " + rv.length + " bytes and key: " + key.toBase64() /* + ": " + Base64.encode(rv, 0, 64) */);
|
||||
return rv;
|
||||
@ -447,13 +458,15 @@ public final class ElGamalAESEngine {
|
||||
* or a 514-byte ElGamal block and several 32-byte session tags for a new session.
|
||||
* So the returned encrypted data will be at least 32 bytes larger than paddedSize.
|
||||
*
|
||||
* @param target public key to which the data should be encrypted.
|
||||
* @param target public key to which the data should be encrypted, must be ELGAMAL_2048.
|
||||
* May be null if key and currentTag are non-null.
|
||||
* @param key session key to use during encryption
|
||||
* @param tagsForDelivery session tags to be associated with the key or null;
|
||||
* 200 max enforced at receiver
|
||||
* @param currentTag sessionTag to use, or null if it should use ElG (i.e. new session)
|
||||
* @param paddedSize minimum size in bytes of the body after padding it (if less than the
|
||||
* body's real size, no bytes are appended but the body is not truncated)
|
||||
* @throws IllegalArgumentException on bad target EncType
|
||||
*
|
||||
*/
|
||||
public byte[] encrypt(byte data[], PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery,
|
||||
@ -468,6 +481,7 @@ public final class ElGamalAESEngine {
|
||||
*
|
||||
* @param tagsForDelivery session tags to be associated with the key or null;
|
||||
* 200 max enforced at receiver
|
||||
* @throws IllegalArgumentException on bad target EncType
|
||||
* @deprecated unused
|
||||
*/
|
||||
public byte[] encrypt(byte data[], PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, long paddedSize) {
|
||||
@ -479,6 +493,7 @@ public final class ElGamalAESEngine {
|
||||
* No new session key
|
||||
* No current tag (encrypt as new session)
|
||||
*
|
||||
* @throws IllegalArgumentException on bad target EncType
|
||||
* @deprecated unused
|
||||
*/
|
||||
public byte[] encrypt(byte data[], PublicKey target, SessionKey key, long paddedSize) {
|
||||
@ -573,11 +588,10 @@ public final class ElGamalAESEngine {
|
||||
* - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
|
||||
* </pre>
|
||||
*
|
||||
* @param target unused, this is AES encrypt only using the session key and tag
|
||||
* @param tagsForDelivery session tags to be associated with the key or null;
|
||||
* 200 max enforced at receiver
|
||||
*/
|
||||
private byte[] encryptExistingSession(byte data[], PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery,
|
||||
private byte[] encryptExistingSession(byte data[], SessionKey key, Set<SessionTag> tagsForDelivery,
|
||||
SessionTag currentTag, SessionKey newKey, long paddedSize) {
|
||||
//_log.debug("Encrypting to an EXISTING session");
|
||||
byte rawTag[] = currentTag.getData();
|
||||
|
@ -25,6 +25,7 @@ import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.crypto.TagSetHandle;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -283,6 +284,8 @@ public class TransientSessionKeyManager extends SessionKeyManager {
|
||||
* Retrieve the session key currently associated with encryption to the target.
|
||||
* Generates a new session and session key if not previously exising.
|
||||
*
|
||||
* @param target public key to which the data should be encrypted, must be ELGAMAL_2048.
|
||||
* @throws IllegalArgumentException on bad target EncType
|
||||
* @return non-null
|
||||
* @since 0.9
|
||||
*/
|
||||
@ -310,6 +313,9 @@ public class TransientSessionKeyManager extends SessionKeyManager {
|
||||
*
|
||||
* Racy if called after getCurrentKey() to check for a current session;
|
||||
* use getCurrentOrNewKey() in that case.
|
||||
*
|
||||
* @param target public key to which the data should be encrypted, must be ELGAMAL_2048.
|
||||
* @throws IllegalArgumentException on bad target EncType
|
||||
*/
|
||||
@Override
|
||||
public void createSession(PublicKey target, SessionKey key) {
|
||||
@ -322,6 +328,9 @@ public class TransientSessionKeyManager extends SessionKeyManager {
|
||||
*
|
||||
*/
|
||||
private OutboundSession createAndReturnSession(PublicKey target, SessionKey key) {
|
||||
EncType type = target.getType();
|
||||
if (type != EncType.ELGAMAL_2048)
|
||||
throw new IllegalArgumentException("Bad public key type " + type);
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("New OB session, sesskey: " + key + " target: " + toString(target));
|
||||
OutboundSession sess = new OutboundSession(_context, _log, target, key);
|
||||
|
@ -10,6 +10,7 @@ import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.DataHelper;
|
||||
@ -425,6 +426,13 @@ public class IterativeSearchJob extends FloodSearchJob {
|
||||
// request encrypted reply
|
||||
// now covered by version check above, which is more recent
|
||||
//if (DatabaseLookupMessage.supportsEncryptedReplies(ri)) {
|
||||
EncType type = ri.getIdentity().getPublicKey().getType();
|
||||
if (type != EncType.ELGAMAL_2048) {
|
||||
failed(peer, false);
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getJobId() + ": Can't do encrypted lookup to " + peer + " with EncType " + type);
|
||||
return;
|
||||
}
|
||||
if (true) {
|
||||
MessageWrapper.OneTimeSession sess;
|
||||
if (isClientReplyTunnel)
|
||||
|
@ -3,6 +3,7 @@ package net.i2p.router.networkdb.kademlia;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.crypto.SessionKeyManager;
|
||||
import net.i2p.crypto.TagSetHandle;
|
||||
import net.i2p.data.Certificate;
|
||||
@ -40,9 +41,14 @@ public class MessageWrapper {
|
||||
*
|
||||
* @param from must be a local client with a session key manager,
|
||||
* or null to use the router's session key manager
|
||||
* @param to must be ELGAMAL_2048 EncType
|
||||
* @return null on encrypt failure
|
||||
*/
|
||||
static WrappedMessage wrap(RouterContext ctx, I2NPMessage m, Hash from, RouterInfo to) {
|
||||
PublicKey sentTo = to.getIdentity().getPublicKey();
|
||||
if (sentTo.getType() != EncType.ELGAMAL_2048)
|
||||
return null;
|
||||
|
||||
PayloadGarlicConfig payload = new PayloadGarlicConfig(Certificate.NULL_CERT,
|
||||
ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE),
|
||||
m.getMessageExpiration(),
|
||||
@ -63,7 +69,6 @@ public class MessageWrapper {
|
||||
if (msg == null)
|
||||
return null;
|
||||
TagSetHandle tsh = null;
|
||||
PublicKey sentTo = to.getIdentity().getPublicKey();
|
||||
if (!sentTags.isEmpty())
|
||||
tsh = skm.tagsDelivered(sentTo, sentKey, sentTags);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
@ -118,10 +123,15 @@ public class MessageWrapper {
|
||||
* to hide the contents from the OBEP.
|
||||
* Forces ElGamal.
|
||||
*
|
||||
* @param to must be ELGAMAL_2048 EncType
|
||||
* @return null on encrypt failure
|
||||
* @since 0.9.5
|
||||
*/
|
||||
static GarlicMessage wrap(RouterContext ctx, I2NPMessage m, RouterInfo to) {
|
||||
PublicKey key = to.getIdentity().getPublicKey();
|
||||
if (key.getType() != EncType.ELGAMAL_2048)
|
||||
return null;
|
||||
|
||||
PayloadGarlicConfig payload = new PayloadGarlicConfig(Certificate.NULL_CERT,
|
||||
ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE),
|
||||
m.getMessageExpiration(),
|
||||
@ -129,7 +139,6 @@ public class MessageWrapper {
|
||||
payload.setRecipient(to);
|
||||
|
||||
SessionKey sentKey = ctx.keyGenerator().generateSessionKey();
|
||||
PublicKey key = to.getIdentity().getPublicKey();
|
||||
GarlicMessage msg = GarlicMessageBuilder.buildMessage(ctx, payload, null, null,
|
||||
key, sentKey, null);
|
||||
return msg;
|
||||
|
@ -12,6 +12,7 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.crypto.EncType;
|
||||
import net.i2p.crypto.SHA256Generator;
|
||||
import net.i2p.crypto.SigType;
|
||||
import net.i2p.data.DataFormatException;
|
||||
@ -469,6 +470,9 @@ public abstract class TunnelPeerSelector extends ConnectChecker {
|
||||
maxLen++;
|
||||
if (cap.length() <= maxLen)
|
||||
return true;
|
||||
if (peer.getIdentity().getPublicKey().getType() != EncType.ELGAMAL_2048)
|
||||
return true;
|
||||
|
||||
// otherwise, it contains flags we aren't trying to focus on,
|
||||
// so don't exclude it based on published capacity
|
||||
|
||||
|
Reference in New Issue
Block a user