2 // System.Security.Cryptography.X509Certificates.X509KeyUsageExtension
5 // Tim Coleman (tim@timcoleman.com)
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // Copyright (C) Tim Coleman, 2004
9 // Copyright (C) 2004-2005 Novell Inc. (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 #if NET_2_0 && SECURITY_DEP
37 namespace System
.Security
.Cryptography
.X509Certificates
{
39 public sealed class X509KeyUsageExtension
: X509Extension
{
41 internal const string oid
= "2.5.29.15";
42 internal const string friendlyName
= "Key Usage";
44 internal const X509KeyUsageFlags all
= X509KeyUsageFlags
.EncipherOnly
| X509KeyUsageFlags
.CrlSign
|
45 X509KeyUsageFlags
.KeyCertSign
| X509KeyUsageFlags
.KeyAgreement
| X509KeyUsageFlags
.DataEncipherment
|
46 X509KeyUsageFlags
.KeyEncipherment
| X509KeyUsageFlags
.NonRepudiation
|
47 X509KeyUsageFlags
.DigitalSignature
| X509KeyUsageFlags
.DecipherOnly
;
49 private X509KeyUsageFlags _keyUsages
;
50 private AsnDecodeStatus _status
;
54 public X509KeyUsageExtension ()
56 _oid
= new Oid (oid
, friendlyName
);
59 public X509KeyUsageExtension (AsnEncodedData encodedKeyUsage
, bool critical
)
61 // ignore the Oid provided by encodedKeyUsage (our rules!)
62 _oid
= new Oid (oid
, friendlyName
);
63 _raw
= encodedKeyUsage
.RawData
;
64 base.Critical
= critical
;
65 _status
= Decode (this.RawData
);
68 public X509KeyUsageExtension (X509KeyUsageFlags keyUsages
, bool critical
)
70 _oid
= new Oid (oid
, friendlyName
);
71 base.Critical
= critical
;
72 _keyUsages
= GetValidFlags (keyUsages
);
78 public X509KeyUsageFlags KeyUsages
{
81 case AsnDecodeStatus
.Ok
:
82 case AsnDecodeStatus
.InformationNotAvailable
:
85 throw new CryptographicException ("Badly encoded extension.");
92 public override void CopyFrom (AsnEncodedData encodedData
)
94 if (encodedData
== null)
95 throw new ArgumentNullException ("encodedData");
97 X509Extension ex
= (encodedData
as X509Extension
);
99 throw new ArgumentException (Locale
.GetText ("Wrong type."), "encodedData");
102 _oid
= new Oid (oid
, friendlyName
);
104 _oid
= new Oid (ex
._oid
);
106 RawData
= ex
.RawData
;
107 base.Critical
= ex
.Critical
;
108 // and we deal with the rest later
109 _status
= Decode (this.RawData
);
114 internal X509KeyUsageFlags
GetValidFlags (X509KeyUsageFlags flags
)
116 if ((flags
& all
) != flags
)
117 return (X509KeyUsageFlags
) 0;
121 internal AsnDecodeStatus
Decode (byte[] extension
)
123 if ((extension
== null) || (extension
.Length
== 0))
124 return AsnDecodeStatus
.BadAsn
;
125 if (extension
[0] != 0x03)
126 return AsnDecodeStatus
.BadTag
;
127 if (extension
.Length
< 3)
128 return AsnDecodeStatus
.BadLength
;
129 if (extension
.Length
< 4)
130 return AsnDecodeStatus
.InformationNotAvailable
;
133 ASN1 ex
= new ASN1 (extension
);
135 int i
= 1; // byte zero has the number of unused bits (ASN1's BITSTRING)
136 while (i
< ex
.Value
.Length
)
137 kubits
= (kubits
<< 8) + ex
.Value
[i
++];
139 _keyUsages
= GetValidFlags ((X509KeyUsageFlags
)kubits
);
142 return AsnDecodeStatus
.BadAsn
;
145 return AsnDecodeStatus
.Ok
;
148 internal byte[] Encode ()
151 int kubits
= (int)_keyUsages
;
155 ex
= new ASN1 (0x03, new byte[] { empty }
);
157 // count empty bits (applicable to first byte only)
158 int ku
= ((kubits
< Byte
.MaxValue
) ? kubits
: (kubits
>> 8));
159 while (((ku
& 0x01) == 0x00) && (empty
< 8)) {
164 if (kubits
<= Byte
.MaxValue
) {
165 ex
= new ASN1 (0x03, new byte[] { empty, (byte)kubits }
);
167 ex
= new ASN1 (0x03, new byte[] { empty, (byte)kubits, (byte)(kubits >> 8) }
);
171 return ex
.GetBytes ();
174 internal override string ToString (bool multiLine
)
177 case AsnDecodeStatus
.BadAsn
:
179 case AsnDecodeStatus
.BadTag
:
180 case AsnDecodeStatus
.BadLength
:
181 return FormatUnkownData (_raw
);
182 case AsnDecodeStatus
.InformationNotAvailable
:
183 return "Information Not Available";
186 if (_oid
.Value
!= oid
)
187 return String
.Format ("Unknown Key Usage ({0})", _oid
.Value
);
189 return "Information Not Available";
191 StringBuilder sb
= new StringBuilder ();
193 if ((_keyUsages
& X509KeyUsageFlags
.DigitalSignature
) != 0) {
194 sb
.Append ("Digital Signature");
196 if ((_keyUsages
& X509KeyUsageFlags
.NonRepudiation
) != 0) {
199 sb
.Append ("Non-Repudiation");
201 if ((_keyUsages
& X509KeyUsageFlags
.KeyEncipherment
) != 0) {
204 sb
.Append ("Key Encipherment");
206 if ((_keyUsages
& X509KeyUsageFlags
.DataEncipherment
) != 0) {
209 sb
.Append ("Data Encipherment");
211 if ((_keyUsages
& X509KeyUsageFlags
.KeyAgreement
) != 0) {
214 sb
.Append ("Key Agreement");
216 if ((_keyUsages
& X509KeyUsageFlags
.KeyCertSign
) != 0) {
219 sb
.Append ("Certificate Signing");
221 if ((_keyUsages
& X509KeyUsageFlags
.CrlSign
) != 0) {
224 sb
.Append ("Off-line CRL Signing, CRL Signing");
226 if ((_keyUsages
& X509KeyUsageFlags
.EncipherOnly
) != 0) {
229 sb
.Append ("Encipher Only");
231 if ((_keyUsages
& X509KeyUsageFlags
.DecipherOnly
) != 0) {
234 sb
.Append ("Decipher Only");
237 int ku
= (int)_keyUsages
;
239 sb
.Append (((byte)ku
).ToString ("x2"));
240 if (ku
> Byte
.MaxValue
) {
242 sb
.Append (((byte)(ku
>> 8)).ToString ("x2"));
247 sb
.Append (Environment
.NewLine
);
249 return sb
.ToString ();