Xamarin Public Jenkins (auto-signing) e79aa3c0ed Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
2016-08-03 10:59:49 +00:00

119 lines
4.3 KiB
C#

//
// RijndaelManaged.cs: Use CommonCrypto AES when possible,
// fallback on RijndaelManagedTransform otherwise
//
// Authors:
// Sebastien Pouliot <sebastien@xamarin.com>
//
// Copyright 2012 Xamarin Inc.
//
using System;
using System.Security.Cryptography;
using Mono.Security.Cryptography;
using Crimson.CommonCrypto;
namespace System.Security.Cryptography {
public sealed class RijndaelManaged : Rijndael {
public RijndaelManaged ()
{
}
public override void GenerateIV ()
{
IVValue = KeyBuilder.IV (BlockSizeValue >> 3);
}
public override void GenerateKey ()
{
KeyValue = KeyBuilder.Key (KeySizeValue >> 3);
}
public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
{
// AES is Rijndael with a 128 bits block size, so we can use CommonCrypto in this case
if (BlockSize == 128) {
IntPtr decryptor = IntPtr.Zero;
switch (Mode) {
case CipherMode.CBC:
decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.AES128, CCOptions.None, rgbKey, rgbIV);
return new FastCryptorTransform (decryptor, this, false, rgbIV);
case CipherMode.ECB:
decryptor = Cryptor.Create (CCOperation.Decrypt, CCAlgorithm.AES128, CCOptions.ECBMode, rgbKey, rgbIV);
return new FastCryptorTransform (decryptor, this, false, rgbIV);
default:
// CFB cipher mode is not supported by the (old) API we used (for compatibility) so we fallback for them
// FIXME: benchmark if we're better with RijndaelManagedTransform or CryptorTransform for CFB mode
break;
}
}
return NewEncryptor(rgbKey,
ModeValue,
rgbIV,
FeedbackSizeValue,
RijndaelManagedTransformMode.Decrypt);
}
public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
{
if (BlockSize == 128) {
IntPtr encryptor = IntPtr.Zero;
switch (Mode) {
case CipherMode.CBC:
encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.AES128, CCOptions.None, rgbKey, rgbIV);
return new FastCryptorTransform (encryptor, this, true, rgbIV);
case CipherMode.ECB:
encryptor = Cryptor.Create (CCOperation.Encrypt, CCAlgorithm.AES128, CCOptions.ECBMode, rgbKey, rgbIV);
return new FastCryptorTransform (encryptor, this, true, rgbIV);
default:
// CFB cipher mode is not supported by the (old) API we used (for compatibility) so we fallback for them
// FIXME: benchmark if we're better with RijndaelManagedTransform or CryptorTransform for CFB mode
break;
}
}
return NewEncryptor(rgbKey,
ModeValue,
rgbIV,
FeedbackSizeValue,
RijndaelManagedTransformMode.Encrypt);
}
private ICryptoTransform NewEncryptor (byte[] rgbKey,
CipherMode mode,
byte[] rgbIV,
int feedbackSize,
RijndaelManagedTransformMode encryptMode) {
// Build the key if one does not already exist
if (rgbKey == null) {
rgbKey = Utils.GenerateRandom(KeySizeValue / 8);
}
// If not ECB mode, make sure we have an IV. In CoreCLR we do not support ECB, so we must have
// an IV in all cases.
#if !FEATURE_CRYPTO
if (mode != CipherMode.ECB) {
#endif // !FEATURE_CRYPTO
if (rgbIV == null) {
rgbIV = Utils.GenerateRandom(BlockSizeValue / 8);
}
#if !FEATURE_CRYPTO
}
#endif // !FEATURE_CRYPTO
// Create the encryptor/decryptor object
return new RijndaelManagedTransform (rgbKey,
mode,
rgbIV,
BlockSizeValue,
feedbackSize,
PaddingValue,
encryptMode);
}
}
}