Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / security / cryptography / rngcryptoserviceprovider.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 // 
8
9 //
10 // RNGCryptoServiceProvider.cs
11 //
12
13 namespace System.Security.Cryptography {
14     using Microsoft.Win32;
15     using System.Runtime.CompilerServices;
16     using System.Runtime.InteropServices;
17     using System.Security;
18     using System.Runtime.Versioning;
19     using System.Diagnostics.Contracts;
20
21 #if !FEATURE_CORECLR
22 [System.Runtime.InteropServices.ComVisible(true)]
23 #endif // !FEATURE_CORECLR
24     public sealed class RNGCryptoServiceProvider : RandomNumberGenerator {
25 #if !FEATURE_CORECLR 
26         [System.Security.SecurityCritical] // auto-generated
27         SafeProvHandle m_safeProvHandle;
28         bool m_ownsHandle;
29 #else // !FEATURE_CORECLR
30         #if FEATURE_CORECLR
31         [System.Security.SecurityCritical] // auto-generated
32         #endif
33         SafeCspHandle m_cspHandle;
34 #endif // !FEATURE_CORECLR
35
36         //
37         // public constructors
38         //
39
40 #if !FEATURE_CORECLR
41
42 #if !FEATURE_PAL
43         public RNGCryptoServiceProvider() : this((CspParameters) null) {}
44 #else // !FEATURE_PAL 
45         public RNGCryptoServiceProvider() { }
46 #endif // !FEATURE_PAL
47
48 #if !FEATURE_PAL
49         public RNGCryptoServiceProvider(string str) : this((CspParameters) null) {}
50
51         public RNGCryptoServiceProvider(byte[] rgb) : this((CspParameters) null) {}
52
53         [System.Security.SecuritySafeCritical]  // auto-generated
54         public RNGCryptoServiceProvider(CspParameters cspParams) {
55             if (cspParams != null) {
56                 m_safeProvHandle = Utils.AcquireProvHandle(cspParams);
57                 m_ownsHandle = true;
58             }
59             else {
60                 m_safeProvHandle = Utils.StaticProvHandle;
61                 m_ownsHandle = false;
62             }
63         }
64
65         [System.Security.SecuritySafeCritical]  // auto-generated
66         protected override void Dispose(bool disposing) {
67             base.Dispose(disposing);
68
69             if (disposing && m_ownsHandle) {
70                 m_safeProvHandle.Dispose();
71             }
72         }
73 #endif // !FEATURE_PAL
74
75 #else // !FEATURE_CORECLR
76
77         #if FEATURE_CORECLR
78         [System.Security.SecuritySafeCritical] // auto-generated
79         #endif
80         public RNGCryptoServiceProvider() {
81             m_cspHandle = CapiNative.AcquireCsp(null,
82                                                 CapiNative.ProviderNames.MicrosoftEnhanced,
83                                                 CapiNative.ProviderType.RsaFull,
84                                                 CapiNative.CryptAcquireContextFlags.VerifyContext);
85         }
86 #endif // !FEATURE_CORECLR
87
88         //
89         // public methods
90         //
91 #if !FEATURE_CORECLR
92         [System.Security.SecuritySafeCritical]  // auto-generated
93         public override void GetBytes(byte[] data) {
94             if (data == null) throw new ArgumentNullException("data");
95             Contract.EndContractBlock();
96 #if !FEATURE_PAL
97             GetBytes(m_safeProvHandle, data, data.Length);
98 #else
99             if (!Win32Native.Random(true, data, data.Length))
100                 throw new CryptographicException(Marshal.GetLastWin32Error());
101 #endif // !FEATURE_PAL
102         }
103
104         [System.Security.SecuritySafeCritical]  // auto-generated
105         public override void GetNonZeroBytes(byte[] data) {
106             if (data == null)
107                 throw new ArgumentNullException("data");
108             Contract.EndContractBlock();
109
110 #if !FEATURE_PAL
111             GetNonZeroBytes(m_safeProvHandle, data, data.Length);
112 #else
113             GetBytes(data);
114
115             int indexOfFirst0Byte = data.Length;
116             for (int i = 0; i < data.Length; i++) {
117                 if (data[i] == 0) {
118                     indexOfFirst0Byte = i;
119                     break;
120                 }
121             }
122             for (int i = indexOfFirst0Byte; i < data.Length; i++) {
123                 if (data[i] != 0) {
124                     data[indexOfFirst0Byte++] = data[i];
125                 }
126             }
127
128             while (indexOfFirst0Byte < data.Length) {
129                 // this should be more than enough to fill the rest in one iteration
130                 byte[] tmp = new byte[2 * (data.Length - indexOfFirst0Byte)];
131                 GetBytes(tmp);
132
133                 for (int i = 0; i < tmp.Length; i++) {
134                     if (tmp[i] != 0) {
135                         data[indexOfFirst0Byte++] = tmp[i];
136                         if (indexOfFirst0Byte >= data.Length) break;
137                     }
138                 }
139             }
140 #endif // !FEATURE_PAL
141         }
142
143 #else // !FEATURE_CORECLR
144
145         #if FEATURE_CORECLR
146         [System.Security.SecuritySafeCritical] // auto-generated
147         #endif
148         protected override void Dispose(bool disposing) {
149             try {
150                 if (disposing) {
151                     if (m_cspHandle != null) {
152                         m_cspHandle.Dispose();
153                     }
154                 }
155             }
156             finally {
157                 base.Dispose(disposing);
158             }
159         }
160
161         #if FEATURE_CORECLR
162         [System.Security.SecuritySafeCritical] // auto-generated
163         #endif
164         public override void GetBytes(byte[] data) {
165             if (data == null) {
166                 throw new ArgumentNullException("data");
167             }
168             Contract.EndContractBlock();
169
170             if (data.Length > 0) {
171                 CapiNative.GenerateRandomBytes(m_cspHandle, data);
172             }
173         }
174
175         #if FEATURE_CORECLR
176         [System.Security.SecuritySafeCritical] // auto-generated
177         #endif
178         public override void GetBytes(byte[] data, int offset, int count) {
179             if (data == null) throw new ArgumentNullException("data");
180             if (offset < 0) throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
181             if (count < 0) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
182             if (offset + count > data.Length) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
183
184             if (count > 0) {
185                 CapiNative.GenerateRandomBytes(m_cspHandle, data, offset, count);
186             }
187         }
188 #endif // !FEATURE_CORECLR
189
190 #if !FEATURE_PAL
191         [System.Security.SecurityCritical]  // auto-generated
192         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
193         [ResourceExposure(ResourceScope.None)]
194         private static extern void GetBytes(SafeProvHandle hProv, byte[] randomBytes, int count);
195
196         [System.Security.SecurityCritical]  // auto-generated
197         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
198         [ResourceExposure(ResourceScope.None)]
199         private static extern void GetNonZeroBytes(SafeProvHandle hProv, byte[] randomBytes, int count);
200 #endif
201     }
202 }