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.
38 namespace System.Security.Cryptography.X509Certificates {
40 public sealed class X509BasicConstraintsExtension : X509Extension {
42 internal const string oid = "2.5.29.19";
43 internal const string friendlyName = "Basic Constraints";
45 private bool _certificateAuthority;
46 private bool _hasPathLengthConstraint;
47 private int _pathLengthConstraint;
48 private AsnDecodeStatus _status;
52 public X509BasicConstraintsExtension ()
54 _oid = new Oid (oid, friendlyName);
57 public X509BasicConstraintsExtension (AsnEncodedData encodedBasicConstraints, bool critical)
59 // ignore the Oid provided by encodedKeyUsage (our rules!)
60 _oid = new Oid (oid, friendlyName);
61 _raw = encodedBasicConstraints.RawData;
62 base.Critical = critical;
63 _status = Decode (this.RawData);
66 public X509BasicConstraintsExtension (bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical)
68 if (hasPathLengthConstraint) {
69 if (pathLengthConstraint < 0)
70 throw new ArgumentOutOfRangeException ("pathLengthConstraint");
71 _pathLengthConstraint = pathLengthConstraint;
73 _hasPathLengthConstraint = hasPathLengthConstraint;
74 _certificateAuthority = certificateAuthority;
75 _oid = new Oid (oid, friendlyName);
76 base.Critical = critical;
82 public bool CertificateAuthority {
85 case AsnDecodeStatus.Ok:
86 case AsnDecodeStatus.InformationNotAvailable:
87 return _certificateAuthority;
89 throw new CryptographicException ("Badly encoded extension.");
94 public bool HasPathLengthConstraint {
97 case AsnDecodeStatus.Ok:
98 case AsnDecodeStatus.InformationNotAvailable:
99 return _hasPathLengthConstraint;
101 throw new CryptographicException ("Badly encoded extension.");
106 public int PathLengthConstraint {
109 case AsnDecodeStatus.Ok:
110 case AsnDecodeStatus.InformationNotAvailable:
111 return _pathLengthConstraint;
113 throw new CryptographicException ("Badly encoded extension.");
120 public override void CopyFrom (AsnEncodedData asnEncodedData)
122 if (asnEncodedData == null)
123 throw new ArgumentNullException ("asnEncodedData");
125 X509Extension ex = (asnEncodedData as X509Extension);
127 throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
130 _oid = new Oid (oid, friendlyName);
132 _oid = new Oid (ex._oid);
134 RawData = ex.RawData;
135 base.Critical = ex.Critical;
136 // and we deal with the rest later
137 _status = Decode (this.RawData);
142 internal AsnDecodeStatus Decode (byte[] extension)
144 if ((extension == null) || (extension.Length == 0))
145 return AsnDecodeStatus.BadAsn;
146 if (extension [0] != 0x30)
147 return AsnDecodeStatus.BadTag;
148 if (extension.Length < 3) {
149 if (!((extension.Length == 2) && (extension [1] == 0x00)))
150 return AsnDecodeStatus.BadLength;
154 ASN1 sequence = new ASN1 (extension);
156 ASN1 a = sequence [n++];
157 if ((a != null) && (a.Tag == 0x01)) {
158 _certificateAuthority = (a.Value [0] == 0xFF);
161 if ((a != null) && (a.Tag == 0x02)) {
162 _hasPathLengthConstraint = true;
163 _pathLengthConstraint = ASN1Convert.ToInt32 (a);
167 return AsnDecodeStatus.BadAsn;
170 return AsnDecodeStatus.Ok;
173 internal byte[] Encode ()
175 ASN1 ex = new ASN1 (0x30);
177 if (_certificateAuthority)
178 ex.Add (new ASN1 (0x01, new byte[] { 0xFF }));
179 if (_hasPathLengthConstraint) {
180 // MS encodes the 0 (pathLengthConstraint is OPTIONAL)
181 // and in a long form (02 00 versus 02 01 00)
182 if (_pathLengthConstraint == 0)
183 ex.Add (new ASN1 (0x02, new byte[] { 0x00 }));
185 ex.Add (ASN1Convert.FromInt32 (_pathLengthConstraint));
188 return ex.GetBytes ();
191 internal override string ToString (bool multiLine)
194 case AsnDecodeStatus.BadAsn:
196 case AsnDecodeStatus.BadTag:
197 case AsnDecodeStatus.BadLength:
198 return FormatUnkownData (_raw);
199 case AsnDecodeStatus.InformationNotAvailable:
200 return "Information Not Available";
203 if (_oid.Value != oid)
204 return String.Format ("Unknown Key Usage ({0})", _oid.Value);
206 StringBuilder sb = new StringBuilder ();
208 sb.Append ("Subject Type=");
209 if (_certificateAuthority)
212 sb.Append ("End Entity");
214 sb.Append (Environment.NewLine);
218 sb.Append ("Path Length Constraint=");
219 if (_hasPathLengthConstraint)
220 sb.Append (_pathLengthConstraint);
224 sb.Append (Environment.NewLine);
226 return sb.ToString ();