File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / axTLS / bindings / csharp / axTLS.cs
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Sep 28 11:55:55 2012 UTC (12 years, 9 months ago) by misho
Branches: v1_4_8, MAIN
CVS tags: datecs, HEAD
axTLS

    1: /*
    2:  * Copyright (c) 2007, Cameron Rich
    3:  * 
    4:  * All rights reserved.
    5:  * 
    6:  * Redistribution and use in source and binary forms, with or without 
    7:  * modification, are permitted provided that the following conditions are met:
    8:  *
    9:  * * Redistributions of source code must retain the above copyright notice, 
   10:  *   this list of conditions and the following disclaimer.
   11:  * * Redistributions in binary form must reproduce the above copyright notice, 
   12:  *   this list of conditions and the following disclaimer in the documentation 
   13:  *   and/or other materials provided with the distribution.
   14:  * * Neither the name of the axTLS project nor the names of its contributors 
   15:  *   may be used to endorse or promote products derived from this software 
   16:  *   without specific prior written permission.
   17:  *
   18:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   19:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   21:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
   22:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   23:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   24:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   25:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   26:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   27:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   28:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   29:  */
   30: 
   31: /**
   32:  * A wrapper around the unmanaged interface to give a semi-decent C# API
   33:  */
   34: 
   35: using System;
   36: using System.Runtime.InteropServices;
   37: using System.Net.Sockets;
   38: 
   39: /**
   40:  * @defgroup csharp_api C# API.
   41:  *
   42:  * Ensure that the appropriate Dispose() methods are called when finished with
   43:  * various objects - otherwise memory leaks will result.
   44:  * @{
   45:  */
   46: namespace axTLS
   47: {
   48:     /**
   49:      * @class SSL
   50:      * @ingroup csharp_api 
   51:      * @brief A representation of an SSL connection.
   52:      */
   53:     public class SSL
   54:     {
   55:         public IntPtr m_ssl;    /**< A pointer to the real SSL type */
   56: 
   57:         /**
   58:          * @brief Store the reference to an SSL context.
   59:          * @param ip [in] A reference to an SSL object.
   60:          */
   61:         public SSL(IntPtr ip)
   62:         {
   63:             m_ssl = ip;
   64:         }
   65: 
   66:         /**
   67:          * @brief Free any used resources on this connection. 
   68:          * 
   69:          * A "Close Notify" message is sent on this connection (if possible). 
   70:          * It is up to the application to close the socket.
   71:          */
   72:         public void Dispose()
   73:         {
   74:             axtls.ssl_free(m_ssl);
   75:         }
   76: 
   77:         /**
   78:          * @brief Return the result of a handshake.
   79:          * @return SSL_OK if the handshake is complete and ok.
   80:          * @see ssl.h for the error code list.
   81:          */
   82:         public int HandshakeStatus()
   83:         {
   84:             return axtls.ssl_handshake_status(m_ssl);
   85:         }
   86: 
   87:         /**
   88:          * @brief Return the SSL cipher id.
   89:          * @return The cipher id which is one of:
   90:          * - SSL_AES128_SHA (0x2f)
   91:          * - SSL_AES256_SHA (0x35)
   92:          * - SSL_RC4_128_SHA (0x05)
   93:          * - SSL_RC4_128_MD5 (0x04)
   94:          */
   95:         public byte GetCipherId()
   96:         {
   97:             return axtls.ssl_get_cipher_id(m_ssl);
   98:         }
   99: 
  100:         /**
  101:          * @brief Get the session id for a handshake. 
  102:          * 
  103:          * This will be a 32 byte sequence and is available after the first
  104:          * handshaking messages are sent.
  105:          * @return The session id as a 32 byte sequence.
  106:          * @note A SSLv23 handshake may have only 16 valid bytes.
  107:          */
  108:         public byte[] GetSessionId()
  109:         {
  110:             IntPtr ptr = axtls.ssl_get_session_id(m_ssl);
  111:             byte sess_id_size = axtls.ssl_get_session_id_size(m_ssl);
  112:             byte[] result = new byte[sess_id_size];
  113:             Marshal.Copy(ptr, result, 0, sess_id_size);
  114:             return result;
  115:         }
  116: 
  117:         /**
  118:          * @brief Retrieve an X.509 distinguished name component.
  119:          * 
  120:          * When a handshake is complete and a certificate has been exchanged, 
  121:          * then the details of the remote certificate can be retrieved.
  122:          *
  123:          * This will usually be used by a client to check that the server's 
  124:          * common name matches the URL.
  125:          *
  126:          * A full handshake needs to occur for this call to work.
  127:          *
  128:          * @param component [in] one of:
  129:          * - SSL_X509_CERT_COMMON_NAME
  130:          * - SSL_X509_CERT_ORGANIZATION
  131:          * - SSL_X509_CERT_ORGANIZATIONAL_NAME
  132:          * - SSL_X509_CA_CERT_COMMON_NAME
  133:          * - SSL_X509_CA_CERT_ORGANIZATION
  134:          * - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
  135:          * @return The appropriate string (or null if not defined)
  136:          */
  137:         public string GetCertificateDN(int component)
  138:         {
  139:             return axtls.ssl_get_cert_dn(m_ssl, component);
  140:         }
  141:     }
  142: 
  143:     /**
  144:      * @class SSLUtil
  145:      * @ingroup csharp_api 
  146:      * @brief Some global helper functions.
  147:      */
  148:     public class SSLUtil
  149:     {
  150: 
  151:         /**
  152:          * @brief Return the build mode of the axTLS project.
  153:          * @return The build mode is one of:
  154:          * - SSL_BUILD_SERVER_ONLY
  155:          * - SSL_BUILD_ENABLE_VERIFICATION
  156:          * - SSL_BUILD_ENABLE_CLIENT
  157:          * - SSL_BUILD_FULL_MODE
  158:          */
  159:         public static int BuildMode()
  160:         {
  161:             return axtls.ssl_get_config(axtls.SSL_BUILD_MODE);
  162:         }
  163: 
  164:         /**
  165:          * @brief Return the number of chained certificates that the 
  166:          * client/server supports.
  167:          * @return The number of supported server certificates.
  168:          */
  169:         public static int MaxCerts()
  170:         {
  171:             return axtls.ssl_get_config(axtls.SSL_MAX_CERT_CFG_OFFSET);
  172:         }
  173: 
  174:         /**
  175:          * @brief Return the number of CA certificates that the client/server
  176:          * supports.
  177:          * @return The number of supported CA certificates.
  178:          */
  179:         public static int MaxCACerts()
  180:         {
  181:             return axtls.ssl_get_config(axtls.SSL_MAX_CA_CERT_CFG_OFFSET);
  182:         }
  183: 
  184:         /**
  185:          * @brief Indicate if PEM is supported.
  186:          * @return true if PEM supported.
  187:          */
  188:         public static bool HasPEM()
  189:         {
  190:             return axtls.ssl_get_config(axtls.SSL_HAS_PEM) > 0 ? true : false;
  191:         }
  192: 
  193:         /**
  194:          * @brief Display the text string of the error.
  195:          * @param error_code [in] The integer error code.
  196:          */
  197:         public static void DisplayError(int error_code)
  198:         {
  199:             axtls.ssl_display_error(error_code);
  200:         }
  201: 
  202:         /**
  203:          * @brief Return the version of the axTLS project.
  204:          */
  205:         public static string Version()
  206:         {
  207:             return axtls.ssl_version();
  208:         }
  209:     }
  210: 
  211:     /**
  212:      * @class SSLCTX
  213:      * @ingroup csharp_api 
  214:      * @brief A base object for SSLServer/SSLClient.
  215:      */
  216:     public class SSLCTX
  217:     {
  218:         /**
  219:          * @brief A reference to the real client/server context.
  220:          */
  221:         protected IntPtr m_ctx;
  222: 
  223:         /**
  224:          * @brief Establish a new client/server context.
  225:          *
  226:          * This function is called before any client/server SSL connections are 
  227:          * made.  If multiple threads are used, then each thread will have its 
  228:          * own SSLCTX context. Any number of connections may be made with a 
  229:          * single context. 
  230:          *
  231:          * Each new connection will use the this context's private key and 
  232:          * certificate chain. If a different certificate chain is required, 
  233:          * then a different context needs to be be used.
  234:          *
  235:          * @param options [in]  Any particular options. At present the options
  236:          * supported are:
  237:          * - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if 
  238:          * the server authentication fails. The certificate can be 
  239:          * authenticated later with a call to VerifyCert().
  240:          * - SSL_CLIENT_AUTHENTICATION (server only): Enforce client 
  241:          * authentication i.e. each handshake will include a "certificate 
  242:          * request" message from the server.
  243:          * - SSL_DISPLAY_BYTES (full mode build only): Display the byte 
  244:          * sequences during the handshake.
  245:          * - SSL_DISPLAY_STATES (full mode build only): Display the state 
  246:          * changes during the handshake.
  247:          * - SSL_DISPLAY_CERTS (full mode build only): Display the 
  248:          * certificates that are passed during a handshake.
  249:          * - SSL_DISPLAY_RSA (full mode build only): Display the RSA key 
  250:          * details that are passed during a handshake.
  251:          * @param num_sessions [in] The number of sessions to be used for 
  252:          * session caching. If this value is 0, then there is no session 
  253:          * caching.
  254:          * @return A client/server context.
  255:          */
  256:         protected SSLCTX(uint options, int num_sessions)
  257:         {
  258:             m_ctx = axtls.ssl_ctx_new(options, num_sessions);
  259:         }
  260: 
  261:         /**
  262:          * @brief Remove a client/server context.
  263:          *
  264:          * Frees any used resources used by this context. Each connection will 
  265:          * be sent a "Close Notify" alert (if possible).
  266:          */
  267:         public void Dispose()
  268:         {
  269:             axtls.ssl_ctx_free(m_ctx);
  270:         }
  271: 
  272:         /**
  273:          * @brief Read the SSL data stream.
  274:          * @param ssl [in] An SSL object reference.
  275:          * @param in_data [out] After a successful read, the decrypted data 
  276:          * will be here. It will be null otherwise.
  277:          * @return The number of decrypted bytes:
  278:          * - if > 0, then the handshaking is complete and we are returning the 
  279:          * number of decrypted bytes. 
  280:          * - SSL_OK if the handshaking stage is successful (but not yet 
  281:          * complete).  
  282:          * - < 0 if an error.
  283:          * @see ssl.h for the error code list.
  284:          * @note Use in_data before doing any successive ssl calls.
  285:          */
  286:         public int Read(SSL ssl, out byte[] in_data)
  287:         {
  288:             IntPtr ptr = IntPtr.Zero;
  289:             int ret = axtls.ssl_read(ssl.m_ssl, ref ptr);
  290: 
  291:             if (ret > axtls.SSL_OK)
  292:             {
  293:                 in_data = new byte[ret];
  294:                 Marshal.Copy(ptr, in_data, 0, ret);
  295:             }
  296:             else
  297:             {
  298:                 in_data = null;
  299:             }
  300: 
  301:             return ret;
  302:         }
  303: 
  304:         /**
  305:          * @brief Write to the SSL data stream.
  306:          * @param ssl [in] An SSL obect reference.
  307:          * @param out_data [in] The data to be written
  308:          * @return The number of bytes sent, or if < 0 if an error.
  309:          * @see ssl.h for the error code list.
  310:          */
  311:         public int Write(SSL ssl, byte[] out_data)
  312:         {
  313:             return axtls.ssl_write(ssl.m_ssl, out_data, out_data.Length);
  314:         }
  315: 
  316:         /**
  317:          * @brief Write to the SSL data stream.
  318:          * @param ssl [in] An SSL obect reference.
  319:          * @param out_data [in] The data to be written
  320:          * @param out_len [in] The number of bytes to be written
  321:          * @return The number of bytes sent, or if < 0 if an error.
  322:          * @see ssl.h for the error code list.
  323:          */
  324:         public int Write(SSL ssl, byte[] out_data, int out_len)
  325:         {
  326:             return axtls.ssl_write(ssl.m_ssl, out_data, out_len);
  327:         }
  328: 
  329:         /**
  330:          * @brief Find an ssl object based on a Socket reference.
  331:          *
  332:          * Goes through the list of SSL objects maintained in a client/server 
  333:          * context to look for a socket match.
  334:          * @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
  335:          * @return A reference to the SSL object. Returns null if the object 
  336:          * could not be found.
  337:          */
  338:         public SSL Find(Socket s)
  339:         {
  340:             int client_fd = s.Handle.ToInt32();
  341:             return new SSL(axtls.  ssl_find(m_ctx, client_fd));
  342:         }
  343: 
  344:         /**
  345:          * @brief Authenticate a received certificate.
  346:          * 
  347:          * This call is usually made by a client after a handshake is complete 
  348:          * and the context is in SSL_SERVER_VERIFY_LATER mode.
  349:          * @param ssl [in] An SSL object reference.
  350:          * @return SSL_OK if the certificate is verified.
  351:          */
  352:         public int VerifyCert(SSL ssl)
  353:         {
  354:             return axtls.ssl_verify_cert(ssl.m_ssl);
  355:         }
  356: 
  357:         /**
  358:          * @brief Force the client to perform its handshake again.
  359:          *
  360:          * For a client this involves sending another "client hello" message.
  361:          * For the server is means sending a "hello request" message.
  362:          *
  363:          * This is a blocking call on the client (until the handshake 
  364:          * completes).
  365:          * @param ssl [in] An SSL object reference.
  366:          * @return SSL_OK if renegotiation instantiation was ok
  367:          */
  368:         public int Renegotiate(SSL ssl)
  369:         {
  370:             return axtls.ssl_renegotiate(ssl.m_ssl);
  371:         }
  372: 
  373:         /**
  374:          * @brief Load a file into memory that is in binary DER or ASCII PEM 
  375:          * format.
  376:          *
  377:          * These are temporary objects that are used to load private keys,
  378:          * certificates etc into memory.
  379:          * @param obj_type [in] The format of the file. Can be one of:
  380:          * - SSL_OBJ_X509_CERT (no password required)
  381:          * - SSL_OBJ_X509_CACERT (no password required)
  382:          * - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
  383:          * - SSL_OBJ_P8 (RC4-128 encrypted data supported)
  384:          * - SSL_OBJ_P12 (RC4-128 encrypted data supported)
  385:          *
  386:          * PEM files are automatically detected (if supported).
  387:          * @param filename [in] The location of a file in DER/PEM format.
  388:          * @param password [in] The password used. Can be null if not required.
  389:          * @return SSL_OK if all ok
  390:          */
  391:         public int ObjLoad(int obj_type, string filename, string password)
  392:         {
  393:             return axtls.ssl_obj_load(m_ctx, obj_type, filename, password);
  394:         }
  395: 
  396:         /**
  397:          * @brief Transfer binary data into the object loader.
  398:          *
  399:          * These are temporary objects that are used to load private keys,
  400:          * certificates etc into memory.
  401:          * @param obj_type [in] The format of the memory data.
  402:          * @param data [in] The binary data to be loaded.
  403:          * @param len [in] The amount of data to be loaded.
  404:          * @param password [in] The password used. Can be null if not required.
  405:          * @return SSL_OK if all ok
  406:          */
  407:         public int ObjLoad(int obj_type, byte[] data, int len, string password)
  408:         {
  409:             return axtls.ssl_obj_memory_load(m_ctx, obj_type, 
  410:                                             data, len, password);
  411:         }
  412:     }
  413: 
  414:     /**
  415:      * @class SSLServer
  416:      * @ingroup csharp_api 
  417:      * @brief The server context.
  418:      *
  419:      * All server connections are started within a server context.
  420:      */
  421:     public class SSLServer : SSLCTX
  422:     {
  423:         /**
  424:          * @brief Start a new server context.
  425:          * 
  426:          * @see SSLCTX for details.
  427:          */
  428:         public SSLServer(uint options, int num_sessions) :
  429:                             base(options, num_sessions) {}
  430: 
  431:         /**
  432:          * @brief Establish a new SSL connection to an SSL client.
  433:          *
  434:          * It is up to the application to establish the initial socket 
  435:          * connection.
  436:          *
  437:          * Call Dispose() when the connection is to be removed.
  438:          * @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
  439:          * @return An SSL object reference.
  440:          */
  441:         public SSL Connect(Socket s)
  442:         {
  443:             int client_fd = s.Handle.ToInt32();
  444:             return new SSL(axtls.ssl_server_new(m_ctx, client_fd));
  445:         }
  446:     }
  447: 
  448:     /**
  449:      * @class SSLClient
  450:      * @ingroup csharp_api
  451:      * @brief The client context.
  452:      *
  453:      * All client connections are started within a client context.
  454:      */
  455:     public class SSLClient : SSLCTX
  456:     {
  457:         /**
  458:          * @brief Start a new client context.
  459:          * 
  460:          * @see SSLCTX for details.
  461:          */
  462:         public SSLClient(uint options, int num_sessions) :
  463:                         base(options, num_sessions) {}
  464: 
  465:         /**
  466:          * @brief Establish a new SSL connection to an SSL server.
  467:          *
  468:          * It is up to the application to establish the initial socket 
  469:          * connection.
  470:          *
  471:          * This is a blocking call - it will finish when the handshake is 
  472:          * complete (or has failed).
  473:          *
  474:          * Call Dispose() when the connection is to be removed.
  475:          * @param s [in] A reference to a <A HREF="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemnetsocketssocketclasstopic.asp">Socket</A> object.
  476:          * @param session_id [in] A 32 byte session id for session resumption. 
  477:          * This can be null if no session resumption is not required.
  478:          * @return An SSL object reference. Use SSL.handshakeStatus() to check 
  479:          * if a handshake succeeded.
  480:          */
  481:         public SSL Connect(Socket s, byte[] session_id)
  482:         {
  483:             int client_fd = s.Handle.ToInt32();
  484:             byte sess_id_size = (byte)(session_id != null ? 
  485:                                 session_id.Length : 0);
  486:             return new SSL(axtls.ssl_client_new(m_ctx, client_fd, session_id,
  487:                         sess_id_size));
  488:         }
  489:     }
  490: }
  491: /** @} */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>