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 #if MONOTOUCH || MONODROID
37 extern alias MonoSecurity;
38 using MonoSecurity::Mono.Security;
43 namespace System.Security.Cryptography.X509Certificates {
45 public sealed class X509BasicConstraintsExtension : X509Extension {
47 internal const string oid = "2.5.29.19";
48 internal const string friendlyName = "Basic Constraints";
50 private bool _certificateAuthority;
51 private bool _hasPathLengthConstraint;
52 private int _pathLengthConstraint;
53 private AsnDecodeStatus _status;
57 public X509BasicConstraintsExtension ()
59 _oid = new Oid (oid, friendlyName);
62 public X509BasicConstraintsExtension (AsnEncodedData encodedBasicConstraints, bool critical)
64 // ignore the Oid provided by encodedKeyUsage (our rules!)
65 _oid = new Oid (oid, friendlyName);
66 _raw = encodedBasicConstraints.RawData;
67 base.Critical = critical;
68 _status = Decode (this.RawData);
71 public X509BasicConstraintsExtension (bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical)
73 if (hasPathLengthConstraint) {
74 if (pathLengthConstraint < 0)
75 throw new ArgumentOutOfRangeException ("pathLengthConstraint");
76 _pathLengthConstraint = pathLengthConstraint;
78 _hasPathLengthConstraint = hasPathLengthConstraint;
79 _certificateAuthority = certificateAuthority;
80 _oid = new Oid (oid, friendlyName);
81 base.Critical = critical;
87 public bool CertificateAuthority {
90 case AsnDecodeStatus.Ok:
91 case AsnDecodeStatus.InformationNotAvailable:
92 return _certificateAuthority;
94 throw new CryptographicException ("Badly encoded extension.");
99 public bool HasPathLengthConstraint {
102 case AsnDecodeStatus.Ok:
103 case AsnDecodeStatus.InformationNotAvailable:
104 return _hasPathLengthConstraint;
106 throw new CryptographicException ("Badly encoded extension.");
111 public int PathLengthConstraint {
114 case AsnDecodeStatus.Ok:
115 case AsnDecodeStatus.InformationNotAvailable:
116 return _pathLengthConstraint;
118 throw new CryptographicException ("Badly encoded extension.");
125 public override void CopyFrom (AsnEncodedData asnEncodedData)
127 if (asnEncodedData == null)
128 throw new ArgumentNullException ("asnEncodedData");
130 X509Extension ex = (asnEncodedData as X509Extension);
132 throw new ArgumentException (Locale.GetText ("Wrong type."), "asnEncodedData");
135 _oid = new Oid (oid, friendlyName);
137 _oid = new Oid (ex._oid);
139 RawData = ex.RawData;
140 base.Critical = ex.Critical;
141 // and we deal with the rest later
142 _status = Decode (this.RawData);
147 internal AsnDecodeStatus Decode (byte[] extension)
149 if ((extension == null) || (extension.Length == 0))
150 return AsnDecodeStatus.BadAsn;
151 if (extension [0] != 0x30)
152 return AsnDecodeStatus.BadTag;
153 if (extension.Length < 3) {
154 if (!((extension.Length == 2) && (extension [1] == 0x00)))
155 return AsnDecodeStatus.BadLength;
159 ASN1 sequence = new ASN1 (extension);
161 ASN1 a = sequence [n++];
162 if ((a != null) && (a.Tag == 0x01)) {
163 _certificateAuthority = (a.Value [0] == 0xFF);
166 if ((a != null) && (a.Tag == 0x02)) {
167 _hasPathLengthConstraint = true;
168 _pathLengthConstraint = ASN1Convert.ToInt32 (a);
172 return AsnDecodeStatus.BadAsn;
175 return AsnDecodeStatus.Ok;
178 internal byte[] Encode ()
180 ASN1 ex = new ASN1 (0x30);
182 if (_certificateAuthority)
183 ex.Add (new ASN1 (0x01, new byte[] { 0xFF }));
184 if (_hasPathLengthConstraint) {
185 // MS encodes the 0 (pathLengthConstraint is OPTIONAL)
186 // and in a long form (02 00 versus 02 01 00)
187 if (_pathLengthConstraint == 0)
188 ex.Add (new ASN1 (0x02, new byte[] { 0x00 }));
190 ex.Add (ASN1Convert.FromInt32 (_pathLengthConstraint));
193 return ex.GetBytes ();
196 internal override string ToString (bool multiLine)
199 case AsnDecodeStatus.BadAsn:
201 case AsnDecodeStatus.BadTag:
202 case AsnDecodeStatus.BadLength:
203 return FormatUnkownData (_raw);
204 case AsnDecodeStatus.InformationNotAvailable:
205 return "Information Not Available";
208 if (_oid.Value != oid)
209 return String.Format ("Unknown Key Usage ({0})", _oid.Value);
211 StringBuilder sb = new StringBuilder ();
213 sb.Append ("Subject Type=");
214 if (_certificateAuthority)
217 sb.Append ("End Entity");
219 sb.Append (Environment.NewLine);
223 sb.Append ("Path Length Constraint=");
224 if (_hasPathLengthConstraint)
225 sb.Append (_pathLengthConstraint);
229 sb.Append (Environment.NewLine);
231 return sb.ToString ();