org/objectweb/proactive/ext/security/crypto/Session.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.ext.security.crypto;
00032 
00033 import java.io.IOException;
00034 import java.io.Serializable;
00035 import java.security.AlgorithmParameters;
00036 import java.security.PublicKey;
00037 import java.security.SecureRandom;
00038 import java.security.cert.CertificateEncodingException;
00039 import java.security.cert.X509Certificate;
00040 
00041 import javax.crypto.Cipher;
00042 import javax.crypto.Mac;
00043 import javax.crypto.SecretKey;
00044 import javax.crypto.spec.IvParameterSpec;
00045 
00046 import org.objectweb.proactive.core.util.log.Loggers;
00047 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00048 import org.objectweb.proactive.ext.security.Communication;
00049 import org.objectweb.proactive.ext.security.PolicyRule;
00050 import org.objectweb.proactive.ext.security.ProActiveSecurity;
00051 import org.objectweb.proactive.ext.security.SecurityContext;
00052 
00053 
00054 public class Session implements Serializable {
00055     // the session identifiant
00056     public long sessionID;
00057     protected static Object synchronizationObject = new Object();
00058 
00059     // The clients authentication and signing certificate.
00060     public X509Certificate distantOACertificate;
00061 
00062     // The clients public key for encryption and decryption.
00063     public PublicKey distantOAPublicKey;
00064 
00065     // Client Side Cipher.
00066     public transient Cipher cl_cipher;
00067 
00068     // Server Cipher.
00069     public transient Cipher se_cipher;
00070 
00071     //  the communication policy
00072     private Communication communication;
00073 
00074     // RSA Cipher.
00075     public transient Cipher rsa_eng;
00076 
00077     // Client side MAC
00078     public transient Mac cl_mac;
00079 
00080     // Server side MAC
00081     public transient Mac se_mac;
00082     public byte[] cl_sec_key;
00083     public byte[] se_sec_key;
00084     public byte[] cl_mac_enc;
00085     public byte[] se_mac_enc;
00086     public transient IvParameterSpec se_iv;
00087     public transient IvParameterSpec cl_iv;
00088 
00089     /* indicate if all security exchanged have been done
00090      * if not the sender must wait until this session is validated
00091      */
00092     protected boolean isSessionValidated;
00093     public AlgorithmParameters seCipherAlgParams;
00094     public AlgorithmParameters clCipherAlgParams;
00095     public AlgorithmParameters seMacAlgParams;
00096     public AlgorithmParameters clMacAlgParams;
00097     public byte[] encodedSeCipherAlgParams;
00098     public byte[] encodedClCipherAlgParams;
00099     public byte[] encodedSeMacAlgParams;
00100     public byte[] encodedClMacAlgParams;
00101 
00102     // Server Random
00103     public byte[] se_rand;
00104 
00105     // Client Random
00106     public byte[] cl_rand;
00107     public SecretKey se_hmac_key;
00108     public SecretKey se_aes_key;
00109     public SecretKey cl_hmac_key;
00110     public SecretKey cl_aes_key;
00111 
00112     //    public boolean cipher = false;
00113     //  public byte[] iv;
00114     public transient SecureRandom sec_rand;
00115 
00116     // security context associated to the sesssion
00117     public SecurityContext securityContext;
00118     public static int ACT_AS_CLIENT = 1;
00119     public static int ACT_AS_SERVER = 2;
00120 
00121     public Session() {
00122     }
00123 
00124     public Session(long sessionID, Communication policy)
00125         throws Exception {
00126         this.communication = policy;
00127         isSessionValidated = false;
00128         //        synchronized (synchronizationObject) {
00129         se_rand = new byte[32]; // Server Random
00130         cl_rand = new byte[32]; // Client Random
00131         sec_rand = new SecureRandom();
00132         cl_cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
00133         se_cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); // Server Cipher.
00134         rsa_eng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); // RSA Cipher.
00135         cl_mac = Mac.getInstance("HMACSHA1", "BC"); // Client side MAC
00136         se_mac = Mac.getInstance("HMACSHA1", "BC"); // Server side MAC
00137         //      }
00138         this.sessionID = sessionID;
00139         distantOACertificate = null; // The clients public key for encryption and decryption.
00140         distantOAPublicKey = null; // The clients authentication and signing certificate.
00141     }
00142 
00143     public boolean isID(long ID) {
00144         if (ID == this.sessionID) {
00145             return true;
00146         }
00147 
00148         return false;
00149     }
00150 
00151     public X509Certificate get_otherPublicCertificate(long id) {
00152         if (this.sessionID == id) {
00153             return distantOACertificate;
00154         }
00155 
00156         return null;
00157     }
00158 
00159     public long getSessionID() {
00160         return sessionID;
00161     }
00162 
00163     public void setDistantOACertificate(X509Certificate distantBodyCertificate) {
00164         distantOACertificate = distantBodyCertificate;
00165     }
00166 
00167     public X509Certificate getDistantOACertificate() {
00168         return distantOACertificate;
00169     }
00170 
00171     public PublicKey getDistantOAPublicKey() {
00172         return distantOAPublicKey;
00173     }
00174 
00175     public void setDistantOAPublicKey(PublicKey distantOAPublicKey) {
00176         this.distantOAPublicKey = distantOAPublicKey;
00177     }
00178 
00179     public synchronized byte[][] writePDU(byte[] in, int type)
00180         throws Exception {
00181         byte[] mac = null;
00182         switch (type) {
00183         case 1:
00184             // act as client
00185             if (communication.isIntegrityEnabled()) {
00186                 cl_mac.update(in); // Update plain text into MAC
00187             }
00188             if (communication.isConfidentialityEnabled()) {
00189                 try {
00190                     cl_cipher.init(Cipher.ENCRYPT_MODE, cl_aes_key, cl_iv,
00191                         sec_rand);
00192                     // TODO_SECURITY find why I need to force the encrypt_mode here
00193                     // seems to happen when a method call is sent by an object to itself.
00194                     // relation with AC ?
00195                     in = cl_cipher.doFinal(in); // Encrypt data for recipient.
00196                 } catch (Exception bex) {
00197                     bex.printStackTrace();
00198                     throw (new IOException("PDU failed to encrypt " +
00199                         bex.getMessage()));
00200                 }
00201             }
00202 
00203             if (communication.isIntegrityEnabled()) {
00204                 ProActiveLogger.getLogger(Loggers.SECURITY_SESSION).debug("writePDU as client cl_mac :" +
00205                     displayByte(cl_hmac_key.getEncoded()));
00206                 mac = cl_mac.doFinal();
00207             }
00208             break;
00209         case 2:
00210             // act as server
00211             if (communication.isIntegrityEnabled()) {
00212                 se_mac.update(in); // Update plain text into MAC
00213             }
00214             if (communication.isConfidentialityEnabled()) {
00215                 try {
00216                     in = se_cipher.doFinal(in); // Encrypt data for recipient.
00217                 } catch (Exception bex) {
00218                     bex.printStackTrace();
00219                     throw (new IOException("PDU failed to encrypt " +
00220                         bex.getMessage()));
00221                 }
00222             }
00223 
00224             if (communication.isIntegrityEnabled()) {
00225                 mac = se_mac.doFinal();
00226             }
00227             break;
00228         default:
00229             break;
00230         }
00231 
00232         //
00233         // Load mac with previous MAC value.
00234         // This forces each exchange into a chain
00235         // so that if any of the blocks are replayed out
00236         // of sequence the replayed blocks will fail.
00237         //
00238         //        cl_mac.update(mac);
00239         return new byte[][] { in, mac };
00240     }
00241 
00242     public static boolean isEqual(byte[] a, byte[] b) {
00243         if ((a == null) || (b == null)) {
00244             return (false);
00245         }
00246 
00247         if (a.length != b.length) {
00248             return (false);
00249         }
00250 
00251         for (int t = 0; t < a.length; t++) {
00252             if (a[t] != b[t]) {
00253                 return (false);
00254             }
00255         }
00256 
00257         return (true);
00258     }
00259 
00260     public synchronized byte[] readPDU(byte[] in, byte[] mac, int type)
00261         throws IOException {
00262         // in is the encrypted data
00263         // mac is the mac
00264         switch (type) {
00265         case 1:
00266             // act as client 
00267             if (communication.isConfidentialityEnabled()) {
00268                 try {
00269                     in = se_cipher.doFinal(in);
00270                 } catch (Exception ex) {
00271                     ProActiveLogger.getLogger(Loggers.SECURITY_SESSION).debug("PDU Cipher code decryption failed, session " +
00272                         sessionID);
00273                     throw new IOException("PDU failed to decrypt " +
00274                         ex.getMessage());
00275                 }
00276             }
00277             if (communication.isIntegrityEnabled()) {
00278                 se_mac.update(in); // MAC is taken on plain text.
00279 
00280                 byte[] m = null;
00281                 m = se_mac.doFinal();
00282 
00283                 if (!isEqual(m, mac)) {
00284                     ProActiveLogger.getLogger(Loggers.SECURITY_SESSION).debug("PDU Mac code failed , session " +
00285                         sessionID);
00286                     throw new IOException("PDU Mac code failed ");
00287                 }
00288             }
00289             break;
00290         case 2:
00291             // act as server
00292             if (communication.isConfidentialityEnabled()) {
00293                 try {
00294                     in = cl_cipher.doFinal(in);
00295                 } catch (Exception ex) {
00296                     ProActiveLogger.getLogger(Loggers.SECURITY_SESSION).debug("PDU Cipher code decryption failed, session " +
00297                         sessionID);
00298                     throw new IOException("PDU failed to decrypt " +
00299                         ex.getMessage());
00300                 }
00301             }
00302             if (communication.isIntegrityEnabled()) {
00303                 cl_mac.update(in); // MAC is taken on plain text.
00304 
00305                 byte[] m = null;
00306                 m = cl_mac.doFinal();
00307 
00308                 ProActiveLogger.getLogger(Loggers.SECURITY_SESSION).debug("readPDU as server cl_mac :" +
00309                     displayByte(cl_hmac_key.getEncoded()));
00310                 if (!isEqual(m, mac)) {
00311                     throw new IOException("PDU Mac code failed, session " +
00312                         sessionID);
00313                 }
00314             }
00315             break;
00316         default:
00317             break;
00318         }
00319 
00320         //
00321         // Load mac with previous MAC value.
00322         // This forces each exchange into a chain
00323         // so that if any of the blocks are replayed out
00324         // of sequence the replayed blocks will fail.
00325         //
00326         //        se_mac.update(m);
00327         return (in);
00328     }
00329 
00330     // implements Serializable
00331     private void writeObject(java.io.ObjectOutputStream out)
00332         throws IOException {
00333         out.defaultWriteObject();
00334         if (se_iv != null) {
00335             out.write(se_iv.getIV());
00336         } else {
00337             out.write(new byte[16]);
00338         }
00339         if (cl_iv != null) {
00340             out.write(cl_iv.getIV());
00341         } else {
00342             out.write(new byte[16]);
00343         }
00344 
00345         byte[] cert = new byte[0];
00346         try {
00347             if (distantOACertificate != null) {
00348                 cert = distantOACertificate.getEncoded();
00349             }
00350         } catch (CertificateEncodingException e) {
00351             e.printStackTrace();
00352         }
00353         out.writeInt(cert.length);
00354         out.write(cert);
00355     }
00356 
00357     private void readObject(java.io.ObjectInputStream in)
00358         throws IOException, ClassNotFoundException {
00359         in.defaultReadObject();
00360 
00361         //if (cipher) {
00362         byte[] temp = new byte[16];
00363         in.read(temp);
00364 
00365         se_iv = new IvParameterSpec(temp);
00366 
00367         in.read(temp);
00368         cl_iv = new IvParameterSpec(temp);
00369         sec_rand = new SecureRandom();
00370 
00371         ProActiveSecurity.loadProvider();
00372 
00373         int i = in.readInt();
00374         byte[] certEncoded = new byte[i];
00375         in.read(certEncoded);
00376 
00377         distantOACertificate = ProActiveSecurity.decodeCertificate(certEncoded);
00378 
00379         try {
00380             cl_cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
00381             se_cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC"); // Server Cipher.
00382             rsa_eng = Cipher.getInstance("RSA/None/OAEPPadding", "BC"); // RSA Cipher.
00383             sec_rand = new SecureRandom();
00384             cl_mac = Mac.getInstance("HMACSHA1", "BC"); // Client side MAC
00385             se_mac = Mac.getInstance("HMACSHA1", "BC"); // Server side MAC
00386 
00387             if ((se_iv != null) && (se_aes_key != null)) {
00388                 se_cipher.init(Cipher.DECRYPT_MODE, (SecretKey) se_aes_key,
00389                     se_iv);
00390             }
00391 
00392             if ((cl_iv != null) && (cl_aes_key != null)) {
00393                 cl_cipher.init(Cipher.ENCRYPT_MODE, cl_aes_key, cl_iv, sec_rand);
00394             }
00395 
00396             if ((se_mac != null) && (se_hmac_key != null)) {
00397                 se_mac.init(se_hmac_key);
00398             }
00399             if ((cl_mac != null) && (cl_hmac_key != null)) {
00400                 System.out.println("readObject session cl_mac : " +
00401                     displayByte(cl_hmac_key.getEncoded()));
00402                 cl_mac.init(cl_hmac_key);
00403             }
00404         } catch (Exception e) {
00405             e.printStackTrace();
00406         }
00407 
00408         //    }
00409     }
00410 
00411     public static String displayByte(byte[] in) {
00412         byte ch = 0x00;
00413 
00414         int i = 0;
00415 
00416         if ((in == null) || (in.length <= 0)) {
00417             return null;
00418         }
00419 
00420         String[] pseudo = {
00421                 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C",
00422                 "D", "E", "F"
00423             };
00424 
00425         StringBuffer out = new StringBuffer(in.length * 2);
00426 
00427         while (i < in.length) {
00428             ch = (byte) (in[i] & 0xF0); // Strip off   high nibble
00429 
00430             ch = (byte) (ch >>> 4);
00431             // shift the bits down
00432             ch = (byte) (ch & 0x0F);
00433             //     must do this is high order bit is on!
00434             out.append(pseudo[(int) ch]); // convert the   nibble to a String Character
00435 
00436             ch = (byte) (in[i] & 0x0F); // Strip off   low nibble 
00437 
00438             out.append(pseudo[(int) ch]); // convert the    nibble to a String Character
00439 
00440             i++;
00441         }
00442 
00443         String rslt = new String(out);
00444 
00445         return rslt;
00446     }
00447 
00448     public String toString() {
00449         return "ID : " + sessionID + "\n" + "cl_rand : " +
00450         displayByte(cl_rand) + "\n" + "se_rand : " + displayByte(se_rand);
00451     }
00452 
00457     public void setPolicy(PolicyRule resultPolicy) {
00458     }
00459 
00460     public Communication getCommunication() {
00461         return communication;
00462     }
00463 
00467     public SecurityContext getSecurityContext() {
00468         return securityContext;
00469     }
00470 
00474     public void setSecurityContext(SecurityContext securityContext) {
00475         this.securityContext = securityContext;
00476     }
00477 
00478     public boolean isSessionValidated() {
00479         return isSessionValidated;
00480     }
00481 
00482     public void setSessionValidated(boolean isSessionValidated) {
00483         this.isSessionValidated = isSessionValidated;
00484         //   System.out.println("session " + sessionID + " validated ");
00485     }
00486 }

Generated on Mon Jan 22 15:16:10 2007 for ProActive by  doxygen 1.5.1