Ignore:
Timestamp:
Oct 27, 2016 7:58:01 AM (3 years ago)
Author:
ming
Message:

Fixed #1975: Add support to select elliptic curve and signature algorithm for TLS

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ssl_sock_ossl.c

    r5459 r5472  
    5050#include <openssl/err.h> 
    5151#include <openssl/x509v3.h> 
    52  
     52#include <openssl/rand.h> 
     53#include <openssl/engine.h> 
     54 
     55#if !defined(OPENSSL_NO_EC) 
     56   extern int tls1_ec_nid2curve_id(int nid); 
     57   extern int tls1_ec_curve_id2nid(int curve_id); 
     58#endif 
    5359 
    5460#ifdef _MSC_VER 
     
    300306} openssl_ciphers[PJ_SSL_SOCK_MAX_CIPHERS]; 
    301307 
     308/* OpenSSL available curves */ 
     309static unsigned openssl_curves_num; 
     310static struct openssl_curves_t { 
     311    pj_ssl_curve    id; 
     312    const char      *name; 
     313} openssl_curves[PJ_SSL_SOCK_MAX_CURVES]; 
     314 
    302315/* OpenSSL application data index */ 
    303316static int sslsock_idx; 
     
    329342 
    330343    /* Init available ciphers */ 
    331     if (openssl_cipher_num == 0) { 
     344    if (openssl_cipher_num == 0 || openssl_curves_num == 0) { 
    332345        SSL_METHOD *meth = NULL; 
    333346        SSL_CTX *ctx; 
     
    335348        STACK_OF(SSL_CIPHER) *sk_cipher; 
    336349        unsigned i, n; 
     350        int nid; 
     351        const char *cname; 
    337352 
    338353        meth = (SSL_METHOD*)SSLv23_server_method(); 
     
    353368 
    354369        ssl = SSL_new(ctx); 
     370 
    355371        sk_cipher = SSL_get_ciphers(ssl); 
    356372 
     
    366382            openssl_ciphers[i].name = SSL_CIPHER_get_name(c); 
    367383        } 
     384        openssl_cipher_num = n; 
     385 
     386        ssl->session = SSL_SESSION_new(); 
     387 
     388#if !defined(OPENSSL_NO_EC) 
     389        openssl_curves_num = SSL_get_shared_curve(ssl,-1); 
     390        if (openssl_curves_num > PJ_ARRAY_SIZE(openssl_curves)) 
     391            openssl_curves_num = PJ_ARRAY_SIZE(openssl_curves); 
     392 
     393        for (i = 0; i < openssl_curves_num; i++) { 
     394            nid = SSL_get_shared_curve(ssl, i); 
     395 
     396            if (nid & TLSEXT_nid_unknown) { 
     397                cname = "curve unknown"; 
     398                nid &= 0xFFFF; 
     399            } else { 
     400                cname = EC_curve_nid2nist(nid); 
     401                if (!cname) 
     402                    cname = OBJ_nid2sn(nid); 
     403            } 
     404 
     405            openssl_curves[i].id   = tls1_ec_nid2curve_id(nid); 
     406            openssl_curves[i].name = cname; 
     407        } 
     408#else 
     409        openssl_curves_num = 0; 
     410#endif 
    368411 
    369412        SSL_free(ssl); 
    370413        SSL_CTX_free(ctx); 
    371  
    372         openssl_cipher_num = n; 
    373414    } 
    374415 
     
    376417    sslsock_idx = SSL_get_ex_new_index(0, "SSL socket", NULL, NULL, NULL); 
    377418 
    378     return PJ_SUCCESS; 
     419    return status; 
    379420} 
    380421 
     
    499540/* Setting SSL sock cipher list */ 
    500541static pj_status_t set_cipher_list(pj_ssl_sock_t *ssock); 
    501  
     542/* Setting SSL sock curves list */ 
     543static pj_status_t set_curves_list(pj_ssl_sock_t *ssock); 
     544/* Setting sigalgs list */ 
     545static pj_status_t set_sigalgs(pj_ssl_sock_t *ssock); 
     546/* Setting entropy for rng */ 
     547static void set_entropy(pj_ssl_sock_t *ssock); 
    502548 
    503549/* Create and initialize new SSL context and instance */ 
     
    523569    /* Make sure OpenSSL library has been initialized */ 
    524570    init_openssl(); 
     571 
     572    set_entropy(ssock); 
    525573 
    526574    if (ssock->param.proto == PJ_SSL_SOCK_PROTO_DEFAULT) 
     
    776824        return status; 
    777825 
     826    /* Set curve list */ 
     827    status = set_curves_list(ssock); 
     828    if (status != PJ_SUCCESS) 
     829        return status; 
     830 
     831    /* Set sigalg list */ 
     832    status = set_sigalgs(ssock); 
     833    if (status != PJ_SUCCESS) 
     834        return status; 
     835 
    778836    /* Setup SSL BIOs */ 
    779837    ssock->ossl_rbio = BIO_new(BIO_s_mem()); 
     
    940998} 
    941999 
     1000static pj_status_t set_curves_list(pj_ssl_sock_t *ssock) 
     1001{ 
     1002#if !defined(OPENSSL_NO_EC) 
     1003    int ret; 
     1004    int curves[PJ_SSL_SOCK_MAX_CURVES]; 
     1005    int cnt; 
     1006 
     1007    if (ssock->param.curves_num == 0) 
     1008        return PJ_SUCCESS; 
     1009 
     1010    for (cnt = 0; cnt < ssock->param.curves_num; cnt++) { 
     1011        curves[cnt] = tls1_ec_curve_id2nid(ssock->param.curves[cnt]); 
     1012    } 
     1013 
     1014    if( ssock->ossl_ssl->server ) { 
     1015        ret = SSL_set1_curves(ssock->ossl_ssl, curves, 
     1016                              ssock->param.curves_num); 
     1017        if (ret < 1) 
     1018            return GET_SSL_STATUS(ssock); 
     1019    } else { 
     1020        ret = SSL_CTX_set1_curves(ssock->ossl_ctx, curves, 
     1021                                  ssock->param.curves_num); 
     1022        if (ret < 1) 
     1023            return GET_SSL_STATUS(ssock); 
     1024    } 
     1025 
     1026    return PJ_SUCCESS; 
     1027#else 
     1028    return PJ_ENOTSUP; 
     1029#endif 
     1030} 
     1031 
     1032static pj_status_t set_sigalgs(pj_ssl_sock_t *ssock) 
     1033{ 
     1034    int ret; 
     1035 
     1036    if (ssock->param.sigalgs.ptr && ssock->param.sigalgs.slen) { 
     1037        if (ssock->is_server) { 
     1038            ret = SSL_set1_client_sigalgs_list(ssock->ossl_ssl, 
     1039                                               ssock->param.sigalgs.ptr); 
     1040        } else { 
     1041            ret = SSL_set1_sigalgs_list(ssock->ossl_ssl, 
     1042                                        ssock->param.sigalgs.ptr); 
     1043        } 
     1044 
     1045        if (ret < 1) 
     1046            return GET_SSL_STATUS(ssock); 
     1047    } 
     1048 
     1049    return PJ_SUCCESS; 
     1050} 
     1051 
     1052static void set_entropy(pj_ssl_sock_t *ssock) 
     1053{ 
     1054    int ret; 
     1055 
     1056    switch (ssock->param.entropy_type) { 
     1057#ifndef OPENSSL_NO_EGD 
     1058        case PJ_SSL_ENTROPY_EGD: 
     1059            ret = RAND_egd(ssock->param.entropy_path.ptr); 
     1060            break; 
     1061#endif 
     1062        case PJ_SSL_ENTROPY_RANDOM: 
     1063            ret = RAND_load_file("/dev/random",255); 
     1064            break; 
     1065        case PJ_SSL_ENTROPY_URANDOM: 
     1066            ret = RAND_load_file("/dev/urandom",255); 
     1067            break; 
     1068        case PJ_SSL_ENTROPY_FILE: 
     1069            ret = RAND_load_file(ssock->param.entropy_path.ptr,255); 
     1070            break; 
     1071        case PJ_SSL_ENTROPY_NONE: 
     1072            default: 
     1073            return; 
     1074            break; 
     1075    } 
     1076 
     1077    if (ret < 0) { 
     1078        PJ_LOG(3, (ssock->pool->obj_name, "SSL failed to reseed with " 
     1079                                          "entropy type %d", 
     1080                                          ssock->param.entropy_type)); 
     1081    } 
     1082} 
    9421083 
    9431084/* Parse OpenSSL ASN1_TIME to pj_time_val and GMT info */ 
     
    22322373} 
    22332374 
     2375/* Get available curves. */ 
     2376PJ_DEF(pj_status_t) pj_ssl_curve_get_availables(pj_ssl_curve curves[], 
     2377                                                unsigned *curve_num) 
     2378{ 
     2379    unsigned i; 
     2380 
     2381    PJ_ASSERT_RETURN(curves && curve_num, PJ_EINVAL); 
     2382 
     2383    if (openssl_curves_num == 0) { 
     2384        init_openssl(); 
     2385        shutdown_openssl(); 
     2386    } 
     2387 
     2388    if (openssl_curves_num == 0) { 
     2389        *curve_num = 0; 
     2390        return PJ_ENOTFOUND; 
     2391    } 
     2392 
     2393    *curve_num = PJ_MIN(*curve_num, openssl_curves_num); 
     2394 
     2395    for (i = 0; i < *curve_num; ++i) 
     2396    curves[i] = openssl_curves[i].id; 
     2397 
     2398    return PJ_SUCCESS; 
     2399} 
     2400 
     2401/* Get curve name string. */ 
     2402PJ_DEF(const char*) pj_ssl_curve_name(pj_ssl_curve curve) 
     2403{ 
     2404    unsigned i; 
     2405 
     2406    if (openssl_curves_num == 0) { 
     2407        init_openssl(); 
     2408        shutdown_openssl(); 
     2409    } 
     2410 
     2411    for (i = 0; i < openssl_curves_num; ++i) { 
     2412        if (curve == openssl_curves[i].id) 
     2413            return openssl_curves[i].name; 
     2414    } 
     2415 
     2416    return NULL; 
     2417} 
     2418 
     2419/* Get curve ID from curve name string. */ 
     2420PJ_DEF(pj_ssl_curve) pj_ssl_curve_id(const char *curve_name) 
     2421{ 
     2422    unsigned i; 
     2423 
     2424    if (openssl_curves_num == 0) { 
     2425        init_openssl(); 
     2426        shutdown_openssl(); 
     2427    } 
     2428 
     2429    for (i = 0; i < openssl_curves_num; ++i) { 
     2430        if (!pj_ansi_stricmp(openssl_curves[i].name, curve_name)) 
     2431            return openssl_curves[i].id; 
     2432    } 
     2433 
     2434    return PJ_TLS_UNKNOWN_CURVE; 
     2435} 
     2436 
     2437/* Check if the specified curve is supported by SSL/TLS backend. */ 
     2438PJ_DEF(pj_bool_t) pj_ssl_curve_is_supported(pj_ssl_curve curve) 
     2439{ 
     2440    unsigned i; 
     2441 
     2442    if (openssl_curves_num == 0) { 
     2443        init_openssl(); 
     2444        shutdown_openssl(); 
     2445    } 
     2446 
     2447    for (i = 0; i < openssl_curves_num; ++i) { 
     2448        if (curve == openssl_curves[i].id) 
     2449            return PJ_TRUE; 
     2450    } 
     2451 
     2452    return PJ_FALSE; 
     2453} 
    22342454 
    22352455/* 
Note: See TracChangeset for help on using the changeset viewer.