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)); // linux does not requires cloning the file descriptor with CRIOGET Session sess = new Session (); sess.cipher = cipher; sess.keylen = (uint) rgbKey.Length; fixed (byte* k = &rgbKey [0]) { sess.key = (IntPtr) k; try { if (Helper.SessionOp (ref sess) < 0) throw new CryptographicException (Marshal.GetLastWin32Error ()); } finally { sess.key = IntPtr.Zero; } } 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) { save_iv = 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; }
public HashHelper(Cipher algo) { 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 (); sess.mac = algo; if (Helper.SessionOp (ref sess) < 0) throw new CryptographicException (Marshal.GetLastWin32Error ()); context.ses = sess.ses; context.op = CryptoOperation.Encrypt; // change this value if the driver (e.g. mv_cesa) has a limit that // it can process in a single shot (e.g. 1932 for SHA1) BufferBlockSize = Int32.MaxValue; }
public CryptoDevTransform(SymmetricAlgorithm algo, Cipher cipher, bool encryption, byte[] rgbKey, byte[] rgbIV, int bufferBlockSize) { 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; sess.keylen = (uint) rgbKey.Length; fixed (byte* k = &rgbKey [0]) sess.key = (IntPtr) k; if (Helper.SessionOp (ref sess) < 0) throw new CryptographicException (Marshal.GetLastWin32Error ()); 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]; fixed (byte* i = &iv [0]) context.iv = (IntPtr) i; } // 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; }
static bool IsNewCryptoDev() { bool result; // check if this is a new crypto dev module by testing for SHA2_224_HMAC. // see discussion here https://github.com/nmav/cryptodev-linux/commit/d87ab5584893d06a21fe7cbf6e052d6757f9aa91#diff-535166266eead3c57bed2059c5006818 Session session = new Session (); session.mac = (Cipher)107; // CRYPTO_SHA2_224_HMAC if (IntPtr.Size == 4) { result = ioctl32 (fildes, (int)CD_CIOCGSESSION, ref session) == 0; ioctl32 (fildes, (int)CD_CIOCFSESSION, ref session); } else { result = ioctl64 (fildes, CD_CIOCGSESSION, ref session) == 0; ioctl64 (fildes, CD_CIOCFSESSION, ref session); } return result; }
static bool Is(Cipher algo, KernelMode mode) { // asking the kernel for availability turns out to be very costly long key = (((long) algo << 32) | (long) mode); if (availability.Contains (key)) return true; bool result = false; Session session = new Session (); fixed (byte* k = &null_key [0]) { switch (algo) { case Cipher.AES_CBC: case Cipher.AES_ECB: session.cipher = algo; session.keylen = 32; session.key = (IntPtr)k; break; case Cipher.SHA1: // OCF requires a single buffer that include room for the digest at the end. Its not // compatible with how HashAlgorithm works. if (mode == KernelMode.Ocf) return false; session.mac = algo; break; // accept both SHA256 and SHA2_256 and use the correct one case Cipher.SHA256: case Cipher.SHA256_NEW: case Cipher.SHA2_256: if (mode == KernelMode.Ocf) return false; if (sha256.HasValue) { session.mac = sha256.Value; } else { if (mode == KernelMode.Ocf) session.mac = Cipher.SHA2_256; else session.mac = IsNewCryptoDev() ? Cipher.SHA256_NEW : Cipher.SHA256; sha256 = session.mac; } break; default: return false; } ulong ciocgsession = mode == KernelMode.CryptoDev ? CD_CIOCGSESSION : OCF_CIOCGSESSION; if (IntPtr.Size == 4) { result = ioctl32 (fildes, (int)ciocgsession, ref session) == 0; ioctl32 (fildes, (int)CD_CIOCFSESSION, ref session); } else { result = ioctl64 (fildes, ciocgsession, ref session) == 0; ioctl64 (fildes, CD_CIOCFSESSION, ref session); } } if (result) { Mode = mode; availability.Add (key); } return result; }
static extern int ioctl64(int fdc, ulong request, ref Session session);
static extern int ioctl32(int fdc, int request, ref Session session);
internal static int SessionOp(ref Session session) { if (session.mac == Cipher.SHA256 || session.mac == Cipher.SHA2_256 || session.mac == Cipher.SHA256_NEW) session.mac = sha256.Value; if (IntPtr.Size == 4) return ioctl32 (fildes, (int) CIOCGSESSION, ref session); else return ioctl64 (fildes, CIOCGSESSION, ref session); }
static bool Is(Cipher algo, KernelMode mode) { // asking the kernel for availability turns out to be very costly long key = (((long) algo << 32) | (long) mode); if (availability.Contains (key)) return true; bool result = false; fixed (byte* k = &null_key [0]) { Session session = new Session (); switch (algo) { case Cipher.AES_CBC: case Cipher.AES_ECB: session.cipher = algo; session.keylen = 32; 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; } ulong ciocgsession = mode == KernelMode.CryptoDev ? CD_CIOCGSESSION : OCF_CIOCGSESSION; if (IntPtr.Size == 4) result = ioctl32 (fildes, (int) ciocgsession, ref session) == 0; else result = ioctl64 (fildes, ciocgsession, ref session) == 0; } if (result) { Mode = mode; availability.Add (key); } return result; }
internal static int SessionOp(ref Session session) { if (IntPtr.Size == 4) return ioctl32 (fildes, (int) CIOCGSESSION, ref session); else return ioctl64 (fildes, CIOCGSESSION, ref session); }
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; } 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; }