diff options
-rw-r--r-- | crypto/src/crypto/engines/RC2WrapEngine.cs | 248 |
1 files changed, 93 insertions, 155 deletions
diff --git a/crypto/src/crypto/engines/RC2WrapEngine.cs b/crypto/src/crypto/engines/RC2WrapEngine.cs index 20768701f..0dd20c176 100644 --- a/crypto/src/crypto/engines/RC2WrapEngine.cs +++ b/crypto/src/crypto/engines/RC2WrapEngine.cs @@ -111,96 +111,66 @@ namespace Org.BouncyCastle.Crypto.Engines * @param inLen * @return */ - public virtual byte[] Wrap( - byte[] input, - int inOff, - int length) + public virtual byte[] Wrap(byte[] input, int inOff, int length) { if (!forWrapping) - { throw new InvalidOperationException("Not initialized for wrapping"); - } - int len = length + 1; - if ((len % 8) != 0) - { - len += 8 - (len % 8); - } + int len = (length + 8) & ~7; + int ivLen = iv.Length; - byte [] keyToBeWrapped = new byte[len]; + // Let TEMP = IV || WKCKS. + byte[] TEMP = Arrays.CopyOf(iv, ivLen + len + 8); + TEMP[ivLen] = (byte)length; + Array.Copy(input, inOff, TEMP, ivLen + 1, length); - keyToBeWrapped[0] = (byte)length; - Array.Copy(input, inOff, keyToBeWrapped, 1, length); - - byte[] pad = new byte[keyToBeWrapped.Length - length - 1]; - - if (pad.Length > 0) + int padLen = len - length - 1; + if (padLen > 0) { - sr.NextBytes(pad); - Array.Copy(pad, 0, keyToBeWrapped, length + 1, pad.Length); - } + sr.NextBytes(TEMP, ivLen + len - padLen, padLen); + } - // Compute the CMS Key Checksum, (section 5.6.1), call this CKS. - byte[] CKS = CalculateCmsKeyChecksum(keyToBeWrapped); + // Compute the CMS Key Checksum, (section 5.6.1), call this CKS. + CalculateCmsKeyChecksum(TEMP, ivLen, len, TEMP, ivLen + len); - // Let WKCKS = WK || CKS where || is concatenation. - byte[] WKCKS = new byte[keyToBeWrapped.Length + CKS.Length]; - - Array.Copy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.Length); - Array.Copy(CKS, 0, WKCKS, keyToBeWrapped.Length, CKS.Length); - - // Encrypt WKCKS in CBC mode using KEK as the key and IV as the - // initialization vector. Call the results TEMP1. - byte [] TEMP1 = new byte[WKCKS.Length]; - - Array.Copy(WKCKS, 0, TEMP1, 0, WKCKS.Length); - - int noOfBlocks = WKCKS.Length / engine.GetBlockSize(); - int extraBytes = WKCKS.Length % engine.GetBlockSize(); - - if (extraBytes != 0) - { - throw new InvalidOperationException("Not multiple of block length"); - } + int blockSize = engine.GetBlockSize(); - engine.Init(true, paramPlusIV); + // Encrypt WKCKS in CBC mode using KEK as the key and IV as the initialization vector. + { + engine.Init(true, paramPlusIV); - for (int i = 0; i < noOfBlocks; i++) - { - int currentBytePos = i * engine.GetBlockSize(); + int pos = ivLen; + while (pos < TEMP.Length) + { + engine.ProcessBlock(TEMP, pos, TEMP, pos); + pos += blockSize; + } - engine.ProcessBlock(TEMP1, currentBytePos, TEMP1, currentBytePos); + if (pos != TEMP.Length) + throw new InvalidOperationException("Not multiple of block length"); } - // Left TEMP2 = IV || TEMP1. - byte[] TEMP2 = new byte[this.iv.Length + TEMP1.Length]; - - Array.Copy(this.iv, 0, TEMP2, 0, this.iv.Length); - Array.Copy(TEMP1, 0, TEMP2, this.iv.Length, TEMP1.Length); - - // Reverse the order of the octets in TEMP2 and call the result TEMP3. - byte[] TEMP3 = new byte[TEMP2.Length]; - - for (int i = 0; i < TEMP2.Length; i++) - { - TEMP3[i] = TEMP2[TEMP2.Length - (i + 1)]; - } + // Reverse the order of the octets in TEMP. + Array.Reverse(TEMP); - // Encrypt TEMP3 in CBC mode using the KEK and an initialization vector + // Encrypt TEMP in CBC mode using the KEK and an initialization vector // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the desired // result. It is 40 octets long if a 168 bit key is being wrapped. - ParametersWithIV param2 = new ParametersWithIV(this.parameters, IV2); - - this.engine.Init(true, param2); - - for (int i = 0; i < noOfBlocks + 1; i++) { - int currentBytePos = i * engine.GetBlockSize(); + engine.Init(true, new ParametersWithIV(this.parameters, IV2)); - engine.ProcessBlock(TEMP3, currentBytePos, TEMP3, currentBytePos); - } + int pos = 0; + while (pos < TEMP.Length) + { + engine.ProcessBlock(TEMP, pos, TEMP, pos); + pos += blockSize; + } - return TEMP3; + if (pos != TEMP.Length) + throw new InvalidOperationException("Not multiple of block length"); + } + + return TEMP; } /** @@ -212,28 +182,16 @@ namespace Org.BouncyCastle.Crypto.Engines * @return * @throws InvalidCipherTextException */ - public virtual byte[] Unwrap( - byte[] input, - int inOff, - int length) + public virtual byte[] Unwrap(byte[] input, int inOff, int length) { if (forWrapping) - { throw new InvalidOperationException("Not set for unwrapping"); - } - if (input == null) - { throw new InvalidCipherTextException("Null pointer as ciphertext"); - } - if (length % engine.GetBlockSize() != 0) - { - throw new InvalidCipherTextException("Ciphertext not multiple of " - + engine.GetBlockSize()); - } + throw new InvalidCipherTextException("Ciphertext not multiple of " + engine.GetBlockSize()); - /* + /* // Check if the length of the cipher text is reasonable given the key // type. It must be 40 bytes for a 168 bit key and either 32, 40, or // 48 bytes for a 128, 192, or 256 bit key. If the length is not supported @@ -249,82 +207,64 @@ namespace Org.BouncyCastle.Crypto.Engines } */ - // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK - // and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3. - ParametersWithIV param2 = new ParametersWithIV(this.parameters, IV2); - - this.engine.Init(false, param2); + int blockSize = engine.GetBlockSize(); - byte [] TEMP3 = new byte[length]; + byte[] TEMP = new byte[length]; - Array.Copy(input, inOff, TEMP3, 0, length); + // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK + // and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP. + { + engine.Init(false, new ParametersWithIV(this.parameters, IV2)); - for (int i = 0; i < (TEMP3.Length / engine.GetBlockSize()); i++) - { - int currentBytePos = i * engine.GetBlockSize(); - - engine.ProcessBlock(TEMP3, currentBytePos, TEMP3, currentBytePos); - } - - // Reverse the order of the octets in TEMP3 and call the result TEMP2. - byte[] TEMP2 = new byte[TEMP3.Length]; - - for (int i = 0; i < TEMP3.Length; i++) - { - TEMP2[i] = TEMP3[TEMP3.Length - (i + 1)]; - } - - // Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining octets. - this.iv = new byte[8]; - - byte[] TEMP1 = new byte[TEMP2.Length - 8]; - - Array.Copy(TEMP2, 0, this.iv, 0, 8); - Array.Copy(TEMP2, 8, TEMP1, 0, TEMP2.Length - 8); + int pos = 0; + while (pos < TEMP.Length) + { + engine.ProcessBlock(input, inOff + pos, TEMP, pos); + pos += blockSize; + } - // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV - // found in the previous step. Call the result WKCKS. - this.paramPlusIV = new ParametersWithIV(this.parameters, this.iv); + if (pos != TEMP.Length) + throw new InvalidOperationException("Not multiple of block length"); + } - this.engine.Init(false, this.paramPlusIV); + // Reverse the order of the octets in TEMP. + Array.Reverse(TEMP); - byte[] LCEKPADICV = new byte[TEMP1.Length]; + // Decompose TEMP into IV, the first 8 octets, and LCEKPADICV, the remaining octets. + this.iv = Arrays.CopyOf(TEMP, 8); - Array.Copy(TEMP1, 0, LCEKPADICV, 0, TEMP1.Length); + // Decrypt LCEKPADICV using TRIPLedeS in CBC mode using the KEK and the IV + // found in the previous step. Call the result WKCKS. + this.paramPlusIV = new ParametersWithIV(this.parameters, this.iv); - for (int i = 0; i < (LCEKPADICV.Length / engine.GetBlockSize()); i++) { - int currentBytePos = i * engine.GetBlockSize(); + this.engine.Init(false, this.paramPlusIV); - engine.ProcessBlock(LCEKPADICV, currentBytePos, LCEKPADICV, currentBytePos); - } + int pos = 8; + while (pos < TEMP.Length) + { + engine.ProcessBlock(TEMP, pos, TEMP, pos); + pos += blockSize; + } - // Decompose LCEKPADICV. CKS is the last 8 octets and WK, the wrapped key, are - // those octets before the CKS. - byte[] result = new byte[LCEKPADICV.Length - 8]; - byte[] CKStoBeVerified = new byte[8]; + if (pos != TEMP.Length) + throw new InvalidOperationException("Not multiple of block length"); + } - Array.Copy(LCEKPADICV, 0, result, 0, LCEKPADICV.Length - 8); - Array.Copy(LCEKPADICV, LCEKPADICV.Length - 8, CKStoBeVerified, 0, 8); + // Decompose LCEKPADICV. CKS is the last 8 octets and WK, the wrapped key, are + // those octets before the CKS. - // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare - // with the CKS extracted in the above step. If they are not equal, return error. - if (!CheckCmsKeyChecksum(result, CKStoBeVerified)) - { - throw new InvalidCipherTextException( - "Checksum inside ciphertext is corrupted"); - } + // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare + // with the CKS extracted in the above step. If they are not equal, return error. + if (!CheckCmsKeyChecksum(TEMP, 8, TEMP.Length - 16, TEMP, TEMP.Length - 8)) + throw new InvalidCipherTextException("Checksum inside ciphertext is corrupted"); - if ((result.Length - ((result[0] & 0xff) + 1)) > 7) - { - throw new InvalidCipherTextException( - "too many pad bytes (" + (result.Length - ((result[0] & 0xff) + 1)) + ")"); - } + int padLen = TEMP.Length - 16 - TEMP[8] - 1; + if ((padLen & 7) != padLen) + throw new InvalidCipherTextException("Invalid padding length (" + padLen + ")"); // CEK is the wrapped key, now extracted for use in data decryption. - byte[] CEK = new byte[result[0]]; - Array.Copy(result, 1, CEK, 0, CEK.Length); - return CEK; + return Arrays.CopyOfRange(TEMP, 9, 9 + TEMP[8]); } /** @@ -340,15 +280,12 @@ namespace Org.BouncyCastle.Crypto.Engines * @throws Exception * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum */ - private byte[] CalculateCmsKeyChecksum( - byte[] key) + private void CalculateCmsKeyChecksum(byte[] key, int keyOff, int keyLen, byte[] cks, int cksOff) { - sha1.BlockUpdate(key, 0, key.Length); + sha1.BlockUpdate(key, keyOff, keyLen); sha1.DoFinal(digest, 0); - byte[] result = new byte[8]; - Array.Copy(digest, 0, result, 0, 8); - return result; + Array.Copy(digest, 0, cks, cksOff, 8); } /** @@ -357,11 +294,12 @@ namespace Org.BouncyCastle.Crypto.Engines * @return * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum */ - private bool CheckCmsKeyChecksum( - byte[] key, - byte[] checksum) + private bool CheckCmsKeyChecksum(byte[] key, int keyOff, int keyLen, byte[] cks, int cksOff) { - return Arrays.FixedTimeEquals(CalculateCmsKeyChecksum(key), checksum); + sha1.BlockUpdate(key, keyOff, keyLen); + sha1.DoFinal(digest, 0); + + return Arrays.FixedTimeEquals(8, digest, 0, cks, cksOff); } } } |