javacommons/gcfprotocols/secureconnection/src/nativesecureconnection.cpp
changeset 21 2a9601315dfc
child 87 1627c337e51e
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  ?Description
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include "nativesecureconnection.h"
       
    20 #include "jniarrayutils.h"
       
    21 #include "logger.h"
       
    22 #include "nativecertificatemanager.h"
       
    23 
       
    24 using namespace java;
       
    25 
       
    26 NativeSecureConnection::NativeSecureConnection(const char * aName,
       
    27         int aMode, const char * aHost, int aPort) :
       
    28         NativeSocketConnection(aName, aMode, aHost, aPort)
       
    29 {
       
    30     JELOG2(ESOCKET);
       
    31     mName = NULL;
       
    32     mHost = NULL;
       
    33     mName = new char[strlen(aName) + 1];
       
    34     strcpy(mName, aName);
       
    35     mHost = new char[strlen(aHost) + 1];
       
    36     strcpy(mHost, aHost);
       
    37     mMode = aMode;
       
    38     mPort = aPort;
       
    39     mSecureSocketBuffer = NULL;
       
    40 }
       
    41 
       
    42 int NativeSecureConnection::doHandshake(int aSocket, int aType, int aApn, int * err1, int *err2)
       
    43 {
       
    44     JELOG2(ESOCKET);
       
    45     int ret;
       
    46     //int temp;
       
    47     mSockDesc = aSocket;
       
    48     initialiseSslConnection();
       
    49     if (mSockDesc == -1)
       
    50     {
       
    51         mSockDesc = socketOpen(-1, aType, aApn,err1);
       
    52     }
       
    53     //LOG1(ESOCKET,EInfo ,"setdefault  =  %d",&temp);
       
    54     //err = &temp;
       
    55     LOG1(ESOCKET,EInfo, "setdefault  =  %d", *err1);
       
    56     if (mSockDesc < 0)
       
    57     {
       
    58         return mSockDesc;      // error code, whie creating socket
       
    59     }
       
    60     ret = secureHandshake();
       
    61 
       
    62     if (ret < 0)
       
    63     {
       
    64         // ssl handshake failed
       
    65         LOG(ESOCKET,EInfo,"secure handshake failed");
       
    66         ELOG1(ESOCKET, "handshake error code =  %d",
       
    67               ret);
       
    68     }
       
    69     else
       
    70     {  // handshake ok, verify the certificate
       
    71         X509 * peer = SSL_get_peer_certificate(mSslObj);
       
    72         getCertificateInformation(peer);
       
    73         int validflag = NativeCertificateManager::validateX509Certificate(peer);
       
    74         LOG1(ESOCKET,EInfo, " NativeCertificateManager::validateX509Certificate returned %d",validflag);
       
    75         if (validflag < 0)
       
    76         {
       
    77             *err2 = validflag;
       
    78             return 0;
       
    79         }
       
    80         ret = SSL_get_verify_result(mSslObj);
       
    81 
       
    82         LOG1(ESOCKET,EInfo, "Secure socket is open, socket descriptor is %d",
       
    83              mSockDesc);
       
    84     }
       
    85     return ret;
       
    86 }
       
    87 
       
    88 X509* NativeSecureConnection::getCertificate()
       
    89 {
       
    90     X509 * peer = SSL_get_peer_certificate(mSslObj);
       
    91     return peer;
       
    92 }
       
    93 
       
    94 OS_EXPORT int NativeSecureConnection::readBytes(JNIEnv& aJni,
       
    95         jbyteArray aJavaBuffer)
       
    96 {
       
    97     JELOG2(ESOCKET);
       
    98     if (mSecureSocketBuffer == NULL)
       
    99     {
       
   100         /*
       
   101         Memory is allocated to mSecureSocketBuffer only once during the first call of this readBytes() function
       
   102         Since the value of mBufferSize will be unknown(uninitialized) during the constructor call, it is not
       
   103         possible to do this operation inside the constructor.
       
   104         */
       
   105 
       
   106         mSecureSocketBuffer = new char[mBufferSize];
       
   107     }
       
   108     // secureSocketRead() function will actually make the OpenC call to read the data from the socket
       
   109     mBytesRead = secureSocketRead(mSecureSocketBuffer, mBufferSize);
       
   110 
       
   111     /* Copy the data read from the native buffer to the java buffer. Copy only "bytesRead" number of bytes.
       
   112        Because it is possible that the java request for some 'n' bytes to be read, but actually lesser bytes of data was
       
   113        read from the socket.
       
   114     */
       
   115     if (mBytesRead > 0)
       
   116     {
       
   117         JNIArrayUtils::CopyToJava(aJni, mSecureSocketBuffer, mBytesRead,
       
   118                                   aJavaBuffer, 0, mBytesRead);
       
   119     }
       
   120     else if (mBytesRead < 0)
       
   121         return mBytesRead;   // holds ssl read error code
       
   122 
       
   123     return mBytesRead;
       
   124 }
       
   125 
       
   126 OS_EXPORT int NativeSecureConnection::writeBytes(JNIEnv& aJni,
       
   127         jbyteArray aJavaBuffer, int aOffset, int aLength)
       
   128 {
       
   129     JELOG2(ESOCKET);
       
   130     char* iWriteBuffer = new char[aLength + 1];
       
   131 
       
   132     /* Copy the data to be written from java buffer to the native buffer.  */
       
   133     JNIArrayUtils::CopyToNative(aJni, aJavaBuffer, aOffset, aLength,
       
   134                                 iWriteBuffer);
       
   135 
       
   136     // secureSocketWrite() function will actually make the OpenC call to read the data from the socket
       
   137     int num = secureSocketWrite(iWriteBuffer, aLength);
       
   138     delete[] iWriteBuffer;
       
   139     iWriteBuffer = NULL;
       
   140     return num;
       
   141 }
       
   142 
       
   143 
       
   144 /* -------------------------------------------------------------
       
   145 This function initialises all the SSL libraries
       
   146 
       
   147 Open C APIs used
       
   148 
       
   149 SSL_load_error_strings(): Loads and registers all the libssl error
       
   150                           strings
       
   151 
       
   152 OpenSSL_add_all_algorithms(): adds all algorithms to the the internal
       
   153                               table.
       
   154 
       
   155 SSL_library_init(): iniitializes SSL library by registering algorithms
       
   156                     This should be called before calling any SSL apis
       
   157 
       
   158 SSL_CTX_new: creates a new context object as a framework to
       
   159              establish TLS/SSL enabled connections.
       
   160              It initializes the list of ciphers, the session cache
       
   161              setting,the callbacks, the keys and certificates, and
       
   162              the options to its default values
       
   163 
       
   164 SSL_new : SSL_new Creates a new SSL structure and inherits the settings
       
   165           of underlying ctx
       
   166 
       
   167 --------------------------------------------------------------*/
       
   168 
       
   169 OS_EXPORT void NativeSecureConnection::initialiseSslConnection()
       
   170 {
       
   171     JELOG2(ESOCKET);
       
   172 
       
   173 
       
   174     SSL_load_error_strings(); // No return value
       
   175 
       
   176     ERR_load_BIO_strings();   // No return value
       
   177 
       
   178     OpenSSL_add_all_algorithms(); // No return value
       
   179 
       
   180 
       
   181     SSL_library_init();
       
   182 
       
   183 
       
   184     mCtxObj = SSL_CTX_new(SSLv23_client_method());
       
   185     if (mCtxObj == NULL)
       
   186     {
       
   187         ELOG(ESOCKET, "Initialize ssl connection, ctx is null");
       
   188     }
       
   189     if ((mSslObj = SSL_new(mCtxObj)) == NULL)
       
   190     {
       
   191         ELOG(ESOCKET, "SSL_new failed");
       
   192     }
       
   193     else
       
   194     {
       
   195         ILOG(ESOCKET, "SSL_new success");
       
   196     }
       
   197 }
       
   198 
       
   199 /* -------------------------------------------------------------
       
   200 This function performs SSL handshake with the server
       
   201 
       
   202 Open C APIs used:
       
   203 
       
   204 BIO_new_socket(): returns a socket BIO (I/O abstraction)
       
   205 
       
   206 SSL_set_bio(): connect a SSL object with a BIO
       
   207 
       
   208 SSL_connect(): SSL_connect()initiates the TLS/SSL handshake with a server.
       
   209               The communication channel must already have been set and assigned
       
   210               to the ssl by setting an underlying BIO.
       
   211 -----------------------------------------------------------------*/
       
   212 
       
   213 OS_EXPORT int NativeSecureConnection::secureHandshake()
       
   214 {
       
   215     JELOG2(ESOCKET);
       
   216     int retVal;
       
   217     int error;
       
   218     // set up bio object
       
   219     mBio = BIO_new_socket(mSockDesc, BIO_NOCLOSE);
       
   220     if (mBio == NULL)
       
   221     {
       
   222         ELOG(ESOCKET, "BIO_new_socket failed");
       
   223     }
       
   224     else
       
   225     {
       
   226         ILOG(ESOCKET, "BIO_new_socket success");
       
   227     }
       
   228 
       
   229     //Set the bio object to SSL
       
   230     SSL_set_bio(mSslObj, mBio, mBio);
       
   231     retVal = SSL_connect(mSslObj);
       
   232 
       
   233     // If SSL_connect fails it returns -1. To get the error code SSL_get_error() api
       
   234     // is called along with return value and ssl object
       
   235     if (retVal < 0)
       
   236     {
       
   237         error = SSL_get_error(mSslObj, retVal);
       
   238         retVal = -error;
       
   239 
       
   240     }
       
   241     return retVal;
       
   242 
       
   243 }
       
   244 
       
   245 
       
   246 /*--------------------------------------------------------------
       
   247 This function calls SSL_write() to send data over a secure socket
       
   248 
       
   249 ---------------------------------------------------------------*/
       
   250 
       
   251 int NativeSecureConnection::secureSocketWrite(char *aBuf, int len)
       
   252 {
       
   253 
       
   254     ILOG1(ESOCKET, "writebuffer is %s", aBuf);
       
   255     int error;
       
   256     int retVal = SSL_write(mSslObj, aBuf, len);
       
   257     ILOG1(ESOCKET, "--NativeSecureConnection::secureSocketWrite len=  %d", retVal);
       
   258     if (retVal < 0)
       
   259     {
       
   260         ELOG1(ESOCKET, "secure socket write returned %d", retVal);
       
   261 
       
   262         // If SSL_write fails it returns -1. To get the error code
       
   263         // SSL_get_error() api is called along with return value
       
   264         // and ssl object
       
   265         error = SSL_get_error(mSslObj, retVal);
       
   266         retVal = -error;
       
   267     }
       
   268     return retVal;
       
   269 }
       
   270 
       
   271 
       
   272 /*------------------------------------------------------------
       
   273 This function calls SSL_read() to recieve data over a secure socket
       
   274 
       
   275 -------------------------------------------------------------*/
       
   276 
       
   277 int NativeSecureConnection::secureSocketRead(char *aBuf, int len)
       
   278 {
       
   279 
       
   280     int error;
       
   281     int retVal = SSL_read(mSslObj, aBuf, len);
       
   282     ILOG1(ESOCKET, "no of bytes read is %d", retVal);
       
   283     if (retVal < 0)
       
   284     {
       
   285         // If SSL_read fails it returns -1. To get the error code
       
   286         // SSL_get_error() api is called along with return value
       
   287         // and ssl object
       
   288         error = SSL_get_error(mSslObj, retVal);
       
   289         retVal = -error;
       
   290     }
       
   291     return retVal;
       
   292 }
       
   293 
       
   294 OS_EXPORT void NativeSecureConnection::stopReading()
       
   295 {
       
   296     return;
       
   297 }
       
   298 
       
   299 OS_EXPORT void NativeSecureConnection::stopWriting()
       
   300 {
       
   301     return;
       
   302 }
       
   303 
       
   304 
       
   305 /*--------------------------------------------------------------
       
   306 This function closes the secure socket
       
   307 
       
   308 Open C APIs used :
       
   309 
       
   310 SSL_CTX_free(): decrements the reference count of ctx
       
   311                  and removes the SSL_CTX object pointed to by ctx
       
   312                  and frees up the allocated memory if the reference count has reached 0.
       
   313 
       
   314 ERR_free_strings(): frees all the loaded error strings
       
   315 
       
   316 close() : closes the secure socket descriptor
       
   317 
       
   318 ---------------------------------------------------------------*/
       
   319 int NativeSecureConnection::secureSocketClose()
       
   320 {
       
   321     JELOG2(ESOCKET);
       
   322     int retVal;
       
   323 
       
   324     SSL_CTX_free(mCtxObj); // No return value
       
   325 
       
   326 
       
   327     ERR_free_strings(); // No return value
       
   328 
       
   329     retVal = close(mSockDesc);
       
   330     if (retVal < 0)
       
   331     {
       
   332         retVal = -errno;
       
   333     }
       
   334     return retVal;
       
   335 
       
   336 }
       
   337 
       
   338 /*--------------------------------------------------------------
       
   339 This function gets the peer certificate related information
       
   340 
       
   341 Open C APIs used
       
   342 
       
   343 X509_get_serialNumber(): gets the serial number of the certificate
       
   344 
       
   345 X509_get_subject_name(): get the certificate subject name
       
   346 
       
   347 X509_get_version(): returns certifcates version
       
   348 
       
   349 X509_get_notBefore(): get the certificate time after, value is string
       
   350                       in the form of yymmddhhmmss (time w.r.t to GMT)
       
   351 
       
   352 X509_get_notAfter(): get the certificate time after, value is string
       
   353                      in the form of yymmddhhmmss (time w.r.t to GMT)
       
   354 
       
   355 SSL_CIPHER_get_name(): returns the name of the SSL cipher
       
   356 
       
   357 ----------------------------------------------------------------*/
       
   358 void NativeSecureConnection::getCertificateInformation(X509 *aPeer)
       
   359 {
       
   360     JELOG2(ESOCKET);
       
   361     ASN1_INTEGER *x1 = X509_get_serialNumber(aPeer);
       
   362 
       
   363     // conversion of serial number into a string
       
   364     BIGNUM *bntmp = ASN1_INTEGER_to_BN(x1, NULL);
       
   365     char *serial_no = BN_bn2hex(bntmp);
       
   366 
       
   367 
       
   368     char subject_name[512];
       
   369     X509_NAME_oneline(X509_get_subject_name(aPeer), subject_name,
       
   370                       sizeof(subject_name));
       
   371 
       
   372     // get the certificate issure name, value is string
       
   373     char issuer_name[512];
       
   374     X509_NAME_oneline(X509_get_issuer_name(aPeer), issuer_name,
       
   375                       sizeof(issuer_name));
       
   376 
       
   377     long version = X509_get_version(aPeer);
       
   378     char version_string[10];
       
   379     sprintf(version_string,"%ld",version);
       
   380 
       
   381 
       
   382     ASN1_TIME *cert_time;
       
   383     char *time_notbef;
       
   384     cert_time = X509_get_notBefore(aPeer);
       
   385     time_notbef = (char*) cert_time->data;
       
   386 
       
   387     ASN1_TIME *cert_time_after;
       
   388     char *time_notafter;
       
   389     cert_time_after = X509_get_notAfter(aPeer);
       
   390     time_notafter = (char*) cert_time_after->data;
       
   391 
       
   392     // get the signature algorithm type, value is string. ex = sha1WithRSAEncryption
       
   393     int type = OBJ_obj2nid((aPeer)->sig_alg->algorithm);
       
   394     const char *alg_name = OBJ_nid2ln(type);
       
   395 
       
   396     //get the cipher name used by this ssl
       
   397     const char *cipher_name = SSL_CIPHER_get_name(SSL_get_current_cipher(
       
   398                                   mSslObj));
       
   399 
       
   400     const char *protocol_name = SSL_get_version(mSslObj);
       
   401 
       
   402     PLOG1(ESOCKET, "Peer certificate subject name %s", subject_name);
       
   403     PLOG1(ESOCKET, "Peer certificate issuer name %s", issuer_name);
       
   404     PLOG1(ESOCKET, "Peer certificate serial number %s", serial_no);
       
   405     PLOG1(ESOCKET, "Peer certificate serial number strlen %d", strlen(
       
   406               serial_no));
       
   407     PLOG1(ESOCKET, "Peer certificate version string  %s", version_string);
       
   408     PLOG1(ESOCKET, "Peer certificate get not before time %s", time_notbef);
       
   409     PLOG1(ESOCKET, "Peer certificate get not time after %s",
       
   410           time_notafter);
       
   411     PLOG1(ESOCKET, "alg_name %s", alg_name);
       
   412     PLOG1(ESOCKET, "current cipher %s", cipher_name);
       
   413     PLOG1(ESOCKET, "current protocol %s", protocol_name);
       
   414 
       
   415     // Allocate memory for 9 string as we know that 9 certificate properties will be retrieved
       
   416     mResult = (char **) malloc(9 * sizeof(char *));
       
   417 
       
   418     mResult[0] = (char *) malloc((strlen(subject_name) + 1) * sizeof(char));
       
   419     strcpy(mResult[0], subject_name);
       
   420 
       
   421     mResult[1] = (char *) malloc((strlen(issuer_name) + 1) * sizeof(char));
       
   422     strcpy(mResult[1], issuer_name);
       
   423 
       
   424     mResult[2] = (char *) malloc((strlen(serial_no) + 1) * sizeof(char));
       
   425     strcpy(mResult[2], serial_no);
       
   426 
       
   427     mResult[3] = (char *) malloc((strlen(time_notbef) + 1) * sizeof(char));
       
   428     strcpy(mResult[3], time_notbef);
       
   429 
       
   430     mResult[4] = (char *) malloc((strlen(time_notafter) + 1) * sizeof(char));
       
   431     strcpy(mResult[4], time_notafter);
       
   432 
       
   433     mResult[5] = (char *) malloc((strlen(alg_name) + 1) * sizeof(char));
       
   434     strcpy(mResult[5], alg_name);
       
   435 
       
   436     mResult[6] = (char *) malloc(20 * sizeof(char));
       
   437     strcpy(mResult[6], version_string);
       
   438 
       
   439     mResult[7] = (char *) malloc(50 * sizeof(char));
       
   440     strcpy(mResult[7], protocol_name);
       
   441 
       
   442     mResult[8] = (char *) malloc(50 * sizeof(char));
       
   443     strcpy(mResult[8], cipher_name);
       
   444 }
       
   445 
       
   446 OS_EXPORT char ** NativeSecureConnection::getSecurityInfo()
       
   447 {
       
   448     JELOG2(ESOCKET);
       
   449     return mResult;
       
   450 }
       
   451 
       
   452 NativeSecureConnection::~NativeSecureConnection()
       
   453 {
       
   454     JELOG2(ESOCKET);
       
   455     if (mSecureSocketBuffer != NULL)
       
   456     {
       
   457         delete[] mSecureSocketBuffer;
       
   458         mSecureSocketBuffer = NULL;
       
   459     }
       
   460     int i;
       
   461     for (i=0; i<9; i++)
       
   462     {
       
   463         delete[] mResult[i];
       
   464     }
       
   465     mResult = NULL;
       
   466 }