2005-05-16 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / Mono.Security.X509 / X520Attributes.cs
1 //
2 // X520.cs: X.520 related stuff (attributes, RDN)
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2002, 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
38 namespace Mono.Security.X509 {
39
40         // References:
41         // 1.   Information technology - Open Systems Interconnection - The Directory: Selected attribute types 
42         //      http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-X.520 
43         // 2.   Internet X.509 Public Key Infrastructure Certificate and CRL Profile
44         //      http://www.ietf.org/rfc/rfc3280.txt
45
46         /* 
47          * AttributeTypeAndValue ::= SEQUENCE {
48          *      type     AttributeType,
49          *      value    AttributeValue 
50          * }
51          * 
52          * AttributeType ::= OBJECT IDENTIFIER
53          * 
54          * AttributeValue ::= ANY DEFINED BY AttributeType
55          */
56 #if INSIDE_CORLIB
57         internal
58 #else
59         public 
60 #endif
61         class X520 {
62
63                 public abstract class AttributeTypeAndValue {
64                         private string oid;
65                         private string attrValue;
66                         private int upperBound;
67                         private byte encoding;
68
69                         protected AttributeTypeAndValue (string oid, int upperBound)
70                         {
71                                 this.oid = oid;
72                                 this.upperBound = upperBound;
73                                 this.encoding = 0xFF;
74                         }
75
76                         protected AttributeTypeAndValue (string oid, int upperBound, byte encoding) 
77                         {
78                                 this.oid = oid;
79                                 this.upperBound = upperBound;
80                                 this.encoding = encoding;
81                         }
82
83                         public string Value {
84                                 get { return attrValue; }
85                                 set { 
86                                         if ((attrValue != null) && (attrValue.Length > upperBound)) {
87                                                 string msg = Locale.GetText ("Value length bigger than upperbound ({0}).");
88                                                 throw new FormatException (String.Format (msg, upperBound));
89                                         }
90                                         attrValue = value; 
91                                 }
92                         }
93
94                         public ASN1 ASN1 {
95                                 get { return GetASN1 (); }
96                         }
97
98                         internal ASN1 GetASN1 (byte encoding) 
99                         {
100                                 byte encode = encoding;
101                                 if (encode == 0xFF)
102                                         encode = SelectBestEncoding ();
103                                         
104                                 ASN1 asn1 = new ASN1 (0x30);
105                                 asn1.Add (ASN1Convert.FromOid (oid));
106                                 switch (encode) {
107                                         case 0x13:
108                                                 // PRINTABLESTRING
109                                                 asn1.Add (new ASN1 (0x13, Encoding.ASCII.GetBytes (attrValue)));
110                                                 break;
111                                         case 0x16:
112                                                 // IA5STRING
113                                                 asn1.Add (new ASN1 (0x16, Encoding.ASCII.GetBytes (attrValue)));
114                                                 break;
115                                         case 0x1E:
116                                                 // BMPSTRING
117                                                 asn1.Add (new ASN1 (0x1E, Encoding.BigEndianUnicode.GetBytes (attrValue)));
118                                                 break;
119                                 }
120                                 return asn1;
121                         }
122
123                         internal ASN1 GetASN1 () 
124                         {
125                                 return GetASN1 (encoding);
126                         }
127
128                         public byte[] GetBytes (byte encoding) 
129                         {
130                                 return GetASN1 (encoding) .GetBytes ();
131                         }
132
133                         public byte[] GetBytes () 
134                         {
135                                 return GetASN1 () .GetBytes ();
136                         }
137
138                         private byte SelectBestEncoding ()
139                         {
140                                 char[] notPrintableString = { '@', '_' };
141                                 if (attrValue.IndexOfAny (notPrintableString) != -1)
142                                         return 0x1E; // BMPSTRING
143                                 else
144                                         return 0x13; // PRINTABLESTRING
145                         }
146                 }
147
148                 public class Name : AttributeTypeAndValue {
149
150                         public Name () : base ("2.5.4.41", 32768) 
151                         {
152                         }
153                 }
154
155                 public class CommonName : AttributeTypeAndValue {
156
157                         public CommonName () : base ("2.5.4.3", 64) 
158                         {
159                         }
160                 }
161
162                 public class LocalityName : AttributeTypeAndValue {
163
164                         public LocalityName () : base ("2.5.4.7", 128)
165                         {
166                         }
167                 }
168
169                 public class StateOrProvinceName : AttributeTypeAndValue {
170
171                         public StateOrProvinceName () : base ("2.5.4.8", 128) 
172                         {
173                         }
174                 }
175                  
176                 public class OrganizationName : AttributeTypeAndValue {
177
178                         public OrganizationName () : base ("2.5.4.10", 64)
179                         {
180                         }
181                 }
182                  
183                 public class OrganizationalUnitName : AttributeTypeAndValue {
184
185                         public OrganizationalUnitName () : base ("2.5.4.11", 64)
186                         {
187                         }
188                 }
189
190                 // NOTE: Not part of RFC2253
191                 public class EmailAddress : AttributeTypeAndValue 
192                 {
193                         public EmailAddress () : base ("1.2.840.113549.1.9.1", 128, 0x16)
194                         {
195                         }
196                 }
197
198                 /* -- Naming attributes of type X520Title
199                  * id-at-title             AttributeType ::= { id-at 12 }
200                  * 
201                  * X520Title ::= CHOICE {
202                  *       teletexString     TeletexString   (SIZE (1..ub-title)),
203                  *       printableString   PrintableString (SIZE (1..ub-title)),
204                  *       universalString   UniversalString (SIZE (1..ub-title)),
205                  *       utf8String        UTF8String      (SIZE (1..ub-title)),
206                  *       bmpString         BMPString       (SIZE (1..ub-title)) 
207                  * }
208                  */
209                 public class Title : AttributeTypeAndValue {
210
211                         public Title () : base ("2.5.4.12", 64) {}
212                 }
213
214                 public class CountryName : AttributeTypeAndValue {
215
216                         // (0x13) PRINTABLESTRING
217                         public CountryName () : base ("2.5.4.6", 2, 0x13) 
218                         {
219                         }
220                 }
221         }
222         
223         /* From RFC3280
224          * --  specifications of Upper Bounds MUST be regarded as mandatory
225          * --  from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
226          * 
227          * --  Upper Bounds
228          * 
229          * ub-name INTEGER ::= 32768
230          * ub-common-name INTEGER ::= 64
231          * ub-locality-name INTEGER ::= 128
232          * ub-state-name INTEGER ::= 128
233          * ub-organization-name INTEGER ::= 64
234          * ub-organizational-unit-name INTEGER ::= 64
235          * ub-title INTEGER ::= 64
236          * ub-serial-number INTEGER ::= 64
237          * ub-match INTEGER ::= 128
238          * ub-emailaddress-length INTEGER ::= 128
239          * ub-common-name-length INTEGER ::= 64
240          * ub-country-name-alpha-length INTEGER ::= 2
241          * ub-country-name-numeric-length INTEGER ::= 3
242          * ub-domain-defined-attributes INTEGER ::= 4
243          * ub-domain-defined-attribute-type-length INTEGER ::= 8
244          * ub-domain-defined-attribute-value-length INTEGER ::= 128
245          * ub-domain-name-length INTEGER ::= 16
246          * ub-extension-attributes INTEGER ::= 256
247          * ub-e163-4-number-length INTEGER ::= 15
248          * ub-e163-4-sub-address-length INTEGER ::= 40
249          * ub-generation-qualifier-length INTEGER ::= 3
250          * ub-given-name-length INTEGER ::= 16
251          * ub-initials-length INTEGER ::= 5
252          * ub-integer-options INTEGER ::= 256
253          * ub-numeric-user-id-length INTEGER ::= 32
254          * ub-organization-name-length INTEGER ::= 64
255          * ub-organizational-unit-name-length INTEGER ::= 32
256          * ub-organizational-units INTEGER ::= 4
257          * ub-pds-name-length INTEGER ::= 16
258          * ub-pds-parameter-length INTEGER ::= 30
259          * ub-pds-physical-address-lines INTEGER ::= 6
260          * ub-postal-code-length INTEGER ::= 16
261          * ub-pseudonym INTEGER ::= 128
262          * ub-surname-length INTEGER ::= 40
263          * ub-terminal-id-length INTEGER ::= 24
264          * ub-unformatted-address-length INTEGER ::= 180
265          * ub-x121-address-length INTEGER ::= 16
266          * 
267          * -- Note - upper bounds on string types, such as TeletexString, are
268          * -- measured in characters.  Excepting PrintableString or IA5String, a
269          * -- significantly greater number of octets will be required to hold
270          * -- such a value.  As a minimum, 16 octets, or twice the specified
271          * -- upper bound, whichever is the larger, should be allowed for
272          * -- TeletexString.  For UTF8String or UniversalString at least four
273          * -- times the upper bound should be allowed.
274          */
275 }