File: RijndaelManaged.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (119 lines) | stat: -rw-r--r-- 4,352 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// 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);
        }                            
	}
}