diff options
Diffstat (limited to 'core/src/main/jdk1.1/org/bouncycastle/crypto')
14 files changed, 0 insertions, 3639 deletions
diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java deleted file mode 100644 index 30808802..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEParticipant.java +++ /dev/null @@ -1,573 +0,0 @@ -package org.bouncycastle.crypto.agreement.jpake; - -import java.math.BigInteger; -import java.security.SecureRandom; - -import org.bouncycastle.crypto.CryptoException; -import org.bouncycastle.crypto.Digest; -import org.bouncycastle.crypto.digests.SHA256Digest; -import org.bouncycastle.util.Arrays; - -/** - * A participant in a Password Authenticated Key Exchange by Juggling (J-PAKE) exchange. - * <p/> - * <p/> - * The J-PAKE exchange is defined by Feng Hao and Peter Ryan in the paper - * <a href="http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf"> - * "Password Authenticated Key Exchange by Juggling, 2008."</a> - * <p/> - * <p/> - * The J-PAKE protocol is symmetric. - * There is no notion of a <i>client</i> or <i>server</i>, but rather just two <i>participants</i>. - * An instance of {@link JPAKEParticipant} represents one participant, and - * is the primary interface for executing the exchange. - * <p/> - * <p/> - * To execute an exchange, construct a {@link JPAKEParticipant} on each end, - * and call the following 7 methods - * (once and only once, in the given order, for each participant, sending messages between them as described): - * <ol> - * <li>{@link #createRound1PayloadToSend()} - and send the payload to the other participant</li> - * <li>{@link #validateRound1PayloadReceived(JPAKERound1Payload)} - use the payload received from the other participant</li> - * <li>{@link #createRound2PayloadToSend()} - and send the payload to the other participant</li> - * <li>{@link #validateRound2PayloadReceived(JPAKERound2Payload)} - use the payload received from the other participant</li> - * <li>{@link #calculateKeyingMaterial()}</li> - * <li>{@link #createRound3PayloadToSend(BigInteger)} - and send the payload to the other participant</li> - * <li>{@link #validateRound3PayloadReceived(JPAKERound3Payload, BigInteger)} - use the payload received from the other participant</li> - * </ol> - * <p/> - * <p/> - * Each side should derive a session key from the keying material returned by {@link #calculateKeyingMaterial()}. - * The caller is responsible for deriving the session key using a secure key derivation function (KDF). - * <p/> - * <p/> - * Round 3 is an optional key confirmation process. - * If you do not execute round 3, then there is no assurance that both participants are using the same key. - * (i.e. if the participants used different passwords, then their session keys will differ.) - * <p/> - * <p/> - * If the round 3 validation succeeds, then the keys are guaranteed to be the same on both sides. - * <p/> - * <p/> - * The symmetric design can easily support the asymmetric cases when one party initiates the communication. - * e.g. Sometimes the round1 payload and round2 payload may be sent in one pass. - * Also, in some cases, the key confirmation payload can be sent together with the round2 payload. - * These are the trivial techniques to optimize the communication. - * <p/> - * <p/> - * The key confirmation process is implemented as specified in - * <a href="http://csrc.nist.gov/publications/nistpubs/800-56A/SP800-56A_Revision1_Mar08-2007.pdf">NIST SP 800-56A Revision 1</a>, - * Section 8.2 Unilateral Key Confirmation for Key Agreement Schemes. - * <p/> - * <p/> - * This class is stateful and NOT threadsafe. - * Each instance should only be used for ONE complete J-PAKE exchange - * (i.e. a new {@link JPAKEParticipant} should be constructed for each new J-PAKE exchange). - * <p/> - * <p/> - * See {@link JPAKEExample} for example usage. - */ -public class JPAKEParticipant -{ - /* - * Possible internal states. Used for state checking. - */ - - public static final int STATE_INITIALIZED = 0; - public static final int STATE_ROUND_1_CREATED = 10; - public static final int STATE_ROUND_1_VALIDATED = 20; - public static final int STATE_ROUND_2_CREATED = 30; - public static final int STATE_ROUND_2_VALIDATED = 40; - public static final int STATE_KEY_CALCULATED = 50; - public static final int STATE_ROUND_3_CREATED = 60; - public static final int STATE_ROUND_3_VALIDATED = 70; - - /** - * Unique identifier of this participant. - * The two participants in the exchange must NOT share the same id. - */ - private String participantId; - - /** - * Shared secret. This only contains the secret between construction - * and the call to {@link #calculateKeyingMaterial()}. - * <p/> - * i.e. When {@link #calculateKeyingMaterial()} is called, this buffer overwritten with 0's, - * and the field is set to null. - */ - private char[] password; - - /** - * Digest to use during calculations. - */ - private Digest digest; - - /** - * Source of secure random data. - */ - private SecureRandom random; - - private BigInteger p; - private BigInteger q; - private BigInteger g; - - /** - * The participantId of the other participant in this exchange. - */ - private String partnerParticipantId; - - /** - * Alice's x1 or Bob's x3. - */ - private BigInteger x1; - /** - * Alice's x2 or Bob's x4. - */ - private BigInteger x2; - /** - * Alice's g^x1 or Bob's g^x3. - */ - private BigInteger gx1; - /** - * Alice's g^x2 or Bob's g^x4. - */ - private BigInteger gx2; - /** - * Alice's g^x3 or Bob's g^x1. - */ - private BigInteger gx3; - /** - * Alice's g^x4 or Bob's g^x2. - */ - private BigInteger gx4; - /** - * Alice's B or Bob's A. - */ - private BigInteger b; - - /** - * The current state. - * See the <tt>STATE_*</tt> constants for possible values. - */ - private int state; - - /** - * Convenience constructor for a new {@link JPAKEParticipant} that uses - * the {@link JPAKEPrimeOrderGroups#NIST_3072} prime order group, - * a SHA-256 digest, and a default {@link SecureRandom} implementation. - * <p/> - * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}. - * - * @param participantId unique identifier of this participant. - * The two participants in the exchange must NOT share the same id. - * @param password shared secret. - * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called). - * Caller should clear the input password as soon as possible. - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if password is empty - */ - public JPAKEParticipant( - String participantId, - char[] password) - { - this( - participantId, - password, - JPAKEPrimeOrderGroups.NIST_3072); - } - - - /** - * Convenience constructor for a new {@link JPAKEParticipant} that uses - * a SHA-256 digest and a default {@link SecureRandom} implementation. - * <p/> - * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}. - * - * @param participantId unique identifier of this participant. - * The two participants in the exchange must NOT share the same id. - * @param password shared secret. - * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called). - * Caller should clear the input password as soon as possible. - * @param group prime order group. - * See {@link JPAKEPrimeOrderGroups} for standard groups - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if password is empty - */ - public JPAKEParticipant( - String participantId, - char[] password, - JPAKEPrimeOrderGroup group) - { - this( - participantId, - password, - group, - new SHA256Digest(), - new SecureRandom()); - } - - - /** - * Construct a new {@link JPAKEParticipant}. - * <p/> - * After construction, the {@link #getState() state} will be {@link #STATE_INITIALIZED}. - * - * @param participantId unique identifier of this participant. - * The two participants in the exchange must NOT share the same id. - * @param password shared secret. - * A defensive copy of this array is made (and cleared once {@link #calculateKeyingMaterial()} is called). - * Caller should clear the input password as soon as possible. - * @param group prime order group. - * See {@link JPAKEPrimeOrderGroups} for standard groups - * @param digest digest to use during zero knowledge proofs and key confirmation (SHA-256 or stronger preferred) - * @param random source of secure random data for x1 and x2, and for the zero knowledge proofs - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if password is empty - */ - public JPAKEParticipant( - String participantId, - char[] password, - JPAKEPrimeOrderGroup group, - Digest digest, - SecureRandom random) - { - JPAKEUtil.validateNotNull(participantId, "participantId"); - JPAKEUtil.validateNotNull(password, "password"); - JPAKEUtil.validateNotNull(group, "p"); - JPAKEUtil.validateNotNull(digest, "digest"); - JPAKEUtil.validateNotNull(random, "random"); - if (password.length == 0) - { - throw new IllegalArgumentException("Password must not be empty."); - } - - this.participantId = participantId; - - /* - * Create a defensive copy so as to fully encapsulate the password. - * - * This array will contain the password for the lifetime of this - * participant BEFORE {@link #calculateKeyingMaterial()} is called. - * - * i.e. When {@link #calculateKeyingMaterial()} is called, the array will be cleared - * in order to remove the password from memory. - * - * The caller is responsible for clearing the original password array - * given as input to this constructor. - */ - this.password = Arrays.copyOf(password, password.length); - - this.p = group.getP(); - this.q = group.getQ(); - this.g = group.getG(); - - this.digest = digest; - this.random = random; - - this.state = STATE_INITIALIZED; - } - - /** - * Gets the current state of this participant. - * See the <tt>STATE_*</tt> constants for possible values. - */ - public int getState() - { - return this.state; - } - - /** - * Creates and returns the payload to send to the other participant during round 1. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_CREATED}. - */ - public JPAKERound1Payload createRound1PayloadToSend() - { - if (this.state >= STATE_ROUND_1_CREATED) - { - throw new IllegalStateException("Round1 payload already created for " + participantId); - } - - this.x1 = JPAKEUtil.generateX1(q, random); - this.x2 = JPAKEUtil.generateX2(q, random); - - this.gx1 = JPAKEUtil.calculateGx(p, g, x1); - this.gx2 = JPAKEUtil.calculateGx(p, g, x2); - BigInteger[] knowledgeProofForX1 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random); - BigInteger[] knowledgeProofForX2 = JPAKEUtil.calculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random); - - this.state = STATE_ROUND_1_CREATED; - - return new JPAKERound1Payload(participantId, gx1, gx2, knowledgeProofForX1, knowledgeProofForX2); - } - - /** - * Validates the payload received from the other participant during round 1. - * <p/> - * <p/> - * Must be called prior to {@link #createRound2PayloadToSend()}. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_1_VALIDATED}. - * - * @throws CryptoException if validation fails. - * @throws IllegalStateException if called multiple times. - */ - public void validateRound1PayloadReceived(JPAKERound1Payload round1PayloadReceived) - throws CryptoException - { - if (this.state >= STATE_ROUND_1_VALIDATED) - { - throw new IllegalStateException("Validation already attempted for round1 payload for" + participantId); - } - this.partnerParticipantId = round1PayloadReceived.getParticipantId(); - this.gx3 = round1PayloadReceived.getGx1(); - this.gx4 = round1PayloadReceived.getGx2(); - - BigInteger[] knowledgeProofForX3 = round1PayloadReceived.getKnowledgeProofForX1(); - BigInteger[] knowledgeProofForX4 = round1PayloadReceived.getKnowledgeProofForX2(); - - JPAKEUtil.validateParticipantIdsDiffer(participantId, round1PayloadReceived.getParticipantId()); - JPAKEUtil.validateGx4(gx4); - JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX3, round1PayloadReceived.getParticipantId(), digest); - JPAKEUtil.validateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX4, round1PayloadReceived.getParticipantId(), digest); - - this.state = STATE_ROUND_1_VALIDATED; - } - - /** - * Creates and returns the payload to send to the other participant during round 2. - * <p/> - * <p/> - * {@link #validateRound1PayloadReceived(JPAKERound1Payload)} must be called prior to this method. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_CREATED}. - * - * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times - */ - public JPAKERound2Payload createRound2PayloadToSend() - { - if (this.state >= STATE_ROUND_2_CREATED) - { - throw new IllegalStateException("Round2 payload already created for " + this.participantId); - } - if (this.state < STATE_ROUND_1_VALIDATED) - { - throw new IllegalStateException("Round1 payload must be validated prior to creating Round2 payload for " + this.participantId); - } - BigInteger gA = JPAKEUtil.calculateGA(p, gx1, gx3, gx4); - BigInteger s = JPAKEUtil.calculateS(password); - BigInteger x2s = JPAKEUtil.calculateX2s(q, x2, s); - BigInteger A = JPAKEUtil.calculateA(p, q, gA, x2s); - BigInteger[] knowledgeProofForX2s = JPAKEUtil.calculateZeroKnowledgeProof(p, q, gA, A, x2s, participantId, digest, random); - - this.state = STATE_ROUND_2_CREATED; - - return new JPAKERound2Payload(participantId, A, knowledgeProofForX2s); - } - - /** - * Validates the payload received from the other participant during round 2. - * <p/> - * <p/> - * Note that this DOES NOT detect a non-common password. - * The only indication of a non-common password is through derivation - * of different keys (which can be detected explicitly by executing round 3 and round 4) - * <p/> - * <p/> - * Must be called prior to {@link #calculateKeyingMaterial()}. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_2_VALIDATED}. - * - * @throws CryptoException if validation fails. - * @throws IllegalStateException if called prior to {@link #validateRound1PayloadReceived(JPAKERound1Payload)}, or multiple times - */ - public void validateRound2PayloadReceived(JPAKERound2Payload round2PayloadReceived) - throws CryptoException - { - if (this.state >= STATE_ROUND_2_VALIDATED) - { - throw new IllegalStateException("Validation already attempted for round2 payload for" + participantId); - } - if (this.state < STATE_ROUND_1_VALIDATED) - { - throw new IllegalStateException("Round1 payload must be validated prior to validating Round2 payload for " + this.participantId); - } - BigInteger gB = JPAKEUtil.calculateGA(p, gx3, gx1, gx2); - this.b = round2PayloadReceived.getA(); - BigInteger[] knowledgeProofForX4s = round2PayloadReceived.getKnowledgeProofForX2s(); - - JPAKEUtil.validateParticipantIdsDiffer(participantId, round2PayloadReceived.getParticipantId()); - JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round2PayloadReceived.getParticipantId()); - JPAKEUtil.validateGa(gB); - JPAKEUtil.validateZeroKnowledgeProof(p, q, gB, b, knowledgeProofForX4s, round2PayloadReceived.getParticipantId(), digest); - - this.state = STATE_ROUND_2_VALIDATED; - } - - /** - * Calculates and returns the key material. - * A session key must be derived from this key material using a secure key derivation function (KDF). - * The KDF used to derive the key is handled externally (i.e. not by {@link JPAKEParticipant}). - * <p/> - * <p/> - * The keying material will be identical for each participant if and only if - * each participant's password is the same. i.e. If the participants do not - * share the same password, then each participant will derive a different key. - * Therefore, if you immediately start using a key derived from - * the keying material, then you must handle detection of incorrect keys. - * If you want to handle this detection explicitly, you can optionally perform - * rounds 3 and 4. See {@link JPAKEParticipant} for details on how to execute - * rounds 3 and 4. - * <p/> - * <p/> - * The keying material will be in the range <tt>[0, p-1]</tt>. - * <p/> - * <p/> - * {@link #validateRound2PayloadReceived(JPAKERound2Payload)} must be called prior to this method. - * <p/> - * <p/> - * As a side effect, the internal {@link #password} array is cleared, since it is no longer needed. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_KEY_CALCULATED}. - * - * @throws IllegalStateException if called prior to {@link #validateRound2PayloadReceived(JPAKERound2Payload)}, - * or if called multiple times. - */ - public BigInteger calculateKeyingMaterial() - { - if (this.state >= STATE_KEY_CALCULATED) - { - throw new IllegalStateException("Key already calculated for " + participantId); - } - if (this.state < STATE_ROUND_2_VALIDATED) - { - throw new IllegalStateException("Round2 payload must be validated prior to creating key for " + participantId); - } - BigInteger s = JPAKEUtil.calculateS(password); - - /* - * Clear the password array from memory, since we don't need it anymore. - * - * Also set the field to null as a flag to indicate that the key has already been calculated. - */ - Arrays.fill(password, (char)0); - this.password = null; - - BigInteger keyingMaterial = JPAKEUtil.calculateKeyingMaterial(p, q, gx4, x2, s, b); - - /* - * Clear the ephemeral private key fields as well. - * Note that we're relying on the garbage collector to do its job to clean these up. - * The old objects will hang around in memory until the garbage collector destroys them. - * - * If the ephemeral private keys x1 and x2 are leaked, - * the attacker might be able to brute-force the password. - */ - this.x1 = null; - this.x2 = null; - this.b = null; - - /* - * Do not clear gx* yet, since those are needed by round 3. - */ - - this.state = STATE_KEY_CALCULATED; - - return keyingMaterial; - } - - - /** - * Creates and returns the payload to send to the other participant during round 3. - * <p/> - * <p/> - * See {@link JPAKEParticipant} for more details on round 3. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_CREATED}. - * - * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}. - * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times - */ - public JPAKERound3Payload createRound3PayloadToSend(BigInteger keyingMaterial) - { - if (this.state >= STATE_ROUND_3_CREATED) - { - throw new IllegalStateException("Round3 payload already created for " + this.participantId); - } - if (this.state < STATE_KEY_CALCULATED) - { - throw new IllegalStateException("Keying material must be calculated prior to creating Round3 payload for " + this.participantId); - } - - BigInteger macTag = JPAKEUtil.calculateMacTag( - this.participantId, - this.partnerParticipantId, - this.gx1, - this.gx2, - this.gx3, - this.gx4, - keyingMaterial, - this.digest); - - this.state = STATE_ROUND_3_CREATED; - - return new JPAKERound3Payload(participantId, macTag); - } - - /** - * Validates the payload received from the other participant during round 3. - * <p/> - * <p/> - * See {@link JPAKEParticipant} for more details on round 3. - * <p/> - * <p/> - * After execution, the {@link #getState() state} will be {@link #STATE_ROUND_3_VALIDATED}. - * - * @param keyingMaterial The keying material as returned from {@link #calculateKeyingMaterial()}. - * @throws CryptoException if validation fails. - * @throws IllegalStateException if called prior to {@link #calculateKeyingMaterial()}, or multiple times - */ - public void validateRound3PayloadReceived(JPAKERound3Payload round3PayloadReceived, BigInteger keyingMaterial) - throws CryptoException - { - if (this.state >= STATE_ROUND_3_VALIDATED) - { - throw new IllegalStateException("Validation already attempted for round3 payload for" + participantId); - } - if (this.state < STATE_KEY_CALCULATED) - { - throw new IllegalStateException("Keying material must be calculated validated prior to validating Round3 payload for " + this.participantId); - } - JPAKEUtil.validateParticipantIdsDiffer(participantId, round3PayloadReceived.getParticipantId()); - JPAKEUtil.validateParticipantIdsEqual(this.partnerParticipantId, round3PayloadReceived.getParticipantId()); - - JPAKEUtil.validateMacTag( - this.participantId, - this.partnerParticipantId, - this.gx1, - this.gx2, - this.gx3, - this.gx4, - keyingMaterial, - this.digest, - round3PayloadReceived.getMacTag()); - - - /* - * Clear the rest of the fields. - */ - this.gx1 = null; - this.gx2 = null; - this.gx3 = null; - this.gx4 = null; - - this.state = STATE_ROUND_3_VALIDATED; - } - -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java deleted file mode 100644 index 5a2f4022..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/agreement/jpake/JPAKEPrimeOrderGroup.java +++ /dev/null @@ -1,122 +0,0 @@ -package org.bouncycastle.crypto.agreement.jpake; - -import java.math.BigInteger; - -/** - * A pre-computed prime order group for use during a J-PAKE exchange. - * <p/> - * <p/> - * Typically a Schnorr group is used. In general, J-PAKE can use any prime order group - * that is suitable for public key cryptography, including elliptic curve cryptography. - * <p/> - * <p/> - * See {@link JPAKEPrimeOrderGroups} for convenient standard groups. - * <p/> - * <p/> - * NIST <a href="http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/DSA2_All.pdf">publishes</a> - * many groups that can be used for the desired level of security. - */ -public class JPAKEPrimeOrderGroup -{ - private BigInteger p; - private BigInteger q; - private BigInteger g; - - /** - * Constructs a new {@link JPAKEPrimeOrderGroup}. - * <p/> - * <p/> - * In general, you should use one of the pre-approved groups from - * {@link JPAKEPrimeOrderGroups}, rather than manually constructing one. - * <p/> - * <p/> - * The following basic checks are performed: - * <ul> - * <li>p-1 must be evenly divisible by q</li> - * <li>g must be in [2, p-1]</li> - * <li>g^q mod p must equal 1</li> - * <li>p must be prime (within reasonably certainty)</li> - * <li>q must be prime (within reasonably certainty)</li> - * </ul> - * <p/> - * <p/> - * The prime checks are performed using {@link BigInteger#isProbablePrime(int)}, - * and are therefore subject to the same probability guarantees. - * <p/> - * <p/> - * These checks prevent trivial mistakes. - * However, due to the small uncertainties if p and q are not prime, - * advanced attacks are not prevented. - * Use it at your own risk. - * - * @throws NullPointerException if any argument is null - * @throws IllegalArgumentException if any of the above validations fail - */ - public JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g) - { - /* - * Don't skip the checks on user-specified groups. - */ - this(p, q, g, false); - } - - /** - * Internal package-private constructor used by the pre-approved - * groups in {@link JPAKEPrimeOrderGroups}. - * These pre-approved groups can avoid the expensive checks. - */ - JPAKEPrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, boolean skipChecks) - { - JPAKEUtil.validateNotNull(p, "p"); - JPAKEUtil.validateNotNull(q, "q"); - JPAKEUtil.validateNotNull(g, "g"); - - if (!skipChecks) - { - if (!p.subtract(JPAKEUtil.ONE).mod(q).equals(JPAKEUtil.ZERO)) - { - throw new IllegalArgumentException("p-1 must be evenly divisible by q"); - } - if (g.compareTo(BigInteger.valueOf(2)) == -1 || g.compareTo(p.subtract(JPAKEUtil.ONE)) == 1) - { - throw new IllegalArgumentException("g must be in [2, p-1]"); - } - if (!g.modPow(q, p).equals(JPAKEUtil.ONE)) - { - throw new IllegalArgumentException("g^q mod p must equal 1"); - } - /* - * Note that these checks do not guarantee that p and q are prime. - * We just have reasonable certainty that they are prime. - */ - if (!p.isProbablePrime(20)) - { - throw new IllegalArgumentException("p must be prime"); - } - if (!q.isProbablePrime(20)) - { - throw new IllegalArgumentException("q must be prime"); - } - } - - this.p = p; - this.q = q; - this.g = g; - } - - public BigInteger getP() - { - return p; - } - - public BigInteger getQ() - { - return q; - } - - public BigInteger getG() - { - return g; - } - -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java deleted file mode 100644 index 5bfee7e6..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/digests/SkeinEngine.java +++ /dev/null @@ -1,817 +0,0 @@ -package org.bouncycastle.crypto.digests; - -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import org.bouncycastle.crypto.DataLengthException; -import org.bouncycastle.crypto.engines.ThreefishEngine; -import org.bouncycastle.crypto.macs.SkeinMac; -import org.bouncycastle.crypto.params.SkeinParameters; -import org.bouncycastle.util.Arrays; -import org.bouncycastle.util.Memoable; - -/** - * Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block - * sizes, based on the {@link ThreefishEngine Threefish} tweakable block cipher. - * <p/> - * This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3 - * competition in October 2010. - * <p/> - * Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir - * Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker. - * <p/> - * This implementation is the basis for {@link SkeinDigest} and {@link SkeinMac}, implementing the - * parameter based configuration system that allows Skein to be adapted to multiple applications. <br> - * Initialising the engine with {@link SkeinParameters} allows standard and arbitrary parameters to - * be applied during the Skein hash function. - * <p/> - * Implemented: - * <ul> - * <li>256, 512 and 1024 bit internal states.</li> - * <li>Full 96 bit input length.</li> - * <li>Parameters defined in the Skein specification, and arbitrary other pre and post message - * parameters.</li> - * <li>Arbitrary output size in 1 byte intervals.</li> - * </ul> - * <p/> - * Not implemented: - * <ul> - * <li>Sub-byte length input (bit padding).</li> - * <li>Tree hashing.</li> - * </ul> - * - * @see SkeinParameters - */ -public class SkeinEngine - implements Memoable -{ - /** - * 256 bit block size - Skein 256 - */ - public static final int SKEIN_256 = ThreefishEngine.BLOCKSIZE_256; - /** - * 512 bit block size - Skein 512 - */ - public static final int SKEIN_512 = ThreefishEngine.BLOCKSIZE_512; - /** - * 1024 bit block size - Skein 1024 - */ - public static final int SKEIN_1024 = ThreefishEngine.BLOCKSIZE_1024; - - // Minimal at present, but more complex when tree hashing is implemented - private static class Configuration - { - private byte[] bytes = new byte[32]; - - public Configuration(long outputSizeBits) - { - // 0..3 = ASCII SHA3 - bytes[0] = (byte)'S'; - bytes[1] = (byte)'H'; - bytes[2] = (byte)'A'; - bytes[3] = (byte)'3'; - - // 4..5 = version number in LSB order - bytes[4] = 1; - bytes[5] = 0; - - // 8..15 = output length - ThreefishEngine.wordToBytes(outputSizeBits, bytes, 8); - } - - public byte[] getBytes() - { - return bytes; - } - - } - - public static class Parameter - { - private int type; - private byte[] value; - - public Parameter(int type, byte[] value) - { - this.type = type; - this.value = value; - } - - public int getType() - { - return type; - } - - public byte[] getValue() - { - return value; - } - - } - - /** - * The parameter type for the Skein key. - */ - private static final int PARAM_TYPE_KEY = 0; - - /** - * The parameter type for the Skein configuration block. - */ - private static final int PARAM_TYPE_CONFIG = 4; - - /** - * The parameter type for the message. - */ - private static final int PARAM_TYPE_MESSAGE = 48; - - /** - * The parameter type for the output transformation. - */ - private static final int PARAM_TYPE_OUTPUT = 63; - - /** - * Precalculated UBI(CFG) states for common state/output combinations without key or other - * pre-message params. - */ - private static final Hashtable INITIAL_STATES = new Hashtable(); - - static - { - // From Appendix C of the Skein 1.3 NIST submission - initialState(SKEIN_256, 128, new long[]{ - 0xe1111906964d7260L, - 0x883daaa77c8d811cL, - 0x10080df491960f7aL, - 0xccf7dde5b45bc1c2L}); - - initialState(SKEIN_256, 160, new long[]{ - 0x1420231472825e98L, - 0x2ac4e9a25a77e590L, - 0xd47a58568838d63eL, - 0x2dd2e4968586ab7dL}); - - initialState(SKEIN_256, 224, new long[]{ - 0xc6098a8c9ae5ea0bL, - 0x876d568608c5191cL, - 0x99cb88d7d7f53884L, - 0x384bddb1aeddb5deL}); - - initialState(SKEIN_256, 256, new long[]{ - 0xfc9da860d048b449L, - 0x2fca66479fa7d833L, - 0xb33bc3896656840fL, - 0x6a54e920fde8da69L}); - - initialState(SKEIN_512, 128, new long[]{ - 0xa8bc7bf36fbf9f52L, - 0x1e9872cebd1af0aaL, - 0x309b1790b32190d3L, - 0xbcfbb8543f94805cL, - 0x0da61bcd6e31b11bL, - 0x1a18ebead46a32e3L, - 0xa2cc5b18ce84aa82L, - 0x6982ab289d46982dL}); - - initialState(SKEIN_512, 160, new long[]{ - 0x28b81a2ae013bd91L, - 0xc2f11668b5bdf78fL, - 0x1760d8f3f6a56f12L, - 0x4fb747588239904fL, - 0x21ede07f7eaf5056L, - 0xd908922e63ed70b8L, - 0xb8ec76ffeccb52faL, - 0x01a47bb8a3f27a6eL}); - - initialState(SKEIN_512, 224, new long[]{ - 0xccd0616248677224L, - 0xcba65cf3a92339efL, - 0x8ccd69d652ff4b64L, - 0x398aed7b3ab890b4L, - 0x0f59d1b1457d2bd0L, - 0x6776fe6575d4eb3dL, - 0x99fbc70e997413e9L, - 0x9e2cfccfe1c41ef7L}); - - initialState(SKEIN_512, 384, new long[]{ - 0xa3f6c6bf3a75ef5fL, - 0xb0fef9ccfd84faa4L, - 0x9d77dd663d770cfeL, - 0xd798cbf3b468fddaL, - 0x1bc4a6668a0e4465L, - 0x7ed7d434e5807407L, - 0x548fc1acd4ec44d6L, - 0x266e17546aa18ff8L}); - - initialState(SKEIN_512, 512, new long[]{ - 0x4903adff749c51ceL, - 0x0d95de399746df03L, - 0x8fd1934127c79bceL, - 0x9a255629ff352cb1L, - 0x5db62599df6ca7b0L, - 0xeabe394ca9d5c3f4L, - 0x991112c71a75b523L, - 0xae18a40b660fcc33L}); - } - - private static void initialState(int blockSize, int outputSize, long[] state) - { - INITIAL_STATES.put(variantIdentifier(blockSize / 8, outputSize / 8), state); - } - - private static Integer variantIdentifier(int blockSizeBytes, int outputSizeBytes) - { - return new Integer((outputSizeBytes << 16) | blockSizeBytes); - } - - private static class UbiTweak - { - /** - * Point at which position might overflow long, so switch to add with carry logic - */ - private static final long LOW_RANGE = Long.MAX_VALUE - Integer.MAX_VALUE; - - /** - * Bit 127 = final - */ - private static final long T1_FINAL = 1L << 63; - - /** - * Bit 126 = first - */ - private static final long T1_FIRST = 1L << 62; - - /** - * UBI uses a 128 bit tweak - */ - private long tweak[] = new long[2]; - - /** - * Whether 64 bit position exceeded - */ - private boolean extendedPosition; - - public UbiTweak() - { - reset(); - } - - public void reset(UbiTweak tweak) - { - this.tweak = Arrays.clone(tweak.tweak, this.tweak); - this.extendedPosition = tweak.extendedPosition; - } - - public void reset() - { - tweak[0] = 0; - tweak[1] = 0; - extendedPosition = false; - setFirst(true); - } - - public void setType(int type) - { - // Bits 120..125 = type - tweak[1] = (tweak[1] & 0xFFFFFFC000000000L) | ((type & 0x3FL) << 56); - } - - public int getType() - { - return (int)((tweak[1] >>> 56) & 0x3FL); - } - - public void setFirst(boolean first) - { - if (first) - { - tweak[1] |= T1_FIRST; - } - else - { - tweak[1] &= ~T1_FIRST; - } - } - - public boolean isFirst() - { - return ((tweak[1] & T1_FIRST) != 0); - } - - public void setFinal(boolean last) - { - if (last) - { - tweak[1] |= T1_FINAL; - } - else - { - tweak[1] &= ~T1_FINAL; - } - } - - public boolean isFinal() - { - return ((tweak[1] & T1_FINAL) != 0); - } - - /** - * Advances the position in the tweak by the specified value. - */ - public void advancePosition(int advance) - { - // Bits 0..95 = position - if (extendedPosition) - { - long[] parts = new long[3]; - parts[0] = tweak[0] & 0xFFFFFFFFL; - parts[1] = (tweak[0] >>> 32) & 0xFFFFFFFFL; - parts[2] = tweak[1] & 0xFFFFFFFFL; - - long carry = advance; - for (int i = 0; i < parts.length; i++) - { - carry += parts[i]; - parts[i] = carry; - carry >>>= 32; - } - tweak[0] = ((parts[1] & 0xFFFFFFFFL) << 32) | (parts[0] & 0xFFFFFFFFL); - tweak[1] = (tweak[1] & 0xFFFFFFFF00000000L) | (parts[2] & 0xFFFFFFFFL); - } - else - { - long position = tweak[0]; - position += advance; - tweak[0] = position; - if (position > LOW_RANGE) - { - extendedPosition = true; - } - } - } - - public long[] getWords() - { - return tweak; - } - - public String toString() - { - return getType() + " first: " + isFirst() + ", final: " + isFinal(); - } - - } - - /** - * The Unique Block Iteration chaining mode. - */ - // TODO: This might be better as methods... - private class UBI - { - private final UbiTweak tweak = new UbiTweak(); - - /** - * Buffer for the current block of message data - */ - private byte[] currentBlock; - - /** - * Offset into the current message block - */ - private int currentOffset; - - /** - * Buffer for message words for feedback into encrypted block - */ - private long[] message; - - public UBI(int blockSize) - { - currentBlock = new byte[blockSize]; - message = new long[currentBlock.length / 8]; - } - - public void reset(UBI ubi) - { - currentBlock = Arrays.clone(ubi.currentBlock, currentBlock); - currentOffset = ubi.currentOffset; - message = Arrays.clone(ubi.message, this.message); - tweak.reset(ubi.tweak); - } - - public void reset(int type) - { - tweak.reset(); - tweak.setType(type); - currentOffset = 0; - } - - public void update(byte[] value, int offset, int len, long[] output) - { - /* - * Buffer complete blocks for the underlying Threefish cipher, only flushing when there - * are subsequent bytes (last block must be processed in doFinal() with final=true set). - */ - int copied = 0; - while (len > copied) - { - if (currentOffset == currentBlock.length) - { - processBlock(output); - tweak.setFirst(false); - currentOffset = 0; - } - - int toCopy = Math.min((len - copied), currentBlock.length - currentOffset); - System.arraycopy(value, offset + copied, currentBlock, currentOffset, toCopy); - copied += toCopy; - currentOffset += toCopy; - tweak.advancePosition(toCopy); - } - } - - private void processBlock(long[] output) - { - threefish.init(true, chain, tweak.getWords()); - for (int i = 0; i < message.length; i++) - { - message[i] = ThreefishEngine.bytesToWord(currentBlock, i * 8); - } - - threefish.processBlock(message, output); - - for (int i = 0; i < output.length; i++) - { - output[i] ^= message[i]; - } - } - - public void doFinal(long[] output) - { - // Pad remainder of current block with zeroes - for (int i = currentOffset; i < currentBlock.length; i++) - { - currentBlock[i] = 0; - } - - tweak.setFinal(true); - processBlock(output); - } - - } - - /** - * Underlying Threefish tweakable block cipher - */ - private ThreefishEngine threefish; - - /** - * Size of the digest output, in bytes - */ - private int outputSizeBytes; - - /** - * The current chaining/state value - */ - long[] chain; - - /** - * The initial state value - */ - private long[] initialState; - - /** - * The (optional) key parameter - */ - private byte[] key; - - /** - * Parameters to apply prior to the message - */ - private Parameter[] preMessageParameters; - - /** - * Parameters to apply after the message, but prior to output - */ - private Parameter[] postMessageParameters; - - /** - * The current UBI operation - */ - private UBI ubi; - - /** - * Buffer for single byte update method - */ - private final byte[] singleByte = new byte[1]; - - /** - * Constructs a Skein engine. - * - * @param blockSizeBits the internal state size in bits - one of {@link #SKEIN_256}, {@link #SKEIN_512} or - * {@link #SKEIN_1024}. - * @param outputSizeBits the output/digest size to produce in bits, which must be an integral number of - * bytes. - */ - public SkeinEngine(int blockSizeBits, int outputSizeBits) - { - if (outputSizeBits % 8 != 0) - { - throw new IllegalArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits); - } - // TODO: Prevent digest sizes > block size? - this.outputSizeBytes = outputSizeBits / 8; - - this.threefish = new ThreefishEngine(blockSizeBits); - this.ubi = new UBI(threefish.getBlockSize()); - } - - /** - * Creates a SkeinEngine as an exact copy of an existing instance. - */ - public SkeinEngine(SkeinEngine engine) - { - this(engine.getBlockSize() * 8, engine.getOutputSize() * 8); - copyIn(engine); - } - - private void copyIn(SkeinEngine engine) - { - this.ubi.reset(engine.ubi); - this.chain = Arrays.clone(engine.chain, this.chain); - this.initialState = Arrays.clone(engine.initialState, this.initialState); - this.key = Arrays.clone(engine.key, this.key); - this.preMessageParameters = clone(engine.preMessageParameters, this.preMessageParameters); - this.postMessageParameters = clone(engine.postMessageParameters, this.postMessageParameters); - } - - private static Parameter[] clone(Parameter[] data, Parameter[] existing) - { - if (data == null) - { - return null; - } - if ((existing == null) || (existing.length != data.length)) - { - existing = new Parameter[data.length]; - } - System.arraycopy(data, 0, existing, 0, existing.length); - return existing; - } - - public Memoable copy() - { - return new SkeinEngine(this); - } - - public void reset(Memoable other) - { - SkeinEngine s = (SkeinEngine)other; - if ((getBlockSize() != s.getBlockSize()) || (outputSizeBytes != s.outputSizeBytes)) - { - throw new IllegalArgumentException("Incompatible parameters in provided SkeinEngine."); - } - copyIn(s); - } - - public int getOutputSize() - { - return outputSizeBytes; - } - - public int getBlockSize() - { - return threefish.getBlockSize(); - } - - /** - * Initialises the Skein engine with the provided parameters. See {@link SkeinParameters} for - * details on the parameterisation of the Skein hash function. - * - * @param params the parameters to apply to this engine, or <code>null</code> to use no parameters. - */ - public void init(SkeinParameters params) - { - this.chain = null; - this.key = null; - this.preMessageParameters = null; - this.postMessageParameters = null; - - if (params != null) - { - byte[] key = params.getKey(); - if (key.length < 16) - { - throw new IllegalArgumentException("Skein key must be at least 128 bits."); - } - initParams(params.getParameters()); - } - createInitialState(); - - // Initialise message block - ubiInit(PARAM_TYPE_MESSAGE); - } - - private void initParams(Hashtable parameters) - { - Enumeration keys = parameters.keys(); - final Vector pre = new Vector(); - final Vector post = new Vector(); - - while (keys.hasMoreElements()) - { - Integer type = (Integer)keys.nextElement(); - byte[] value = (byte[])parameters.get(type); - - if (type.intValue() == PARAM_TYPE_KEY) - { - this.key = value; - } - else if (type.intValue() < PARAM_TYPE_MESSAGE) - { - pre.addElement(new Parameter(type.intValue(), value)); - } - else - { - post.addElement(new Parameter(type.intValue(), value)); - } - } - preMessageParameters = new Parameter[pre.size()]; - pre.copyInto(preMessageParameters); - sort(preMessageParameters); - - postMessageParameters = new Parameter[post.size()]; - post.copyInto(postMessageParameters); - sort(postMessageParameters); - } - - private static void sort(Parameter[] params) - { - if (params == null) - { - return; - } - // Insertion sort, for Java 1.1 compatibility - for (int i = 1; i < params.length; i++) - { - Parameter param = params[i]; - int hole = i; - while (hole > 0 && param.getType() < params[hole - 1].getType()) - { - params[hole] = params[hole - 1]; - hole = hole - 1; - } - params[hole] = param; - } - } - - /** - * Calculate the initial (pre message block) chaining state. - */ - private void createInitialState() - { - long[] precalc = (long[])INITIAL_STATES.get(variantIdentifier(getBlockSize(), getOutputSize())); - if ((key == null) && (precalc != null)) - { - // Precalculated UBI(CFG) - chain = Arrays.clone(precalc); - } - else - { - // Blank initial state - chain = new long[getBlockSize() / 8]; - - // Process key block - if (key != null) - { - ubiComplete(SkeinParameters.PARAM_TYPE_KEY, key); - } - - // Process configuration block - ubiComplete(PARAM_TYPE_CONFIG, new Configuration(outputSizeBytes * 8).getBytes()); - } - - // Process additional pre-message parameters - if (preMessageParameters != null) - { - for (int i = 0; i < preMessageParameters.length; i++) - { - Parameter param = preMessageParameters[i]; - ubiComplete(param.getType(), param.getValue()); - } - } - initialState = Arrays.clone(chain); - } - - /** - * Reset the engine to the initial state (with the key and any pre-message parameters , ready to - * accept message input. - */ - public void reset() - { - System.arraycopy(initialState, 0, chain, 0, chain.length); - - ubiInit(PARAM_TYPE_MESSAGE); - } - - private void ubiComplete(int type, byte[] value) - { - ubiInit(type); - this.ubi.update(value, 0, value.length, chain); - ubiFinal(); - } - - private void ubiInit(int type) - { - this.ubi.reset(type); - } - - private void ubiFinal() - { - ubi.doFinal(chain); - } - - private void checkInitialised() - { - if (this.ubi == null) - { - throw new IllegalArgumentException("Skein engine is not initialised."); - } - } - - public void update(byte in) - { - singleByte[0] = in; - update(singleByte, 0, 1); - } - - public void update(byte[] in, int inOff, int len) - { - checkInitialised(); - ubi.update(in, inOff, len, chain); - } - - public int doFinal(byte[] out, int outOff) - { - checkInitialised(); - if (out.length < (outOff + outputSizeBytes)) - { - throw new DataLengthException("Output buffer is too short to hold output of " + outputSizeBytes + " bytes"); - } - - // Finalise message block - ubiFinal(); - - // Process additional post-message parameters - if (postMessageParameters != null) - { - for (int i = 0; i < postMessageParameters.length; i++) - { - Parameter param = postMessageParameters[i]; - ubiComplete(param.getType(), param.getValue()); - } - } - - // Perform the output transform - final int blockSize = getBlockSize(); - final int blocksRequired = ((outputSizeBytes + blockSize - 1) / blockSize); - for (int i = 0; i < blocksRequired; i++) - { - final int toWrite = Math.min(blockSize, outputSizeBytes - (i * blockSize)); - output(i, out, outOff + (i * blockSize), toWrite); - } - - reset(); - - return outputSizeBytes; - } - - private void output(long outputSequence, byte[] out, int outOff, int outputBytes) - { - byte[] currentBytes = new byte[8]; - ThreefishEngine.wordToBytes(outputSequence, currentBytes, 0); - - // Output is a sequence of UBI invocations all of which use and preserve the pre-output - // state - long[] outputWords = new long[chain.length]; - ubiInit(PARAM_TYPE_OUTPUT); - this.ubi.update(currentBytes, 0, currentBytes.length, outputWords); - ubi.doFinal(outputWords); - - final int wordsRequired = ((outputBytes + 8 - 1) / 8); - for (int i = 0; i < wordsRequired; i++) - { - int toWrite = Math.min(8, outputBytes - (i * 8)); - if (toWrite == 8) - { - ThreefishEngine.wordToBytes(outputWords[i], out, outOff + (i * 8)); - } - else - { - ThreefishEngine.wordToBytes(outputWords[i], currentBytes, 0); - System.arraycopy(currentBytes, 0, out, outOff + (i * 8), toWrite); - } - } - } - -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java deleted file mode 100644 index 76051c3f..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/encodings/PKCS1Encoding.java +++ /dev/null @@ -1,410 +0,0 @@ -package org.bouncycastle.crypto.encodings; - -import java.security.SecureRandom; - -import org.bouncycastle.crypto.AsymmetricBlockCipher; -import org.bouncycastle.crypto.CipherParameters; -import org.bouncycastle.crypto.InvalidCipherTextException; -import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.crypto.params.ParametersWithRandom; - -/** - * this does your basic PKCS 1 v1.5 padding - whether or not you should be using this - * depends on your application - see PKCS1 Version 2 for details. - */ -public class PKCS1Encoding - implements AsymmetricBlockCipher -{ - /** - * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to - * work with one of these set the system property org.bouncycastle.pkcs1.strict to false. - * <p> - * The system property is checked during construction of the encoding object, it is set to - * true by default. - * </p> - */ - public static final String STRICT_LENGTH_ENABLED_PROPERTY = "org.bouncycastle.pkcs1.strict"; - - private static final int HEADER_LENGTH = 10; - - private SecureRandom random; - private AsymmetricBlockCipher engine; - private boolean forEncryption; - private boolean forPrivateKey; - private boolean useStrictLength; - private int pLen = -1; - private byte[] fallback = null; - - /** - * Basic constructor. - * @param cipher - */ - public PKCS1Encoding( - AsymmetricBlockCipher cipher) - { - this.engine = cipher; - this.useStrictLength = useStrict(); - } - - /** - * Constructor for decryption with a fixed plaintext length. - * - * @param cipher The cipher to use for cryptographic operation. - * @param pLen Length of the expected plaintext. - */ - public PKCS1Encoding( - AsymmetricBlockCipher cipher, - int pLen) - { - this.engine = cipher; - this.useStrictLength = useStrict(); - this.pLen = pLen; - } - - /** - * Constructor for decryption with a fixed plaintext length and a fallback - * value that is returned, if the padding is incorrect. - * - * @param cipher - * The cipher to use for cryptographic operation. - * @param fallback - * The fallback value, we don't to a arraycopy here. - */ - public PKCS1Encoding( - AsymmetricBlockCipher cipher, - byte[] fallback) - { - this.engine = cipher; - this.useStrictLength = useStrict(); - this.fallback = fallback; - this.pLen = fallback.length; - } - - - - // - // for J2ME compatibility - // - private boolean useStrict() - { - // required if security manager has been installed. - String strict = System.getProperty(STRICT_LENGTH_ENABLED_PROPERTY); - - return strict == null || strict.equals("true"); - } - - public AsymmetricBlockCipher getUnderlyingCipher() - { - return engine; - } - - public void init( - boolean forEncryption, - CipherParameters param) - { - AsymmetricKeyParameter kParam; - - if (param instanceof ParametersWithRandom) - { - ParametersWithRandom rParam = (ParametersWithRandom)param; - - this.random = rParam.getRandom(); - kParam = (AsymmetricKeyParameter)rParam.getParameters(); - } - else - { - this.random = new SecureRandom(); - kParam = (AsymmetricKeyParameter)param; - } - - engine.init(forEncryption, param); - - this.forPrivateKey = kParam.isPrivate(); - this.forEncryption = forEncryption; - } - - public int getInputBlockSize() - { - int baseBlockSize = engine.getInputBlockSize(); - - if (forEncryption) - { - return baseBlockSize - HEADER_LENGTH; - } - else - { - return baseBlockSize; - } - } - - public int getOutputBlockSize() - { - int baseBlockSize = engine.getOutputBlockSize(); - - if (forEncryption) - { - return baseBlockSize; - } - else - { - return baseBlockSize - HEADER_LENGTH; - } - } - - public byte[] processBlock( - byte[] in, - int inOff, - int inLen) - throws InvalidCipherTextException - { - if (forEncryption) - { - return encodeBlock(in, inOff, inLen); - } - else - { - return decodeBlock(in, inOff, inLen); - } - } - - private byte[] encodeBlock( - byte[] in, - int inOff, - int inLen) - throws InvalidCipherTextException - { - if (inLen > getInputBlockSize()) - { - throw new IllegalArgumentException("input data too large"); - } - - byte[] block = new byte[engine.getInputBlockSize()]; - - if (forPrivateKey) - { - block[0] = 0x01; // type code 1 - - for (int i = 1; i != block.length - inLen - 1; i++) - { - block[i] = (byte)0xFF; - } - } - else - { - random.nextBytes(block); // random fill - - block[0] = 0x02; // type code 2 - - // - // a zero byte marks the end of the padding, so all - // the pad bytes must be non-zero. - // - for (int i = 1; i != block.length - inLen - 1; i++) - { - while (block[i] == 0) - { - block[i] = (byte)random.nextInt(); - } - } - } - - block[block.length - inLen - 1] = 0x00; // mark the end of the padding - System.arraycopy(in, inOff, block, block.length - inLen, inLen); - - return engine.processBlock(block, 0, block.length); - } - - /** - * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext - * for encryption. - * - * @param encoded The Plaintext. - * @param pLen Expected length of the plaintext. - * @return Either 0, if the encoding is correct, or -1, if it is incorrect. - */ - private static int checkPkcs1Encoding(byte[] encoded, int pLen) { - int correct = 0; - /* - * Check if the first two bytes are 0 2 - */ - correct |= (encoded[0] ^ 2); - - /* - * Now the padding check, check for no 0 byte in the padding - */ - int plen = encoded.length - ( - pLen /* Lenght of the PMS */ - + 1 /* Final 0-byte before PMS */ - ); - - for (int i = 1; i < plen; i++) { - int tmp = encoded[i]; - tmp |= tmp >> 1; - tmp |= tmp >> 2; - tmp |= tmp >> 4; - correct |= (tmp & 1) - 1; - } - - /* - * Make sure the padding ends with a 0 byte. - */ - correct |= encoded[encoded.length - (pLen +1)]; - - /* - * Return 0 or 1, depending on the result. - */ - correct |= correct >> 1; - correct |= correct >> 2; - correct |= correct >> 4; - return ~((correct & 1) - 1); - } - - - /** - * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct. - * - * @param in The encrypted block. - * @param inOff Offset in the encrypted block. - * @param inLen Length of the encrypted block. - * //@param pLen Length of the desired output. - * @return The plaintext without padding, or a random value if the padding was incorrect. - * - * @throws InvalidCipherTextException - */ - private byte[] decodeBlockOrRandom(byte[] in, int inOff, int inLen) - throws InvalidCipherTextException - { - if (!forPrivateKey) - { - throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing"); - } - - byte[] block = engine.processBlock(in, inOff, inLen); - byte[] random = null; - if (this.fallback == null) - { - random = new byte[this.pLen]; - this.random.nextBytes(random); - } - else - { - random = fallback; - } - - /* - * TODO: This is a potential dangerous side channel. However, you can - * fix this by changing the RSA engine in a way, that it will always - * return blocks of the same length and prepend them with 0 bytes if - * needed. - */ - if (block.length < getOutputBlockSize()) - { - throw new InvalidCipherTextException("block truncated"); - } - - /* - * TODO: Potential side channel. Fix it by making the engine always - * return blocks of the correct length. - */ - if (useStrictLength && block.length != engine.getOutputBlockSize()) - { - throw new InvalidCipherTextException("block incorrect size"); - } - - /* - * Check the padding. - */ - int correct = PKCS1Encoding.checkPkcs1Encoding(block, this.pLen); - - /* - * Now, to a constant time constant memory copy of the decrypted value - * or the random value, depending on the validity of the padding. - */ - byte[] result = new byte[this.pLen]; - for (int i = 0; i < this.pLen; i++) - { - result[i] = (byte)((block[i + (block.length - pLen)] & (~correct)) | (random[i] & correct)); - } - - return result; - } - - /** - * @exception InvalidCipherTextException if the decrypted block is not in PKCS1 format. - */ - private byte[] decodeBlock( - byte[] in, - int inOff, - int inLen) - throws InvalidCipherTextException - { - /* - * If the length of the expected plaintext is known, we use a constant-time decryption. - * If the decryption fails, we return a random value. - */ - if (this.pLen != -1) { - return this.decodeBlockOrRandom(in, inOff, inLen); - } - - byte[] block = engine.processBlock(in, inOff, inLen); - - if (block.length < getOutputBlockSize()) - { - throw new InvalidCipherTextException("block truncated"); - } - - byte type = block[0]; - - if (forPrivateKey) - { - if (type != 2) - { - throw new InvalidCipherTextException("unknown block type"); - } - } - else - { - if (type != 1) - { - throw new InvalidCipherTextException("unknown block type"); - } - } - - if (useStrictLength && block.length != engine.getOutputBlockSize()) - { - throw new InvalidCipherTextException("block incorrect size"); - } - - // - // find and extract the message block. - // - int start; - - for (start = 1; start != block.length; start++) - { - byte pad = block[start]; - - if (pad == 0) - { - break; - } - if (type == 1 && pad != (byte)0xff) - { - throw new InvalidCipherTextException("block padding incorrect"); - } - } - - start++; // data should start at the next byte - - if (start > block.length || start < HEADER_LENGTH) - { - throw new InvalidCipherTextException("no data in block"); - } - - byte[] result = new byte[block.length - start]; - - System.arraycopy(block, start, result, 0, result.length); - - return result; - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java deleted file mode 100644 index b5c74512..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/engines/NullEngine.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.bouncycastle.crypto.engines; - -import org.bouncycastle.crypto.BlockCipher; -import org.bouncycastle.crypto.CipherParameters; -import org.bouncycastle.crypto.DataLengthException; -import org.bouncycastle.crypto.OutputLengthException; - -/** - * The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting. - * Provided for the sake of completeness. - */ -public class NullEngine implements BlockCipher -{ - private boolean initialised; - protected static final int DEFAULT_BLOCK_SIZE = 1; - private int blockSize; - - /** - * Constructs a null engine with a block size of 1 byte. - */ - public NullEngine() - { - this(DEFAULT_BLOCK_SIZE); - } - - /** - * Constructs a null engine with a specific block size. - * - * @param blockSize the block size in bytes. - */ - public NullEngine(int blockSize) - { - this.blockSize = blockSize; - } - - /* (non-Javadoc) - * @see org.bouncycastle.crypto.BlockCipher#init(boolean, org.bouncycastle.crypto.CipherParameters) - */ - public void init(boolean forEncryption, CipherParameters params) throws IllegalArgumentException - { - // we don't mind any parameters that may come in - this.initialised = true; - } - - /* (non-Javadoc) - * @see org.bouncycastle.crypto.BlockCipher#getAlgorithmName() - */ - public String getAlgorithmName() - { - return "Null"; - } - - /* (non-Javadoc) - * @see org.bouncycastle.crypto.BlockCipher#getBlockSize() - */ - public int getBlockSize() - { - return blockSize; - } - - /* (non-Javadoc) - * @see org.bouncycastle.crypto.BlockCipher#processBlock(byte[], int, byte[], int) - */ - public int processBlock(byte[] in, int inOff, byte[] out, int outOff) - throws DataLengthException, IllegalStateException - { - if (!initialised) - { - throw new IllegalStateException("Null engine not initialised"); - } - if ((inOff + blockSize) > in.length) - { - throw new DataLengthException("input buffer too short"); - } - - if ((outOff + blockSize) > out.length) - { - throw new OutputLengthException("output buffer too short"); - } - - for (int i = 0; i < blockSize; ++i) - { - out[outOff + i] = in[inOff + i]; - } - - return blockSize; - } - - /* (non-Javadoc) - * @see org.bouncycastle.crypto.BlockCipher#reset() - */ - public void reset() - { - // nothing needs to be done - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java deleted file mode 100644 index 3cbe9182..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/DSAParameterGenerationParameters.java +++ /dev/null @@ -1,80 +0,0 @@ -package org.bouncycastle.crypto.params; - -import java.security.SecureRandom; - -public class DSAParameterGenerationParameters -{ - public static final int DIGITAL_SIGNATURE_USAGE = 1; - public static final int KEY_ESTABLISHMENT_USAGE = 2; - - private int l; - private int n; - private int usageIndex; - private int certainty; - private SecureRandom random; - - /** - * Construct without a usage index, this will do a random construction of G. - * - * @param L desired length of prime P in bits (the effective key size). - * @param N desired length of prime Q in bits. - * @param certainty certainty level for prime number generation. - * @param random the source of randomness to use. - */ - public DSAParameterGenerationParameters( - int L, - int N, - int certainty, - SecureRandom random) - { - this(L, N, certainty, random, -1); - } - - /** - * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G. - * - * @param L desired length of prime P in bits (the effective key size). - * @param N desired length of prime Q in bits. - * @param certainty certainty level for prime number generation. - * @param random the source of randomness to use. - * @param usageIndex a valid usage index. - */ - public DSAParameterGenerationParameters( - int L, - int N, - int certainty, - SecureRandom random, - int usageIndex) - { - this.l = L; - this.n = N; - this.certainty = certainty; - this.usageIndex = usageIndex; - this.random = random; - } - - public int getL() - { - return l; - } - - public int getN() - { - return n; - } - - public int getCertainty() - { - return certainty; - } - - public SecureRandom getRandom() - { - return random; - } - - public int getUsageIndex() - { - return usageIndex; - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java deleted file mode 100644 index 0f41955a..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/params/HKDFParameters.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.bouncycastle.crypto.params; - -import org.bouncycastle.crypto.DerivationParameters; -import org.bouncycastle.util.Arrays; - -/** - * Parameter class for the HKDFBytesGenerator class. - */ -public class HKDFParameters - implements DerivationParameters -{ - private byte[] ikm; - private boolean skipExpand; - private byte[] salt; - private byte[] info; - - private HKDFParameters(final byte[] ikm, final boolean skip, - final byte[] salt, final byte[] info) - { - if (ikm == null) - { - throw new IllegalArgumentException( - "IKM (input keying material) should not be null"); - } - - this.ikm = Arrays.clone(ikm); - - this.skipExpand = skip; - - if (salt == null || salt.length == 0) - { - this.salt = null; - } - else - { - this.salt = Arrays.clone(salt); - } - - if (info == null) - { - this.info = new byte[0]; - } - else - { - this.info = Arrays.clone(info); - } - } - - /** - * Generates parameters for HKDF, specifying both the optional salt and - * optional info. Step 1: Extract won't be skipped. - * - * @param ikm the input keying material or seed - * @param salt the salt to use, may be null for a salt for hashLen zeros - * @param info the info to use, may be null for an info field of zero bytes - */ - public HKDFParameters(final byte[] ikm, final byte[] salt, final byte[] info) - { - this(ikm, false, salt, info); - } - - /** - * Factory method that makes the HKDF skip the extract part of the key - * derivation function. - * - * @param ikm the input keying material or seed, directly used for step 2: - * Expand - * @param info the info to use, may be null for an info field of zero bytes - * @return HKDFParameters that makes the implementation skip step 1 - */ - public static HKDFParameters skipExtractParameters(final byte[] ikm, - final byte[] info) - { - - return new HKDFParameters(ikm, true, null, info); - } - - public static HKDFParameters defaultParameters(final byte[] ikm) - { - return new HKDFParameters(ikm, false, null, null); - } - - /** - * Returns the input keying material or seed. - * - * @return the keying material - */ - public byte[] getIKM() - { - return Arrays.clone(ikm); - } - - /** - * Returns if step 1: extract has to be skipped or not - * - * @return true for skipping, false for no skipping of step 1 - */ - public boolean skipExtract() - { - return skipExpand; - } - - /** - * Returns the salt, or null if the salt should be generated as a byte array - * of HashLen zeros. - * - * @return the salt, or null - */ - public byte[] getSalt() - { - return Arrays.clone(salt); - } - - /** - * Returns the info field, which may be empty (null is converted to empty). - * - * @return the info field, never null - */ - public byte[] getInfo() - { - return Arrays.clone(info); - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java deleted file mode 100644 index ded87a71..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/BasicEntropySourceProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.bouncycastle.crypto.prng; - -import java.security.SecureRandom; - -/** - * An EntropySourceProvider where entropy generation is based on a SecureRandom output using SecureRandom.generateSeed(). - */ -public class BasicEntropySourceProvider - implements EntropySourceProvider -{ - private SecureRandom _sr; - private boolean _predictionResistant; - - /** - * Create a entropy source provider based on the passed in SecureRandom. - * - * @param random the SecureRandom to base EntropySource construction on. - * @param isPredictionResistant boolean indicating if the SecureRandom is based on prediction resistant entropy or not (true if it is). - */ - public BasicEntropySourceProvider(SecureRandom random, boolean isPredictionResistant) - { - _sr = random; - _predictionResistant = isPredictionResistant; - } - - /** - * Return an entropy source that will create bitsRequired bits of entropy on - * each invocation of getEntropy(). - * - * @param bitsRequired size (in bits) of entropy to be created by the provided source. - * @return an EntropySource that generates bitsRequired bits of entropy on each call to its getEntropy() method. - */ - public EntropySource get(final int bitsRequired) - { - return new EntropySource() - { - public boolean isPredictionResistant() - { - return _predictionResistant; - } - - public byte[] getEntropy() - { - byte[] rv = new byte[(bitsRequired + 7) / 8]; - - _sr.nextBytes(rv); - - return rv; - } - - public int entropySize() - { - return bitsRequired; - } - }; - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java deleted file mode 100644 index 666a8541..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/prng/SP800SecureRandomBuilder.java +++ /dev/null @@ -1,289 +0,0 @@ -package org.bouncycastle.crypto.prng; - -import java.security.SecureRandom; - -import org.bouncycastle.crypto.BlockCipher; -import org.bouncycastle.crypto.Digest; -import org.bouncycastle.crypto.Mac; -import org.bouncycastle.crypto.prng.drbg.CTRSP800DRBG; -import org.bouncycastle.crypto.prng.drbg.DualECPoints; -import org.bouncycastle.crypto.prng.drbg.DualECSP800DRBG; -import org.bouncycastle.crypto.prng.drbg.HMacSP800DRBG; -import org.bouncycastle.crypto.prng.drbg.HashSP800DRBG; -import org.bouncycastle.crypto.prng.drbg.SP80090DRBG; - -/** - * Builder class for making SecureRandom objects based on SP 800-90A Deterministic Random Bit Generators (DRBG). - */ -public class SP800SecureRandomBuilder -{ - private SecureRandom random; - private EntropySourceProvider entropySourceProvider; - - private byte[] personalizationString; - private int securityStrength = 256; - private int entropyBitsRequired = 256; - - /** - * Basic constructor, creates a builder using an EntropySourceProvider based on the default SecureRandom with - * predictionResistant set to false. - * <p> - * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if - * the default SecureRandom does for its generateSeed() call. - * </p> - */ - public SP800SecureRandomBuilder() - { - this(new SecureRandom(), false); - } - - /** - * Construct a builder with an EntropySourceProvider based on the passed in SecureRandom and the passed in value - * for prediction resistance. - * <p> - * Any SecureRandom created from a builder constructed like this will make use of input passed to SecureRandom.setSeed() if - * the passed in SecureRandom does for its generateSeed() call. - * </p> - * @param entropySource - * @param predictionResistant - */ - public SP800SecureRandomBuilder(SecureRandom entropySource, boolean predictionResistant) - { - this.random = entropySource; - this.entropySourceProvider = new BasicEntropySourceProvider(random, predictionResistant); - } - - /** - * Create a builder which makes creates the SecureRandom objects from a specified entropy source provider. - * <p> - * <b>Note:</b> If this constructor is used any calls to setSeed() in the resulting SecureRandom will be ignored. - * </p> - * @param entropySourceProvider a provider of EntropySource objects. - */ - public SP800SecureRandomBuilder(EntropySourceProvider entropySourceProvider) - { - this.random = null; - this.entropySourceProvider = entropySourceProvider; - } - - /** - * Set the personalization string for DRBG SecureRandoms created by this builder - * @param personalizationString the personalisation string for the underlying DRBG. - * @return the current builder. - */ - public SP800SecureRandomBuilder setPersonalizationString(byte[] personalizationString) - { - this.personalizationString = personalizationString; - - return this; - } - - /** - * Set the security strength required for DRBGs used in building SecureRandom objects. - * - * @param securityStrength the security strength (in bits) - * @return the current builder. - */ - public SP800SecureRandomBuilder setSecurityStrength(int securityStrength) - { - this.securityStrength = securityStrength; - - return this; - } - - /** - * Set the amount of entropy bits required for seeding and reseeding DRBGs used in building SecureRandom objects. - * - * @param entropyBitsRequired the number of bits of entropy to be requested from the entropy source on each seed/reseed. - * @return the current builder. - */ - public SP800SecureRandomBuilder setEntropyBitsRequired(int entropyBitsRequired) - { - this.entropyBitsRequired = entropyBitsRequired; - - return this; - } - - /** - * Build a SecureRandom based on a SP 800-90A Hash DRBG. - * - * @param digest digest algorithm to use in the DRBG underneath the SecureRandom. - * @param nonce nonce value to use in DRBG construction. - * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. - * @return a SecureRandom supported by a Hash DRBG. - */ - public SP800SecureRandom buildHash(Digest digest, byte[] nonce, boolean predictionResistant) - { - return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HashDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant); - } - - /** - * Build a SecureRandom based on a SP 800-90A CTR DRBG. - * - * @param cipher the block cipher to base the DRBG on. - * @param keySizeInBits key size in bits to be used with the block cipher. - * @param nonce nonce value to use in DRBG construction. - * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. - * @return a SecureRandom supported by a CTR DRBG. - */ - public SP800SecureRandom buildCTR(BlockCipher cipher, int keySizeInBits, byte[] nonce, boolean predictionResistant) - { - return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new CTRDRBGProvider(cipher, keySizeInBits, nonce, personalizationString, securityStrength), predictionResistant); - } - - /** - * Build a SecureRandom based on a SP 800-90A HMAC DRBG. - * - * @param hMac HMAC algorithm to use in the DRBG underneath the SecureRandom. - * @param nonce nonce value to use in DRBG construction. - * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. - * @return a SecureRandom supported by a HMAC DRBG. - */ - public SP800SecureRandom buildHMAC(Mac hMac, byte[] nonce, boolean predictionResistant) - { - return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new HMacDRBGProvider(hMac, nonce, personalizationString, securityStrength), predictionResistant); - } - - /** - * Build a SecureRandom based on a SP 800-90A Dual EC DRBG. - * - * @param digest digest algorithm to use in the DRBG underneath the SecureRandom. - * @param nonce nonce value to use in DRBG construction. - * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. - * @return a SecureRandom supported by a Dual EC DRBG. - */ - public SP800SecureRandom buildDualEC(Digest digest, byte[] nonce, boolean predictionResistant) - { - return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new DualECDRBGProvider(digest, nonce, personalizationString, securityStrength), predictionResistant); - } - - /** - * Build a SecureRandom based on a SP 800-90A Dual EC DRBG. - * - * @param pointSet an array of DualECPoints to use for DRB generation. - * @param digest digest algorithm to use in the DRBG underneath the SecureRandom. - * @param nonce nonce value to use in DRBG construction. - * @param predictionResistant specify whether the underlying DRBG in the resulting SecureRandom should reseed on each request for bytes. - * @return a SecureRandom supported by a Dual EC DRBG. - */ - public SP800SecureRandom buildDualEC(DualECPoints[] pointSet, Digest digest, byte[] nonce, boolean predictionResistant) - { - return new SP800SecureRandom(random, entropySourceProvider.get(entropyBitsRequired), new ConfigurableDualECDRBGProvider(pointSet, digest, nonce, personalizationString, securityStrength), predictionResistant); - } - - private static class HashDRBGProvider - implements DRBGProvider - { - private final Digest digest; - private final byte[] nonce; - private final byte[] personalizationString; - private final int securityStrength; - - public HashDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength) - { - this.digest = digest; - this.nonce = nonce; - this.personalizationString = personalizationString; - this.securityStrength = securityStrength; - } - - public SP80090DRBG get(EntropySource entropySource) - { - return new HashSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce); - } - } - - private static class DualECDRBGProvider - implements DRBGProvider - { - private final Digest digest; - private final byte[] nonce; - private final byte[] personalizationString; - private final int securityStrength; - - public DualECDRBGProvider(Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength) - { - this.digest = digest; - this.nonce = nonce; - this.personalizationString = personalizationString; - this.securityStrength = securityStrength; - } - - public SP80090DRBG get(EntropySource entropySource) - { - return new DualECSP800DRBG(digest, securityStrength, entropySource, personalizationString, nonce); - } - } - - private static class ConfigurableDualECDRBGProvider - implements DRBGProvider - { - private final DualECPoints[] pointSet; - private final Digest digest; - private final byte[] nonce; - private final byte[] personalizationString; - private final int securityStrength; - - public ConfigurableDualECDRBGProvider(DualECPoints[] pointSet, Digest digest, byte[] nonce, byte[] personalizationString, int securityStrength) - { - this.pointSet = new DualECPoints[pointSet.length]; - System.arraycopy(pointSet, 0, this.pointSet, 0, pointSet.length); - this.digest = digest; - this.nonce = nonce; - this.personalizationString = personalizationString; - this.securityStrength = securityStrength; - } - - public SP80090DRBG get(EntropySource entropySource) - { - return new DualECSP800DRBG(pointSet, digest, securityStrength, entropySource, personalizationString, nonce); - } - } - - private static class HMacDRBGProvider - implements DRBGProvider - { - private final Mac hMac; - private final byte[] nonce; - private final byte[] personalizationString; - private final int securityStrength; - - public HMacDRBGProvider(Mac hMac, byte[] nonce, byte[] personalizationString, int securityStrength) - { - this.hMac = hMac; - this.nonce = nonce; - this.personalizationString = personalizationString; - this.securityStrength = securityStrength; - } - - public SP80090DRBG get(EntropySource entropySource) - { - return new HMacSP800DRBG(hMac, securityStrength, entropySource, personalizationString, nonce); - } - } - - private static class CTRDRBGProvider - implements DRBGProvider - { - - private final BlockCipher blockCipher; - private final int keySizeInBits; - private final byte[] nonce; - private final byte[] personalizationString; - private final int securityStrength; - - public CTRDRBGProvider(BlockCipher blockCipher, int keySizeInBits, byte[] nonce, byte[] personalizationString, int securityStrength) - { - this.blockCipher = blockCipher; - this.keySizeInBits = keySizeInBits; - this.nonce = nonce; - this.personalizationString = personalizationString; - this.securityStrength = securityStrength; - } - - public SP80090DRBG get(EntropySource entropySource) - { - return new CTRSP800DRBG(blockCipher, keySizeInBits, securityStrength, entropySource, personalizationString, nonce); - } - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java deleted file mode 100644 index f15e4047..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/signers/RSADigestSigner.java +++ /dev/null @@ -1,238 +0,0 @@ -package org.bouncycastle.crypto.signers; - -import java.io.IOException; -import java.util.Hashtable; - -import org.bouncycastle.asn1.ASN1Encoding; -import org.bouncycastle.asn1.ASN1ObjectIdentifier; -import org.bouncycastle.asn1.DERNull; -import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; -import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; -import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; -import org.bouncycastle.asn1.x509.AlgorithmIdentifier; -import org.bouncycastle.asn1.x509.DigestInfo; -import org.bouncycastle.asn1.x509.X509ObjectIdentifiers; -import org.bouncycastle.crypto.AsymmetricBlockCipher; -import org.bouncycastle.crypto.CipherParameters; -import org.bouncycastle.crypto.CryptoException; -import org.bouncycastle.crypto.DataLengthException; -import org.bouncycastle.crypto.Digest; -import org.bouncycastle.crypto.Signer; -import org.bouncycastle.crypto.encodings.PKCS1Encoding; -import org.bouncycastle.crypto.engines.RSABlindedEngine; -import org.bouncycastle.crypto.params.AsymmetricKeyParameter; -import org.bouncycastle.crypto.params.ParametersWithRandom; -import org.bouncycastle.util.Arrays; - -public class RSADigestSigner - implements Signer -{ - private final AsymmetricBlockCipher rsaEngine = new PKCS1Encoding(new RSABlindedEngine()); - private AlgorithmIdentifier algId; - private Digest digest; - private boolean forSigning; - - private static final Hashtable oidMap = new Hashtable(); - - /* - * Load OID table. - */ - static - { - oidMap.put("RIPEMD128", TeleTrusTObjectIdentifiers.ripemd128); - oidMap.put("RIPEMD160", TeleTrusTObjectIdentifiers.ripemd160); - oidMap.put("RIPEMD256", TeleTrusTObjectIdentifiers.ripemd256); - - oidMap.put("SHA-1", X509ObjectIdentifiers.id_SHA1); - oidMap.put("SHA-224", NISTObjectIdentifiers.id_sha224); - oidMap.put("SHA-256", NISTObjectIdentifiers.id_sha256); - oidMap.put("SHA-384", NISTObjectIdentifiers.id_sha384); - oidMap.put("SHA-512", NISTObjectIdentifiers.id_sha512); - - oidMap.put("MD2", PKCSObjectIdentifiers.md2); - oidMap.put("MD4", PKCSObjectIdentifiers.md4); - oidMap.put("MD5", PKCSObjectIdentifiers.md5); - } - - public RSADigestSigner( - Digest digest) - { - this(digest, (ASN1ObjectIdentifier)oidMap.get(digest.getAlgorithmName())); - } - - public RSADigestSigner( - Digest digest, - ASN1ObjectIdentifier digestOid) - { - this.digest = digest; - this.algId = new AlgorithmIdentifier(digestOid, DERNull.INSTANCE); - } - - /** - * @deprecated - */ - public String getAlgorithmName() - { - return digest.getAlgorithmName() + "withRSA"; - } - - /** - * initialise the signer for signing or verification. - * - * @param forSigning - * true if for signing, false otherwise - * @param parameters - * necessary parameters. - */ - public void init( - boolean forSigning, - CipherParameters parameters) - { - this.forSigning = forSigning; - AsymmetricKeyParameter k; - - if (parameters instanceof ParametersWithRandom) - { - k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).getParameters(); - } - else - { - k = (AsymmetricKeyParameter)parameters; - } - - if (forSigning && !k.isPrivate()) - { - throw new IllegalArgumentException("signing requires private key"); - } - - if (!forSigning && k.isPrivate()) - { - throw new IllegalArgumentException("verification requires public key"); - } - - reset(); - - rsaEngine.init(forSigning, parameters); - } - - /** - * update the internal digest with the byte b - */ - public void update( - byte input) - { - digest.update(input); - } - - /** - * update the internal digest with the byte array in - */ - public void update( - byte[] input, - int inOff, - int length) - { - digest.update(input, inOff, length); - } - - /** - * Generate a signature for the message we've been loaded with using the key - * we were initialised with. - */ - public byte[] generateSignature() - throws CryptoException, DataLengthException - { - if (!forSigning) - { - throw new IllegalStateException("RSADigestSigner not initialised for signature generation."); - } - - byte[] hash = new byte[digest.getDigestSize()]; - digest.doFinal(hash, 0); - - try - { - byte[] data = derEncode(hash); - return rsaEngine.processBlock(data, 0, data.length); - } - catch (IOException e) - { - throw new CryptoException("unable to encode signature: " + e.getMessage(), e); - } - } - - /** - * return true if the internal state represents the signature described in - * the passed in array. - */ - public boolean verifySignature( - byte[] signature) - { - if (forSigning) - { - throw new IllegalStateException("RSADigestSigner not initialised for verification"); - } - - byte[] hash = new byte[digest.getDigestSize()]; - - digest.doFinal(hash, 0); - - byte[] sig; - byte[] expected; - - try - { - sig = rsaEngine.processBlock(signature, 0, signature.length); - expected = derEncode(hash); - } - catch (Exception e) - { - return false; - } - - if (sig.length == expected.length) - { - return Arrays.constantTimeAreEqual(sig, expected); - } - else if (sig.length == expected.length - 2) // NULL left out - { - int sigOffset = sig.length - hash.length - 2; - int expectedOffset = expected.length - hash.length - 2; - - expected[1] -= 2; // adjust lengths - expected[3] -= 2; - - int nonEqual = 0; - - for (int i = 0; i < hash.length; i++) - { - nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]); - } - - for (int i = 0; i < sigOffset; i++) - { - nonEqual |= (sig[i] ^ expected[i]); // check header less NULL - } - - return nonEqual == 0; - } - else - { - return false; - } - } - - public void reset() - { - digest.reset(); - } - - private byte[] derEncode( - byte[] hash) - throws IOException - { - DigestInfo dInfo = new DigestInfo(algId, hash); - - return dInfo.getEncoded(ASN1Encoding.DER); - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java deleted file mode 100644 index b8153b06..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/AbstractTlsContext.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.bouncycastle.crypto.tls; - -import java.security.SecureRandom; - -import org.bouncycastle.crypto.prng.DigestRandomGenerator; -import org.bouncycastle.crypto.prng.RandomGenerator; -import org.bouncycastle.util.Times; - -abstract class AbstractTlsContext - implements TlsContext -{ - private static long counter = Times.nanoTime(); - - private synchronized static long nextCounterValue() - { - return ++counter; - } - - private RandomGenerator nonceRandom; - private SecureRandom secureRandom; - private SecurityParameters securityParameters; - - private ProtocolVersion clientVersion = null; - private ProtocolVersion serverVersion = null; - private TlsSession session = null; - private Object userObject = null; - - AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters) - { - secureRandom.setSeed(nextCounterValue()); - secureRandom.setSeed(Times.nanoTime()); - - this.nonceRandom = new DigestRandomGenerator(TlsUtils.createHash(HashAlgorithm.sha256)); - byte[] nonceSeed = new byte[32]; - secureRandom.nextBytes(nonceSeed); - this.nonceRandom.addSeedMaterial(nonceSeed); - - this.secureRandom = secureRandom; - this.securityParameters = securityParameters; - } - - public RandomGenerator getNonceRandomGenerator() - { - return nonceRandom; - } - - public SecureRandom getSecureRandom() - { - return secureRandom; - } - - public SecurityParameters getSecurityParameters() - { - return securityParameters; - } - - public ProtocolVersion getClientVersion() - { - return clientVersion; - } - - void setClientVersion(ProtocolVersion clientVersion) - { - this.clientVersion = clientVersion; - } - - public ProtocolVersion getServerVersion() - { - return serverVersion; - } - - void setServerVersion(ProtocolVersion serverVersion) - { - this.serverVersion = serverVersion; - } - - public TlsSession getResumableSession() - { - return session; - } - - void setResumableSession(TlsSession session) - { - this.session = session; - } - - public Object getUserObject() - { - return userObject; - } - - public void setUserObject(Object userObject) - { - this.userObject = userObject; - } - - public byte[] exportKeyingMaterial(String asciiLabel, byte[] context_value, int length) - { - if (context_value != null && !TlsUtils.isValidUint16(context_value.length)) - { - throw new IllegalArgumentException("'context_value' must have length less than 2^16 (or be null)"); - } - - SecurityParameters sp = getSecurityParameters(); - byte[] cr = sp.getClientRandom(), sr = sp.getServerRandom(); - - int seedLength = cr.length + sr.length; - if (context_value != null) - { - seedLength += (2 + context_value.length); - } - - byte[] seed = new byte[seedLength]; - int seedPos = 0; - - System.arraycopy(cr, 0, seed, seedPos, cr.length); - seedPos += cr.length; - System.arraycopy(sr, 0, seed, seedPos, sr.length); - seedPos += sr.length; - if (context_value != null) - { - TlsUtils.writeUint16(context_value.length, seed, seedPos); - seedPos += 2; - System.arraycopy(context_value, 0, seed, seedPos, context_value.length); - seedPos += context_value.length; - } - - if (seedPos != seedLength) - { - throw new IllegalStateException("error in calculation of seed for export"); - } - - return TlsUtils.PRF(this, sp.getMasterSecret(), asciiLabel, seed, length); - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java deleted file mode 100644 index 2d3cf267..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReassembler.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.bouncycastle.crypto.tls; - -import java.util.Vector; - -class DTLSReassembler -{ - - private short msg_type; - private byte[] body; - - private Vector missing = new Vector(); - - DTLSReassembler(short msg_type, int length) - { - this.msg_type = msg_type; - this.body = new byte[length]; - this.missing.addElement(new Range(0, length)); - } - - short getType() - { - return msg_type; - } - - byte[] getBodyIfComplete() - { - return missing.isEmpty() ? body : null; - } - - void contributeFragment(short msg_type, int length, byte[] buf, int off, int fragment_offset, - int fragment_length) - { - - int fragment_end = fragment_offset + fragment_length; - - if (this.msg_type != msg_type || this.body.length != length || fragment_end > length) - { - return; - } - - if (fragment_length == 0) - { - // NOTE: Empty messages still require an empty fragment to complete it - if (fragment_offset == 0 && !missing.isEmpty()) - { - Range firstRange = (Range)missing.firstElement(); - if (firstRange.getEnd() == 0) - { - missing.removeElementAt(0); - } - } - return; - } - - for (int i = 0; i < missing.size(); ++i) - { - Range range = (Range)missing.elementAt(i); - if (range.getStart() >= fragment_end) - { - break; - } - if (range.getEnd() > fragment_offset) - { - - int copyStart = Math.max(range.getStart(), fragment_offset); - int copyEnd = Math.min(range.getEnd(), fragment_end); - int copyLength = copyEnd - copyStart; - - System.arraycopy(buf, off + copyStart - fragment_offset, body, copyStart, - copyLength); - - if (copyStart == range.getStart()) - { - if (copyEnd == range.getEnd()) - { - missing.removeElementAt(i--); - } - else - { - range.setStart(copyEnd); - } - } - else - { - if (copyEnd == range.getEnd()) - { - range.setEnd(copyStart); - } - else - { - missing.insertElementAt(new Range(copyEnd, range.getEnd()), ++i); - range.setEnd(copyStart); - } - } - } - } - } - - void reset() - { - this.missing.removeAllElements(); - this.missing.addElement(new Range(0, body.length)); - } - - private static class Range - { - - private int start, end; - - Range(int start, int end) - { - this.start = start; - this.end = end; - } - - public int getStart() - { - return start; - } - - public void setStart(int start) - { - this.start = start; - } - - public int getEnd() - { - return end; - } - - public void setEnd(int end) - { - this.end = end; - } - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java deleted file mode 100644 index af694ac9..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/DTLSReliableHandshake.java +++ /dev/null @@ -1,457 +0,0 @@ -package org.bouncycastle.crypto.tls; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import org.bouncycastle.crypto.Digest; -import org.bouncycastle.util.Integers; - -class DTLSReliableHandshake -{ - private final static int MAX_RECEIVE_AHEAD = 10; - - private DTLSRecordLayer recordLayer; - - private TlsHandshakeHash handshakeHash; - - private Hashtable currentInboundFlight = new Hashtable(); - private Hashtable previousInboundFlight = null; - private Vector outboundFlight = new Vector(); - private boolean sending = true; - - private int message_seq = 0, next_receive_seq = 0; - - DTLSReliableHandshake(TlsContext context, DTLSRecordLayer transport) - { - this.recordLayer = transport; - this.handshakeHash = new DeferredHash(); - this.handshakeHash.init(context); - } - - void notifyHelloComplete() - { - this.handshakeHash = handshakeHash.notifyPRFDetermined(); - } - - TlsHandshakeHash getHandshakeHash() - { - return handshakeHash; - } - - TlsHandshakeHash prepareToFinish() - { - TlsHandshakeHash result = handshakeHash; - this.handshakeHash = handshakeHash.stopTracking(); - return result; - } - - void sendMessage(short msg_type, byte[] body) - throws IOException - { - TlsUtils.checkUint24(body.length); - - if (!sending) - { - checkInboundFlight(); - sending = true; - outboundFlight.removeAllElements(); - } - - Message message = new Message(message_seq++, msg_type, body); - - outboundFlight.addElement(message); - - writeMessage(message); - updateHandshakeMessagesDigest(message); - } - - byte[] receiveMessageBody(short msg_type) - throws IOException - { - Message message = receiveMessage(); - if (message.getType() != msg_type) - { - throw new TlsFatalAlert(AlertDescription.unexpected_message); - } - - return message.getBody(); - } - - Message receiveMessage() - throws IOException - { - if (sending) - { - sending = false; - prepareInboundFlight(); - } - - // Check if we already have the next message waiting - { - DTLSReassembler next = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(next_receive_seq)); - if (next != null) - { - byte[] body = next.getBodyIfComplete(); - if (body != null) - { - previousInboundFlight = null; - return updateHandshakeMessagesDigest(new Message(next_receive_seq++, next.getType(), body)); - } - } - } - - byte[] buf = null; - - // TODO Check the conditions under which we should reset this - int readTimeoutMillis = 1000; - - for (; ; ) - { - int receiveLimit = recordLayer.getReceiveLimit(); - if (buf == null || buf.length < receiveLimit) - { - buf = new byte[receiveLimit]; - } - - // TODO Handle records containing multiple handshake messages - - try - { - for (; ; ) - { - int received = recordLayer.receive(buf, 0, receiveLimit, readTimeoutMillis); - if (received < 0) - { - break; - } - if (received < 12) - { - continue; - } - int fragment_length = TlsUtils.readUint24(buf, 9); - if (received != (fragment_length + 12)) - { - continue; - } - int seq = TlsUtils.readUint16(buf, 4); - if (seq > (next_receive_seq + MAX_RECEIVE_AHEAD)) - { - continue; - } - short msg_type = TlsUtils.readUint8(buf, 0); - int length = TlsUtils.readUint24(buf, 1); - int fragment_offset = TlsUtils.readUint24(buf, 6); - if (fragment_offset + fragment_length > length) - { - continue; - } - - if (seq < next_receive_seq) - { - /* - * NOTE: If we receive the previous flight of incoming messages in full - * again, retransmit our last flight - */ - if (previousInboundFlight != null) - { - DTLSReassembler reassembler = (DTLSReassembler)previousInboundFlight.get(Integers - .valueOf(seq)); - if (reassembler != null) - { - - reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, - fragment_length); - - if (checkAll(previousInboundFlight)) - { - - resendOutboundFlight(); - - /* - * TODO[DTLS] implementations SHOULD back off handshake packet - * size during the retransmit backoff. - */ - readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000); - - resetAll(previousInboundFlight); - } - } - } - } - else - { - - DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq)); - if (reassembler == null) - { - reassembler = new DTLSReassembler(msg_type, length); - currentInboundFlight.put(Integers.valueOf(seq), reassembler); - } - - reassembler.contributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length); - - if (seq == next_receive_seq) - { - byte[] body = reassembler.getBodyIfComplete(); - if (body != null) - { - previousInboundFlight = null; - return updateHandshakeMessagesDigest(new Message(next_receive_seq++, - reassembler.getType(), body)); - } - } - } - } - } - catch (IOException e) - { - // NOTE: Assume this is a timeout for the moment - } - - resendOutboundFlight(); - - /* - * TODO[DTLS] implementations SHOULD back off handshake packet size during the - * retransmit backoff. - */ - readTimeoutMillis = Math.min(readTimeoutMillis * 2, 60000); - } - } - - void finish() - { - DTLSHandshakeRetransmit retransmit = null; - if (!sending) - { - checkInboundFlight(); - } - else if (currentInboundFlight != null) - { - /* - * RFC 6347 4.2.4. In addition, for at least twice the default MSL defined for [TCP], - * when in the FINISHED state, the node that transmits the last flight (the server in an - * ordinary handshake or the client in a resumed handshake) MUST respond to a retransmit - * of the peer's last flight with a retransmit of the last flight. - */ - retransmit = new DTLSHandshakeRetransmit() - { - public void receivedHandshakeRecord(int epoch, byte[] buf, int off, int len) - throws IOException - { - /* - * TODO Need to handle the case where the previous inbound flight contains - * messages from two epochs. - */ - if (len < 12) - { - return; - } - int fragment_length = TlsUtils.readUint24(buf, off + 9); - if (len != (fragment_length + 12)) - { - return; - } - int seq = TlsUtils.readUint16(buf, off + 4); - if (seq >= next_receive_seq) - { - return; - } - - short msg_type = TlsUtils.readUint8(buf, off); - - // TODO This is a hack that only works until we try to support renegotiation - int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0; - if (epoch != expectedEpoch) - { - return; - } - - int length = TlsUtils.readUint24(buf, off + 1); - int fragment_offset = TlsUtils.readUint24(buf, off + 6); - if (fragment_offset + fragment_length > length) - { - return; - } - - DTLSReassembler reassembler = (DTLSReassembler)currentInboundFlight.get(Integers.valueOf(seq)); - if (reassembler != null) - { - reassembler.contributeFragment(msg_type, length, buf, off + 12, fragment_offset, - fragment_length); - if (checkAll(currentInboundFlight)) - { - resendOutboundFlight(); - resetAll(currentInboundFlight); - } - } - } - }; - } - - recordLayer.handshakeSuccessful(retransmit); - } - - void resetHandshakeMessagesDigest() - { - handshakeHash.reset(); - } - - /** - * Check that there are no "extra" messages left in the current inbound flight - */ - private void checkInboundFlight() - { - Enumeration e = currentInboundFlight.keys(); - while (e.hasMoreElements()) - { - Integer key = (Integer)e.nextElement(); - if (key.intValue() >= next_receive_seq) - { - // TODO Should this be considered an error? - } - } - } - - private void prepareInboundFlight() - { - resetAll(currentInboundFlight); - previousInboundFlight = currentInboundFlight; - currentInboundFlight = new Hashtable(); - } - - private void resendOutboundFlight() - throws IOException - { - recordLayer.resetWriteEpoch(); - for (int i = 0; i < outboundFlight.size(); ++i) - { - writeMessage((Message)outboundFlight.elementAt(i)); - } - } - - private Message updateHandshakeMessagesDigest(Message message) - throws IOException - { - if (message.getType() != HandshakeType.hello_request) - { - byte[] body = message.getBody(); - byte[] buf = new byte[12]; - TlsUtils.writeUint8(message.getType(), buf, 0); - TlsUtils.writeUint24(body.length, buf, 1); - TlsUtils.writeUint16(message.getSeq(), buf, 4); - TlsUtils.writeUint24(0, buf, 6); - TlsUtils.writeUint24(body.length, buf, 9); - handshakeHash.update(buf, 0, buf.length); - handshakeHash.update(body, 0, body.length); - } - return message; - } - - private void writeMessage(Message message) - throws IOException - { - int sendLimit = recordLayer.getSendLimit(); - int fragmentLimit = sendLimit - 12; - - // TODO Support a higher minimum fragment size? - if (fragmentLimit < 1) - { - // TODO Should we be throwing an exception here? - throw new TlsFatalAlert(AlertDescription.internal_error); - } - - int length = message.getBody().length; - - // NOTE: Must still send a fragment if body is empty - int fragment_offset = 0; - do - { - int fragment_length = Math.min(length - fragment_offset, fragmentLimit); - writeHandshakeFragment(message, fragment_offset, fragment_length); - fragment_offset += fragment_length; - } - while (fragment_offset < length); - } - - private void writeHandshakeFragment(Message message, int fragment_offset, int fragment_length) - throws IOException - { - RecordLayerBuffer fragment = new RecordLayerBuffer(12 + fragment_length); - TlsUtils.writeUint8(message.getType(), fragment); - TlsUtils.writeUint24(message.getBody().length, fragment); - TlsUtils.writeUint16(message.getSeq(), fragment); - TlsUtils.writeUint24(fragment_offset, fragment); - TlsUtils.writeUint24(fragment_length, fragment); - fragment.write(message.getBody(), fragment_offset, fragment_length); - - fragment.sendToRecordLayer(recordLayer); - } - - private static boolean checkAll(Hashtable inboundFlight) - { - Enumeration e = inboundFlight.elements(); - while (e.hasMoreElements()) - { - if (((DTLSReassembler)e.nextElement()).getBodyIfComplete() == null) - { - return false; - } - } - return true; - } - - private static void resetAll(Hashtable inboundFlight) - { - Enumeration e = inboundFlight.elements(); - while (e.hasMoreElements()) - { - ((DTLSReassembler)e.nextElement()).reset(); - } - } - - static class Message - { - private final int message_seq; - private final short msg_type; - private final byte[] body; - - private Message(int message_seq, short msg_type, byte[] body) - { - this.message_seq = message_seq; - this.msg_type = msg_type; - this.body = body; - } - - public int getSeq() - { - return message_seq; - } - - public short getType() - { - return msg_type; - } - - public byte[] getBody() - { - return body; - } - } - - static class RecordLayerBuffer extends ByteArrayOutputStream - { - RecordLayerBuffer(int size) - { - super(size); - } - - void sendToRecordLayer(DTLSRecordLayer recordLayer) throws IOException - { - recordLayer.send(buf, 0, count); - buf = null; - } - } -} diff --git a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java b/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java deleted file mode 100644 index f6c96b92..00000000 --- a/core/src/main/jdk1.1/org/bouncycastle/crypto/tls/UDPTransport.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.bouncycastle.crypto.tls; - -import java.io.IOException; -import java.net.DatagramPacket; -import java.net.DatagramSocket; - -public class UDPTransport - implements DatagramTransport -{ - protected final static int MIN_IP_OVERHEAD = 20; - protected final static int MAX_IP_OVERHEAD = MIN_IP_OVERHEAD + 64; - protected final static int UDP_OVERHEAD = 8; - - protected final DatagramSocket socket; - protected final int receiveLimit, sendLimit; - - public UDPTransport(DatagramSocket socket, int mtu) - throws IOException - { - // - // In 1.3 and earlier sockets were bound and connected during creation - // - //if (!socket.isBound() || !socket.isConnected()) - //{ - // throw new IllegalArgumentException("'socket' must be bound and connected"); - //} - - this.socket = socket; - - // NOTE: As of JDK 1.6, can use NetworkInterface.getMTU - - this.receiveLimit = mtu - MIN_IP_OVERHEAD - UDP_OVERHEAD; - this.sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD; - } - - public int getReceiveLimit() - { - return receiveLimit; - } - - public int getSendLimit() - { - // TODO[DTLS] Implement Path-MTU discovery? - return sendLimit; - } - - public int receive(byte[] buf, int off, int len, int waitMillis) - throws IOException - { - socket.setSoTimeout(waitMillis); - - if (off == 0) - { - DatagramPacket packet = new DatagramPacket(buf, len); - socket.receive(packet); - - return packet.getLength(); - } - else - { - byte[] rv = new byte[len]; - - DatagramPacket packet = new DatagramPacket(rv, len); - socket.receive(packet); - - System.arraycopy(rv, 0, buf, off, packet.getLength()); - - return packet.getLength(); - } - } - - public void send(byte[] buf, int off, int len) - throws IOException - { - if (len > getSendLimit()) - { - /* - * RFC 4347 4.1.1. "If the application attempts to send a record larger than the MTU, - * the DTLS implementation SHOULD generate an error, thus avoiding sending a packet - * which will be fragmented." - */ - throw new TlsFatalAlert(AlertDescription.internal_error); - } - - if (off == 0) - { - DatagramPacket packet = new DatagramPacket(buf, len); - socket.send(packet); - } - else - { - byte[] data = new byte[len]; - - System.arraycopy(buf, off, data, 0, len); - - DatagramPacket packet = new DatagramPacket(data, len); - socket.send(packet); - } - } - - public void close() - throws IOException - { - socket.close(); - } -} |