2004-05-13 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Xml / KeyInfoX509Data.cs
1 //
2 // KeyInfoX509Data.cs - KeyInfoX509Data implementation for XML Signature
3 //
4 // Author:
5 //      Sebastien Pouliot (spouliot@motus.com)
6 //      Atsushi Enomoto (atsushi@ximian.com)
7 //
8 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
9 // (C) 2004 Novell Inc.
10 //
11
12 using System.Collections;
13 using System.Security.Cryptography.X509Certificates;
14 using System.Xml;
15
16 namespace System.Security.Cryptography.Xml {
17
18         // FIXME: framework class isn't documented so compatibility isn't assured!
19         internal class IssuerSerial
20         {
21                 public string Issuer;
22                 public string Serial;
23
24                 public IssuerSerial (string issuer, string serial) 
25                 {
26                         Issuer = issuer;
27                         Serial = serial;
28                 }
29         }
30
31         public class KeyInfoX509Data : KeyInfoClause 
32         {
33
34                 private byte[] x509crl;
35                 private ArrayList IssuerSerialList;
36                 private ArrayList SubjectKeyIdList;
37                 private ArrayList SubjectNameList;
38                 private ArrayList X509CertificateList;
39
40                 public KeyInfoX509Data () 
41                 {
42                         IssuerSerialList = new ArrayList ();
43                         SubjectKeyIdList = new ArrayList ();
44                         SubjectNameList = new ArrayList ();
45                         X509CertificateList = new ArrayList ();
46                 }
47
48                 public KeyInfoX509Data (byte[] rgbCert) : this ()
49                 {
50                         AddCertificate (new X509Certificate (rgbCert));
51                 }
52
53                 public KeyInfoX509Data (X509Certificate cert) : this ()
54                 {
55                         AddCertificate (cert);
56                 }
57
58                 public ArrayList Certificates {
59                         get { return X509CertificateList.Count != 0 ? X509CertificateList : null; }
60                 }
61
62                 public byte[] CRL {
63                         get { return x509crl; }
64                         set { x509crl = value; }
65                 }
66
67                 public ArrayList IssuerSerials {
68                         get { return IssuerSerialList.Count != 0 ? IssuerSerialList : null; }
69                 }
70
71                 public ArrayList SubjectKeyIds {
72                         get { return SubjectKeyIdList.Count != 0 ? SubjectKeyIdList : null; }
73                 }
74
75                 public ArrayList SubjectNames {
76                         get { return SubjectNameList.Count != 0 ? SubjectNameList : null; }
77                 }
78
79                 public void AddCertificate (X509Certificate certificate) 
80                 {
81                         X509CertificateList.Add (certificate);
82                 }
83
84                 public void AddIssuerSerial (string issuerName, string serialNumber) 
85                 {
86                         IssuerSerial isser = new IssuerSerial (issuerName, serialNumber);
87                         IssuerSerialList.Add (isser);
88                 }
89
90                 public void AddSubjectKeyId (byte[] subjectKeyId) 
91                 {
92                         SubjectKeyIdList.Add (subjectKeyId);
93                 }
94
95                 public void AddSubjectName (string subjectName) 
96                 {
97                         SubjectNameList.Add (subjectName);
98                 }
99
100                 public override XmlElement GetXml () 
101                 {
102                         // sanity check
103                         int count = IssuerSerialList.Count + SubjectKeyIdList.Count + SubjectNameList.Count + X509CertificateList.Count;
104                         if ((x509crl == null) && (count == 0))
105                                 throw new CryptographicException ("value");
106
107                         XmlDocument document = new XmlDocument ();
108                         XmlElement xel = document.CreateElement (XmlSignature.ElementNames.X509Data, XmlSignature.NamespaceURI);
109                         // FIXME: hack to match MS implementation
110                         xel.SetAttribute ("xmlns", XmlSignature.NamespaceURI);
111                         // <X509IssuerSerial>
112                         if (IssuerSerialList.Count > 0) {
113                                 foreach (IssuerSerial iser in IssuerSerialList) {
114                                         XmlElement isl = document.CreateElement (XmlSignature.ElementNames.X509IssuerSerial, XmlSignature.NamespaceURI);
115                                         XmlElement xin = document.CreateElement (XmlSignature.ElementNames.X509IssuerName, XmlSignature.NamespaceURI);
116                                         xin.InnerText = iser.Issuer;
117                                         isl.AppendChild (xin);
118                                         XmlElement xsn = document.CreateElement (XmlSignature.ElementNames.X509SerialNumber, XmlSignature.NamespaceURI);
119                                         xsn.InnerText = iser.Serial;
120                                         isl.AppendChild (xsn);
121                                         xel.AppendChild (isl);
122                                 }
123                         }
124                         // <X509SKI>
125                         if (SubjectKeyIdList.Count > 0) {
126                                 foreach (byte[] skid in SubjectKeyIdList) {
127                                         XmlElement ski = document.CreateElement (XmlSignature.ElementNames.X509SKI, XmlSignature.NamespaceURI);
128                                         ski.InnerText = Convert.ToBase64String (skid);
129                                         xel.AppendChild (ski);
130                                 }
131                         }
132                         // <X509SubjectName>
133                         if (SubjectNameList.Count > 0) {
134                                 foreach (string subject in SubjectNameList) {
135                                         XmlElement sn = document.CreateElement (XmlSignature.ElementNames.X509SubjectName, XmlSignature.NamespaceURI);
136                                         sn.InnerText = subject;
137                                         xel.AppendChild (sn);
138                                 }
139                         }
140                         // <X509Certificate>
141                         if (X509CertificateList.Count > 0) {
142                                 foreach (X509Certificate x509 in X509CertificateList) {
143                                         XmlElement cert = document.CreateElement (XmlSignature.ElementNames.X509Certificate, XmlSignature.NamespaceURI);
144                                         cert.InnerText = Convert.ToBase64String (x509.GetRawCertData ());
145                                         xel.AppendChild (cert);
146                                 }
147                         }
148                         // only one <X509CRL> 
149                         if (x509crl != null) {
150                                 XmlElement crl = document.CreateElement (XmlSignature.ElementNames.X509CRL, XmlSignature.NamespaceURI);
151                                 crl.InnerText = Convert.ToBase64String (x509crl);
152                                 xel.AppendChild (crl);
153                         }
154                         return xel;
155                 }
156
157                 public override void LoadXml (XmlElement element) 
158                 {
159                         if (element == null)
160                                 throw new ArgumentNullException ("element");
161
162                         IssuerSerialList.Clear ();
163                         SubjectKeyIdList.Clear ();
164                         SubjectNameList.Clear ();
165                         X509CertificateList.Clear ();
166                         x509crl = null;
167
168                         if ((element.LocalName != XmlSignature.ElementNames.X509Data) || (element.NamespaceURI != XmlSignature.NamespaceURI))
169                                 throw new CryptographicException ("element");
170
171                         XmlElement [] xnl = null;
172                         // <X509IssuerSerial>
173                         xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509IssuerSerial);
174                         if (xnl != null) {
175                                 for (int i=0; i < xnl.Length; i++) {
176                                         XmlElement xel = (XmlElement) xnl[i];
177                                         XmlElement issuer = XmlSignature.GetChildElement (xel, XmlSignature.ElementNames.X509IssuerName, XmlSignature.NamespaceURI);
178                                         XmlElement serial = XmlSignature.GetChildElement (xel, XmlSignature.ElementNames.X509SerialNumber, XmlSignature.NamespaceURI);
179                                         AddIssuerSerial (issuer.InnerText, serial.InnerText);
180                                 }
181                         }
182                         // <X509SKI>
183                         xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509SKI);
184                         if (xnl != null) {
185                                 for (int i=0; i < xnl.Length; i++) {
186                                         byte[] skid = Convert.FromBase64String (xnl[i].InnerXml);
187                                         AddSubjectKeyId (skid);
188                                 }
189                         }
190                         // <X509SubjectName>
191                         xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509SubjectName);
192                         if (xnl != null) {
193                                 for (int i=0; i < xnl.Length; i++) {
194                                         AddSubjectName (xnl[i].InnerXml);
195                                 }
196                         }
197                         // <X509Certificate>
198                         xnl = XmlSignature.GetChildElements (element, XmlSignature.ElementNames.X509Certificate);
199                         if (xnl != null) {
200                                 for (int i=0; i < xnl.Length; i++) {
201                                         byte[] cert = Convert.FromBase64String (xnl[i].InnerXml);
202                                         AddCertificate (new X509Certificate (cert));
203                                 }
204                         }
205                         // only one <X509CRL> 
206                         XmlElement x509el = XmlSignature.GetChildElement (element, XmlSignature.ElementNames.X509CRL, XmlSignature.NamespaceURI);
207                         if (x509el != null) {
208                                 x509crl = Convert.FromBase64String (x509el.InnerXml);
209                         }
210                 }
211         }
212 }