2 // System.Security.Cryptography.X509BasicConstraintsExtension
5 // Sebastien Pouliot <sebastien@ximian.com>
6 // Tim Coleman (tim@timcoleman.com)
8 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) Tim Coleman, 2004
10 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
34 extern alias MonoSecurity;
38 using MonoSecurity::Mono.Security;
40 namespace System.Security.Cryptography.X509Certificates {
42 public sealed class X509BasicConstraintsExtension : X509Extension {
44 internal const string oid = "2.5.29.19";
45 internal const string friendlyName = "Basic Constraints";
47 private bool _certificateAuthority;
48 private bool _hasPathLengthConstraint;
49 private int _pathLengthConstraint;
50 private AsnDecodeStatus _status;
54 public X509BasicConstraintsExtension ()
56 _oid = new Oid (oid, friendlyName);
59 public X509BasicConstraintsExtension (AsnEncodedData encodedBasicConstraints, bool critical)
61 // ignore the Oid provided by encodedKeyUsage (our rules!)
62 _oid = new Oid (oid, friendlyName);
63 _raw = encodedBasicConstraints.RawData;
64 base.Critical = critical;
65 _status = Decode (this.RawData);
68 public X509BasicConstraintsExtension (bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical)
70 if (hasPathLengthConstraint) {
71 if (pathLengthConstraint < 0)
72 throw new ArgumentOutOfRangeException ("pathLengthConstraint");
73 _pathLengthConstraint = pathLengthConstraint;
75 _hasPathLengthConstraint = hasPathLengthConstraint;
76 _certificateAuthority = certificateAuthority;
77 _oid = new Oid (oid, friendlyName);
78 base.Critical = critical;
84 public bool CertificateAuthority {
87 case AsnDecodeStatus.Ok:
88 case AsnDecodeStatus.InformationNotAvailable:
89 return _certificateAuthority;
91 throw new CryptographicException ("Badly encoded extension.");
96 public bool HasPathLengthConstraint {
99 case AsnDecodeStatus.Ok:
100 case AsnDecodeStatus.InformationNotAvailable:
101 return _hasPathLengthConstraint;
103 throw new CryptographicException ("Badly encoded extension.");
108 public int PathLengthConstraint {
111 case AsnDecodeStatus.Ok:
112 case AsnDecodeStatus.InformationNotAvailable:
113 return _pathLengthConstraint;
115 throw new CryptographicException ("Badly encoded extension.");
122 public override void CopyFrom (AsnEncodedData asnEncodedData)
124 if (asnEncodedData == null)
125 throw new ArgumentNullException ("asnEncodedData");
127 X509Extension ex = (asnEncodedData as X509Extension);
129 throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
132 _oid = new Oid (oid, friendlyName);
134 _oid = new Oid (ex._oid);
136 RawData = ex.RawData;
137 base.Critical = ex.Critical;
138 // and we deal with the rest later
139 _status = Decode (this.RawData);
144 internal AsnDecodeStatus Decode (byte[] extension)
146 if ((extension == null) || (extension.Length == 0))
147 return AsnDecodeStatus.BadAsn;
148 if (extension [0] != 0x30)
149 return AsnDecodeStatus.BadTag;
150 if (extension.Length < 3) {
151 if (!((extension.Length == 2) && (extension [1] == 0x00)))
152 return AsnDecodeStatus.BadLength;
156 ASN1 sequence = new ASN1 (extension);
158 ASN1 a = sequence [n++];
159 if ((a != null) && (a.Tag == 0x01)) {
160 _certificateAuthority = (a.Value [0] == 0xFF);
163 if ((a != null) && (a.Tag == 0x02)) {
164 _hasPathLengthConstraint = true;
165 _pathLengthConstraint = ASN1Convert.ToInt32 (a);
169 return AsnDecodeStatus.BadAsn;
172 return AsnDecodeStatus.Ok;
175 internal byte[] Encode ()
177 ASN1 ex = new ASN1 (0x30);
179 if (_certificateAuthority)
180 ex.Add (new ASN1 (0x01, new byte[] { 0xFF }));
181 if (_hasPathLengthConstraint) {
182 // MS encodes the 0 (pathLengthConstraint is OPTIONAL)
183 // and in a long form (02 00 versus 02 01 00)
184 if (_pathLengthConstraint == 0)
185 ex.Add (new ASN1 (0x02, new byte[] { 0x00 }));
187 ex.Add (ASN1Convert.FromInt32 (_pathLengthConstraint));
190 return ex.GetBytes ();
193 internal override string ToString (bool multiLine)
196 case AsnDecodeStatus.BadAsn:
198 case AsnDecodeStatus.BadTag:
199 case AsnDecodeStatus.BadLength:
200 return FormatUnkownData (_raw);
201 case AsnDecodeStatus.InformationNotAvailable:
202 return "Information Not Available";
205 if (_oid.Value != oid)
206 return String.Format ("Unknown Key Usage ({0})", _oid.Value);
208 StringBuilder sb = new StringBuilder ();
210 sb.Append ("Subject Type=");
211 if (_certificateAuthority)
214 sb.Append ("End Entity");
216 sb.Append (Environment.NewLine);
220 sb.Append ("Path Length Constraint=");
221 if (_hasPathLengthConstraint)
222 sb.Append (_pathLengthConstraint);
226 sb.Append (Environment.NewLine);
228 return sb.ToString ();