Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java')
-rw-r--r--core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java294
1 files changed, 0 insertions, 294 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java b/core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java
deleted file mode 100644
index 548969ac..00000000
--- a/core/src/main/java/org/bouncycastle/crypto/engines/RFC5649WrapEngine.java
+++ /dev/null
@@ -1,294 +0,0 @@
-package org.bouncycastle.crypto.engines;
-
-import org.bouncycastle.crypto.BlockCipher;
-import org.bouncycastle.crypto.CipherParameters;
-import org.bouncycastle.crypto.InvalidCipherTextException;
-import org.bouncycastle.crypto.Wrapper;
-import org.bouncycastle.crypto.params.KeyParameter;
-import org.bouncycastle.crypto.params.ParametersWithIV;
-import org.bouncycastle.crypto.params.ParametersWithRandom;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Pack;
-
-/**
- * An implementation of the AES Key Wrap with Padding specification
- * as described in RFC 5649.
- * <p>
- * For details on the specification see:
- * <a href="https://tools.ietf.org/html/rfc5649">https://tools.ietf.org/html/rfc5649</a>
- * </p>
- */
-public class RFC5649WrapEngine
- implements Wrapper
-{
- private BlockCipher engine;
- private KeyParameter param;
- private boolean forWrapping;
-
- // The AIV as defined in the RFC
- private byte[] highOrderIV = {(byte)0xa6, (byte)0x59, (byte)0x59, (byte)0xa6};
- private byte[] preIV = highOrderIV;
-
- private byte[] extractedAIV = null;
-
- public RFC5649WrapEngine(BlockCipher engine)
- {
- this.engine = engine;
- }
-
- public void init(boolean forWrapping, CipherParameters param)
- {
- this.forWrapping = forWrapping;
-
- if (param instanceof ParametersWithRandom)
- {
- param = ((ParametersWithRandom)param).getParameters();
- }
-
- if (param instanceof KeyParameter)
- {
- this.param = (KeyParameter)param;
- }
- else if (param instanceof ParametersWithIV)
- {
- this.preIV = ((ParametersWithIV)param).getIV();
- this.param = (KeyParameter)((ParametersWithIV)param).getParameters();
- if (this.preIV.length != 4)
- {
- throw new IllegalArgumentException("IV length not equal to 4");
- }
- }
- }
-
- public String getAlgorithmName()
- {
- return engine.getAlgorithmName();
- }
-
- /**
- * Pads the plaintext (i.e., the key to be wrapped)
- * as per section 4.1 of RFC 5649.
- *
- * @param plaintext The key being wrapped.
- * @return The padded key.
- */
- private byte[] padPlaintext(byte[] plaintext)
- {
- int plaintextLength = plaintext.length;
- int numOfZerosToAppend = (8 - (plaintextLength % 8)) % 8;
- byte[] paddedPlaintext = new byte[plaintextLength + numOfZerosToAppend];
- System.arraycopy(plaintext, 0, paddedPlaintext, 0, plaintextLength);
- if (numOfZerosToAppend != 0)
- {
- // plaintext (i.e., key to be wrapped) does not have
- // a multiple of 8 octet blocks so it must be padded
- byte[] zeros = new byte[numOfZerosToAppend];
- System.arraycopy(zeros, 0, paddedPlaintext, plaintextLength, numOfZerosToAppend);
- }
- return paddedPlaintext;
- }
-
- public byte[] wrap(byte[] in, int inOff, int inLen)
- {
- if (!forWrapping)
- {
- throw new IllegalStateException("not set for wrapping");
- }
- byte[] iv = new byte[8];
-
- // MLI = size of key to be wrapped
- byte[] mli = Pack.intToBigEndian(inLen);
- // copy in the fixed portion of the AIV
- System.arraycopy(preIV, 0, iv, 0, preIV.length);
- // copy in the MLI after the AIV
- System.arraycopy(mli, 0, iv, preIV.length, mli.length);
-
- // get the relevant plaintext to be wrapped
- byte[] relevantPlaintext = new byte[inLen];
- System.arraycopy(in, inOff, relevantPlaintext, 0, inLen);
- byte[] paddedPlaintext = padPlaintext(relevantPlaintext);
-
- if (paddedPlaintext.length == 8)
- {
- // if the padded plaintext contains exactly 8 octets,
- // then prepend iv and encrypt using AES in ECB mode.
-
- // prepend the IV to the plaintext
- byte[] paddedPlainTextWithIV = new byte[paddedPlaintext.length + iv.length];
- System.arraycopy(iv, 0, paddedPlainTextWithIV, 0, iv.length);
- System.arraycopy(paddedPlaintext, 0, paddedPlainTextWithIV, iv.length, paddedPlaintext.length);
-
- engine.init(true, param);
- for (int i = 0; i < paddedPlainTextWithIV.length; i += engine.getBlockSize())
- {
- engine.processBlock(paddedPlainTextWithIV, i, paddedPlainTextWithIV, i);
- }
-
- return paddedPlainTextWithIV;
- }
- else
- {
- // otherwise, apply the RFC 3394 wrap to
- // the padded plaintext with the new IV
- Wrapper wrapper = new RFC3394WrapEngine(engine);
- ParametersWithIV paramsWithIV = new ParametersWithIV(param, iv);
- wrapper.init(true, paramsWithIV);
- return wrapper.wrap(paddedPlaintext, inOff, paddedPlaintext.length);
- }
-
- }
-
- public byte[] unwrap(byte[] in, int inOff, int inLen)
- throws InvalidCipherTextException
- {
- if (forWrapping)
- {
- throw new IllegalStateException("not set for unwrapping");
- }
-
- int n = inLen / 8;
-
- if ((n * 8) != inLen)
- {
- throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
- }
-
- if (n == 1)
- {
- throw new InvalidCipherTextException("unwrap data must be at least 16 bytes");
- }
-
- byte[] relevantCiphertext = new byte[inLen];
- System.arraycopy(in, inOff, relevantCiphertext, 0, inLen);
- byte[] decrypted = new byte[inLen];
- byte[] paddedPlaintext;
-
- if (n == 2)
- {
- // When there are exactly two 64-bit blocks of ciphertext,
- // they are decrypted as a single block using AES in ECB.
- engine.init(false, param);
- for (int i = 0; i < relevantCiphertext.length; i += engine.getBlockSize())
- {
- engine.processBlock(relevantCiphertext, i, decrypted, i);
- }
-
- // extract the AIV
- extractedAIV = new byte[8];
- System.arraycopy(decrypted, 0, extractedAIV, 0, extractedAIV.length);
- paddedPlaintext = new byte[decrypted.length - extractedAIV.length];
- System.arraycopy(decrypted, extractedAIV.length, paddedPlaintext, 0, paddedPlaintext.length);
- }
- else
- {
- // Otherwise, unwrap as per RFC 3394 but don't check IV the same way
- decrypted = rfc3394UnwrapNoIvCheck(in, inOff, inLen);
- paddedPlaintext = decrypted;
- }
-
- // Decompose the extracted AIV to the fixed portion and the MLI
- byte[] extractedHighOrderAIV = new byte[4];
- byte[] mliBytes = new byte[4];
- System.arraycopy(extractedAIV, 0, extractedHighOrderAIV, 0, extractedHighOrderAIV.length);
- System.arraycopy(extractedAIV, extractedHighOrderAIV.length, mliBytes, 0, mliBytes.length);
- int mli = Pack.bigEndianToInt(mliBytes, 0);
-
- // Even if a check fails we still continue and check everything
- // else in order to avoid certain timing based side-channel attacks.
- boolean isValid = true;
-
- // Check the fixed portion of the AIV
- if (!Arrays.constantTimeAreEqual(extractedHighOrderAIV, preIV))
- {
- isValid = false;
- }
-
- // Check the MLI against the actual length
- int upperBound = paddedPlaintext.length;
- int lowerBound = upperBound - 8;
- if (mli <= lowerBound)
- {
- isValid = false;
- }
- if (mli > upperBound)
- {
- isValid = false;
- }
-
- // Check the number of padded zeros
- int expectedZeros = upperBound - mli;
- byte[] zeros = new byte[expectedZeros];
- byte[] pad = new byte[expectedZeros];
- System.arraycopy(paddedPlaintext, paddedPlaintext.length - expectedZeros, pad, 0, expectedZeros);
- if (!Arrays.constantTimeAreEqual(pad, zeros))
- {
- isValid = false;
- }
-
- // Extract the plaintext from the padded plaintext
- byte[] plaintext = new byte[mli];
- System.arraycopy(paddedPlaintext, 0, plaintext, 0, plaintext.length);
-
- if (!isValid)
- {
- throw new InvalidCipherTextException("checksum failed");
- }
-
- return plaintext;
- }
-
- /**
- * Performs steps 1 and 2 of the unwrap process defined in RFC 3394.
- * This code is duplicated from RFC3394WrapEngine because that class
- * will throw an error during unwrap because the IV won't match up.
- *
- * @param in
- * @param inOff
- * @param inLen
- * @return Unwrapped data.
- */
- private byte[] rfc3394UnwrapNoIvCheck(byte[] in, int inOff, int inLen)
- {
- byte[] iv = new byte[8];
- byte[] block = new byte[inLen - iv.length];
- byte[] a = new byte[iv.length];
- byte[] buf = new byte[8 + iv.length];
-
- System.arraycopy(in, inOff, a, 0, iv.length);
- System.arraycopy(in, inOff + iv.length, block, 0, inLen - iv.length);
-
- engine.init(false, param);
-
- int n = inLen / 8;
- n = n - 1;
-
- for (int j = 5; j >= 0; j--)
- {
- for (int i = n; i >= 1; i--)
- {
- System.arraycopy(a, 0, buf, 0, iv.length);
- System.arraycopy(block, 8 * (i - 1), buf, iv.length, 8);
-
- int t = n * j + i;
- for (int k = 1; t != 0; k++)
- {
- byte v = (byte)t;
-
- buf[iv.length - k] ^= v;
-
- t >>>= 8;
- }
-
- engine.processBlock(buf, 0, buf, 0);
- System.arraycopy(buf, 0, a, 0, 8);
- System.arraycopy(buf, 8, block, 8 * (i - 1), 8);
- }
- }
-
- // set the extracted AIV
- extractedAIV = a;
-
- return block;
- }
-
-}