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