CertificateMessage.java revision 6b811c5daec1b28e6f63b57f98a032236f2c3cf7
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.xnet.provider.jsse;
19
20import org.apache.harmony.xnet.provider.jsse.Message;
21import org.apache.harmony.xnet.provider.jsse.Handshake;
22import org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream;
23import org.apache.harmony.xnet.provider.jsse.AlertProtocol;
24
25import java.io.IOException;
26import java.security.cert.Certificate;
27import java.security.cert.CertificateEncodingException;
28import java.security.cert.CertificateException;
29import java.security.cert.CertificateFactory;
30import java.security.cert.X509Certificate;
31import java.util.Vector;
32
33/**
34 * Represents server/client certificate message
35 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS
36 * 1.0 spec., 7.4.2. Server certificate; 7.4.6. Client certificate</a>
37 *
38 */
39public class CertificateMessage extends Message {
40
41    /**
42     * Certificates
43     */
44    X509Certificate[] certs;
45
46    /**
47     * Certificates in encoded form
48     */
49    byte[][] encoded_certs;
50
51    /**
52     * Creates inbound message
53     *
54     * @param in
55     * @param length
56     * @throws IOException
57     */
58    public CertificateMessage(HandshakeIODataStream in, int length)
59            throws IOException {
60        int l = in.readUint24(); // total_length
61        if (l == 0) {  // message contais no certificates
62            if (length != 3) { // no more bytes after total_length
63                fatalAlert(AlertProtocol.DECODE_ERROR,
64                        "DECODE ERROR: incorrect CertificateMessage");
65            }
66            certs = new X509Certificate[0];
67            encoded_certs = new byte[0][0];
68            this.length = 3;
69            return;
70        }
71        CertificateFactory cf;
72        try {
73            cf = CertificateFactory.getInstance("X509");
74        } catch (CertificateException e) {
75            fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
76            return;
77        }
78        Vector<Certificate> certs_vector = new Vector<Certificate>();
79        int size = 0;
80        int enc_size = 0;
81        while (l > 0) {
82            size = in.readUint24();
83            l -= 3;
84            try {
85                certs_vector.add(cf.generateCertificate(in));
86            } catch (CertificateException e) {
87                fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR", e);
88            }
89            l -= size;
90            enc_size += size;
91        }
92        certs = new X509Certificate[certs_vector.size()];
93        for (int i = 0; i < certs.length; i++) {
94            certs[i] = (X509Certificate) certs_vector.elementAt(i);
95        }
96        this.length = 3 + 3 * certs.length + enc_size;
97        if (this.length != length) {
98            fatalAlert(AlertProtocol.DECODE_ERROR,
99                    "DECODE ERROR: incorrect CertificateMessage");
100        }
101
102    }
103
104    /**
105     * Creates outbound message
106     *
107     * @param certs
108     */
109    public CertificateMessage(X509Certificate[] certs) {
110        if (certs == null) {
111            this.certs = new X509Certificate[0];
112            encoded_certs = new byte[0][0];
113            length = 3;
114            return;
115        }
116        this.certs = certs;
117        if (encoded_certs == null) {
118            encoded_certs = new byte[certs.length][];
119            for (int i = 0; i < certs.length; i++) {
120                try {
121                    encoded_certs[i] = certs[i].getEncoded();
122                } catch (CertificateEncodingException e) {
123                    fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR",
124                            e);
125                }
126            }
127        }
128        length = 3 + 3 * encoded_certs.length;
129        for (int i = 0; i < encoded_certs.length; i++) {
130            length += encoded_certs[i].length;
131        }
132    }
133
134    /**
135     * Sends message
136     *
137     * @param out
138     */
139    @Override
140    public void send(HandshakeIODataStream out) {
141
142        int total_length = 0;
143        if (encoded_certs == null) {
144            encoded_certs = new byte[certs.length][];
145            for (int i = 0; i < certs.length; i++) {
146                try {
147                    encoded_certs[i] = certs[i].getEncoded();
148                } catch (CertificateEncodingException e) {
149                    fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR",
150                            e);
151                }
152            }
153        }
154        total_length = 3 * encoded_certs.length;
155        for (int i = 0; i < encoded_certs.length; i++) {
156            total_length += encoded_certs[i].length;
157        }
158        out.writeUint24(total_length);
159        for (int i = 0; i < encoded_certs.length; i++) {
160            out.writeUint24(encoded_certs[i].length);
161            out.write(encoded_certs[i]);
162        }
163
164    }
165
166    /**
167     * Returns message type
168     *
169     * @return
170     */
171    @Override
172    public int getType() {
173        return Handshake.CERTIFICATE;
174    }
175
176}
177