UsingTasks are not collected expectedly when imports are involved.
[mono.git] / mcs / class / Mono.Security / Mono.Security.X509 / X509CertificateBuilder.cs
1 //
2 // X509CertificateBuilder.cs: Handles building of X.509 certificates.
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 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.Security.Cryptography;
34
35 namespace Mono.Security.X509 {
36         // From RFC3280
37         /*
38          * Certificate  ::=  SEQUENCE  {
39          *      tbsCertificate       TBSCertificate,
40          *      signatureAlgorithm   AlgorithmIdentifier,
41          *      signature            BIT STRING  
42          * }
43          * TBSCertificate  ::=  SEQUENCE  {
44          *      version         [0]  Version DEFAULT v1,
45          *      serialNumber         CertificateSerialNumber,
46          *      signature            AlgorithmIdentifier,
47          *      issuer               Name,
48          *      validity             Validity,
49          *      subject              Name,
50          *      subjectPublicKeyInfo SubjectPublicKeyInfo,
51          *      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
52          *                           -- If present, version MUST be v2 or v3
53          *      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
54          *                           -- If present, version MUST be v2 or v3
55          *      extensions      [3]  Extensions OPTIONAL
56          *                           -- If present, version MUST be v3 --  
57          * }
58          * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
59          * CertificateSerialNumber  ::=  INTEGER
60          * Validity ::= SEQUENCE {
61          *      notBefore      Time,
62          *      notAfter       Time  
63          * }
64          * Time ::= CHOICE {
65          *      utcTime        UTCTime,
66          *      generalTime    GeneralizedTime 
67          * }
68          */
69         public class X509CertificateBuilder : X509Builder {
70  
71                 private byte version;
72                 private byte[] sn;
73                 private string issuer;
74                 private DateTime notBefore;
75                 private DateTime notAfter;
76                 private string subject;
77                 private AsymmetricAlgorithm aa;
78                 private byte[] issuerUniqueID;
79                 private byte[] subjectUniqueID;
80                 private X509ExtensionCollection extensions;
81
82                 public X509CertificateBuilder () : this (3) {}
83         
84                 public X509CertificateBuilder (byte version) 
85                 {
86                         if (version > 3)
87                                 throw new ArgumentException ("Invalid certificate version");
88                         this.version = version;
89                         extensions = new X509ExtensionCollection ();
90                 }
91
92                 public byte Version {
93                         get { return version; }
94                         set { version = value; }
95                 }
96
97                 public byte[] SerialNumber {
98                         get { return sn; }
99                         set { sn = value; }
100                 }
101
102                 public string IssuerName {
103                         get { return issuer; }
104                         set { issuer = value; }
105                 }
106
107                 public DateTime NotBefore {
108                         get { return notBefore; }
109                         set { notBefore = value; }
110                 }
111
112                 public DateTime NotAfter {
113                         get { return notAfter; }
114                         set { notAfter = value; }
115                 }
116
117                 public string SubjectName {
118                         get { return subject; }
119                         set { subject = value; }
120                 }
121
122                 public AsymmetricAlgorithm SubjectPublicKey {
123                         get { return aa; }
124                         set { aa = value; }
125                 }
126
127                 public byte[] IssuerUniqueId {
128                         get { return issuerUniqueID; }
129                         set { issuerUniqueID = value; }
130                 }
131
132                 public byte[] SubjectUniqueId {
133                         get { return subjectUniqueID; }
134                         set { subjectUniqueID = value; }
135                 }
136
137                 public X509ExtensionCollection Extensions {
138                         get { return extensions; }
139                 }
140
141
142                 /* SubjectPublicKeyInfo  ::=  SEQUENCE  {
143                  *      algorithm            AlgorithmIdentifier,
144                  *      subjectPublicKey     BIT STRING  }
145                  */
146                 private ASN1 SubjectPublicKeyInfo () 
147                 {
148                         ASN1 keyInfo = new ASN1 (0x30);
149                         if (aa is RSA) {
150                                 keyInfo.Add (PKCS7.AlgorithmIdentifier ("1.2.840.113549.1.1.1"));
151                                 RSAParameters p = (aa as RSA).ExportParameters (false);
152                                 /* RSAPublicKey ::= SEQUENCE {
153                                  *       modulus            INTEGER,    -- n
154                                  *       publicExponent     INTEGER  }  -- e
155                                  */
156                                 ASN1 key = new ASN1 (0x30);
157                                 key.Add (ASN1Convert.FromUnsignedBigInteger (p.Modulus));
158                                 key.Add (ASN1Convert.FromUnsignedBigInteger (p.Exponent));
159                                 keyInfo.Add (new ASN1 (UniqueIdentifier (key.GetBytes ())));
160                         }
161                         else if (aa is DSA) {
162                                 DSAParameters p = (aa as DSA).ExportParameters (false);
163                                 /* Dss-Parms  ::=  SEQUENCE  {
164                                  *       p             INTEGER,
165                                  *       q             INTEGER,
166                                  *       g             INTEGER  }
167                                  */
168                                 ASN1 param = new ASN1 (0x30);
169                                 param.Add (ASN1Convert.FromUnsignedBigInteger (p.P));
170                                 param.Add (ASN1Convert.FromUnsignedBigInteger (p.Q));
171                                 param.Add (ASN1Convert.FromUnsignedBigInteger (p.G));
172                                 keyInfo.Add (PKCS7.AlgorithmIdentifier ("1.2.840.10040.4.1", param));
173                                 ASN1 key = keyInfo.Add (new ASN1 (0x03));
174                                 // DSAPublicKey ::= INTEGER  -- public key, y
175                                 key.Add (ASN1Convert.FromUnsignedBigInteger (p.Y));
176                         }
177                         else
178                                 throw new NotSupportedException ("Unknown Asymmetric Algorithm " + aa.ToString ());
179                         return keyInfo;
180                 }
181
182                 private byte[] UniqueIdentifier (byte[] id) 
183                 {
184                         // UniqueIdentifier  ::=  BIT STRING
185                         ASN1 uid = new ASN1 (0x03);
186                         // first byte in a BITSTRING is the number of unused bits in the first byte
187                         byte[] v = new byte [id.Length + 1];
188                         Buffer.BlockCopy (id, 0, v, 1, id.Length);
189                         uid.Value = v;
190                         return uid.GetBytes ();
191                 }
192
193                 protected override ASN1 ToBeSigned (string oid) 
194                 {
195                         // TBSCertificate
196                         ASN1 tbsCert = new ASN1 (0x30);
197
198                         if (version > 1) {
199                                 // TBSCertificate / [0] Version DEFAULT v1,
200                                 byte[] ver = { (byte)(version - 1) };
201                                 ASN1 v = tbsCert.Add (new ASN1 (0xA0));
202                                 v.Add (new ASN1 (0x02, ver));
203                         }
204
205                         // TBSCertificate / CertificateSerialNumber,
206                         tbsCert.Add (new ASN1 (0x02, sn));
207
208                         // TBSCertificate / AlgorithmIdentifier,
209                         tbsCert.Add (PKCS7.AlgorithmIdentifier (oid));
210
211                         // TBSCertificate / Name
212                         tbsCert.Add (X501.FromString (issuer));
213
214                         // TBSCertificate / Validity
215                         ASN1 validity = tbsCert.Add (new ASN1 (0x30));
216                         // TBSCertificate / Validity / Time
217                         validity.Add (ASN1Convert.FromDateTime (notBefore));
218                         // TBSCertificate / Validity / Time
219                         validity.Add (ASN1Convert.FromDateTime (notAfter));
220
221                         // TBSCertificate / Name
222                         tbsCert.Add (X501.FromString (subject));
223
224                         // TBSCertificate / SubjectPublicKeyInfo
225                         tbsCert.Add (SubjectPublicKeyInfo ());
226                         
227                         if (version > 1) {
228                                 // TBSCertificate / [1]  IMPLICIT UniqueIdentifier OPTIONAL
229                                 if (issuerUniqueID != null)
230                                         tbsCert.Add (new ASN1 (0xA1, UniqueIdentifier (issuerUniqueID)));
231
232                                 // TBSCertificate / [2]  IMPLICIT UniqueIdentifier OPTIONAL
233                                 if (subjectUniqueID != null)
234                                         tbsCert.Add (new ASN1 (0xA1, UniqueIdentifier (subjectUniqueID)));
235
236                                 // TBSCertificate / [3]  Extensions OPTIONAL
237                                 if ((version > 2) &&  (extensions.Count > 0))
238                                         tbsCert.Add (new ASN1 (0xA3, extensions.GetBytes ()));
239                         }
240
241                         return tbsCert;
242                 }
243         }
244 }