Welcome to mirror list, hosted at ThFree Co, Russian Federation.

CertificateRequest.java « tls « crypto « bouncycastle « org « java « main « src « core - gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 68e051eaaff6164219d76960f78b7fb657b33e3b (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package org.bouncycastle.crypto.tls;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;

import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x500.X500Name;

/**
 * Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
 * <pre>
 * struct {
 *     ClientCertificateType certificate_types&lt;1..2^8-1&gt;;
 *     DistinguishedName certificate_authorities&lt;3..2^16-1&gt;;
 * } CertificateRequest;
 * </pre>
 *
 * @see ClientCertificateType
 * @see X500Name
 */
public class CertificateRequest
{
    protected short[] certificateTypes;
    protected Vector supportedSignatureAlgorithms;
    protected Vector certificateAuthorities;

    /**
     * @param certificateTypes       see {@link ClientCertificateType} for valid constants.
     * @param certificateAuthorities a {@link Vector} of {@link X500Name}.
     */
    public CertificateRequest(short[] certificateTypes, Vector supportedSignatureAlgorithms, Vector certificateAuthorities)
    {
        this.certificateTypes = certificateTypes;
        this.supportedSignatureAlgorithms = supportedSignatureAlgorithms;
        this.certificateAuthorities = certificateAuthorities;
    }

    /**
     * @return an array of certificate types
     * @see ClientCertificateType
     */
    public short[] getCertificateTypes()
    {
        return certificateTypes;
    }

    /**
     * @return a {@link Vector} of {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
     */
    public Vector getSupportedSignatureAlgorithms()
    {
        return supportedSignatureAlgorithms;
    }

    /**
     * @return a {@link Vector} of {@link X500Name}
     */
    public Vector getCertificateAuthorities()
    {
        return certificateAuthorities;
    }

    /**
     * Encode this {@link CertificateRequest} to an {@link OutputStream}.
     *
     * @param output the {@link OutputStream} to encode to.
     * @throws IOException
     */
    public void encode(OutputStream output)
        throws IOException
    {
        if (certificateTypes == null || certificateTypes.length == 0)
        {
            TlsUtils.writeUint8(0, output);
        }
        else
        {
            TlsUtils.writeUint8ArrayWithUint8Length(certificateTypes, output);
        }

        if (supportedSignatureAlgorithms != null)
        {
            // TODO Check whether SignatureAlgorithm.anonymous is allowed here
            TlsUtils.encodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, output);
        }

        if (certificateAuthorities == null || certificateAuthorities.isEmpty())
        {
            TlsUtils.writeUint16(0, output);
        }
        else
        {
            Vector derEncodings = new Vector(certificateAuthorities.size());

            int totalLength = 0;
            for (int i = 0; i < certificateAuthorities.size(); ++i)
            {
                X500Name certificateAuthority = (X500Name)certificateAuthorities.elementAt(i);
                byte[] derEncoding = certificateAuthority.getEncoded(ASN1Encoding.DER);
                derEncodings.addElement(derEncoding);
                totalLength += derEncoding.length + 2;
            }

            TlsUtils.checkUint16(totalLength);
            TlsUtils.writeUint16(totalLength, output);

            for (int i = 0; i < derEncodings.size(); ++i)
            {
                byte[] derEncoding = (byte[])derEncodings.elementAt(i);
                TlsUtils.writeOpaque16(derEncoding, output);
            }
        }
    }

    /**
     * Parse a {@link CertificateRequest} from an {@link InputStream}.
     * 
     * @param context
     *            the {@link TlsContext} of the current connection.
     * @param input
     *            the {@link InputStream} to parse from.
     * @return a {@link CertificateRequest} object.
     * @throws IOException
     */
    public static CertificateRequest parse(TlsContext context, InputStream input)
        throws IOException
    {
        int numTypes = TlsUtils.readUint8(input);
        short[] certificateTypes = new short[numTypes];
        for (int i = 0; i < numTypes; ++i)
        {
            certificateTypes[i] = TlsUtils.readUint8(input);
        }

        Vector supportedSignatureAlgorithms = null;
        if (TlsUtils.isTLSv12(context))
        {
            // TODO Check whether SignatureAlgorithm.anonymous is allowed here
            supportedSignatureAlgorithms = TlsUtils.parseSupportedSignatureAlgorithms(false, input);
        }

        Vector certificateAuthorities = new Vector();
        byte[] certAuthData = TlsUtils.readOpaque16(input);
        ByteArrayInputStream bis = new ByteArrayInputStream(certAuthData);
        while (bis.available() > 0)
        {
            byte[] derEncoding = TlsUtils.readOpaque16(bis);
            ASN1Primitive asn1 = TlsUtils.readDERObject(derEncoding);
            certificateAuthorities.addElement(X500Name.getInstance(asn1));
        }

        return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
    }
}