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