[xbuild] Actually delete common files (CopyLocal) during Clean.
[mono.git] / mcs / class / corlib / Mono.Security.X509.Extensions / KeyUsageExtension.cs
1 //
2 // KeyUsageExtension.cs: Handles X.509 KeyUsage extensions.
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Globalization;
32 using System.Text;
33
34 using Mono.Security;
35 using Mono.Security.X509;
36
37 namespace Mono.Security.X509.Extensions {
38
39         /*
40          * id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
41          * 
42          * KeyUsage ::= BIT STRING {
43          *      digitalSignature        (0),
44          *      nonRepudiation          (1),
45          *      keyEncipherment         (2),
46          *      dataEncipherment        (3),
47          *      keyAgreement            (4),
48          *      keyCertSign             (5),
49          *      cRLSign                 (6),
50          *      encipherOnly            (7),
51          *      decipherOnly            (8) 
52          * }
53          */
54         // note: because nothing is simple in ASN.1 bits are reversed
55         [Flags]
56 #if INSIDE_CORLIB
57         internal
58 #else
59         public 
60 #endif
61         enum KeyUsages {
62                 digitalSignature = 0x80,
63                 nonRepudiation = 0x40,
64                 keyEncipherment = 0x20,
65                 dataEncipherment = 0x10,
66                 keyAgreement = 0x08,
67                 keyCertSign = 0x04,
68                 cRLSign = 0x02,
69                 encipherOnly = 0x01,
70                 decipherOnly = 0x800,
71                 none = 0x0
72         }
73
74 #if INSIDE_CORLIB
75         internal
76 #else
77         public 
78 #endif
79         class KeyUsageExtension : X509Extension {
80
81                 private int kubits;
82
83                 public KeyUsageExtension (ASN1 asn1) : base (asn1) {}
84
85                 public KeyUsageExtension (X509Extension extension) : base (extension) {}
86
87                 public KeyUsageExtension () : base ()
88                 {
89                         extnOid = "2.5.29.15";
90                 }
91
92                 protected override void Decode () 
93                 {
94                         ASN1 bitString = new ASN1 (extnValue.Value);
95                         if (bitString.Tag != 0x03)
96                                 throw new ArgumentException ("Invalid KeyUsage extension");
97                         int i = 1; // byte zero has the number of unused bits (ASN1's BITSTRING)
98                         while (i < bitString.Value.Length)
99                                 kubits = (kubits << 8) + bitString.Value [i++];
100                 }
101
102                 protected override void Encode ()
103                 {
104                         extnValue = new ASN1 (0x04);
105
106                         ushort ku = (ushort) kubits;
107                         byte unused = 16;
108                         if (ku > 0) {
109                                 // count the unused bits
110                                 for (unused = 15; unused > 0; unused--) {
111                                         if ((ku & 0x8000) == 0x8000)
112                                                 break;
113                                         ku <<= 1;
114                                 }
115
116                                 if (kubits > Byte.MaxValue) {
117                                         unused -= 8;
118                                         extnValue.Add (new ASN1 (0x03, new byte[] { unused, (byte) kubits, (byte) (kubits >> 8) }));
119                                 } else {
120                                         extnValue.Add (new ASN1 (0x03, new byte[] { unused, (byte) kubits }));
121                                 }
122                         } else {
123                                 // note: a BITSTRING with a 0 length is invalid (in ASN.1), so would an
124                                 // empty OCTETSTRING (at the parent level) so we're encoding a 0
125                                 extnValue.Add (new ASN1 (0x03, new byte[] { 7, 0 }));
126                         }
127                 }
128
129                 public KeyUsages KeyUsage {
130                         get { return (KeyUsages) kubits; }
131                         set { kubits = Convert.ToInt32 (value, CultureInfo.InvariantCulture); }
132                 }
133
134                 public override string Name {
135                         get { return "Key Usage"; }
136                 }
137
138                 public bool Support (KeyUsages usage) 
139                 {
140                         int x = Convert.ToInt32 (usage, CultureInfo.InvariantCulture);
141                         return ((x & kubits) == x);
142                 }
143
144                 public override string ToString () 
145                 {
146                         const string separator = " , ";
147                         StringBuilder sb = new StringBuilder ();
148                         if (Support (KeyUsages.digitalSignature))
149                                 sb.Append ("Digital Signature");
150                         if (Support (KeyUsages.nonRepudiation)) {
151                                 if (sb.Length > 0)
152                                         sb.Append (separator);
153                                 sb.Append ("Non-Repudiation");
154                         }
155                         if (Support (KeyUsages.keyEncipherment)) {
156                                 if (sb.Length > 0)
157                                         sb.Append (separator);
158                                 sb.Append ("Key Encipherment");
159                         }
160                         if (Support (KeyUsages.dataEncipherment)) {
161                                 if (sb.Length > 0)
162                                         sb.Append (separator);
163                                 sb.Append ("Data Encipherment");
164                         }
165                         if (Support (KeyUsages.keyAgreement)) {
166                                 if (sb.Length > 0)
167                                         sb.Append (separator);
168                                 sb.Append ("Key Agreement");            
169                         }
170                         if (Support (KeyUsages.keyCertSign)) {
171                                 if (sb.Length > 0)
172                                         sb.Append (separator);
173                                 sb.Append ("Certificate Signing");
174                         }
175                         if (Support (KeyUsages.cRLSign)) {
176                                 if (sb.Length > 0)
177                                         sb.Append (separator);
178                                 sb.Append ("CRL Signing");
179                         }
180                         if (Support (KeyUsages.encipherOnly)) {
181                                 if (sb.Length > 0)
182                                         sb.Append (separator);
183                                 sb.Append ("Encipher Only ");   // ???
184                         }
185                         if (Support (KeyUsages.decipherOnly)) {
186                                 if (sb.Length > 0)
187                                         sb.Append (separator);
188                                 sb.Append ("Decipher Only");    // ???
189                         }
190                         sb.Append ("(");
191                         sb.Append (kubits.ToString ("X2", CultureInfo.InvariantCulture));
192                         sb.Append (")");
193                         sb.Append (Environment.NewLine);
194                         return sb.ToString ();
195                 }
196         }
197 }