Ticket #1014: 1014-key_uses_cipher_index.diff

File 1014-key_uses_cipher_index.diff, 46.1 KB (added by nanang, 12 years ago)

implementation with cipher index as key

  • pjsip/include/pjsip/sip_transport_tls.h

     
    2626 */ 
    2727 
    2828#include <pjsip/sip_transport.h> 
     29#include <pj/pool.h> 
    2930#include <pj/ssl_sock.h> 
    3031#include <pj/string.h> 
    3132#include <pj/sock_qos.h> 
     
    106107    int         method; 
    107108 
    108109    /** 
    109      * TLS cipher list string in OpenSSL format. If empty, then default 
    110      * cipher list of the backend will be used. 
     110     * Number of ciphers contained in the specified cipher preference.  
     111     * If this is set to zero, then default cipher list of the backend  
     112     * will be used. 
     113     * 
     114     * Default: 0 (zero). 
    111115     */ 
    112     pj_str_t    ciphers; 
     116    unsigned ciphers_num; 
    113117 
    114118    /** 
    115      * Optionally specify the server name instance to be contacted when 
    116      * making outgoing TLS connection. This setting is useful when the 
    117      * server is hosting multiple domains for the same TLS listening 
    118      * socket. 
    119      * 
    120      * Default: empty. 
     119     * Ciphers and order preference. 
    121120     */ 
    122     pj_str_t    server_name; 
     121    pj_ssl_cipher_idx *ciphers; 
    123122 
    124123    /** 
    125124     * Specifies TLS transport behavior on the server TLS certificate  
     
    246245    pj_strdup_with_null(pool, &dst->cert_file, &src->cert_file); 
    247246    pj_strdup_with_null(pool, &dst->privkey_file, &src->privkey_file); 
    248247    pj_strdup_with_null(pool, &dst->password, &src->password); 
    249     pj_strdup_with_null(pool, &dst->ciphers, &src->ciphers); 
     248    if (src->ciphers_num && src->ciphers) { 
     249        unsigned i; 
     250        dst->ciphers = (pj_ssl_cipher_idx*) 
     251                        pj_pool_calloc(pool, src->ciphers_num, 
     252                                       sizeof(pj_ssl_cipher_idx)); 
     253        for (i=0; i<src->ciphers_num; ++i) 
     254            dst->ciphers[i] = src->ciphers[i]; 
     255    } 
    250256} 
    251257 
    252258 
  • pjsip/src/pjsip/sip_transport_tls.c

     
    293293        ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; 
    294294    if (ssock_param.read_buffer_size < PJSIP_MAX_PKT_LEN) 
    295295        ssock_param.read_buffer_size = PJSIP_MAX_PKT_LEN; 
     296    ssock_param.ciphers_num = listener->tls_setting.ciphers_num; 
     297    ssock_param.ciphers = listener->tls_setting.ciphers; 
    296298    ssock_param.qos_type = listener->tls_setting.qos_type; 
    297299    ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error; 
    298300    pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params, 
     
    862864    ssock_param.cb.on_data_sent = &on_data_sent; 
    863865    ssock_param.async_cnt = 1; 
    864866    ssock_param.ioqueue = pjsip_endpt_get_ioqueue(listener->endpt); 
    865     PJ_TODO(synchronize_tls_cipher_type_with_ssl_sock_cipher_type); 
    866867    ssock_param.server_name = remote_name; 
    867868    ssock_param.timeout = listener->tls_setting.timeout; 
    868869    ssock_param.user_data = NULL; /* pending, must be set later */ 
     
    872873        ssock_param.send_buffer_size = PJSIP_MAX_PKT_LEN; 
    873874    if (ssock_param.read_buffer_size < PJSIP_MAX_PKT_LEN) 
    874875        ssock_param.read_buffer_size = PJSIP_MAX_PKT_LEN; 
     876    ssock_param.ciphers_num = listener->tls_setting.ciphers_num; 
     877    ssock_param.ciphers = listener->tls_setting.ciphers; 
    875878    ssock_param.qos_type = listener->tls_setting.qos_type; 
    876879    ssock_param.qos_ignore_error = listener->tls_setting.qos_ignore_error; 
    877880    pj_memcpy(&ssock_param.qos_params, &listener->tls_setting.qos_params, 
  • pjsip-apps/src/pjsua/pjsua_app.c

     
    234234    puts  ("                      May be specified multiple times"); 
    235235    puts  ("  --stun-srv=FORMAT   Set STUN server host or domain. This option may be"); 
    236236    puts  ("                      specified more than once. FORMAT is hostdom[:PORT]"); 
     237 
     238#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0) 
    237239    puts  (""); 
    238240    puts  ("TLS Options:"); 
    239241    puts  ("  --use-tls           Enable TLS transport (default=no)"); 
    240     puts  ("  --tls-ca-file       Specify TLS CA file (default=none)"); 
    241     puts  ("  --tls-cert-file     Specify TLS certificate file (default=none)"); 
    242     puts  ("  --tls-privkey-file  Specify TLS private key file (default=none)"); 
    243     puts  ("  --tls-password      Specify TLS password to private key file (default=none)"); 
     242    puts  ("  --tls-ca-file=S     Specify TLS CA file (default=none)"); 
     243    puts  ("  --tls-cert-file=S   Specify TLS certificate file (default=none)"); 
     244    puts  ("  --tls-privkey-file=S Specify TLS private key file (default=none)"); 
     245    puts  ("  --tls-password=S    Specify TLS password to private key file (default=none)"); 
    244246    puts  ("  --tls-verify-server Verify server's certificate (default=no)"); 
    245247    puts  ("  --tls-verify-client Verify client's certificate (default=no)"); 
    246     puts  ("  --tls-neg-timeout   Specify TLS negotiation timeout (default=no)"); 
    247     puts  ("  --tls-srv-name      Specify TLS server name for multi-hosting server (optional)"); 
     248    puts  ("  --tls-neg-timeout=N Specify TLS negotiation timeout, in seconds"); 
     249    puts  ("                      (default=0/no timeout)"); 
     250    puts  ("  --tls-cipher=N      Specify prefered TLS cipher index (optional)."); 
     251    puts  ("                      May be specified multiple times."); 
     252    puts  ("  --tls-cipher-list   List the available ciphers"); 
     253#endif 
    248254 
    249255    puts  (""); 
    250256    puts  ("Media Options:"); 
     
    319325    fflush(stdout); 
    320326} 
    321327 
     328#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0) 
    322329 
     330static void dump_tls_cipher_list() 
     331{ 
     332    unsigned i, n; 
     333 
     334    n = pj_ssl_cipher_count(); 
     335    puts("Available ciphers:"); 
     336    puts("-------------------------------"); 
     337    puts("Index |   Code   | Name"); 
     338    puts("-------------------------------"); 
     339    for (i = 0; i < n; ++i) { 
     340        pj_ssl_cipher_info info; 
     341 
     342        pj_ssl_cipher_get_info(i, &info); 
     343        printf("%5d | 0x%06X | %s\n", 
     344               i, info.code, info.name); 
     345    } 
     346    puts("-------------------------------"); 
     347} 
     348 
     349#endif 
     350 
    323351/* Set default config. */ 
    324352static void default_config(struct app_config *cfg) 
    325353{ 
     
    509537           OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS,  
    510538           OPT_DURATION, OPT_NO_TCP, OPT_NO_UDP, OPT_THREAD_CNT, 
    511539           OPT_NOREFERSUB, OPT_ACCEPT_REDIRECT, 
     540#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0) 
    512541           OPT_USE_TLS, OPT_TLS_CA_FILE, OPT_TLS_CERT_FILE, OPT_TLS_PRIV_FILE, 
    513542           OPT_TLS_PASSWORD, OPT_TLS_VERIFY_SERVER, OPT_TLS_VERIFY_CLIENT, 
    514            OPT_TLS_NEG_TIMEOUT, OPT_TLS_SRV_NAME, 
     543           OPT_TLS_NEG_TIMEOUT, OPT_TLS_CIPHER, OPT_TLS_CIPHER_LIST, 
     544#endif 
    515545           OPT_CAPTURE_DEV, OPT_PLAYBACK_DEV, 
    516546           OPT_CAPTURE_LAT, OPT_PLAYBACK_LAT, OPT_NO_TONES, OPT_JB_MAX_SIZE, 
    517547           OPT_STDOUT_REFRESH, OPT_STDOUT_REFRESH_TEXT, OPT_IPV6, OPT_QOS, 
     
    610640        { "max-calls",  1, 0, OPT_MAX_CALLS}, 
    611641        { "duration",   1, 0, OPT_DURATION}, 
    612642        { "thread-cnt", 1, 0, OPT_THREAD_CNT}, 
     643#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0) 
    613644        { "use-tls",    0, 0, OPT_USE_TLS},  
    614645        { "tls-ca-file",1, 0, OPT_TLS_CA_FILE}, 
    615646        { "tls-cert-file",1,0, OPT_TLS_CERT_FILE},  
     
    618649        { "tls-verify-server", 0, 0, OPT_TLS_VERIFY_SERVER}, 
    619650        { "tls-verify-client", 0, 0, OPT_TLS_VERIFY_CLIENT}, 
    620651        { "tls-neg-timeout", 1, 0, OPT_TLS_NEG_TIMEOUT}, 
    621         { "tls-srv-name", 1, 0, OPT_TLS_SRV_NAME}, 
     652        { "tls-cipher", 1, 0, OPT_TLS_CIPHER}, 
     653        { "tls-cipher-list", 0, 0, OPT_TLS_CIPHER_LIST}, 
     654#endif 
    622655        { "capture-dev",    1, 0, OPT_CAPTURE_DEV}, 
    623656        { "playback-dev",   1, 0, OPT_PLAYBACK_DEV}, 
    624657        { "capture-lat",    1, 0, OPT_CAPTURE_LAT}, 
     
    12741307            } 
    12751308            break; 
    12761309 
     1310#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0) 
    12771311        case OPT_USE_TLS: 
    12781312            cfg->use_tls = PJ_TRUE; 
    1279 #if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0 
    1280             PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured")); 
    1281             return -1; 
    1282 #endif 
    12831313            break; 
    12841314             
    12851315        case OPT_TLS_CA_FILE: 
    12861316            cfg->udp_cfg.tls_setting.ca_list_file = pj_str(pj_optarg); 
    1287 #if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0 
    1288             PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured")); 
    1289             return -1; 
    1290 #endif 
    12911317            break; 
    12921318             
    12931319        case OPT_TLS_CERT_FILE: 
    12941320            cfg->udp_cfg.tls_setting.cert_file = pj_str(pj_optarg); 
    1295 #if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0 
    1296             PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured")); 
    1297             return -1; 
    1298 #endif 
    12991321            break; 
    13001322             
    13011323        case OPT_TLS_PRIV_FILE: 
     
    13041326 
    13051327        case OPT_TLS_PASSWORD: 
    13061328            cfg->udp_cfg.tls_setting.password = pj_str(pj_optarg); 
    1307 #if !defined(PJSIP_HAS_TLS_TRANSPORT) || PJSIP_HAS_TLS_TRANSPORT==0 
    1308             PJ_LOG(1,(THIS_FILE, "Error: TLS support is not configured")); 
    1309             return -1; 
    1310 #endif 
    13111329            break; 
    13121330 
    13131331        case OPT_TLS_VERIFY_SERVER: 
     
    13231341            cfg->udp_cfg.tls_setting.timeout.sec = atoi(pj_optarg); 
    13241342            break; 
    13251343 
    1326         case OPT_TLS_SRV_NAME: 
    1327             cfg->udp_cfg.tls_setting.server_name = pj_str(pj_optarg); 
     1344        case OPT_TLS_CIPHER: 
     1345            { 
     1346                pj_ssl_cipher_idx cipher_idx; 
     1347 
     1348                cipher_idx = atoi(pj_optarg); 
     1349                if (cipher_idx < pj_ssl_cipher_count()) { 
     1350                    static pj_ssl_cipher_idx tls_ciphers[100]; 
     1351                    static unsigned tls_ciphers_num = 0; 
     1352 
     1353                    tls_ciphers[tls_ciphers_num++] = cipher_idx; 
     1354                    cfg->udp_cfg.tls_setting.ciphers_num = tls_ciphers_num; 
     1355                    cfg->udp_cfg.tls_setting.ciphers = tls_ciphers; 
     1356                } else { 
     1357                    PJ_LOG(1,(THIS_FILE, "Cipher index out of range. See --tls-cipher-list.")); 
     1358                    return -1; 
     1359                } 
     1360            } 
    13281361            break; 
    13291362 
     1363        case OPT_TLS_CIPHER_LIST: 
     1364            dump_tls_cipher_list(); 
     1365            return -1; 
     1366#endif 
     1367 
    13301368        case OPT_CAPTURE_DEV: 
    13311369            cfg->capture_dev = atoi(pj_optarg); 
    13321370            break; 
     
    17421780        pj_strcat2(&cfg, line); 
    17431781    } 
    17441782 
     1783#if defined(PJSIP_HAS_TLS_TRANSPORT) && (PJSIP_HAS_TLS_TRANSPORT != 0) 
    17451784    /* TLS */ 
    17461785    if (config->use_tls) 
    17471786        pj_strcat2(&cfg, "--use-tls\n"); 
     
    17711810        pj_strcat2(&cfg, line); 
    17721811    } 
    17731812 
    1774     if (config->udp_cfg.tls_setting.server_name.slen) { 
    1775         pj_ansi_sprintf(line, "--tls-srv-name %.*s\n", 
    1776                         (int)config->udp_cfg.tls_setting.server_name.slen,  
    1777                         config->udp_cfg.tls_setting.server_name.ptr); 
    1778         pj_strcat2(&cfg, line); 
    1779     } 
    1780  
    17811813    if (config->udp_cfg.tls_setting.verify_server) 
    17821814        pj_strcat2(&cfg, "--tls-verify-server\n"); 
    17831815 
     
    17901822        pj_strcat2(&cfg, line); 
    17911823    } 
    17921824 
     1825    for (i=0; i<config->udp_cfg.tls_setting.ciphers_num; ++i) { 
     1826        pj_ansi_sprintf(line, "--tls-cipher %d\n", 
     1827                        config->udp_cfg.tls_setting.ciphers[i]); 
     1828        pj_strcat2(&cfg, line); 
     1829    } 
     1830#endif 
     1831 
    17931832    pj_strcat2(&cfg, "\n#\n# Media settings:\n#\n"); 
    17941833 
    17951834    /* SRTP */ 
     
    29072946        const char *verif_msgs[32]; 
    29082947        unsigned verif_msg_cnt; 
    29092948 
    2910         /* Dump server TLS certificate */ 
    2911         pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, "  ", 
    2912                               buf, sizeof(buf)); 
    2913         PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf)); 
     2949        /* Dump server TLS cipher */ 
     2950        PJ_LOG(4,(THIS_FILE, "TLS cipher used: %s (0x%06X)", 
     2951                  ssl_sock_info->cipher_info.name, 
     2952                  ssl_sock_info->cipher_info.code)); 
    29142953 
    2915         /* Dump server TLS certificate verification result */ 
    2916         verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); 
    2917         pj_ssl_cert_get_verify_status_strings(ssl_sock_info->verify_status, 
    2918                                               verif_msgs, &verif_msg_cnt); 
    2919         PJ_LOG(3,(THIS_FILE, "TLS cert verification result of %s : %s", 
    2920                              host_port, 
    2921                              (verif_msg_cnt == 1? verif_msgs[0]:""))); 
    2922         if (verif_msg_cnt > 1) { 
    2923             unsigned i; 
    2924             for (i = 0; i < verif_msg_cnt; ++i) 
    2925                 PJ_LOG(3,(THIS_FILE, "- %s", verif_msgs[i])); 
    2926         } 
     2954        /* Dump server TLS certificate and the verification result, if any */ 
     2955        if (ssl_sock_info->remote_cert_info && 
     2956            ssl_sock_info->remote_cert_info->subject.info.slen) 
     2957        { 
     2958            /* Dump server TLS certificate */ 
     2959            pj_ssl_cert_info_dump(ssl_sock_info->remote_cert_info, "  ", 
     2960                                  buf, sizeof(buf)); 
     2961            PJ_LOG(4,(THIS_FILE, "TLS cert info of %s:\n%s", host_port, buf)); 
    29272962 
    2928         if (ssl_sock_info->verify_status && 
    2929             !app_config.udp_cfg.tls_setting.verify_server)  
    2930         { 
    2931             PJ_LOG(3,(THIS_FILE, "PJSUA is configured to ignore TLS cert " 
    2932                                  "verification errors")); 
     2963            /* Dump server TLS certificate verification result */ 
     2964            verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs); 
     2965            pj_ssl_cert_get_verify_status_strings(ssl_sock_info->verify_status, 
     2966                                                  verif_msgs, &verif_msg_cnt); 
     2967            PJ_LOG(3,(THIS_FILE, "TLS cert verification result of %s : %s", 
     2968                                 host_port, 
     2969                                 (verif_msg_cnt == 1? verif_msgs[0]:""))); 
     2970            if (verif_msg_cnt > 1) { 
     2971                unsigned i; 
     2972                for (i = 0; i < verif_msg_cnt; ++i) 
     2973                    PJ_LOG(3,(THIS_FILE, "- %s", verif_msgs[i])); 
     2974            } 
     2975 
     2976            if (ssl_sock_info->verify_status && 
     2977                !app_config.udp_cfg.tls_setting.verify_server)  
     2978            { 
     2979                PJ_LOG(3,(THIS_FILE, "PJSUA is configured to ignore TLS cert " 
     2980                                     "verification errors")); 
     2981            } 
    29332982        } 
    29342983    } 
    29352984 
  • pjsip-apps/src/symbian_ua/ua.cpp

     
    5656// 
    5757#define ENABLE_SIP_UDP  1 
    5858#define ENABLE_SIP_TCP  0 // experimental 
    59 #define ENABLE_SIP_TLS  0 // experimental 
     59#define ENABLE_SIP_TLS  1 // experimental 
    6060 
    6161#define TLS_SRV_NAME    "pjsip.org"     // TLS servername (required for 
    6262                                        // TLS transport) 
     
    490490        tcfg.qos_params.dscp_val = SIP_QOS_DSCP; 
    491491        tcfg.tls_setting.qos_params = tcfg.qos_params; 
    492492    } 
    493     tcfg.tls_setting.server_name = pj_str(TLS_SRV_NAME); 
    494493    status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tcfg, &tid); 
    495494    if (status != PJ_SUCCESS) { 
    496495            pjsua_perror(THIS_FILE, "Error creating TLS transport", status); 
  • pjlib/include/pj/config.h

     
    791791#endif 
    792792 
    793793 
     794/** 
     795 * Set the default cipher list setting of secure socket for OpenSSL backend. 
     796 * This will be passed to OpenSSL API <tt>SSL_set_cipher_list() / 
     797 * SSL_CTX_set_cipher_list()</tt>, see OpenSSL documentation for more info. 
     798 * 
     799 * Default: "ALL" 
     800 */ 
     801#ifndef PJ_SSL_SOCK_OSSL_CIPHERS 
     802#   define PJ_SSL_SOCK_OSSL_CIPHERS "ALL" 
     803#endif 
     804 
     805 
     806/** 
     807 * Specifies if secure socket for native Symbian backend has cipher names 
     808 * table. The cipher names table can be useful, e.g: for logging or info, 
     809 * however it will increase the binary footprint. 
     810 * 
     811 * Default: 0 
     812 */ 
     813#ifndef PJ_SSL_SOCK_SYMBIAN_HAS_NAME 
     814#   define PJ_SSL_SOCK_SYMBIAN_HAS_NAME 0 
     815#endif 
     816 
     817 
    794818/** @} */ 
    795819 
    796820/******************************************************************** 
  • pjlib/include/pj/ssl_sock.h

     
    238238                                                 unsigned *count); 
    239239 
    240240 
    241 /**  
    242  * Cipher suites enumeration. 
     241/** 
     242 * Definition of cipher-suite index. 
    243243 */ 
    244 typedef enum pj_ssl_cipher { 
     244typedef unsigned pj_ssl_cipher_idx; 
    245245 
    246     /* NULL */ 
    247     PJ_TLS_NULL_WITH_NULL_NULL                  = 0x00000000, 
    248246 
    249     /* TLS/SSLv3 */ 
    250     PJ_TLS_RSA_WITH_NULL_MD5                    = 0x00000001, 
    251     PJ_TLS_RSA_WITH_NULL_SHA                    = 0x00000002, 
    252     PJ_TLS_RSA_WITH_NULL_SHA256                 = 0x0000003B, 
    253     PJ_TLS_RSA_WITH_RC4_128_MD5                 = 0x00000004, 
    254     PJ_TLS_RSA_WITH_RC4_128_SHA                 = 0x00000005, 
    255     PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA            = 0x0000000A, 
    256     PJ_TLS_RSA_WITH_AES_128_CBC_SHA             = 0x0000002F, 
    257     PJ_TLS_RSA_WITH_AES_256_CBC_SHA             = 0x00000035, 
    258     PJ_TLS_RSA_WITH_AES_128_CBC_SHA256          = 0x0000003C, 
    259     PJ_TLS_RSA_WITH_AES_256_CBC_SHA256          = 0x0000003D, 
    260     PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA         = 0x0000000D, 
    261     PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA         = 0x00000010, 
    262     PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA        = 0x00000013, 
    263     PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA        = 0x00000016, 
    264     PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA          = 0x00000030, 
    265     PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA          = 0x00000031, 
    266     PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA         = 0x00000032, 
    267     PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA         = 0x00000033, 
    268     PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA          = 0x00000036, 
    269     PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA          = 0x00000037, 
    270     PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA         = 0x00000038, 
    271     PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA         = 0x00000039, 
    272     PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256       = 0x0000003E, 
    273     PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256       = 0x0000003F, 
    274     PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256      = 0x00000040, 
    275     PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      = 0x00000067, 
    276     PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256       = 0x00000068, 
    277     PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256       = 0x00000069, 
    278     PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256      = 0x0000006A, 
    279     PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      = 0x0000006B, 
    280     PJ_TLS_DH_anon_WITH_RC4_128_MD5             = 0x00000018, 
    281     PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA        = 0x0000001B, 
    282     PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA         = 0x00000034, 
    283     PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA         = 0x0000003A, 
    284     PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256      = 0x0000006C, 
    285     PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256      = 0x0000006D, 
     247/** 
     248 * Definition of cipher-suite info 
     249 */ 
     250typedef struct pj_ssl_cipher_info { 
     251    /** 
     252     * Cipher-suite code as specified in the TLS/SSL specifications. Note 
     253     * that the cipher code will occupy the least significant octets, 
     254     * TLS/SSLv3 cipher code occupies two octets and SSLv2 cipher code 
     255     * occupies three octets. 
     256     */ 
     257    pj_uint32_t          code; 
    286258 
    287     /* TLS (deprecated) */ 
    288     PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5           = 0x00000003, 
    289     PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5       = 0x00000006, 
    290     PJ_TLS_RSA_WITH_IDEA_CBC_SHA                = 0x00000007, 
    291     PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA        = 0x00000008, 
    292     PJ_TLS_RSA_WITH_DES_CBC_SHA                 = 0x00000009, 
    293     PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA     = 0x0000000B, 
    294     PJ_TLS_DH_DSS_WITH_DES_CBC_SHA              = 0x0000000C, 
    295     PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA     = 0x0000000E, 
    296     PJ_TLS_DH_RSA_WITH_DES_CBC_SHA              = 0x0000000F, 
    297     PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA    = 0x00000011, 
    298     PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA             = 0x00000012, 
    299     PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA    = 0x00000014, 
    300     PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA             = 0x00000015, 
    301     PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5       = 0x00000017, 
    302     PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA    = 0x00000019, 
    303     PJ_TLS_DH_anon_WITH_DES_CBC_SHA             = 0x0000001A, 
     259    /** 
     260     * Cipher-suite name. The name may be backend specific, e.g: OpenSSL uses 
     261     * "AES256-SHA" for "TLS_RSA_WITH_AES_256_CBC_SHA". 
     262     */ 
     263    const char          *name; 
    304264 
    305     /* SSLv3 */ 
    306     PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA           = 0x0000001C, 
    307     PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA   = 0x0000001D, 
    308     PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA        = 0x0000001E, 
    309      
    310     /* SSLv2 */ 
    311     PJ_SSL_CK_RC4_128_WITH_MD5                  = 0x00010080, 
    312     PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5         = 0x00020080, 
    313     PJ_SSL_CK_RC2_128_CBC_WITH_MD5              = 0x00030080, 
    314     PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5     = 0x00040080, 
    315     PJ_SSL_CK_IDEA_128_CBC_WITH_MD5             = 0x00050080, 
    316     PJ_SSL_CK_DES_64_CBC_WITH_MD5               = 0x00060040, 
    317     PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5         = 0x000700C0 
     265} pj_ssl_cipher_info; 
    318266 
    319 } pj_ssl_cipher; 
    320267 
    321  
    322268/** 
    323  * Get cipher list supported by SSL/TLS backend. 
     269 * Get the number of cipher-suites supported by SSL/TLS backend. 
    324270 * 
    325  * @param ciphers       The ciphers buffer to receive cipher list. 
    326  * @param cipher_num    Maximum number of ciphers to be received. 
    327  * 
    328  * @return              PJ_SUCCESS when successful. 
     271 * @return              Number of cipher-suites supported by SSL/TLS backend. 
    329272 */ 
    330 PJ_DECL(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[], 
    331                                                   unsigned *cipher_num); 
     273PJ_DECL(unsigned) pj_ssl_cipher_count(); 
    332274 
    333275 
    334276/** 
    335  * Get cipher name string. 
     277 * Get cipher-suite info. 
    336278 * 
    337  * @param cipher        The cipher. 
     279 * @param cipher_idx    The cipher-suite index. 
     280 * @param info          Buffer for receiving the cipher-suite info. 
    338281 * 
    339  * @return              The cipher name or NULL if cipher is not recognized. 
     282 * @return              PJ_SUCCESS when successful. 
    340283 */ 
    341 PJ_DECL(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher); 
     284PJ_DECL(pj_status_t) pj_ssl_cipher_get_info(pj_ssl_cipher_idx cipher_idx, 
     285                                            pj_ssl_cipher_info *info); 
    342286 
    343287 
    344288/** 
     
    490434    pj_ssl_sock_proto proto; 
    491435 
    492436    /** 
    493      * Describes cipher suite being used, this will only be set when connection 
    494      * is established. 
     437     * Describes cipher-suite being used, this will only be set when the 
     438     * connection is established. 
    495439     */ 
    496     pj_ssl_cipher cipher; 
     440    pj_ssl_cipher_info cipher_info; 
    497441 
    498442    /** 
    499443     * Describes local address. 
     
    647591     * Ciphers and order preference. If empty, then default cipher list and 
    648592     * its default order of the backend will be used. 
    649593     */ 
    650     pj_ssl_cipher *ciphers; 
     594    pj_ssl_cipher_idx *ciphers; 
    651595 
    652596    /** 
    653597     * Security negotiation timeout. If this is set to zero (both sec and  
  • pjlib/src/pj/ssl_sock_ossl.c

     
    148148     
    149149    pj_ssl_cert_info      local_cert_info; 
    150150    pj_ssl_cert_info      remote_cert_info; 
     151    pj_ssl_cipher_idx     cipher_idx; 
    151152 
    152153    pj_bool_t             is_server; 
    153154    enum ssl_state        ssl_state; 
     
    269270static int openssl_init_count; 
    270271static int openssl_reg_strerr; 
    271272 
    272 /* OpenSSL available ciphers */ 
    273 static pj_ssl_cipher openssl_ciphers[100]; 
     273/* OpenSSL ciphers */ 
     274#define MAX_CIPHERS 100 
    274275static unsigned openssl_cipher_num; 
     276static pj_ssl_cipher_info openssl_cipher_info[MAX_CIPHERS]; 
    275277 
    276278/* OpenSSL application data index */ 
    277279static int sslsock_idx; 
    278280 
    279  
    280281/* Initialize OpenSSL */ 
    281282static pj_status_t init_openssl(void) 
    282283{ 
     
    301302    SSL_load_error_strings(); 
    302303    OpenSSL_add_all_algorithms(); 
    303304 
    304     /* Init available ciphers */ 
     305    /* Create OpenSSL application data index for SSL socket */ 
     306    sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 
     307 
     308    /* Get available ciphers */ 
    305309    if (openssl_cipher_num == 0) { 
    306310        SSL_METHOD *meth = NULL; 
    307311        SSL_CTX *ctx; 
    308312        SSL *ssl; 
    309313        STACK_OF(SSL_CIPHER) *sk_cipher; 
    310         unsigned i, n; 
     314        unsigned i; 
    311315 
    312316        meth = (SSL_METHOD*)SSLv23_server_method(); 
    313317        if (!meth) 
     
    319323        pj_assert(meth); 
    320324 
    321325        ctx=SSL_CTX_new(meth); 
    322         SSL_CTX_set_cipher_list(ctx, "ALL"); 
     326        SSL_CTX_set_cipher_list(ctx, PJ_SSL_SOCK_OSSL_CIPHERS); 
    323327 
    324328        ssl = SSL_new(ctx); 
    325329        sk_cipher = SSL_get_ciphers(ssl); 
    326330 
    327         n = sk_SSL_CIPHER_num(sk_cipher); 
    328         if (n > PJ_ARRAY_SIZE(openssl_ciphers)) 
    329             n = PJ_ARRAY_SIZE(openssl_ciphers); 
     331        openssl_cipher_num = sk_SSL_CIPHER_num(sk_cipher); 
     332        if (openssl_cipher_num > MAX_CIPHERS) 
     333            openssl_cipher_num = MAX_CIPHERS; 
    330334 
    331         for (i = 0; i < n; ++i) { 
     335        for (i = 0; i < openssl_cipher_num; ++i) { 
    332336            SSL_CIPHER *c; 
     337            pj_ssl_cipher_info *info = &openssl_cipher_info[i]; 
     338 
    333339            c = sk_SSL_CIPHER_value(sk_cipher,i); 
    334             openssl_ciphers[i] = (pj_ssl_cipher) 
    335                                  (pj_uint32_t)c->id & 0x00FFFFFF; 
    336             //printf("%3u: %08x=%s\n", i+1, c->id, SSL_CIPHER_get_name(c)); 
     340            info->code = (pj_uint32_t)(c->id & 0x00FFFFFF); 
     341            info->name = SSL_CIPHER_get_name(c); 
    337342        } 
    338343 
    339344        SSL_free(ssl); 
    340345        SSL_CTX_free(ctx); 
    341  
    342         openssl_cipher_num = n; 
    343346    } 
    344347 
    345     /* Create OpenSSL application data index for SSL socket */ 
    346     sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 
    347  
    348348    return PJ_SUCCESS; 
    349349} 
    350350 
     
    657657/* Generate cipher list with user preference order in OpenSSL format */ 
    658658static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock) 
    659659{ 
    660     char buf[1024]; 
    661660    pj_str_t cipher_list; 
    662     STACK_OF(SSL_CIPHER) *sk_cipher; 
    663     unsigned i; 
    664     int j, ret; 
     661    int ret; 
    665662 
    666     if (ssock->param.ciphers_num == 0) 
    667         return PJ_SUCCESS; 
     663    if (ssock->param.ciphers_num == 0 || ssock->param.ciphers == NULL) { 
     664        pj_cstr(&cipher_list, PJ_SSL_SOCK_OSSL_CIPHERS); 
     665    } else { 
     666        char buf[1024]; 
     667        unsigned i; 
    668668 
    669     pj_strset(&cipher_list, buf, 0); 
     669        pj_strset(&cipher_list, buf, 0); 
    670670 
    671     /* Set SSL with ALL available ciphers */ 
    672     SSL_set_cipher_list(ssock->ossl_ssl, "ALL"); 
     671        /* Generate user specified cipher list in OpenSSL format */ 
     672        for (i = 0; i < ssock->param.ciphers_num; ++i) { 
     673            pj_ssl_cipher_idx ci = ssock->param.ciphers[i]; 
     674            const char *cname; 
    673675 
    674     /* Generate user specified cipher list in OpenSSL format */ 
    675     sk_cipher = SSL_get_ciphers(ssock->ossl_ssl); 
    676     for (i = 0; i < ssock->param.ciphers_num; ++i) { 
    677         for (j = 0; j < sk_SSL_CIPHER_num(sk_cipher); ++j) { 
    678             SSL_CIPHER *c; 
    679             c = sk_SSL_CIPHER_value(sk_cipher, j); 
    680             if (ssock->param.ciphers[i] == (pj_ssl_cipher) 
    681                                            ((pj_uint32_t)c->id & 0x00FFFFFF)) 
    682             { 
    683                 const char *c_name; 
     676            if (ci >= openssl_cipher_num) 
     677                continue; 
    684678 
    685                 c_name = SSL_CIPHER_get_name(c); 
     679            cname = openssl_cipher_info[ci].name; 
    686680 
    687                 /* Check buffer size */ 
    688                 if (cipher_list.slen + pj_ansi_strlen(c_name) + 2 > sizeof(buf)) { 
    689                     pj_assert(!"Insufficient temporary buffer for cipher"); 
    690                     return PJ_ETOOMANY; 
    691                 } 
     681            /* Check buffer size */ 
     682            if (cipher_list.slen + pj_ansi_strlen(cname) + 2 > sizeof(buf)) { 
     683                pj_assert(!"Insufficient temporary buffer for cipher"); 
     684                break; 
     685            } 
    692686 
    693                 /* Add colon separator */ 
    694                 if (cipher_list.slen) 
    695                     pj_strcat2(&cipher_list, ":"); 
     687            /* Add colon separator */ 
     688            if (cipher_list.slen) 
     689                pj_strcat2(&cipher_list, ":"); 
    696690 
    697                 /* Add the cipher */ 
    698                 pj_strcat2(&cipher_list, c_name); 
    699                 break; 
    700             } 
     691            /* Add the cipher */ 
     692            pj_strcat2(&cipher_list, cname); 
    701693        } 
     694 
     695        /* Put NULL termination in the generated cipher list */ 
     696        cipher_list.ptr[cipher_list.slen] = '\0'; 
    702697    } 
    703698 
    704     /* Put NULL termination in the generated cipher list */ 
    705     cipher_list.ptr[cipher_list.slen] = '\0'; 
    706  
    707699    /* Finally, set chosen cipher list */ 
    708     ret = SSL_set_cipher_list(ssock->ossl_ssl, buf); 
     700    ret = SSL_set_cipher_list(ssock->ossl_ssl, cipher_list.ptr); 
    709701    if (ret < 1) { 
    710702        pj_status_t status; 
    711703        GET_SSL_STATUS(status); 
     
    919911static void update_certs_info(pj_ssl_sock_t *ssock) 
    920912{ 
    921913    X509 *x; 
     914    const SSL_CIPHER *c; 
     915    unsigned i; 
     916    pj_uint32_t cid; 
    922917 
    923918    pj_assert(ssock->ssl_state == SSL_STATE_ESTABLISHED); 
    924919 
     920    /* Active cipher */ 
     921    c = SSL_get_current_cipher(ssock->ossl_ssl); 
     922    cid = (pj_uint32_t)(c->id & 0x00FFFFFF); 
     923    for (i=0; i<openssl_cipher_num; ++i) { 
     924        if (cid == openssl_cipher_info[i].code) { 
     925            ssock->cipher_idx = i; 
     926            break; 
     927        } 
     928    } 
     929 
    925930    /* Active local certificate */ 
    926931    x = SSL_get_certificate(ssock->ossl_ssl); 
    927932    if (x) { 
     
    16921697} 
    16931698 
    16941699 
    1695 /* Get available ciphers. */ 
    1696 PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables(pj_ssl_cipher ciphers[], 
    1697                                                  unsigned *cipher_num) 
     1700/* Get ciphers count. */ 
     1701PJ_DEF(unsigned) pj_ssl_cipher_count() 
    16981702{ 
    1699     unsigned i; 
     1703    init_openssl(); 
     1704    return openssl_cipher_num; 
     1705} 
    17001706 
    1701     PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL); 
    17021707 
    1703     if (openssl_cipher_num == 0) { 
    1704         init_openssl(); 
    1705         shutdown_openssl(); 
     1708/* Get cipher info. */ 
     1709PJ_DEF(pj_status_t) pj_ssl_cipher_get_info(pj_ssl_cipher_idx cipher_idx, 
     1710                                           pj_ssl_cipher_info *info) 
     1711{ 
     1712    PJ_ASSERT_RETURN(info, PJ_EINVAL); 
     1713 
     1714    pj_bzero(info, sizeof(*info)); 
     1715    if (cipher_idx < pj_ssl_cipher_count()) { 
     1716        *info = openssl_cipher_info[cipher_idx]; 
     1717        return PJ_SUCCESS; 
    17061718    } 
    17071719 
    1708     if (openssl_cipher_num == 0) 
    1709         return PJ_ENOTFOUND; 
    1710  
    1711     *cipher_num = PJ_MIN(*cipher_num, openssl_cipher_num); 
    1712  
    1713     for (i = 0; i < *cipher_num; ++i) 
    1714         ciphers[i] = openssl_ciphers[i]; 
    1715  
    1716     return PJ_SUCCESS; 
     1720    return PJ_ENOTFOUND; 
    17171721} 
    17181722 
    17191723 
     
    17501754    /* Init secure socket param */ 
    17511755    ssock->param = *param; 
    17521756    ssock->param.read_buffer_size = ((ssock->param.read_buffer_size+7)>>3)<<3; 
    1753     if (param->ciphers_num > 0) { 
     1757    if (param->ciphers_num > 0 && param->ciphers != NULL) { 
    17541758        unsigned i; 
    1755         ssock->param.ciphers = (pj_ssl_cipher*) 
     1759        ssock->param.ciphers = (pj_ssl_cipher_idx*) 
    17561760                               pj_pool_calloc(pool, param->ciphers_num,  
    1757                                               sizeof(pj_ssl_cipher)); 
     1761                                              sizeof(pj_ssl_cipher_idx)); 
    17581762        for (i = 0; i < param->ciphers_num; ++i) 
    17591763            ssock->param.ciphers[i] = param->ciphers[i]; 
    17601764    } 
     
    18431847    pj_sockaddr_cp(&info->local_addr, &ssock->local_addr); 
    18441848     
    18451849    if (info->established) { 
    1846         const SSL_CIPHER *cipher; 
     1850        /* Cipher */ 
     1851        info->cipher_info = openssl_cipher_info[ssock->cipher_idx]; 
    18471852 
    1848         /* Current cipher */ 
    1849         cipher = SSL_get_current_cipher(ssock->ossl_ssl); 
    1850         info->cipher = (cipher->id & 0x00FFFFFF); 
    1851  
    18521853        /* Remote address */ 
    18531854        pj_sockaddr_cp(&info->remote_addr, &ssock->rem_addr); 
    18541855 
  • pjlib/src/pj/ssl_sock_symbian.cpp

     
    115115 
    116116    int Connect(CPjSSLSocket_cb cb, void *key, const TInetAddr &local_addr,  
    117117                const TInetAddr &rem_addr,  
    118                 const TDesC8 &servername = TPtrC8(NULL,0)); 
     118                const TDesC8 &servername = TPtrC8(NULL,0), 
     119                const TDesC8 &ciphers = TPtrC8(NULL,0)); 
    119120    int Send(CPjSSLSocket_cb cb, void *key, const TDesC8 &aDesc, TUint flags); 
    120121    int SendSync(const TDesC8 &aDesc, TUint flags); 
    121122 
     
    146147    TBuf<32>             ssl_proto_; 
    147148    TInetAddr            rem_addr_; 
    148149    TPtrC8               servername_; 
     150    TPtrC8               ciphers_; 
    149151    TInetAddr            local_addr_; 
    150152    TSockXfrLength       sent_len_; 
    151153 
     
    186188int CPjSSLSocket::Connect(CPjSSLSocket_cb cb, void *key,  
    187189                          const TInetAddr &local_addr,  
    188190                          const TInetAddr &rem_addr, 
    189                           const TDesC8 &servername) 
     191                          const TDesC8 &servername, 
     192                          const TDesC8 &ciphers) 
    190193{ 
    191194    pj_status_t status; 
    192195     
     
    213216    cb_ = cb; 
    214217    key_ = key; 
    215218    rem_addr_ = rem_addr; 
     219     
     220    /* Note: the following members only keep the pointer, not the data */ 
    216221    servername_.Set(servername); 
     222    ciphers_.Set(ciphers); 
     223 
    217224    rSock.Connect(rem_addr_, iStatus); 
    218225    SetActive(); 
    219226    state_ = SSL_STATE_CONNECTING; 
     
    318325            if (servername_.Length() > 0) 
    319326                securesock_->SetOpt(KSoSSLDomainName, KSolInetSSL, 
    320327                                    servername_); 
     328            if (ciphers_.Length() > 0) 
     329                securesock_->SetAvailableCipherSuites(ciphers_); 
    321330 
    322331            // FlushSessionCache() seems to also fire signals to all  
    323332            // completed AOs (something like CActiveScheduler::RunIfReady()) 
     
    441450 
    442451    pj_ssl_sock_proto    proto; 
    443452    pj_time_val          timeout; 
    444     unsigned             ciphers_num; 
    445     pj_ssl_cipher       *ciphers; 
    446453    pj_str_t             servername; 
     454    pj_str_t             ciphers; 
     455     
    447456    pj_ssl_cert_info     remote_cert_info; 
     457    pj_ssl_cipher_idx    cipher_idx; 
    448458}; 
    449459 
    450460 
     461/* Available ciphers */ 
     462#define MAX_CIPHERS     32 
     463static unsigned ciphers_num_ = 0; 
     464static pj_ssl_cipher_info ciphers_[MAX_CIPHERS]; 
     465 
     466#if defined(PJ_SSL_SOCK_SYMBIAN_HAS_NAME) && \ 
     467    PJ_SSL_SOCK_SYMBIAN_HAS_NAME != 0 
     468 
     469static const char* CIPHER_NAMES[] = 
     470{ 
     471    "NULL", 
     472    "RSA_WITH_NULL_MD5", 
     473    "RSA_WITH_NULL_SHA", 
     474    "RSA_EXPORT_WITH_RC4_40_MD5", 
     475    "RSA_WITH_RC4_128_MD5", 
     476    "RSA_WITH_RC4_128_SHA", 
     477    "RSA_EXPORT_WITH_RC2_CBC_40_MD5", 
     478    "RSA_WITH_IDEA_CBC_SHA", 
     479    "RSA_EXPORT_WITH_DES40_CBC_SHA", 
     480    "RSA_WITH_DES_CBC_SHA", 
     481    "RSA_WITH_3DES_EDE_CBC_SHA", 
     482    "DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 
     483    "DH_DSS_WITH_DES_CBC_SHA", 
     484    "DH_DSS_WITH_3DES_EDE_CBC_SHA", 
     485    "DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 
     486    "DH_RSA_WITH_DES_CBC_SHA", 
     487    "DH_RSA_WITH_3DES_EDE_CBC_SHA", 
     488    "DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", 
     489    "DHE_DSS_WITH_DES_CBC_SHA", 
     490    "DHE_DSS_WITH_3DES_EDE_CBC_SHA", 
     491    "DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", 
     492    "DHE_RSA_WITH_DES_CBC_SHA", 
     493    "DHE_RSA_WITH_3DES_EDE_CBC_SHA", 
     494    "DH_anon_EXPORT_WITH_RC4_40_MD5", 
     495    "DH_anon_WITH_RC4_128_MD5", 
     496    "DH_anon_EXPORT_WITH_DES40_CBC_SHA", 
     497    "DH_anon_WITH_DES_CBC_SHA", 
     498    "DH_anon_WITH_3DES_EDE_CBC_SHA" 
     499}; 
     500 
     501#endif 
     502     
     503 
    451504static pj_str_t get_cert_name(char *buf, unsigned buf_len, 
    452505                              const CX500DistinguishedName &name) 
    453506{ 
     
    565618static void update_certs_info(pj_ssl_sock_t *ssock) 
    566619{ 
    567620    const CX509Certificate *x; 
     621    TBuf8<4> cipher(0); 
    568622 
    569623    pj_assert(ssock && ssock->sock && 
    570624              ssock->sock->GetState() == CPjSSLSocket::SSL_STATE_ESTABLISHED); 
    571625         
     626    /* Active cipher */ 
     627    if (ssock->sock->GetCipher(cipher) == KErrNone && cipher.Length() >=2) 
     628    { 
     629        pj_uint32_t cid = (cipher[0]<<8) | cipher[1]; 
     630 
     631        for (unsigned i=0; i<ciphers_num_; ++i) { 
     632            if (cid == ciphers_[i].code) { 
     633                ssock->cipher_idx = i; 
     634                break; 
     635            } 
     636        } 
     637    } 
     638     
    572639    /* Active remote certificate */ 
    573640    x = ssock->sock->GetPeerCert(); 
    574641    if (x) { 
     
    580647 
    581648 
    582649/* 
    583  * Get cipher list supported by SSL/TLS backend. 
     650 * Get ciphers count. 
    584651 */ 
    585 PJ_DEF(pj_status_t) pj_ssl_cipher_get_availables (pj_ssl_cipher ciphers[], 
    586                                                   unsigned *cipher_num) 
     652PJ_DEF(unsigned) pj_ssl_cipher_count() 
    587653{ 
    588     /* Available ciphers */ 
    589     static pj_ssl_cipher ciphers_[64]; 
    590     static unsigned ciphers_num_ = 0; 
    591     unsigned i; 
    592  
    593     PJ_ASSERT_RETURN(ciphers && cipher_num, PJ_EINVAL); 
    594      
    595654    if (ciphers_num_ == 0) { 
    596655        RSocket sock; 
    597656        CSecureSocket *secure_sock; 
     
    599658 
    600659        secure_sock = CSecureSocket::NewL(sock, proto); 
    601660        if (secure_sock) { 
    602             TBuf8<128> ciphers_buf(0); 
     661            TBuf8<MAX_CIPHERS*2> ciphers_buf(0); 
     662 
    603663            secure_sock->AvailableCipherSuites(ciphers_buf); 
    604              
    605664            ciphers_num_ = ciphers_buf.Length() / 2; 
    606665            if (ciphers_num_ > PJ_ARRAY_SIZE(ciphers_)) 
    607666                ciphers_num_ = PJ_ARRAY_SIZE(ciphers_); 
    608             for (i = 0; i < ciphers_num_; ++i) 
    609                 ciphers_[i] = (pj_ssl_cipher)(ciphers_buf[i*2]*10 +  
    610                                               ciphers_buf[i*2+1]); 
     667             
     668            for (unsigned i = 0; i < ciphers_num_; ++i) { 
     669                const char *UNKNOWN = "[Unknown]"; 
     670                ciphers_[i].code = (ciphers_buf[i*2]<<8) | ciphers_buf[i*2+1]; 
     671#if defined(PJ_SSL_SOCK_SYMBIAN_HAS_NAME) && \ 
     672    PJ_SSL_SOCK_SYMBIAN_HAS_NAME != 0 
     673                if (ciphers_[i].code < PJ_ARRAY_SIZE(CIPHER_NAMES)) { 
     674                    ciphers_[i].name = CIPHER_NAMES[ciphers_[i].code]; 
     675                } else { 
     676                    ciphers_[i].name = UNKNOWN; 
     677                } 
     678#else 
     679                ciphers_[i].name = UNKNOWN; 
     680#endif 
     681            } 
    611682        } 
    612683         
    613684        delete secure_sock; 
    614685    } 
    615686     
    616     if (ciphers_num_ == 0) { 
    617         return PJ_ENOTFOUND; 
     687    return ciphers_num_; 
     688} 
     689 
     690 
     691/* Get cipher info. */ 
     692PJ_DEF(pj_status_t) pj_ssl_cipher_get_info(pj_ssl_cipher_idx cipher_idx, 
     693                                           pj_ssl_cipher_info *info) 
     694{ 
     695    PJ_ASSERT_RETURN(info, PJ_EINVAL); 
     696 
     697    pj_bzero(info, sizeof(*info)); 
     698    if (cipher_idx < pj_ssl_cipher_count()) { 
     699        *info = ciphers_[cipher_idx]; 
     700        return PJ_SUCCESS; 
    618701    } 
    619      
    620     *cipher_num = PJ_MIN(*cipher_num, ciphers_num_); 
    621     for (i = 0; i < *cipher_num; ++i) 
    622         ciphers[i] = ciphers_[i]; 
    623      
    624     return PJ_SUCCESS; 
     702 
     703    return PJ_ENOTFOUND; 
    625704} 
    626705 
     706 
    627707/* 
    628708 * Create SSL socket instance.  
    629709 */ 
     
    652732    ssock->cb = param->cb; 
    653733    ssock->user_data = param->user_data; 
    654734    ssock->timeout = param->timeout; 
    655     ssock->ciphers_num = param->ciphers_num; 
    656735    if (param->ciphers_num > 0) { 
    657         unsigned i; 
    658         ssock->ciphers = (pj_ssl_cipher*) 
    659                          pj_pool_calloc(pool, param->ciphers_num,  
    660                                         sizeof(pj_ssl_cipher)); 
    661         for (i = 0; i < param->ciphers_num; ++i) 
    662             ssock->ciphers[i] = param->ciphers[i]; 
     736        unsigned cipher_cnt = pj_ssl_cipher_count(); 
     737         
     738        /* Cipher list in Symbian is represented as array of two-octets. */ 
     739        ssock->ciphers.slen = 0; 
     740        ssock->ciphers.ptr  = (char*)pj_pool_alloc(pool, param->ciphers_num*2); 
     741        pj_uint8_t *c = (pj_uint8_t*)ssock->ciphers.ptr; 
     742        for (unsigned i = 0; i < param->ciphers_num; ++i) { 
     743            if (param->ciphers[i] < cipher_cnt) { 
     744                pj_ssl_cipher_info info; 
     745 
     746                pj_ssl_cipher_get_info(param->ciphers[i], &info); 
     747                *c++ = (pj_uint8_t)((info.code & 0xFF00) >> 8); 
     748                *c++ = (pj_uint8_t) (info.code & 0x00FF); 
     749                ssock->ciphers.slen += 2; 
     750            } 
     751        } 
    663752    } 
    664753    pj_strdup_with_null(pool, &ssock->servername, &param->server_name); 
    665754 
     
    780869 
    781870    if (info->established) { 
    782871        /* Cipher suite */ 
    783         TBuf8<4> cipher; 
    784         if (ssock->sock->GetCipher(cipher) == KErrNone) { 
    785             info->cipher = (pj_ssl_cipher)cipher[1];  
    786         } 
     872        info->cipher_info = ciphers_[ssock->cipher_idx];  
    787873 
    788874        /* Remote address */ 
    789875        pj_sockaddr_cp((pj_sockaddr_t*)&info->remote_addr,  
     
    12521338    TPtrC8 servername_((TUint8*)ssock->servername.ptr,  
    12531339                       ssock->servername.slen); 
    12541340     
     1341    /* Convert cipher list to Symbian descriptor */ 
     1342    TPtrC8 ciphers_((TUint8*)ssock->ciphers.ptr,  
     1343                    ssock->ciphers.slen); 
     1344     
    12551345    /* Try to connect */ 
    12561346    status = sock->Connect(&connect_cb, ssock, localaddr_, remaddr_, 
    1257                            servername_); 
     1347                           servername_, ciphers_); 
    12581348    if (status != PJ_SUCCESS && status != PJ_EPENDING) { 
    12591349        delete sock; 
    12601350        return status; 
  • pjlib/src/pj/ssl_sock_common.c

     
    2121#include <pj/errno.h> 
    2222#include <pj/string.h> 
    2323 
    24 /* Cipher name structure */ 
    25 typedef struct cipher_name_t { 
    26     pj_ssl_cipher    cipher; 
    27     const char      *name; 
    28 } cipher_name_t; 
    2924 
    30 /* Cipher name constants */ 
    31 static cipher_name_t cipher_names[] = 
    32 { 
    33     {PJ_TLS_NULL_WITH_NULL_NULL,               "NULL"}, 
    34  
    35     /* TLS/SSLv3 */ 
    36     {PJ_TLS_RSA_WITH_NULL_MD5,                 "TLS_RSA_WITH_NULL_MD5"}, 
    37     {PJ_TLS_RSA_WITH_NULL_SHA,                 "TLS_RSA_WITH_NULL_SHA"}, 
    38     {PJ_TLS_RSA_WITH_NULL_SHA256,              "TLS_RSA_WITH_NULL_SHA256"}, 
    39     {PJ_TLS_RSA_WITH_RC4_128_MD5,              "TLS_RSA_WITH_RC4_128_MD5"}, 
    40     {PJ_TLS_RSA_WITH_RC4_128_SHA,              "TLS_RSA_WITH_RC4_128_SHA"}, 
    41     {PJ_TLS_RSA_WITH_3DES_EDE_CBC_SHA,         "TLS_RSA_WITH_3DES_EDE_CBC_SHA"}, 
    42     {PJ_TLS_RSA_WITH_AES_128_CBC_SHA,          "TLS_RSA_WITH_AES_128_CBC_SHA"}, 
    43     {PJ_TLS_RSA_WITH_AES_256_CBC_SHA,          "TLS_RSA_WITH_AES_256_CBC_SHA"}, 
    44     {PJ_TLS_RSA_WITH_AES_128_CBC_SHA256,       "TLS_RSA_WITH_AES_128_CBC_SHA256"}, 
    45     {PJ_TLS_RSA_WITH_AES_256_CBC_SHA256,       "TLS_RSA_WITH_AES_256_CBC_SHA256"}, 
    46     {PJ_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,      "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"}, 
    47     {PJ_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,      "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"}, 
    48     {PJ_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,     "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"}, 
    49     {PJ_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,     "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"}, 
    50     {PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA,       "TLS_DH_DSS_WITH_AES_128_CBC_SHA"}, 
    51     {PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA,       "TLS_DH_RSA_WITH_AES_128_CBC_SHA"}, 
    52     {PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,      "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"}, 
    53     {PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,      "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}, 
    54     {PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA,       "TLS_DH_DSS_WITH_AES_256_CBC_SHA"}, 
    55     {PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA,       "TLS_DH_RSA_WITH_AES_256_CBC_SHA"}, 
    56     {PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,      "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"}, 
    57     {PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,      "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"}, 
    58     {PJ_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,    "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"}, 
    59     {PJ_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,    "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"}, 
    60     {PJ_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,   "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"}, 
    61     {PJ_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,   "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"}, 
    62     {PJ_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,    "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"}, 
    63     {PJ_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,    "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"}, 
    64     {PJ_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,   "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"}, 
    65     {PJ_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,   "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"}, 
    66     {PJ_TLS_DH_anon_WITH_RC4_128_MD5,          "TLS_DH_anon_WITH_RC4_128_MD5"}, 
    67     {PJ_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,     "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"}, 
    68     {PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA,      "TLS_DH_anon_WITH_AES_128_CBC_SHA"}, 
    69     {PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA,      "TLS_DH_anon_WITH_AES_256_CBC_SHA"}, 
    70     {PJ_TLS_DH_anon_WITH_AES_128_CBC_SHA256,   "TLS_DH_anon_WITH_AES_128_CBC_SHA256"}, 
    71     {PJ_TLS_DH_anon_WITH_AES_256_CBC_SHA256,   "TLS_DH_anon_WITH_AES_256_CBC_SHA256"}, 
    72  
    73     /* TLS (deprecated) */ 
    74     {PJ_TLS_RSA_EXPORT_WITH_RC4_40_MD5,        "TLS_RSA_EXPORT_WITH_RC4_40_MD5"}, 
    75     {PJ_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,    "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"}, 
    76     {PJ_TLS_RSA_WITH_IDEA_CBC_SHA,             "TLS_RSA_WITH_IDEA_CBC_SHA"}, 
    77     {PJ_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,     "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"}, 
    78     {PJ_TLS_RSA_WITH_DES_CBC_SHA,              "TLS_RSA_WITH_DES_CBC_SHA"}, 
    79     {PJ_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,  "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"}, 
    80     {PJ_TLS_DH_DSS_WITH_DES_CBC_SHA,           "TLS_DH_DSS_WITH_DES_CBC_SHA"}, 
    81     {PJ_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,  "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"}, 
    82     {PJ_TLS_DH_RSA_WITH_DES_CBC_SHA,           "TLS_DH_RSA_WITH_DES_CBC_SHA"}, 
    83     {PJ_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"}, 
    84     {PJ_TLS_DHE_DSS_WITH_DES_CBC_SHA,          "TLS_DHE_DSS_WITH_DES_CBC_SHA"}, 
    85     {PJ_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"}, 
    86     {PJ_TLS_DHE_RSA_WITH_DES_CBC_SHA,          "TLS_DHE_RSA_WITH_DES_CBC_SHA"}, 
    87     {PJ_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,    "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"}, 
    88     {PJ_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"}, 
    89     {PJ_TLS_DH_anon_WITH_DES_CBC_SHA,          "TLS_DH_anon_WITH_DES_CBC_SHA"}, 
    90  
    91     /* SSLv3 */ 
    92     {PJ_SSL_FORTEZZA_KEA_WITH_NULL_SHA,        "SSL_FORTEZZA_KEA_WITH_NULL_SHA"}, 
    93     {PJ_SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA,"SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA"}, 
    94     {PJ_SSL_FORTEZZA_KEA_WITH_RC4_128_SHA,     "SSL_FORTEZZA_KEA_WITH_RC4_128_SHA"}, 
    95  
    96     /* SSLv2 */ 
    97     {PJ_SSL_CK_RC4_128_WITH_MD5,               "SSL_CK_RC4_128_WITH_MD5"}, 
    98     {PJ_SSL_CK_RC4_128_EXPORT40_WITH_MD5,      "SSL_CK_RC4_128_EXPORT40_WITH_MD5"}, 
    99     {PJ_SSL_CK_RC2_128_CBC_WITH_MD5,           "SSL_CK_RC2_128_CBC_WITH_MD5"}, 
    100     {PJ_SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5,  "SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5"}, 
    101     {PJ_SSL_CK_IDEA_128_CBC_WITH_MD5,          "SSL_CK_IDEA_128_CBC_WITH_MD5"}, 
    102     {PJ_SSL_CK_DES_64_CBC_WITH_MD5,            "SSL_CK_DES_64_CBC_WITH_MD5"}, 
    103     {PJ_SSL_CK_DES_192_EDE3_CBC_WITH_MD5,      "SSL_CK_DES_192_EDE3_CBC_WITH_MD5"} 
    104 }; 
    105  
    106  
    10725/* 
    10826 * Initialize the SSL socket configuration with the default values. 
    10927 */ 
     
    12947} 
    13048 
    13149 
    132 /* Get cipher name string */ 
    133 PJ_DEF(const char*) pj_ssl_cipher_name(pj_ssl_cipher cipher) 
    134 { 
    135     unsigned i, n; 
    136  
    137     n = PJ_ARRAY_SIZE(cipher_names); 
    138     for (i = 0; i < n; ++i) { 
    139         if (cipher == cipher_names[i].cipher) 
    140             return cipher_names[i].name; 
    141     } 
    142  
    143     return NULL; 
    144 } 
    145  
    146  
    147  
    148  
    14950PJ_DEF(pj_status_t) pj_ssl_cert_get_verify_status_strings( 
    15051                                                pj_uint32_t verify_status,  
    15152                                                const char *error_strings[], 
  • pjlib/src/pjlib-test/ssl_sock.c

     
    3939 
    4040 
    4141static int get_cipher_list(void) { 
    42     pj_status_t status; 
    43     pj_ssl_cipher ciphers[100]; 
    4442    unsigned cipher_num; 
    4543    unsigned i; 
    4644 
    47     cipher_num = PJ_ARRAY_SIZE(ciphers); 
    48     status = pj_ssl_cipher_get_availables(ciphers, &cipher_num); 
    49     if (status != PJ_SUCCESS) { 
    50         app_perror("...FAILED to get available ciphers", status); 
    51         return status; 
    52     } 
    53  
     45    cipher_num = pj_ssl_cipher_count(); 
    5446    PJ_LOG(3, ("", "...Found %u ciphers:", cipher_num)); 
    5547    for (i = 0; i < cipher_num; ++i) { 
    56         const char* st; 
    57         st = pj_ssl_cipher_name(ciphers[i]); 
    58         if (st == NULL) 
    59             st = "[Unknown]"; 
     48        pj_ssl_cipher_info info; 
     49        pj_status_t status; 
    6050 
    61         PJ_LOG(3, ("", "...%3u: 0x%08x=%s", i+1, ciphers[i], st)); 
     51        status = pj_ssl_cipher_get_info(i, &info); 
     52        if (status != PJ_SUCCESS) { 
     53            app_perror("...Failed to get cipher info", status); 
     54            return status; 
     55        } 
     56 
     57        PJ_LOG(3, ("", "...%3u: 0x%06X / %s", i, info.code, info.name)); 
    6258    } 
    6359 
    6460    return PJ_SUCCESS; 
     
    8682 
    8783static void dump_ssl_info(const pj_ssl_sock_info *si) 
    8884{ 
    89     const char *tmp_st; 
    90  
    9185    /* Print cipher name */ 
    92     tmp_st = pj_ssl_cipher_name(si->cipher); 
    93     if (tmp_st == NULL) 
    94         tmp_st = "[Unknown]"; 
    95     PJ_LOG(3, ("", ".....Cipher: %s", tmp_st)); 
     86    PJ_LOG(3, ("", ".....Cipher: 0x%06X / %s", 
     87                   si->cipher_info.code, si->cipher_info.name)); 
    9688 
    9789    /* Print remote certificate info and verification result */ 
    9890    if (si->remote_cert_info && si->remote_cert_info->subject.info.slen)  
     
    492484    return status; 
    493485} 
    494486 
    495  
    496487static int echo_test(pj_ssl_sock_proto srv_proto, pj_ssl_sock_proto cli_proto, 
    497                      pj_ssl_cipher srv_cipher, pj_ssl_cipher cli_cipher, 
     488                     pj_ssl_cipher_idx srv_cipher, pj_ssl_cipher_idx cli_cipher, 
    498489                     pj_bool_t req_client_cert, pj_bool_t client_provide_cert) 
    499490{ 
    500491    pj_pool_t *pool = NULL; 
     
    505496    struct test_state state_serv = { 0 }; 
    506497    struct test_state state_cli = { 0 }; 
    507498    pj_sockaddr addr, listen_addr; 
    508     pj_ssl_cipher ciphers[1]; 
     499    pj_ssl_cipher_idx ciphers[1]; 
    509500    pj_ssl_cert_t *cert = NULL; 
    510501    pj_status_t status; 
    511502 
     
    13301321} 
    13311322 
    13321323 
     1324static pj_ssl_cipher_idx get_cipher_idx(pj_uint32_t cipher_code) { 
     1325    pj_ssl_cipher_idx res; 
     1326    unsigned i, n; 
     1327     
     1328    res = n = pj_ssl_cipher_count(); 
     1329    for (i=0; i<n; ++i) { 
     1330        pj_ssl_cipher_info info; 
     1331        pj_ssl_cipher_get_info(i, &info); 
     1332        if (cipher_code==info.code) 
     1333            return i; 
     1334    } 
     1335 
     1336    return res; 
     1337} 
     1338 
     1339 
     1340#define PJ_TLS_RSA_WITH_DES_CBC_SHA         get_cipher_idx(0x0009) 
     1341#define PJ_TLS_RSA_WITH_AES_256_CBC_SHA     get_cipher_idx(0x0035) 
     1342 
     1343 
    13331344int ssl_sock_test(void) 
    13341345{ 
    13351346    int ret;