Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #5 from symform/crimson.openssl

New Crimson.OpenSsl wrapper ontop of openssl (libcrypto)
  • Loading branch information...
commit b6641f3b460210128ffb9a1d57010c1f4e41a448 2 parents 6f2c6b7 + 39237f1
@spouliot spouliot authored
Showing with 2,220 additions and 344 deletions.
  1. +1 −0  class/Crimson.CryptoDev/.gitignore
  2. +9 −323 class/Crimson.CryptoDev/Crimson.CryptoDev/CryptoDevTransform.cs
  3. +2 −1  class/Crimson.CryptoDev/Makefile
  4. +1 −1  class/Crimson.CryptoDev/Tests/AesKernelTest.cs
  5. +10 −0 class/Crimson.CryptoDev/Tests/CryptoDevTest.cs
  6. +1 −1  class/Crimson.CryptoDev/Tests/RijndaelKernelTest.cs
  7. +1 −1  class/Crimson.CryptoDev/Tests/SHA1KernelTest.cs
  8. +1 −1  class/Crimson.CryptoDev/Tests/SHA256KernelTest.cs
  9. +2 −12 class/Crimson.CryptoDev/tools/generator.cs
  10. +6 −0 class/Crimson.OpenSsl/.gitignore
  11. +2 −0  class/Crimson.OpenSsl/AUTHORS
  12. +89 −0 class/Crimson.OpenSsl/Crimson.OpenSsl/HashHelper.cs
  13. +209 −0 class/Crimson.OpenSsl/Crimson.OpenSsl/Native.cs
  14. +102 −0 class/Crimson.OpenSsl/Crimson.OpenSsl/OpenSslCryptoTransform.cs
  15. +57 −0 class/Crimson.OpenSsl/Crimson.OpenSsl/OpenSslUtil.cs
  16. +20 −0 class/Crimson.OpenSsl/LICENSE
  17. +85 −0 class/Crimson.OpenSsl/Makefile
  18. +19 −0 class/Crimson.OpenSsl/README
  19. +49 −0 class/Crimson.OpenSsl/Tests/AesOpenSslTests.cs
  20. +43 −0 class/Crimson.OpenSsl/Tests/OpenSslTests.cs
  21. +512 −0 class/Crimson.OpenSsl/Tests/RijndaelOpenSslTests.cs
  22. +43 −0 class/Crimson.OpenSsl/Tests/SHA1OpenSslTests.cs
  23. +43 −0 class/Crimson.OpenSsl/Tests/SHA256OpenSslTests.cs
  24. +241 −0 class/Crimson.OpenSsl/tools/generator.cs
  25. +256 −0 class/Crimson.OpenSsl/tools/torture.cs
  26. +5 −0 class/README
  27. +407 −0 common/CryptoTransformBase.cs
  28. +1 −1  tests/HashAlgorithmTest.cs
  29. +1 −1  tests/SHA1Test.cs
  30. +1 −1  tests/SHA256Test.cs
  31. +1 −1  tests/SymmetricAlgorithmTest.cs
View
1  class/Crimson.CryptoDev/.gitignore
@@ -4,3 +4,4 @@ CryptoTools.cs
SymmetricTransform.cs
TestResult.xml
AssemblyInfo.cs
+tools/generator.exe
View
332 class/Crimson.CryptoDev/Crimson.CryptoDev/CryptoDevTransform.cs
@@ -39,46 +39,23 @@
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
+using Crimson.Common;
using Mono.Security.Cryptography;
namespace Crimson.CryptoDev {
- unsafe class CryptoDevTransform : ICryptoTransform {
- bool encrypt;
- int BlockSizeByte;
- byte[] workBuff;
- bool lastBlock;
+ unsafe class CryptoDevTransform : CryptoTransformBase {
Crypt context;
- PaddingMode padding;
- byte[] iv;
byte[] save_iv;
- public CryptoDevTransform (SymmetricAlgorithm algo, Cipher cipher, bool encryption, byte[] rgbKey, byte[] rgbIV, int bufferBlockSize)
+ public CryptoDevTransform (SymmetricAlgorithm algo, Cipher cipher, bool encryption, byte[] rgbKey, byte[] rgbIV, int bufferBlockSize)
+ : base(algo, encryption, rgbKey, rgbIV)
+
{
if (!Helper.IsAvailable (cipher))
throw new CryptographicException (String.Format ("{0} not available from /dev/crypto", algo));
- if (rgbKey == null)
- throw new CryptographicException ("Invalid (null) key");
-
- BlockSizeByte = (algo.BlockSize >> 3);
-
- if (rgbIV == null) {
- rgbIV = KeyBuilder.IV (BlockSizeByte);
- } else {
- // compare the IV length with the "currently selected" block size and *ignore* IV that are too big
- if (rgbIV.Length < BlockSizeByte) {
- string msg = Locale.GetText ("IV is too small ({0} bytes), it should be {1} bytes long.",
- rgbIV.Length, BlockSizeByte);
- throw new CryptographicException (msg);
- }
- rgbIV = (byte[]) rgbIV.Clone ();
- }
-
- encrypt = encryption;
- padding = algo.Padding;
-
// linux does not requires cloning the file descriptor with CRIOGET
Session sess = new Session ();
sess.cipher = cipher;
@@ -101,32 +78,18 @@ public CryptoDevTransform (SymmetricAlgorithm algo, Cipher cipher, bool encrypti
context.op++;
if (algo.Mode != CipherMode.ECB) {
- iv = rgbIV;
save_iv = new byte [BlockSizeByte];
}
- // transform buffer
- workBuff = new byte [BlockSizeByte];
// change this value if the driver (e.g. mv_cesa) has a limit that
// it can process in a single shot (e.g. 1936 for AES)
BufferBlockSize = bufferBlockSize;
}
- ~CryptoDevTransform ()
- {
- Dispose (false);
- }
-
- void IDisposable.Dispose ()
- {
- Dispose (true);
- }
-
- protected virtual void Dispose (bool disposing)
+ protected override void Dispose (bool disposing)
{
if (context.ses != 0) {
Helper.CloseSession (ref context.ses);
- GC.SuppressFinalize (this);
}
}
@@ -134,30 +97,14 @@ protected virtual void Dispose (bool disposing)
get; set;
}
- public virtual bool CanTransformMultipleBlocks {
- get { return true; }
- }
-
- public virtual bool CanReuseTransform {
- get { return false; }
- }
-
- public virtual int InputBlockSize {
- get { return BlockSizeByte; }
- }
-
- public virtual int OutputBlockSize {
- get { return BlockSizeByte; }
- }
-
- void Transform (byte[] input, int inputOffset, byte[] output, int outputOffset, int length)
+ protected override void Transform (byte[] input, int inputOffset, byte[] output, int outputOffset, int length)
{
while (length > 0) {
int size = Math.Min (length, BufferBlockSize);
fixed (byte *v = iv)
fixed (byte *i = &input [inputOffset])
fixed (byte *o = &output [outputOffset]) {
- if (iv != null) {
+ if (save_iv != null) {
context.iv = (IntPtr) v;
if (!encrypt) {
@@ -180,7 +127,7 @@ void Transform (byte[] input, int inputOffset, byte[] output, int outputOffset,
}
}
- if (iv != null) {
+ if (save_iv != null) {
if (encrypt)
Buffer.BlockCopy (output, outputOffset + size - BlockSizeByte, iv, 0, BlockSizeByte);
else
@@ -192,266 +139,5 @@ void Transform (byte[] input, int inputOffset, byte[] output, int outputOffset,
outputOffset += size;
}
}
-
- private void CheckInput (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- if (inputBuffer == null)
- throw new ArgumentNullException ("inputBuffer");
- if (inputOffset < 0)
- throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
- if (inputCount < 0)
- throw new ArgumentOutOfRangeException ("inputCount", "< 0");
- // ordered to avoid possible integer overflow
- if (inputOffset > inputBuffer.Length - inputCount)
- throw new ArgumentException ("inputBuffer", Locale.GetText ("Overflow"));
- }
-
- // this method may get called MANY times so this is the one to optimize
- public virtual int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- CheckInput (inputBuffer, inputOffset, inputCount);
- // check output parameters
- if (outputBuffer == null)
- throw new ArgumentNullException ("outputBuffer");
- if (outputOffset < 0)
- throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
-
- // ordered to avoid possible integer overflow
- int len = outputBuffer.Length - inputCount - outputOffset;
- if (!encrypt && (0 > len) && ((padding == PaddingMode.None) || (padding == PaddingMode.Zeros))) {
- throw new CryptographicException ("outputBuffer", Locale.GetText ("Overflow"));
- } else if (KeepLastBlock) {
- if (0 > len + BlockSizeByte) {
- throw new CryptographicException ("outputBuffer", Locale.GetText ("Overflow"));
- }
- } else {
- if (0 > len) {
- // there's a special case if this is the end of the decryption process
- if (inputBuffer.Length - inputOffset - outputBuffer.Length == BlockSizeByte)
- inputCount = outputBuffer.Length - outputOffset;
- else
- throw new CryptographicException ("outputBuffer", Locale.GetText ("Overflow"));
- }
- }
- return InternalTransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
- }
-
- private bool KeepLastBlock {
- get {
- return ((!encrypt) && (padding != PaddingMode.None) && (padding != PaddingMode.Zeros));
- }
- }
-
- private int InternalTransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- int offs = inputOffset;
- int full;
-
- // this way we don't do a modulo every time we're called
- // and we may save a division
- if (inputCount != BlockSizeByte) {
- if ((inputCount % BlockSizeByte) != 0)
- throw new CryptographicException ("Invalid input block size.");
-
- full = inputCount / BlockSizeByte;
- } else
- full = 1;
-
- if (KeepLastBlock)
- full--;
-
- int total = 0;
-
- if (lastBlock) {
- Transform (workBuff, 0, outputBuffer, outputOffset, BlockSizeByte);
- outputOffset += BlockSizeByte;
- total += BlockSizeByte;
- lastBlock = false;
- }
-
- if (full > 0) {
- int length = full * BlockSizeByte;
- Transform (inputBuffer, offs, outputBuffer, outputOffset, length);
- offs += length;
- outputOffset += length;
- total += length;
- }
-
- if (KeepLastBlock) {
- Buffer.BlockCopy (inputBuffer, offs, workBuff, 0, BlockSizeByte);
- lastBlock = true;
- }
-
- return total;
- }
-
- RandomNumberGenerator _rng;
-
- private void Random (byte[] buffer, int start, int length)
- {
- if (_rng == null) {
- _rng = RandomNumberGenerator.Create ();
- }
- byte[] random = new byte [length];
- _rng.GetBytes (random);
- Buffer.BlockCopy (random, 0, buffer, start, length);
- }
-
- private void ThrowBadPaddingException (PaddingMode padding, int length, int position)
- {
- string msg = String.Format (Locale.GetText ("Bad {0} padding."), padding);
- if (length >= 0)
- msg += String.Format (Locale.GetText (" Invalid length {0}."), length);
- if (position >= 0)
- msg += String.Format (Locale.GetText (" Error found at position {0}."), position);
- throw new CryptographicException (msg);
- }
-
- private byte[] FinalEncrypt (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- // are there still full block to process ?
- int full = (inputCount / BlockSizeByte) * BlockSizeByte;
- int rem = inputCount - full;
- int total = full;
-
- switch (padding) {
- case PaddingMode.ANSIX923:
- case PaddingMode.ISO10126:
- case PaddingMode.PKCS7:
- // we need to add an extra block for padding
- total += BlockSizeByte;
- break;
- default:
- if (inputCount == 0)
- return new byte [0];
- if (rem != 0) {
- if (padding == PaddingMode.None)
- throw new CryptographicException ("invalid block length");
- // zero padding the input (by adding a block for the partial data)
- byte[] paddedInput = new byte [full + BlockSizeByte];
- Buffer.BlockCopy (inputBuffer, inputOffset, paddedInput, 0, inputCount);
- inputBuffer = paddedInput;
- inputOffset = 0;
- inputCount = paddedInput.Length;
- total = inputCount;
- }
- break;
- }
-
- byte[] res = new byte [total];
- int outputOffset = 0;
-
- // process all blocks except the last (final) block
- if (total > BlockSizeByte) {
- outputOffset = InternalTransformBlock (inputBuffer, inputOffset, total - BlockSizeByte, res, 0);
- inputOffset += outputOffset;
- }
-
- // now we only have a single last block to encrypt
- byte pad = (byte) (BlockSizeByte - rem);
- switch (padding) {
- case PaddingMode.ANSIX923:
- // XX 00 00 00 00 00 00 07 (zero + padding length)
- res [res.Length - 1] = pad;
- Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
- // the last padded block will be transformed in-place
- InternalTransformBlock (res, full, BlockSizeByte, res, full);
- break;
- case PaddingMode.ISO10126:
- // XX 3F 52 2A 81 AB F7 07 (random + padding length)
- Random (res, res.Length - pad, pad - 1);
- res [res.Length - 1] = pad;
- Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
- // the last padded block will be transformed in-place
- InternalTransformBlock (res, full, BlockSizeByte, res, full);
- break;
- case PaddingMode.PKCS7:
- // XX 07 07 07 07 07 07 07 (padding length)
- for (int i = res.Length; --i >= (res.Length - pad);)
- res [i] = pad;
- Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
- // the last padded block will be transformed in-place
- InternalTransformBlock (res, full, BlockSizeByte, res, full);
- break;
- default:
- InternalTransformBlock (inputBuffer, inputOffset, BlockSizeByte, res, outputOffset);
- break;
- }
- return res;
- }
-
- private byte[] FinalDecrypt (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- if ((inputCount % BlockSizeByte) > 0)
- throw new CryptographicException ("Invalid input block size.");
-
- int total = inputCount;
- if (lastBlock)
- total += BlockSizeByte;
-
- byte[] res = new byte [total];
- int outputOffset = 0;
-
- if (inputCount > 0)
- outputOffset = InternalTransformBlock (inputBuffer, inputOffset, inputCount, res, 0);
-
- if (lastBlock) {
- Transform (workBuff, 0, res, outputOffset, BlockSizeByte);
- outputOffset += BlockSizeByte;
- lastBlock = false;
- }
-
- // total may be 0 (e.g. PaddingMode.None)
- byte pad = ((total > 0) ? res [total - 1] : (byte) 0);
- switch (padding) {
- case PaddingMode.ANSIX923:
- if ((pad == 0) || (pad > BlockSizeByte))
- ThrowBadPaddingException (padding, pad, -1);
- for (int i = pad - 1; i > 0; i--) {
- if (res [total - 1 - i] != 0x00)
- ThrowBadPaddingException (padding, -1, i);
- }
- total -= pad;
- break;
- case PaddingMode.ISO10126:
- if ((pad == 0) || (pad > BlockSizeByte))
- ThrowBadPaddingException (padding, pad, -1);
- total -= pad;
- break;
- case PaddingMode.PKCS7:
- if ((pad == 0) || (pad > BlockSizeByte))
- ThrowBadPaddingException (padding, pad, -1);
- for (int i = pad - 1; i > 0; i--) {
- if (res [total - 1 - i] != pad)
- ThrowBadPaddingException (padding, -1, i);
- }
- total -= pad;
- break;
- case PaddingMode.None: // nothing to do - it's a multiple of block size
- case PaddingMode.Zeros: // nothing to do - user must unpad himself
- break;
- }
-
- // return output without padding
- if (total > 0) {
- byte[] data = new byte [total];
- Buffer.BlockCopy (res, 0, data, 0, total);
- // zeroize decrypted data (copy with padding)
- Array.Clear (res, 0, res.Length);
- return data;
- }
- else
- return new byte [0];
- }
-
- public virtual byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- CheckInput (inputBuffer, inputOffset, inputCount);
-
- if (encrypt)
- return FinalEncrypt (inputBuffer, inputOffset, inputCount);
- else
- return FinalDecrypt (inputBuffer, inputOffset, inputCount);
- }
}
}
View
3  class/Crimson.CryptoDev/Makefile
@@ -12,7 +12,8 @@ SOURCES = \
Crimson.Security.Cryptography/RijndaelKernel.cs \
CryptoTools.cs \
AssemblyInfo.cs \
- ../../common/Locale.cs
+ ../../common/Locale.cs \
+ ../../common/CryptoTransformBase.cs
all: Crimson.CryptoDev.dll
View
2  class/Crimson.CryptoDev/Tests/AesKernelTest.cs
@@ -40,7 +40,7 @@ public class AesKernelTest : AesTest {
[SetUp]
protected void SetUp ()
{
- CryptoDevTest.EnsureAvailability ();
+ CryptoDevTest.EnsureAvailability (Crimson.CryptoDev.Cipher.AES_CBC);
algo = Create (); // shared
}
View
10 class/Crimson.CryptoDev/Tests/CryptoDevTest.cs
@@ -26,6 +26,7 @@
using System;
using System.IO;
+using Crimson.CryptoDev;
using NUnit.Framework;
@@ -51,5 +52,14 @@ static public void EnsureAvailability ()
// fix by doing "sudo chmod 600 /dev/crypto"
}
}
+
+ static public void EnsureAvailability (Cipher cipher)
+ {
+ EnsureAvailability();
+
+ if (!Crimson.CryptoDev.Helper.IsAvailable (cipher)) {
+ Assert.Ignore (string.Format("{0} not available on this platform", cipher));
+ }
+ }
}
}
View
2  class/Crimson.CryptoDev/Tests/RijndaelKernelTest.cs
@@ -41,7 +41,7 @@ public class RijndaelKernelTest : RijndaelTest {
[SetUp]
protected void SetUp ()
{
- CryptoDevTest.EnsureAvailability ();
+ CryptoDevTest.EnsureAvailability (Crimson.CryptoDev.Cipher.AES_CBC);
algo = Create (); // shared
}
View
2  class/Crimson.CryptoDev/Tests/SHA1KernelTest.cs
@@ -39,7 +39,7 @@ public class SHA1KernelTest : SHA1Test {
[SetUp]
protected void SetUp ()
{
- CryptoDevTest.EnsureAvailability ();
+ CryptoDevTest.EnsureAvailability (Crimson.CryptoDev.Cipher.SHA1);
hash = new SHA1Kernel ();
}
}
View
2  class/Crimson.CryptoDev/Tests/SHA256KernelTest.cs
@@ -39,7 +39,7 @@ public class SHA256KernelTest : SHA256Test {
[SetUp]
protected void SetUp ()
{
- CryptoDevTest.EnsureAvailability ();
+ CryptoDevTest.EnsureAvailability (Crimson.CryptoDev.Cipher.SHA256);
hash = new SHA256Kernel ();
}
}
View
14 class/Crimson.CryptoDev/tools/generator.cs
@@ -76,21 +76,11 @@ public class {0}Kernel : {0} {
public static int BufferBlockSize { get; set; }
- public {0}Kernel ()
- {
- }
-
- ~{0}Kernel ()
- {
- Dispose (false);
- }
-
protected override void Dispose (bool disposing)
{
- if (disposing && (helper != null)) {
+ if (disposing && helper != null) {
helper.Dispose ();
- helper = null;
- GC.SuppressFinalize (this);
+ helper = null;
}
base.Dispose (disposing);
}
View
6 class/Crimson.OpenSsl/.gitignore
@@ -0,0 +1,6 @@
+*.dll*
+Crimson.Security.Cryptography/*.g.cs
+TestResult.xml
+AssemblyInfo.cs
+tools/generator.exe
+torture.exe*
View
2  class/Crimson.OpenSsl/AUTHORS
@@ -0,0 +1,2 @@
+Sebastien Pouliot <sebastien.pouliot@gmail.com>
+Bassam Tabbara <bassam@symform.com>
View
89 class/Crimson.OpenSsl/Crimson.OpenSsl/HashHelper.cs
@@ -0,0 +1,89 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace Crimson.OpenSsl
+{
+ using System;
+ using System.Security.Cryptography;
+
+ internal sealed class HashHelper : IDisposable
+ {
+ private readonly Native.SafeDigestContextHandle context;
+ private readonly int hashSize;
+
+ public HashHelper (Native.SafeDigestHandle digest, int hashSize)
+ {
+ this.hashSize = hashSize >> 3;
+ if (this.hashSize > Native.MaximumDigestSize) {
+ throw new ArgumentOutOfRangeException ("hashSize");
+ }
+
+ this.context = Native.EVP_MD_CTX_create ();
+ Native.ExpectSuccess (Native.EVP_DigestInit_ex (this.context, digest, IntPtr.Zero));
+ }
+
+ public void Dispose ()
+ {
+ this.context.Dispose ();
+ }
+
+ public unsafe void Update (byte[] data, int start, int length)
+ {
+ if (length == 0) {
+ return;
+ }
+
+ if (length < uint.MinValue) {
+ throw new ArgumentOutOfRangeException ("length");
+ }
+
+ fixed (byte* p = &data[start]) {
+ Native.ExpectSuccess (Native.EVP_DigestUpdate (this.context, (IntPtr)p, (uint)length));
+ }
+ }
+
+ public unsafe byte[] Final ()
+ {
+ var digest = new byte[Native.MaximumDigestSize];
+ uint len;
+
+ fixed (byte* p = &digest[0]) {
+ Native.ExpectSuccess (Native.EVP_DigestFinal_ex (this.context, (IntPtr)p, out len));
+ }
+
+ if (len != this.hashSize) {
+ throw new CryptographicException (string.Format ("Mismatched hash length was expecting {0} but got {1}", this.hashSize, len));
+ }
+
+ if (len == digest.Length) {
+ return digest;
+ }
+
+ var trimmed = new byte[this.hashSize];
+ Buffer.BlockCopy (digest, 0, trimmed, 0, this.hashSize);
+ return trimmed;
+ }
+ }
+}
View
209 class/Crimson.OpenSsl/Crimson.OpenSsl/Native.cs
@@ -0,0 +1,209 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace Crimson.OpenSsl
+{
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Security.Cryptography;
+
+ /// <summary>
+ /// Documentation can be found here: http://www.openssl.org/docs/crypto/EVP_DigestInit.html
+ /// </summary>
+ internal static class Native
+ {
+ const string DllName = "libcrypto";
+
+ public static void ExpectSuccess (bool ret)
+ {
+ if (!ret) {
+ throw new CryptographicException ();
+ }
+ }
+ //
+ // Version
+ //
+ [Serializable]
+ public enum SSLeayVersionType
+ {
+ SSLEAY_VERSION = 0,
+ SSLEAY_CFLAGS = 2,
+ SSLEAY_BUILT_ON = 3,
+ SSLEAY_PLATFORM = 4,
+ SSLEAY_DIR = 5,
+ }
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false, CharSet = CharSet.Ansi)]
+ public extern static IntPtr SSLeay_version (SSLeayVersionType type);
+ //
+ // Digests
+ //
+ public const int MaximumDigestSize = 64;
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeDigestHandle EVP_md5 ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeDigestHandle EVP_sha1 ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeDigestHandle EVP_sha256 ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeDigestContextHandle EVP_MD_CTX_create ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ private extern static void EVP_MD_CTX_destroy (IntPtr ctx);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public extern static bool EVP_DigestInit_ex (SafeDigestContextHandle ctx, SafeDigestHandle type, IntPtr impl);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public extern static bool EVP_DigestUpdate (SafeDigestContextHandle ctx, IntPtr d, uint cnt);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public extern static bool EVP_DigestFinal_ex (SafeDigestContextHandle ctx, IntPtr md, out uint s);
+
+ internal sealed class SafeDigestHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ private SafeDigestHandle () :
+ base (false)
+ {
+ }
+
+ protected override bool ReleaseHandle ()
+ {
+ return false;
+ }
+ }
+
+ internal sealed class SafeDigestContextHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal SafeDigestContextHandle (IntPtr handle, bool ownsHandle) :
+ base(ownsHandle)
+ {
+ this.SetHandle (handle);
+ }
+
+ private SafeDigestContextHandle () :
+ base (true)
+ {
+ }
+
+ protected override bool ReleaseHandle ()
+ {
+ EVP_MD_CTX_destroy (this.handle);
+ return true;
+ }
+ }
+ //
+ // Ciphers
+ //
+ [Serializable]
+ public enum CipherOperation
+ {
+ Unchanged = -1,
+ Decrypt = 0,
+ Encrypt = 1,
+ }
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherHandle EVP_aes_128_cbc ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherHandle EVP_aes_192_cbc ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherHandle EVP_aes_256_cbc ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherHandle EVP_aes_128_ecb ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherHandle EVP_aes_192_ecb ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherHandle EVP_aes_256_ecb ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ public extern static SafeCipherContextHandle EVP_CIPHER_CTX_new ();
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ private extern static void EVP_CIPHER_CTX_free (IntPtr a);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public extern static bool EVP_CIPHER_CTX_set_key_length (SafeCipherContextHandle x, int keylen);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public extern static bool EVP_CIPHER_CTX_set_padding (SafeCipherContextHandle x, int padding);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public extern static bool EVP_CipherInit_ex (SafeCipherContextHandle ctx, SafeCipherHandle type, IntPtr impl, IntPtr key, IntPtr iv, CipherOperation enc);
+
+ [DllImport (DllName, CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
+ [return: MarshalAs (UnmanagedType.Bool)]
+ public extern static bool EVP_CipherUpdate (SafeCipherContextHandle ctx, IntPtr outb, out int outl, IntPtr inb, int inl);
+
+ internal sealed class SafeCipherHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ private SafeCipherHandle () :
+ base (false)
+ {
+ }
+
+ protected override bool ReleaseHandle ()
+ {
+ return false;
+ }
+ }
+
+ internal sealed class SafeCipherContextHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ internal SafeCipherContextHandle (IntPtr handle, bool ownsHandle) :
+ base (ownsHandle)
+ {
+ this.SetHandle (handle);
+ }
+
+ private SafeCipherContextHandle () :
+ base (true)
+ {
+ }
+
+ protected override bool ReleaseHandle ()
+ {
+ EVP_CIPHER_CTX_free (this.handle);
+ return true;
+ }
+ }
+ }
+}
View
102 class/Crimson.OpenSsl/Crimson.OpenSsl/OpenSslCryptoTransform.cs
@@ -0,0 +1,102 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace Crimson.OpenSsl
+{
+ using System;
+ using System.Security.Cryptography;
+ using Crimson.Common;
+
+ internal unsafe class OpenSslCryptoTransform : CryptoTransformBase
+ {
+ private readonly Native.SafeCipherContextHandle context;
+
+ public OpenSslCryptoTransform (SymmetricAlgorithm algo, bool encrypt, byte[] rgbKey, byte[] rgbIV)
+ : base (algo, encrypt, rgbKey, rgbIV)
+ {
+ OpenSslUtil.EnsureAvailability ();
+
+ this.context = Native.EVP_CIPHER_CTX_new ();
+
+ var cptr = this.GetCipher (algo.Mode, rgbKey.Length);
+ var op = encrypt ? Native.CipherOperation.Encrypt : Native.CipherOperation.Decrypt;
+
+ fixed (byte* pkey = &rgbKey[0])
+ fixed (byte* piv = &iv[0]) {
+ Native.ExpectSuccess (Native.EVP_CipherInit_ex (this.context, cptr, IntPtr.Zero, (IntPtr)pkey, (IntPtr)piv, op));
+ }
+
+ Native.ExpectSuccess (Native.EVP_CIPHER_CTX_set_key_length (this.context, rgbKey.Length));
+ Native.ExpectSuccess (Native.EVP_CIPHER_CTX_set_padding (this.context, 0));
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ if (disposing) {
+ this.context.Dispose ();
+ }
+
+ base.Dispose (disposing);
+ }
+
+ protected override void Transform (byte[] inputBuffer, int inputOffset, byte[] outputBuffer, int outputOffset, int inputCount)
+ {
+ fixed (byte* input = &inputBuffer[inputOffset])
+ fixed (byte* output = &outputBuffer[outputOffset]) {
+ int outputCount;
+ Native.ExpectSuccess (Native.EVP_CipherUpdate (this.context, (IntPtr)output, out outputCount, (IntPtr)input, inputCount));
+ }
+ }
+
+ private Native.SafeCipherHandle GetCipher (CipherMode mode, int keyLength)
+ {
+ if (mode == CipherMode.CBC) {
+ switch (keyLength) {
+ case 16:
+ return Native.EVP_aes_128_cbc ();
+
+ case 24:
+ return Native.EVP_aes_192_cbc ();
+
+ case 32:
+ return Native.EVP_aes_256_cbc ();
+ }
+ } else if (mode == CipherMode.ECB) {
+ switch (keyLength) {
+ case 16:
+ return Native.EVP_aes_128_ecb ();
+
+ case 24:
+ return Native.EVP_aes_192_ecb ();
+
+ case 32:
+ return Native.EVP_aes_256_ecb ();
+ }
+ }
+
+ throw new CryptographicException (string.Format ("{0} not supported", mode));
+ }
+ }
+}
View
57 class/Crimson.OpenSsl/Crimson.OpenSsl/OpenSslUtil.cs
@@ -0,0 +1,57 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+namespace Crimson.OpenSsl
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Security.Cryptography;
+
+ public class OpenSslUtil
+ {
+ public static bool IsAvailable ()
+ {
+ try {
+ GetVersionInfo ();
+ } catch (DllNotFoundException) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public static void EnsureAvailability ()
+ {
+ if (!IsAvailable ()) {
+ throw new CryptographicException ("libcrypto was not found");
+ }
+ }
+
+ public static string GetVersionInfo ()
+ {
+ return Marshal.PtrToStringAnsi (Native.SSLeay_version (Native.SSLeayVersionType.SSLEAY_VERSION));
+ }
+ }
+}
View
20 class/Crimson.OpenSsl/LICENSE
@@ -0,0 +1,20 @@
+Copyright 2013 Symform Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
85 class/Crimson.OpenSsl/Makefile
@@ -0,0 +1,85 @@
+CSC=gmcs
+
+CSC_FLAGS= -optimize
+#CSC_FLAGS= -debug
+
+SOURCES = \
+ Crimson.OpenSsl/Native.cs \
+ Crimson.OpenSsl/HashHelper.cs \
+ Crimson.OpenSsl/OpenSslCryptoTransform.cs \
+ Crimson.OpenSsl/OpenSslUtil.cs \
+ AssemblyInfo.cs \
+ ../../common/Locale.cs \
+ ../../common/CryptoTransformBase.cs
+
+all: Crimson.OpenSsl.dll
+
+GENERATED_SOURCES = \
+ Crimson.Security.Cryptography/AesOpenSsl.g.cs \
+ Crimson.Security.Cryptography/RijndaelOpenSsl.g.cs \
+ Crimson.Security.Cryptography/SHA1OpenSsl.g.cs \
+ Crimson.Security.Cryptography/SHA256OpenSsl.g.cs
+
+tools/generator.exe: tools/generator.cs
+ $(CSC) -t:exe -out:$@ $^
+
+$(GENERATED_SOURCES): tools/generator.exe
+ mono tools/generator.exe Crimson.Security.Cryptography
+
+AssemblyInfo.cs:
+ @ver='tarball'; \
+ if test -d $(CURDIR)/../../.git; then \
+ cd $(CURDIR)/../..; \
+ LANG=C; export LANG; \
+ branch=`git branch | grep '^\*' | cut -d ' ' -f 2`; \
+ version=`git log --no-color --first-parent -n1 --pretty=format:%h`; \
+ if [ "$$branch" = '(no' ]; then \
+ ver="$$version"; \
+ else \
+ ver="$$branch/$$version"; \
+ fi; \
+ cd $(CURDIR); \
+ fi; \
+ ( \
+ echo "using System.Reflection;"; \
+ echo "[assembly:AssemblyInformationalVersionAttribute(\"$${ver}\")]"; \
+ ) > $@
+
+Crimson.OpenSsl.dll: $(SOURCES) $(GENERATED_SOURCES)
+ $(CSC) $(CSC_FLAGS) $^ -t:library -unsafe -out:$@ -keyfile:../crimson.snk
+
+torture.exe: Crimson.OpenSsl.dll tools/torture.cs
+ dmcs -debug tools/torture.cs -r:Crimson.OpenSsl.dll -out:torture.exe
+
+torture: torture.exe
+ mono --debug torture.exe -v
+
+clean:
+ rm -f torture.exe*
+ rm -f tools/generator.exe
+ rm -f $(GENERATED_SOURCES) AssemblyInfo.cs
+ rm -f *.dll*
+
+BASE_TESTS = \
+ ../../tests/AesTest.cs \
+ ../../tests/HashAlgorithmTest.cs \
+ ../../tests/RijndaelTest.cs \
+ ../../tests/SHA1Test.cs \
+ ../../tests/SHA256Test.cs \
+ ../../tests/SymmetricAlgorithmTest.cs
+
+TESTS = \
+ Tests/AesOpenSslTests.cs \
+ Tests/RijndaelOpenSslTests.cs \
+ Tests/SHA1OpenSslTests.cs \
+ Tests/SHA256OpenSslTests.cs \
+ Tests/OpenSslTests.cs
+
+Crimson.OpenSsl.Tests.dll: $(BASE_TESTS) $(TESTS) Crimson.OpenSsl.dll
+ mcs -debug $(BASE_TESTS) $(TESTS) -t:library -out:$@ -r:Crimson.OpenSsl.dll -pkg:mono-nunit
+
+test: Crimson.OpenSsl.Tests.dll
+
+run-test: test
+ @echo running tests
+ nunit-console Crimson.OpenSsl.Tests.dll
View
19 class/Crimson.OpenSsl/README
@@ -0,0 +1,19 @@
+This assembly goal is to provide a managed wrapper on top of libcrypto[1].
+
+References:
+[1] http://www.openssl.org/
+
+libcrypto Availability
+----------------------
+
+Most Linux distributions ship with openssl.
+
+Building
+--------
+
+If a recent mono is available then 'make' should be enough to build
+the generator (creating the source files) and then build the assembly
+
+You can verify that everything works, if nunit is available, by doing
+'make run-test'
+
View
49 class/Crimson.OpenSsl/Tests/AesOpenSslTests.cs
@@ -0,0 +1,49 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Security.Cryptography;
+using Crimson.Security.Cryptography;
+using Crimson.Test.Base;
+using NUnit.Framework;
+
+namespace Crimson.Test.OpenSsl
+{
+ [TestFixture]
+ public class AesKernelTest : AesTest
+ {
+
+ [SetUp]
+ protected void SetUp ()
+ {
+ algo = Create (); // shared
+ }
+
+ protected override SymmetricAlgorithm Create ()
+ {
+ return new AesOpenSsl ();
+ }
+ }
+}
View
43 class/Crimson.OpenSsl/Tests/OpenSslTests.cs
@@ -0,0 +1,43 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using NUnit.Framework;
+using Crimson.OpenSsl;
+
+namespace Crimson.Test.OpenSsl
+{
+ static class CryptoDevTest
+ {
+
+ static public void EnsureAvailability ()
+ {
+ if (!OpenSslUtil.IsAvailable ()) {
+ Assert.Ignore ("libcrypto not found.");
+ }
+ }
+ }
+}
View
512 class/Crimson.OpenSsl/Tests/RijndaelOpenSslTests.cs
@@ -0,0 +1,512 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Security.Cryptography;
+using Crimson.Security.Cryptography;
+using Crimson.Test.Base;
+using NUnit.Framework;
+
+namespace Crimson.Test.OpenSsl
+{
+ [TestFixture]
+ public class RijndaelOpenSslTests : RijndaelTest
+ {
+ [SetUp]
+ protected void SetUp ()
+ {
+ this.algo = this.Create (); // shared
+ }
+
+ protected override SymmetricAlgorithm Create ()
+ {
+ return new RijndaelOpenSsl ();
+ }
+
+ static bool Compare (byte[] actual, byte[] expected)
+ {
+ if (actual == null)
+ return (expected == null);
+ if (expected == null)
+ return false;
+ if (actual.Length != expected.Length)
+ return false;
+ for (int i = 0; i < actual.Length; i++) {
+ if (actual [i] != expected [i])
+ return false;
+ }
+ return true;
+ }
+
+ [Test]
+ public void CbcIvBlock ()
+ {
+ byte[] key = this.algo.Key;
+ byte[] iv = this.algo.IV;
+ this.algo.Mode = CipherMode.CBC;
+
+ // 1952 = max mv_cesa + one block
+ for (int i = 16; i <= 1952; i += 16) {
+ byte[] data = new byte[i];
+ byte[] enc1 = this.algo.CreateEncryptor ().TransformFinalBlock (data, 0, data.Length);
+ byte[] enc2 = null;
+ using (Rijndael r = new RijndaelManaged()) {
+ r.Mode = CipherMode.CBC;
+ r.Key = key;
+ r.IV = iv;
+ enc2 = this.algo.CreateEncryptor ().TransformFinalBlock (data, 0, data.Length);
+ }
+
+ if (!Compare (enc1, enc2))
+ Assert.Fail ("Data size = " + i);
+ }
+ }
+
+ private static byte[] key1 = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+ private static byte[] key2 = { 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01 };
+ private static byte[] key3 = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
+
+ protected byte[] CombineKeys(byte[] key1, byte[] key2, byte[] key3)
+ {
+ int k1l = key1.Length;
+ int k2l = key2.Length;
+ int k3l = key3.Length;
+ byte[] key = new byte[k1l + k2l + k3l];
+ Array.Copy(key1, 0, key, 0, k1l);
+ Array.Copy(key2, 0, key, k1l, k2l);
+ Array.Copy(key3, 0, key, k1l + k2l, k3l);
+ return key;
+ }
+
+ private Rijndael GetAES()
+ {
+ Rijndael aes = (Rijndael)this.Create();
+ aes.Key = this.CombineKeys(key1, key2, key3);
+ return aes;
+ }
+
+ private byte[] GetData(byte size)
+ {
+ byte[] data = new byte[size];
+ for (byte i = 0; i < size; i++)
+ {
+ data[i] = i;
+ }
+ return data;
+ }
+
+ private byte[] Decrypt(SymmetricAlgorithm algo, PaddingMode padding, byte[] data)
+ {
+ algo.IV = new byte[algo.BlockSize >> 3];
+ algo.Mode = CipherMode.CBC;
+ algo.Padding = padding;
+ ICryptoTransform ct = algo.CreateDecryptor();
+ return ct.TransformFinalBlock(data, 0, data.Length);
+ }
+
+ private byte[] Encrypt(SymmetricAlgorithm algo, PaddingMode padding, byte[] data)
+ {
+ algo.IV = new byte[algo.BlockSize >> 3];
+ algo.Mode = CipherMode.CBC;
+ algo.Padding = padding;
+ ICryptoTransform ct = algo.CreateEncryptor();
+ return ct.TransformFinalBlock(data, 0, data.Length);
+ }
+
+ [Test]
+ [ExpectedException(typeof(CryptographicException))]
+ public void RijndaelNone_SmallerThanOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(8);
+ this.Encrypt(aes, PaddingMode.None, data);
+ }
+
+ [Test]
+ public void RijndaelNone_ExactlyOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(16);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.None, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB", BitConverter.ToString(encdata), "RijndaelNone_ExactlyOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.None, encdata);
+ this.AssertEquals("RijndaelNone_ExactlyOneBlockSize_Decrypt", data, decdata);
+ }
+
+ [Test]
+ [ExpectedException(typeof(CryptographicException))]
+ public void RijndaelNone_MoreThanOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(20);
+ this.Encrypt(aes, PaddingMode.None, data);
+ }
+
+ [Test]
+ public void RijndaelNone_ExactMultipleBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(48);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.None, data);
+ // note: encrypted data is truncated to a multiple of block size
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF", BitConverter.ToString(encdata), "RijndaelNone_ExactMultipleBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.None, encdata);
+ this.AssertEquals("RijndaelNone_ExactMultipleBlockSize_Decrypt", this.GetData(48), decdata);
+ }
+
+ [Test]
+ public void RijndaelPKCS7_SmallerThanOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(8);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.PKCS7, data);
+ Assert.AreEqual("AB-E0-20-5E-BC-28-A0-B7-A7-56-A3-BF-13-55-13-7E", BitConverter.ToString(encdata), "RijndaelPKCS7_SmallerThanOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.PKCS7, encdata);
+ this.AssertEquals("RijndaelPKCS7_SmallerThanOneBlockSize_Decrypt", data, decdata);
+ }
+
+ [Test]
+ public void RijndaelPKCS7_ExactlyOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(16);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.PKCS7, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-60-CE-9F-E0-72-3B-D6-D1-A5-F8-33-D8-25-31-7F-D4", BitConverter.ToString(encdata), "RijndaelPKCS7_ExactlyOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.PKCS7, encdata);
+ this.AssertEquals("RijndaelPKCS7_ExactlyOneBlockSize_Decrypt", data, decdata);
+ }
+
+ [Test]
+ public void RijndaelPKCS7_MoreThanOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(20);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.PKCS7, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-06-3F-D3-51-8D-55-E9-2F-02-4A-4E-F2-91-55-31-83", BitConverter.ToString(encdata), "RijndaelPKCS7_MoreThanOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.PKCS7, encdata);
+ this.AssertEquals("RijndaelPKCS7_MoreThanOneBlockSize_Decrypt", data, decdata);
+ }
+
+ [Test]
+ public void RijndaelPKCS7_ExactMultipleBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(48);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.PKCS7, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF-37-42-81-21-47-A7-E0-AA-64-A7-8B-65-25-95-AA-54", BitConverter.ToString(encdata), "RijndaelPKCS7_ExactMultipleBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.PKCS7, encdata);
+ this.AssertEquals("RijndaelPKCS7_ExactMultipleBlockSize_Decrypt", data, decdata);
+ }
+
+ [Test]
+ public void RijndaelZeros_SmallerThanOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(8);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.Zeros, data);
+ Assert.AreEqual("DD-BE-D7-CE-E2-DD-5C-A3-3E-44-A1-76-00-E5-5B-5D", BitConverter.ToString(encdata), "RijndaelZeros_SmallerThanOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.Zeros, encdata);
+ Assert.AreEqual("00-01-02-03-04-05-06-07-00-00-00-00-00-00-00-00", BitConverter.ToString(decdata), "RijndaelZeros_SmallerThanOneBlockSize_Decrypt");
+ }
+
+ [Test]
+ public void RijndaelZeros_ExactlyOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(16);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.Zeros, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB", BitConverter.ToString(encdata), "RijndaelZeros_ExactlyOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.Zeros, encdata);
+ this.AssertEquals("RijndaelZeros_ExactlyOneBlockSize_Decrypt", data, decdata);
+ }
+
+ [Test]
+ public void RijndaelZeros_MoreThanOneBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(20);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.Zeros, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-04-6C-F7-A5-DE-FF-B4-30-29-7A-0E-04-3B-D4-B8-F2", BitConverter.ToString(encdata), "RijndaelZeros_MoreThanOneBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.Zeros, encdata);
+ Assert.AreEqual("00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-00-00-00-00-00-00-00-00-00-00-00-00", BitConverter.ToString(decdata), "RijndaelZeros_MoreThanOneBlockSize_Decrypt");
+ }
+
+ [Test]
+ public void RijndaelZeros_ExactMultipleBlockSize()
+ {
+ Rijndael aes = this.GetAES();
+ byte[] data = this.GetData(48);
+ byte[] encdata = this.Encrypt(aes, PaddingMode.Zeros, data);
+ Assert.AreEqual("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF", BitConverter.ToString(encdata), "RijndaelZeros_ExactMultipleBlockSize_Encrypt");
+ byte[] decdata = this.Decrypt(aes, PaddingMode.Zeros, encdata);
+ this.AssertEquals("RijndaelZeros_ExactMultipleBlockSize_Decrypt", this.GetData(48), decdata);
+ }
+
+ private byte[] GetKey(SymmetricAlgorithm sa)
+ {
+ byte[] key = new byte[sa.KeySize >> 3];
+ // no weak key this way (DES, TripleDES)
+ for (byte i = 0; i < key.Length; i++)
+ key[i] = i;
+ return key;
+ }
+
+ private byte[] GetIV(SymmetricAlgorithm sa)
+ {
+ return new byte[sa.BlockSize >> 3];
+ }
+
+ private ICryptoTransform GetEncryptor(SymmetricAlgorithm sa, PaddingMode mode)
+ {
+ sa.Mode = CipherMode.ECB; // basic (no) mode
+ sa.Padding = mode;
+ return sa.CreateEncryptor(this.GetKey(sa), this.GetIV(sa));
+ }
+
+ private ICryptoTransform GetDecryptor(SymmetricAlgorithm sa, PaddingMode mode)
+ {
+ sa.Mode = CipherMode.ECB; // basic (no) mode
+ sa.Padding = mode;
+ return sa.CreateDecryptor(this.GetKey(sa), this.GetIV(sa));
+ }
+
+ // the best way to verify padding is to:
+ // a. encrypt data larger than one block with a padding mode "X"
+ // b. decrypt the data with padding mode "None"
+ // c. compare the last (padding) bytes with the expected padding
+
+ private void ANSIX923_Full(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one full block
+ byte[] data = new byte[bs]; // in bytes
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.ANSIX923);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(data.Length * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - ANSI X.923 is all 0 except last byte (length)
+ for (int i = 0; i < bs - 1; i++)
+ Assert.AreEqual(0x00, decdata[decdata.Length - pd + i], i.ToString());
+ Assert.AreEqual(pd, decdata[decdata.Length - 1], "last byte");
+ }
+
+ private void ANSIX923_Partial(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one and an half block
+ byte[] data = new byte[bs + (bs >> 1)]; // in bytes
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.ANSIX923);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(bs * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - ANSI X.923 is all 0 except last byte (length)
+ for (int i = 0; i < pd - 1; i++)
+ Assert.AreEqual(0x00, decdata[decdata.Length - pd + i], i.ToString());
+ Assert.AreEqual(pd, decdata[decdata.Length - 1], "last byte");
+ }
+
+ private void ISO10126_Full(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one full block
+ byte[] data = new byte[bs]; // in bytes
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.ISO10126);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(data.Length * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - ISO10126 is all random except last byte (length)
+ Assert.AreEqual(pd, decdata[decdata.Length - 1], "last byte");
+ }
+
+ private void ISO10126_Partial(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one and an half block
+ byte[] data = new byte[bs + (bs >> 1)]; // in bytes
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.ISO10126);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(bs * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - ISO10126 is all random except last byte (length)
+ Assert.AreEqual(pd, decdata[decdata.Length - 1], "last byte");
+ }
+
+ private void PKCS7_Full(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one full block
+ byte[] data = new byte[bs]; // in bytes
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.PKCS7);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(data.Length * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - PKCS7 is all padding char
+ for (int i = 0; i < bs; i++)
+ Assert.AreEqual(pd, decdata[decdata.Length - pd + i], i.ToString());
+ }
+
+ private void PKCS7_Partial(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one and an half block
+ byte[] data = new byte[bs + (bs >> 1)]; // in bytes
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.PKCS7);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(bs * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - PKCS7 is all padding char
+ for (int i = 0; i < pd; i++)
+ Assert.AreEqual(pd, decdata[decdata.Length - pd + i], i.ToString());
+ }
+
+ private void Zeros_Full(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one full block
+ byte[] data = new byte[bs]; // in bytes
+ for (int i = 0; i < data.Length; i++)
+ data[i] = 0xFF;
+
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.Zeros);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // NO extra block is used for zero padding
+ Assert.AreEqual(data.Length, encdata.Length, "no extra block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ // now validate absence of padding
+ Assert.AreEqual(0xFF, decdata[decdata.Length - 1], "no padding");
+ }
+
+ private void Zeros_Partial(SymmetricAlgorithm sa)
+ {
+ int bs = (sa.BlockSize >> 3);
+ // one and an half block
+ byte[] data = new byte[bs + (bs >> 1)]; // in bytes
+ for (int i = 0; i < data.Length; i++)
+ data[i] = 0xFF;
+
+ ICryptoTransform enc = this.GetEncryptor(sa, PaddingMode.Zeros);
+ byte[] encdata = enc.TransformFinalBlock(data, 0, data.Length);
+ // one block of padding is added
+ Assert.AreEqual(bs * 2, encdata.Length, "one more block added");
+
+ ICryptoTransform dec = this.GetDecryptor(sa, PaddingMode.None);
+ byte[] decdata = dec.TransformFinalBlock(encdata, 0, encdata.Length);
+ Assert.AreEqual(encdata.Length, decdata.Length, "no unpadding");
+
+ int pd = decdata.Length - data.Length;
+ // now validate padding - Zeros is all 0x00 char
+ for (int i = 0; i < pd; i++)
+ Assert.AreEqual(0x00, decdata[decdata.Length - pd + i], i.ToString());
+ }
+
+ [Test]
+ public void Rijndael_ANSIX923_Full()
+ {
+ this.ANSIX923_Full(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_ANSIX923_Partial()
+ {
+ this.ANSIX923_Partial(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_ISO10126_Full()
+ {
+ this.ISO10126_Full(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_ISO10126_Partial()
+ {
+ this.ISO10126_Partial(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_PKCS7_Full()
+ {
+ this.PKCS7_Full(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_PKCS7_Partial()
+ {
+ this.PKCS7_Partial(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_Zeros_Full()
+ {
+ this.Zeros_Full(this.Create());
+ }
+
+ [Test]
+ public void Rijndael_Zeros_Partial()
+ {
+ this.Zeros_Partial(this.Create());
+ }
+ }
+}
View
43 class/Crimson.OpenSsl/Tests/SHA1OpenSslTests.cs
@@ -0,0 +1,43 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Security.Cryptography;
+using Crimson.Security.Cryptography;
+using Crimson.Test.Base;
+using NUnit.Framework;
+
+namespace Crimson.Test.OpenSsl
+{
+ [TestFixture]
+ public class SHA1OpenSslTests : SHA1Test
+ {
+ [SetUp]
+ protected void SetUp ()
+ {
+ hash = new SHA1OpenSsl ();
+ }
+ }
+}
View
43 class/Crimson.OpenSsl/Tests/SHA256OpenSslTests.cs
@@ -0,0 +1,43 @@
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Security.Cryptography;
+using Crimson.Security.Cryptography;
+using Crimson.Test.Base;
+using NUnit.Framework;
+
+namespace Crimson.Test.OpenSsl
+{
+ [TestFixture]
+ public class SHA256OpenSslTests : SHA256Test
+ {
+ [SetUp]
+ protected void SetUp ()
+ {
+ hash = new SHA256OpenSsl ();
+ }
+ }
+}
View
241 class/Crimson.OpenSsl/tools/generator.cs
@@ -0,0 +1,241 @@
+//
+// Author:
+// Sebastien Pouliot <sebastien@gmail.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+
+class Program {
+
+ static void GenerateHash (string name)
+ {
+ string template = @"// NOTE: Generated code DO NOT EDIT
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// 'Software'), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Security.Cryptography;
+using Crimson.OpenSsl;
+
+namespace Crimson.Security.Cryptography {
+
+ public class {0}OpenSsl : {0} {
+
+ private HashHelper helper;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && helper != null)
+ {
+ helper.Dispose();
+ helper = null;
+ }
+ base.Dispose(disposing);
+ }
+
+ public override void Initialize()
+ {
+ helper = new HashHelper(Native.EVP_{1}(), this.HashSize);
+ }
+
+ protected override void HashCore(byte[] data, int start, int length)
+ {
+ if (this.helper == null)
+ {
+ this.Initialize();
+ }
+
+ helper.Update(data, start, length);
+ }
+
+ protected override byte[] HashFinal()
+ {
+ if (this.helper == null)
+ {
+ this.Initialize();
+ }
+
+ return helper.Final();
+ }
+ }
+}";
+ string filename = Path.Combine (OutputDirectory,
+ String.Format ("{0}OpenSsl.g.cs", name));
+ string content = template.Replace ("{0}", name).
+ Replace ("{1}", name.ToLowerInvariant ());
+ File.WriteAllText (filename, content);
+ }
+
+ static void GenerateSymmetricAlgorithm (string name, string fallback)
+ {
+ string template = @"// NOTE: Generated code DO NOT EDIT
+//
+// Author:
+// Bassam Tabbara <bassam@symform.com>
+//
+// Copyright 2013 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// 'Software'), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System.Security.Cryptography;
+using Crimson.OpenSsl;
+
+namespace Crimson.Security.Cryptography {
+
+ public class {0}OpenSsl : {0} {
+
+ public static RandomNumberGenerator Rng = RandomNumberGenerator.Create();
+
+ public override void GenerateIV()
+ {
+ IVValue = new byte[BlockSizeValue >> 3];
+ Rng.GetBytes(IVValue);
+ }
+
+ public override void GenerateKey()
+ {
+ KeyValue = new byte[KeySizeValue >> 3];
+ Rng.GetBytes(KeyValue);
+ }
+
+ public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
+ {
+ try
+ {
+ if (BlockSize == 128)
+ {
+ return new OpenSslCryptoTransform(this, false, rgbKey, rgbIV);
+ }
+ }
+ catch (CryptographicException)
+ {
+ }
+
+ using (var r = this.Fallback())
+ {
+ return r.CreateDecryptor(rgbKey, rgbIV);
+ }
+ }
+
+ public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
+ {
+ try
+ {
+ if (BlockSize == 128)
+ {
+ return new OpenSslCryptoTransform(this, true, rgbKey, rgbIV);
+ }
+ }
+ catch (CryptographicException)
+ {
+ }
+
+ using (var r = this.Fallback())
+ {
+ return r.CreateEncryptor(rgbKey, rgbIV);
+ }
+ }
+
+ private {1} Fallback ()
+ {
+ {1} r = new {1} ();
+ r.Mode = Mode;
+ r.Padding = Padding;
+ r.BlockSize = BlockSize;
+ return r;
+ }
+ }
+}";
+ string filename = Path.Combine (OutputDirectory, String.Format ("{0}OpenSsl.g.cs", name));
+ string content = template.Replace ("{0}", name).Replace ("{1}", fallback);
+ File.WriteAllText (filename, content);
+ }
+
+ static string OutputDirectory { get; set; }
+
+ static void Main (string[] args)
+ {
+ OutputDirectory = args.Length == 0 ? "." : args [0];
+
+ System.IO.Directory.CreateDirectory (OutputDirectory);
+
+ GenerateHash ("SHA1"); // CRYPTO_SHA1
+ GenerateHash ("SHA256"); // CRYPTO_SHA256
+#if UNTESTED
+ GenerateHash ("MD5"); // CRYPTO_MD5
+ GenerateHash ("RIPEMD160"); // CRYPTO_RIPEMD160
+ GenerateHash ("SHA384"); // CRYPTO_SHA2_384
+ GenerateHash ("SHA512"); // CRYPTO_SHA2_512
+#endif
+ GenerateSymmetricAlgorithm ("Rijndael", "RijndaelManaged");
+ GenerateSymmetricAlgorithm ("Aes", "RijndaelManaged");
+#if UNTESTED
+ GenerateSymmetricAlgorithm ("Des", "DESCryptoServiceProvider", null, "DES_CBC");
+ GenerateSymmetricAlgorithm ("TripleDes", "TripleDESCryptoServiceProvider", null, "3DES_CBC");
+ // BLF (Blowfish), CAST, SKIPJACK and Camellia are not part of the .NET framework
+ // and would require a additional base classes and fallbacks
+#endif
+ }
+}
View
256 class/Crimson.OpenSsl/tools/torture.cs
@@ -0,0 +1,256 @@
+//
+// Author:
+// Sebastien Pouliot <sebastien@gmail.com>
+//
+// Copyright 2012 Symform Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Crimson.Security.Cryptography;
+
+class Program {
+
+ static bool verbose;
+
+ static byte[] sha_a_input = Encoding.Default.GetBytes ("abc");
+ static byte[] sha_b_input = Encoding.Default.GetBytes ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ static byte[] sha_c_input;
+
+ static Program ()
+ {
+ sha_c_input = new byte [1000000];
+ for (int i = 0; i < 1000000; i++)
+ sha_c_input[i] = 0x61; // a
+ }
+
+ static void Main (string [] args)
+ {
+ verbose = args.Length > 0;
+
+ Parallel.Invoke (
+ () => { SHA1a (); },
+ () => { SHA1b (); },
+ () => { SHA1c (); },
+ () => { SHA256a (); },
+ () => { SHA256b (); },
+ () => { SHA256c (); },
+ () => { AESa (); },
+ () => { AESb (); },
+ () => { AESc (); },
+ () => { AESd (); }
+ );
+ Console.WriteLine ("End");
+ }
+
+ static void SHA1 (string name, int max, byte[] input, byte[] output)
+ {
+ int i = 0;
+ try {
+ for (; i < max; i++) {
+ using (SHA1 digest = new SHA1OpenSsl ()) {
+ if (!Compare (output, digest.ComputeHash (input)))
+ throw new Exception (name + " " + i.ToString ());
+ }
+ Process (name, i, max);
+ }
+ }
+ catch (Exception e) {
+ Console.WriteLine ("{0} #{1} : {2}", name, i, e);
+ }
+ }
+
+ static byte[] sha1_a_output = new byte [] {
+ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
+ 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d };
+
+ static void SHA1a ()
+ {
+ SHA1 ("SHA1a", 10000, sha_a_input, sha1_a_output);
+ }
+
+ static byte[] sha1_b_output = new byte [] {
+ 0x84, 0x98, 0x3e, 0x44, 0x1c, 0x3b, 0xd2, 0x6e, 0xba, 0xae,
+ 0x4a, 0xa1, 0xf9, 0x51, 0x29, 0xe5, 0xe5, 0x46, 0x70, 0xf1 };
+
+ static void SHA1b ()
+ {
+ SHA1 ("SHA1b", 5000, sha_b_input, sha1_b_output);
+ }
+
+ static byte[] sha1_c_output = new byte [] {
+ 0x34, 0xaa, 0x97, 0x3c, 0xd4, 0xc4, 0xda, 0xa4, 0xf6, 0x1e,
+ 0xeb, 0x2b, 0xdb, 0xad, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6f };
+
+ static void SHA1c ()
+ {
+ SHA1 ("SHA1c", 2000, sha_c_input, sha1_c_output);
+ }
+
+ static void SHA256 (string name, int max, byte[] input, byte[] output)
+ {
+ int i = 0;
+ try {
+ for (; i < max; i++) {
+ using (SHA256 digest = new SHA256OpenSsl ()) {
+ if (!Compare (output, digest.ComputeHash (input)))
+ throw new Exception (name + " " + i.ToString ());
+ }
+ Process (name, i, max);
+ }
+ }
+ catch (Exception e) {
+ Console.WriteLine ("{0} #{1} : {2}", name, i, e);
+ }
+ }
+
+ static byte[] sha256_a_output = new byte [] {
+ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+ 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad };
+
+ static void SHA256a ()
+ {
+ SHA256 ("SHA256a", 8000, sha_a_input, sha256_a_output);
+ }
+
+ static byte[] sha256_b_output = new byte [] {
+ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
+ 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
+ 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
+ 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 };
+
+ static void SHA256b ()
+ {
+ SHA256 ("SHA256b", 4000, sha_b_input, sha256_b_output);
+ }
+
+ static byte[] sha256_c_output = new byte [] {
+ 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
+ 0x81, 0xa1, 0xc7, 0xe2, 0x84, 0xd7, 0x3e, 0x67,
+ 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
+ 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 };
+
+ static void SHA256c ()
+ {
+ SHA256 ("SHA256c", 2000, sha_c_input, sha256_c_output);
+ }
+
+ static void Process (string name, int iteration, int max)
+ {
+ if (!verbose)
+ return;
+ if (iteration % 1000 == 0)
+ Console.WriteLine ("{0} {1}/{2} ({3})", name, iteration, max, Thread.CurrentThread.ManagedThreadId);
+ }
+
+ static byte[] aes_iv = new byte [16];
+
+ static void AES (string name, int max, byte[] key, byte[] input, byte[] expected)
+ {
+ int i = 0;
+ try {
+ for (; i < max; i++) {
+ using (Aes cipher = new AesOpenSsl ()) {
+ cipher.Mode = CipherMode.ECB;
+ cipher.KeySize = key.Length * 8;
+ cipher.Padding = PaddingMode.Zeros;
+
+ byte[] output = new byte [input.Length];
+ ICryptoTransform encryptor = cipher.CreateEncryptor (key, aes_iv);
+ encryptor.TransformBlock (input, 0, input.Length, output, 0);
+ if (!Compare (output, expected))
+ throw new Exception ("encryptor");
+
+ byte[] original = new byte [output.Length];
+ ICryptoTransform decryptor = cipher.CreateDecryptor (key, aes_iv);
+ decryptor.TransformBlock (output, 0, output.Length, original, 0);
+ if (!Compare (original, input))
+ throw new Exception ("decryptor");
+ }
+ Process (name, i, max);
+ }
+ }
+ catch (Exception e) {
+ Console.WriteLine ("{0} #{1} : {2}", name, i, e);
+ }
+ }
+
+
+ static byte[] aes_a_key = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
+ static byte[] aes_a_input = { 0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34 };
+ static byte[] aes_a_expected = { 0x39, 0x25, 0x84, 0x1d, 0x02, 0xdc, 0x09, 0xfb, 0xdc, 0x11, 0x85, 0x97, 0x19, 0x6a, 0x0b, 0x32 };
+
+ static void AESa ()
+ {
+ AES ("AESa", 4000, aes_a_key, aes_a_input, aes_a_expected);
+ }
+
+ static byte[] aes_b_key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
+ static byte[] aes_b_input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+ static byte[] aes_b_expected = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a };
+
+ static void AESb ()
+ {
+ AES ("AESb", 4000, aes_b_key, aes_b_input, aes_b_expected);
+ }
+
+ static byte[] aes_c_key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+ static byte[] aes_c_input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+ static byte[] aes_c_expected = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 };
+
+ static void AESc ()
+ {
+ AES ("AESc", 3000, aes_c_key, aes_c_input, aes_c_expected);
+ }
+
+ static byte[] aes_d_key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
+ static byte[] aes_d_input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+ static byte[] aes_d_expected = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 };
+
+ static void AESd ()
+ {
+ AES ("AESc", 2000, aes_d_key, aes_d_input, aes_d_expected);
+ }
+
+ static bool Compare (byte[] actual, byte[] expected)
+ {
+ if (actual == null)
+ return (expected == null);
+ if (expected == null)
+ return false;
+ if (actual.Length != expected.Length)
+ return false;
+ for (int i=0; i < actual.Length; i++) {
+ if (actual [i] != expected [i])
+ return false;
+ }
+ return true;
+ }
+}
View
5 class/README
@@ -6,6 +6,11 @@ The following assemblies are available in Crimson:
algorithm implementations, either native or hardware accelerated.
Ref: http://home.gna.org/cryptodev-linux/
+* Crimson.OpenSsl.dll
+
+ This assembly provides a wrapper around libcrypto.
+ Ref: http://www.openssl.org/
+
* Crimson.MHash.dll
This assembly provides wrapper around the native hash implementations
View
407 common/CryptoTransformBase.cs
@@ -0,0 +1,407 @@
+//
+// Author:
+// Sebastien Pouliot <sebastien@gmail.com>
+//
+// Copyright 2012 Symform Inc.
+//
+// This code is based on:
+
+//
+// Mono.Security.Cryptography.SymmetricTransform implementation
+//
+// Authors:
+// Thomas Neidhart (tome@sbox.tugraz.at)
+// Sebastien Pouliot <sebastien@ximian.com>
+//
+// Portions (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.