001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Boris Kuznetsov
020: * @version $Revision$
021: */package org.apache.harmony.xnet.provider.jsse;
022:
023: import org.apache.harmony.xnet.provider.jsse.Message;
024: import org.apache.harmony.xnet.provider.jsse.Handshake;
025: import org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream;
026: import org.apache.harmony.xnet.provider.jsse.AlertProtocol;
027:
028: import java.io.IOException;
029: import java.security.cert.CertificateEncodingException;
030: import java.security.cert.CertificateException;
031: import java.security.cert.CertificateFactory;
032: import java.security.cert.X509Certificate;
033: import java.util.Vector;
034:
035: /**
036: *
037: * Represents server/client certificate message
038: * @see TLS 1.0 spec., 7.4.2. Server certificate; 7.4.6. Client certificate
039: * (http://www.ietf.org/rfc/rfc2246.txt)
040: *
041: */
042: public class CertificateMessage extends Message {
043:
044: /**
045: * Certificates
046: */
047: X509Certificate[] certs;
048:
049: /**
050: * Certificates in encoded form
051: */
052: byte[][] encoded_certs;
053:
054: /**
055: * Creates inbound message
056: *
057: * @param in
058: * @param length
059: * @throws IOException
060: */
061: public CertificateMessage(HandshakeIODataStream in, int length)
062: throws IOException {
063: int l = in.readUint24(); // total_length
064: if (l == 0) { // message contais no certificates
065: if (length != 3) { // no more bytes after total_length
066: fatalAlert(AlertProtocol.DECODE_ERROR,
067: "DECODE ERROR: incorrect CertificateMessage");
068: }
069: certs = new X509Certificate[0];
070: encoded_certs = new byte[0][0];
071: this .length = 3;
072: return;
073: }
074: CertificateFactory cf;
075: try {
076: cf = CertificateFactory.getInstance("X509");
077: } catch (CertificateException e) {
078: fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR",
079: e);
080: return;
081: }
082: Vector certs_vector = new Vector();
083: int size = 0;
084: int enc_size = 0;
085: while (l > 0) {
086: size = in.readUint24();
087: l -= 3;
088: try {
089: certs_vector.add(cf.generateCertificate(in));
090: } catch (CertificateException e) {
091: fatalAlert(AlertProtocol.DECODE_ERROR, "DECODE ERROR",
092: e);
093: }
094: l -= size;
095: enc_size += size;
096: }
097: certs = new X509Certificate[certs_vector.size()];
098: for (int i = 0; i < certs.length; i++) {
099: certs[i] = (X509Certificate) certs_vector.elementAt(i);
100: }
101: this .length = 3 + 3 * certs.length + enc_size;
102: if (this .length != length) {
103: fatalAlert(AlertProtocol.DECODE_ERROR,
104: "DECODE ERROR: incorrect CertificateMessage");
105: }
106:
107: }
108:
109: /**
110: * Creates outbound message
111: *
112: * @param certs
113: */
114: public CertificateMessage(X509Certificate[] certs) {
115: if (certs == null) {
116: this .certs = new X509Certificate[0];
117: encoded_certs = new byte[0][0];
118: length = 3;
119: return;
120: }
121: this .certs = certs;
122: if (encoded_certs == null) {
123: encoded_certs = new byte[certs.length][];
124: for (int i = 0; i < certs.length; i++) {
125: try {
126: encoded_certs[i] = certs[i].getEncoded();
127: } catch (CertificateEncodingException e) {
128: fatalAlert(AlertProtocol.INTERNAL_ERROR,
129: "INTERNAL ERROR", e);
130: }
131: }
132: }
133: length = 3 + 3 * encoded_certs.length;
134: for (int i = 0; i < encoded_certs.length; i++) {
135: length += encoded_certs[i].length;
136: }
137: }
138:
139: /**
140: * Sends message
141: *
142: * @param out
143: */
144: public void send(HandshakeIODataStream out) {
145:
146: int total_length = 0;
147: if (encoded_certs == null) {
148: encoded_certs = new byte[certs.length][];
149: for (int i = 0; i < certs.length; i++) {
150: try {
151: encoded_certs[i] = certs[i].getEncoded();
152: } catch (CertificateEncodingException e) {
153: fatalAlert(AlertProtocol.INTERNAL_ERROR,
154: "INTERNAL ERROR", e);
155: }
156: }
157: }
158: total_length = 3 * encoded_certs.length;
159: for (int i = 0; i < encoded_certs.length; i++) {
160: total_length += encoded_certs[i].length;
161: }
162: out.writeUint24(total_length);
163: for (int i = 0; i < encoded_certs.length; i++) {
164: out.writeUint24(encoded_certs[i].length);
165: out.write(encoded_certs[i]);
166: }
167:
168: }
169:
170: /**
171: * Returns message type
172: *
173: * @return
174: */
175: public int getType() {
176: return Handshake.CERTIFICATE;
177: }
178:
179: }
|