Home | History | Annotate | Download | only in jsse
      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 
     18 package org.apache.harmony.xnet.provider.jsse;
     19 
     20 import org.apache.harmony.xnet.provider.jsse.Message;
     21 import org.apache.harmony.xnet.provider.jsse.Handshake;
     22 import org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream;
     23 import org.apache.harmony.xnet.provider.jsse.AlertProtocol;
     24 
     25 import java.io.IOException;
     26 import java.security.cert.Certificate;
     27 import java.security.cert.CertificateEncodingException;
     28 import java.security.cert.CertificateException;
     29 import java.security.cert.CertificateFactory;
     30 import java.security.cert.X509Certificate;
     31 import 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  */
     39 public 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