Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add support for OCF-based AES-CBC

  • Loading branch information...
commit 0c542d04073baa7398eacc405146f1faf9dde339 1 parent 2051b9f
@spouliot spouliot authored
View
43 class/Crimson.CryptoDev/Crimson.CryptoDev/CryptoDev.cs
@@ -33,16 +33,18 @@ namespace Crimson.CryptoDev {
// from cryptodev.h
// CRYPTO_*
- enum Cipher : uint {
- SHA1 = 14,
- SHA256 = 103,
+ public enum Cipher : uint {
+ SHA1 = 14, // both cryptodev and OCF
+ SHA256 = 103, // cryptodev
+ SHA2_256 = 22, // OCF
// ciphers
AES_CBC = 11,
- AES_ECB = 23
+ AES_ECB = 23 // ECB not supported with OCF
}
// session_op
- struct Session {
+ // only important to compute it's size at runtime
+ struct CryptoDevSession {
public Cipher cipher;
public Cipher mac;
public uint keylen;
@@ -59,19 +61,44 @@ public override string ToString ()
#endif
}
+ // session_op
+ struct Session {
+ public Cipher cipher;
+ public Cipher mac;
+ public uint keylen;
+ public IntPtr key; // 32/64 bits size diff
+ public uint mackeylen;
+ public IntPtr mackey; // 32/64 bits size diff
+ public uint ses;
+ public uint crid;
+ public uint pad1;
+ public uint pad2;
+ public uint pad3;
+ public uint pad4;
+#if DEBUG
+ public override string ToString ()
+ {
+ return String.Format ("{0} {1} {2} {3} {4} {5} {6} {7}",
+ cipher, mac, keylen, key, mackeylen, mackey, ses, crid);
+ }
+#endif
+ }
+
// COP_*
enum CryptoOperation : ushort {
Encrypt, // 0
Decrypt // 1
}
+ // note: OCF use CRYPTO_OP_DECRYPT 0 and CRYPTO_OP_ENCRYPT 1
// COP_FLAG_*
[Flags]
enum CryptoFlags : ushort {
None = 0,
- Update = 1,
- Final = 2,
- WriteIv = 4
+ Update = 1, // cryptodev only
+ Final = 2, // cryptodev only
+ WriteIv = 4, // cryptodev only
+ Batch = 8 // OCF only
}
// crypt_op
View
8 class/Crimson.CryptoDev/Crimson.CryptoDev/CryptoDevTransform.cs
@@ -56,8 +56,8 @@ unsafe class CryptoDevTransform : ICryptoTransform {
public CryptoDevTransform (SymmetricAlgorithm algo, Cipher cipher, bool encryption, byte[] rgbKey, byte[] rgbIV, int bufferBlockSize)
{
- if (!Helper.CryptoDevAvailable)
- throw new CryptographicException ("Cannot access /dev/crypto");
+ 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");
@@ -91,6 +91,10 @@ public CryptoDevTransform (SymmetricAlgorithm algo, Cipher cipher, bool encrypti
context.ses = sess.ses;
context.op = encryption ? CryptoOperation.Encrypt : CryptoOperation.Decrypt;
+ // CryptoOperation constants differs in OCF (0 is None, ...)
+ if (Helper.Mode == KernelMode.Ocf)
+ context.op++;
+
if (algo.Mode != CipherMode.ECB) {
iv = rgbIV;
save_iv = new byte [BlockSizeByte];
View
4 class/Crimson.CryptoDev/Crimson.CryptoDev/HashHelper.cs
@@ -36,8 +36,8 @@ unsafe class HashHelper : IDisposable {
public HashHelper (Cipher algo)
{
- if (!Helper.CryptoDevAvailable)
- throw new CryptographicException ("Cannot access /dev/crypto");
+ if (!Helper.IsAvailable (algo))
+ throw new CryptographicException (String.Format ("{0} not available from /dev/crypto", algo));
// linux does not requires cloning the file descriptor with CRIOGET
Session sess = new Session ();
View
139 class/Crimson.CryptoDev/Crimson.CryptoDev/Helper.cs
@@ -30,20 +30,135 @@
namespace Crimson.CryptoDev {
+ public enum KernelMode {
+ Unknown = -1,
+ NotAvailable = 0,
+ CryptoDev = 1,
+ Ocf = 2
+ }
+
// hide platform differences, e.g. 32/64 bits
- static unsafe class Helper {
-
+ public static unsafe class Helper {
+
// shared file descriptor
- static int fildes = Helper.open ("/dev/crypto", 2 /* O_RDWR */);
+ static int fildes = -1;
+ static KernelMode mode;
+
+ static Helper ()
+ {
+ try {
+ fildes = Helper.open ("/dev/crypto", 2 /* O_RDWR */);
+ mode = (fildes == -1) ? KernelMode.NotAvailable : KernelMode.Unknown;
+ }
+ catch (DllNotFoundException) {
+ // libc is not available on Windows (e.g. MS.NET) and we
+ // do not want to crash with a TypeInitializationException
+ mode = KernelMode.NotAvailable;
+ }
+ }
+
+ static public KernelMode Mode {
+ get { return mode; }
+ private set {
+ switch (value) {
+ case KernelMode.CryptoDev:
+ CIOCGSESSION = CD_CIOCGSESSION;
+ CIOCFSESSION = CD_CIOCFSESSION;
+ CIOCCRYPT = CD_CIOCCRYPT;
+ break;
+ case KernelMode.Ocf:
+ CIOCGSESSION = OCF_CIOCGSESSION;
+ CIOCFSESSION = OCF_CIOCFSESSION;
+ CIOCCRYPT = OCF_CIOCCRYPT;
+ break;
+ default:
+ throw new InvalidOperationException ();
+ }
+ mode = value;
+ }
+ }
+
+ static byte[] null_key = new byte [32]; // 128 bit key
+
+ // cryptodev can be available but may not support the algorithm
+ // we wish to use (and we must fallback to another implementation)
+ static public bool IsCryptoDev (Cipher algo)
+ {
+ if (Mode == KernelMode.NotAvailable)
+ return false;
+ return Is (algo, KernelMode.CryptoDev);
+ }
- static public bool CryptoDevAvailable {
- get { return (fildes != -1); }
+ static public bool IsOcf (Cipher algo)
+ {
+ if (Mode == KernelMode.NotAvailable)
+ return false;
+ return Is (algo, KernelMode.Ocf);
}
+
+ // note: calling IsAvailable ensure 'mode' is set and makes
+ // every implementations works properly
+ static public bool IsAvailable (Cipher algo)
+ {
+ if (Mode == KernelMode.NotAvailable)
+ return false;
+ if (Is (algo, KernelMode.CryptoDev))
+ return true;
+ return Is (algo, KernelMode.Ocf);
+ }
+
+ static bool Is (Cipher algo, KernelMode mode)
+ {
+ Session session = new Session ();
+ switch (algo) {
+ case Cipher.AES_CBC:
+ case Cipher.AES_ECB:
+ session.cipher = algo;
+ session.keylen = 32;
+ fixed (byte* k = &null_key[0])
+ session.key = (IntPtr)k;
+ break;
+ case Cipher.SHA1:
+ session.mac = algo;
+ break;
+ // accept both SHA256 and SHA2_256 and use the correct one
+ case Cipher.SHA256:
+ case Cipher.SHA2_256:
+ if (mode == KernelMode.Ocf)
+ session.mac = Cipher.SHA2_256;
+ else
+ session.mac = Cipher.SHA256;
+ break;
+ default:
+ return false;
+ }
- // size will vary for 32/64 bits
- static ulong CIOCGSESSION = Ioctl.IOWR ('c', 102, sizeof (Session));
- static ulong CIOCFSESSION = Ioctl.IOW ('c', 103, sizeof (UInt32));
- static ulong CIOCCRYPT = Ioctl.IOWR ('c', 104, sizeof (Crypt));
+ ulong ciocgsession = mode == KernelMode.CryptoDev ? CD_CIOCGSESSION : OCF_CIOCGSESSION;
+ bool result;
+ if (IntPtr.Size == 4)
+ result = ioctl32 (fildes, (int) ciocgsession, ref session) == 0;
+ else
+ result = ioctl64 (fildes, ciocgsession, ref session) == 0;
+
+ if (result)
+ Mode = mode;
+ return result;
+ }
+
+ // values varies for cryptodev and OCF and for 32/64 bits
+ static ulong CIOCGSESSION = 0;
+ static ulong CIOCFSESSION = 0;
+ static ulong CIOCCRYPT = 0;
+
+ // cryptodev constants : size will vary for 32/64 bits
+ static ulong CD_CIOCGSESSION = Ioctl.IOWR ('c', 102, sizeof (CryptoDevSession));
+ static ulong CD_CIOCFSESSION = Ioctl.IOW ('c', 103, sizeof (UInt32));
+ static ulong CD_CIOCCRYPT = Ioctl.IOWR ('c', 104, sizeof (Crypt));
+
+ // OCF constants : size will vary for 32/64 bits
+ static ulong OCF_CIOCGSESSION = Ioctl.IOWR ('c', 106, sizeof (Session));
+ static ulong OCF_CIOCFSESSION = Ioctl.IOW ('c', 102, sizeof (UInt32));
+ static ulong OCF_CIOCCRYPT = Ioctl.IOWR ('c', 103, sizeof (Crypt));
[DllImport ("libc", SetLastError=true, EntryPoint="open")]
static public extern int open (string path, int oflag);
@@ -58,7 +173,7 @@ static unsafe class Helper {
[DllImport ("libc", SetLastError=true, EntryPoint="ioctl")]
static extern int ioctl64 (int fdc, ulong request, ref Session session);
- static public int SessionOp (ref Session session)
+ static internal int SessionOp (ref Session session)
{
if (IntPtr.Size == 4)
return ioctl32 (fildes, (int) CIOCGSESSION, ref session);
@@ -71,7 +186,7 @@ static public int SessionOp (ref Session session)
[DllImport ("libc", SetLastError=true, EntryPoint="ioctl")]
static extern int ioctl64 (int fdc, ulong request, ref UInt32 session);
- static public int CloseSession (ref UInt32 session)
+ static internal int CloseSession (ref UInt32 session)
{
int result = -1;
if (IntPtr.Size == 4)
@@ -90,7 +205,7 @@ static public int CloseSession (ref UInt32 session)
[DllImport ("libc", SetLastError=true, EntryPoint="ioctl")]
static extern int ioctl64 (int fd, ulong request, ref Crypt crypt);
- static public int CryptOp (ref Crypt crypt)
+ static internal int CryptOp (ref Crypt crypt)
{
if (IntPtr.Size == 4)
return ioctl32 (fildes, (int) CIOCCRYPT, ref crypt);
View
9 class/Crimson.CryptoDev/Crimson.CryptoDev/Ioctl.cs
@@ -70,10 +70,15 @@ static public ulong IOW (ulong type, ulong nr, int size)
#if TEST
static unsafe void Main ()
{
- // IOWR('c', 102, struct session_op)
- Console.WriteLine ("CIOCGSESSION = {0}", IOWR ('c', 102, sizeof (Session)));
+ Console.WriteLine ("// CryptoDev");
+ Console.WriteLine ("CIOCGSESSION = {0}", IOWR ('c', 102, sizeof (CryptoDevSession)));
Console.WriteLine ("CIOCFSESSION = {0}", IOW ('c', 103, sizeof (System.UInt32)));
Console.WriteLine ("CIOCCRYPT = {0}", IOWR ('c', 104, sizeof (Crypt)));
+
+ Console.WriteLine ("// OCF");
+ Console.WriteLine ("CIOCGSESSION = {0}", IOWR ('c', 106, sizeof (Session)));
+ Console.WriteLine ("CIOCFSESSION = {0}", IOW ('c', 102, sizeof (System.UInt32)));
+ Console.WriteLine ("CIOCCRYPT = {0}", IOWR ('c', 103, sizeof (Crypt)));
}
#endif
}
View
8 class/Crimson.CryptoDev/Crimson.Security.Cryptography/RijndaelKernel.cs
@@ -83,7 +83,9 @@ public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
case CipherMode.CBC:
return new CryptoDevTransform (this, Cipher.AES_CBC, false, rgbKey, rgbIV, BufferBlockSize);
case CipherMode.ECB:
- return new CryptoDevTransform (this, Cipher.AES_ECB, false, rgbKey, rgbIV, BufferBlockSize);
+ if (Helper.Mode == KernelMode.CryptoDev)
+ return new CryptoDevTransform (this, Cipher.AES_ECB, false, rgbKey, rgbIV, BufferBlockSize);
+ break;
}
}
}
@@ -103,7 +105,9 @@ public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
case CipherMode.CBC:
return new CryptoDevTransform (this, Cipher.AES_CBC, true, rgbKey, rgbIV, BufferBlockSize);
case CipherMode.ECB:
- return new CryptoDevTransform (this, Cipher.AES_ECB, true, rgbKey, rgbIV, BufferBlockSize);
+ if (Helper.Mode == KernelMode.CryptoDev)
+ return new CryptoDevTransform (this, Cipher.AES_ECB, true, rgbKey, rgbIV, BufferBlockSize);
+ break;
}
}
}
View
13 class/Crimson.CryptoDev/README
@@ -1,16 +1,17 @@
This assembly goal is to provide a managed wrapper on to /dev/crypto
-also known as `cryptodev`.
+as provided by either `cryptodev` [1] or OCF [2].
References:
-* http://home.gna.org/cryptodev-linux/
+[1] http://home.gna.org/cryptodev-linux/
+[2] http://ocf-linux.sourceforge.net
-CryptoDev Availability
+/dev/crypto Availability
----------------------
Most Linux distributions do not ship /dev/crypto so you'll have to:
-1. build it yourself (from the above link);
+1. build it yourself (from one of the above links);
2. install the driver, e.g.
@@ -31,8 +32,8 @@ You can verify that everything works, if nunit is available, by doing
'make run-test'
-mv_cesa specific notes
-----------------------
+cryptodev/mv_cesa specific notes
+--------------------------------
Hardware have limited internal buffers to work on. The drivers should
make this limit invisible to callers. This is not (always) the case.
View
10 class/Crimson.CryptoDev/tools/generator.cs
@@ -143,7 +143,7 @@ public class {0}Kernel : {0} {
static {0}Kernel()
{
- string blockSize = Environment.GetEnvironmentVariable (""CRIMSON_{0}_BUFFER_BLOCK_SIZE"");
+ string blockSize = Environment.GetEnvironmentVariable (""CRIMSON_{4}_BUFFER_BLOCK_SIZE"");
BufferBlockSize = blockSize == null ? Int32.MaxValue : Convert.ToInt32 (blockSize);
}
@@ -178,7 +178,9 @@ public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
case CipherMode.CBC:
return new CryptoDevTransform (this, Cipher.{3}, false, rgbKey, rgbIV, BufferBlockSize);
case CipherMode.ECB:
- return new CryptoDevTransform (this, Cipher.{2}, false, rgbKey, rgbIV, BufferBlockSize);
+ if (Helper.Mode == KernelMode.CryptoDev)
+ return new CryptoDevTransform (this, Cipher.{2}, false, rgbKey, rgbIV, BufferBlockSize);
+ break;
}
}
catch (CryptographicException) {
@@ -196,7 +198,9 @@ public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
case CipherMode.CBC:
return new CryptoDevTransform (this, Cipher.{3}, true, rgbKey, rgbIV, BufferBlockSize);
case CipherMode.ECB:
- return new CryptoDevTransform (this, Cipher.{2}, true, rgbKey, rgbIV, BufferBlockSize);
+ if (Helper.Mode == KernelMode.CryptoDev)
+ return new CryptoDevTransform (this, Cipher.{2}, true, rgbKey, rgbIV, BufferBlockSize);
+ break;
}
}
catch (CryptographicException) {
Please sign in to comment.
Something went wrong with that request. Please try again.