summary refs log tree commit diff
path: root/crypto/src/crypto/tls/Certificate.cs
blob: c59616c95b1a8936ccabc93a0013ce5ce57af88a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections;
using System.IO;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Utilities;

namespace Org.BouncyCastle.Crypto.Tls
{
    /**
     * Parsing and encoding of a <i>Certificate</i> struct from RFC 4346.
     * <p/>
     * <pre>
     * opaque ASN.1Cert&lt;2^24-1&gt;;
     *
     * struct {
     *     ASN.1Cert certificate_list&lt;0..2^24-1&gt;;
     * } Certificate;
     * </pre>
     *
     * @see Org.BouncyCastle.Asn1.X509.X509CertificateStructure
     */
    public class Certificate
    {
        public static readonly Certificate EmptyChain = new Certificate(new X509CertificateStructure[0]);

        /**
        * The certificates.
        */
        protected readonly X509CertificateStructure[] mCertificateList;

        public Certificate(X509CertificateStructure[] certificateList)
        {
            if (certificateList == null)
                throw new ArgumentNullException("certificateList");

            this.mCertificateList = certificateList;
        }

        /**
         * @return an array of {@link org.bouncycastle.asn1.x509.Certificate} representing a certificate
         *         chain.
         */
        public virtual X509CertificateStructure[] GetCertificateList()
        {
            return CloneCertificateList();
        }

        public virtual X509CertificateStructure GetCertificateAt(int index)
        {
            return mCertificateList[index];
        }

        public virtual int Length
        {
            get { return mCertificateList.Length; }
        }

        /**
         * @return <code>true</code> if this certificate chain contains no certificates, or
         *         <code>false</code> otherwise.
         */
        public virtual bool IsEmpty
        {
            get { return mCertificateList.Length == 0; }
        }

        /**
         * Encode this {@link Certificate} to a {@link Stream}.
         *
         * @param output the {@link Stream} to encode to.
         * @throws IOException
         */
        public virtual void Encode(Stream output)
        {
            IList derEncodings = Platform.CreateArrayList(mCertificateList.Length);

            int totalLength = 0;
            foreach (Asn1Encodable asn1Cert in mCertificateList)
            {
                byte[] derEncoding = asn1Cert.GetEncoded(Asn1Encodable.Der);
                derEncodings.Add(derEncoding);
                totalLength += derEncoding.Length + 3;
            }

            TlsUtilities.CheckUint24(totalLength);
            TlsUtilities.WriteUint24(totalLength, output);

            foreach (byte[] derEncoding in derEncodings)
            {
                TlsUtilities.WriteOpaque24(derEncoding, output);
            }
        }

        /**
         * Parse a {@link Certificate} from a {@link Stream}.
         *
         * @param input the {@link Stream} to parse from.
         * @return a {@link Certificate} object.
         * @throws IOException
         */
        public static Certificate Parse(Stream input)
        {
            int totalLength = TlsUtilities.ReadUint24(input);
            if (totalLength == 0)
            {
                return EmptyChain;
            }

            byte[] certListData = TlsUtilities.ReadFully(totalLength, input);

            MemoryStream buf = new MemoryStream(certListData, false);

            IList certificate_list = Platform.CreateArrayList();
            while (buf.Position < buf.Length)
            {
                byte[] derEncoding = TlsUtilities.ReadOpaque24(buf);
                Asn1Object asn1Cert = TlsUtilities.ReadDerObject(derEncoding);
                certificate_list.Add(X509CertificateStructure.GetInstance(asn1Cert));
            }

            X509CertificateStructure[] certificateList = new X509CertificateStructure[certificate_list.Count];
            for (int i = 0; i < certificate_list.Count; ++i)
            {
                certificateList[i] = (X509CertificateStructure)certificate_list[i];
            }
            return new Certificate(certificateList);
        }

        protected virtual X509CertificateStructure[] CloneCertificateList()
        {
            return (X509CertificateStructure[])mCertificateList.Clone();
        }
    }
}