Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 81 additions & 34 deletions pjlib/src/pj/ssl_sock_ossl.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
#include <openssl/opensslconf.h>
#include <openssl/opensslv.h>

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
# include <openssl/decoder.h>
#endif

/* Specify whether server supports session reuse using session ID. */
#define SERVER_SUPPORT_SESSION_REUSE 1

Expand Down Expand Up @@ -255,6 +259,18 @@ static char *SSLErrorString (int err)
}
}

# if OPENSSL_VERSION_NUMBER >= 0x30000000L
#define ERROR_LOG(msg, err, ssock) \
{ \
char err_str[PJ_ERR_MSG_SIZE]; \
char buf[PJ_INET6_ADDRSTRLEN + 10]; \
ERR_error_string_n(err, err_str, sizeof(err_str)); \
PJ_LOG(2,("SSL", "%s (%s): Level: %d err: <%lu> <%s> len: %d peer: %s", \
msg, action, level, err, err_str, len, \
(ssock && pj_sockaddr_has_addr(&ssock->rem_addr)? \
pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3):"???")));\
}
# else
#define ERROR_LOG(msg, err, ssock) \
{ \
char buf[PJ_INET6_ADDRSTRLEN+10]; \
Expand All @@ -268,6 +284,7 @@ static char *SSLErrorString (int err)
(ssock && pj_sockaddr_has_addr(&ssock->rem_addr)? \
pj_sockaddr_print(&ssock->rem_addr, buf, sizeof(buf), 3):"???")));\
}
# endif

static void SSLLogErrors(char * action, int ret, int ssl_err, int len,
pj_ssl_sock_t *ssock)
Expand Down Expand Up @@ -656,6 +673,7 @@ static pj_status_t init_openssl(void)

openssl_init_count = 1;

PJ_LOG(4, (THIS_FILE, "OpenSSL version : %x", OPENSSL_VERSION_NUMBER));
/* Register error subsystem */
status = pj_register_strerror(PJ_SSL_ERRNO_START,
PJ_SSL_ERRNO_SPACE_SIZE,
Expand Down Expand Up @@ -1030,16 +1048,63 @@ static int xname_cmp(const X509_NAME **a, const X509_NAME **b) {

#endif

#if !defined(OPENSSL_NO_DH)

static void set_option(const pj_ssl_sock_t* ssock, SSL_CTX* ctx) {
unsigned long options = SSL_OP_CIPHER_SERVER_PREFERENCE |
#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_OP_SINGLE_ECDH_USE |
#endif
SSL_OP_SINGLE_DH_USE;
options = SSL_CTX_set_options(ctx, options);
PJ_LOG(4, (ssock->pool->obj_name, "SSL DH "
"initialized, PFS cipher-suites enabled"));
}

static void set_dh_use_option(BIO *bio, const pj_ssl_sock_t* ssock,
const pj_str_t *pass, SSL_CTX* ctx)
{
#if OPENSSL_VERSION_NUMBER < 0x30000000L
DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
if (dh != NULL) {
if (SSL_CTX_set_tmp_dh(ctx, dh)) {
set_option(ssock, ctx);
}
DH_free(dh);
}
#else
OSSL_DECODER_CTX* dctx;
EVP_PKEY* dh_pkey = NULL;
const char* format = "PEM";
const char* structure = NULL;
const char* keytype = NULL;

dctx = OSSL_DECODER_CTX_new_for_pkey(&dh_pkey, format, structure, keytype,
0, NULL, NULL);
if (dctx != NULL) {
if (pass->slen) {
OSSL_DECODER_CTX_set_passphrase(dctx,
(const unsigned char*)pass->ptr,
pass->slen);
}

if (OSSL_DECODER_from_bio(dctx, bio)) {
if (SSL_CTX_set0_tmp_dh_pkey(ctx, dh_pkey)) {
set_option(ssock, ctx);
}
}
OSSL_DECODER_CTX_free(dctx);
}
#endif
}

#endif

/* Initialize OpenSSL context for the ssock */
static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
{
ossl_sock_t *ossock = (ossl_sock_t *)ssock;
SSL_CTX *ctx = NULL;
#if !defined(OPENSSL_NO_DH)
BIO *bio;
DH *dh;
long options;
#endif
SSL_METHOD *ssl_method = NULL;
pj_uint32_t ssl_opt = 0;
pj_ssl_cert_t *cert = ssock->cert;
Expand Down Expand Up @@ -1121,6 +1186,14 @@ static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
return GET_SSL_STATUS(ssock);
}

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (ssock->param.proto <= PJ_SSL_SOCK_PROTO_TLS1_1) {
/* TLS 1.0, TLS 1.1 no longer working at the default security
* level of 1 and instead requires security level 0. */
SSL_CTX_set_security_level(ossock->ossl_ctx, 0);
}
#endif

if (ssock->is_server) {
unsigned int sid_ctx = SERVER_SESSION_ID_CONTEXT;

Expand Down Expand Up @@ -1237,22 +1310,9 @@ static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)

#if !defined(OPENSSL_NO_DH)
if (ssock->is_server) {
bio = BIO_new_file(cert->privkey_file.ptr, "r");
BIO *bio = BIO_new_file(cert->privkey_file.ptr, "r");
if (bio != NULL) {
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
if (dh != NULL) {
if (SSL_CTX_set_tmp_dh(ctx, dh)) {
options = SSL_OP_CIPHER_SERVER_PREFERENCE |
#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_OP_SINGLE_ECDH_USE |
#endif
SSL_OP_SINGLE_DH_USE;
options = SSL_CTX_set_options(ctx, options);
PJ_LOG(4,(ssock->pool->obj_name, "SSL DH "
"initialized, PFS cipher-suites enabled"));
}
DH_free(dh);
}
set_dh_use_option(bio, ssock, &cert->privkey_pass, ctx);
BIO_free(bio);
}
}
Expand Down Expand Up @@ -1359,20 +1419,7 @@ static pj_status_t init_ossl_ctx(pj_ssl_sock_t *ssock)
}

if (ssock->is_server) {
dh = PEM_read_bio_DHparams(kbio, NULL, NULL, NULL);
if (dh != NULL) {
if (SSL_CTX_set_tmp_dh(ctx, dh)) {
options = SSL_OP_CIPHER_SERVER_PREFERENCE |
#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x10000000L
SSL_OP_SINGLE_ECDH_USE |
#endif
SSL_OP_SINGLE_DH_USE;
options = SSL_CTX_set_options(ctx, options);
PJ_LOG(4,(ssock->pool->obj_name, "SSL DH "
"initialized, PFS cipher-suites enabled"));
}
DH_free(dh);
}
set_dh_use_option(kbio, ssock, &cert->privkey_pass, ctx);
}
BIO_free(kbio);
}
Expand Down
61 changes: 60 additions & 1 deletion pjsip/src/pjsip/sip_auth_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@

#if PJSIP_AUTH_HAS_DIGEST_SHA256
# include <openssl/sha.h>
# if OPENSSL_VERSION_NUMBER >= 0x30000000L
# include <openssl/evp.h>
# endif
# ifdef _MSC_VER
# include <openssl/opensslv.h>
# if OPENSSL_VERSION_NUMBER >= 0x10100000L
Expand Down Expand Up @@ -276,17 +279,32 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
char ha1[PJSIP_SHA256STRLEN];
char ha2[PJSIP_SHA256STRLEN];
unsigned char digest[32];

#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_CTX pms;
#else
EVP_MD_CTX* mdctx;
const EVP_MD* md;
unsigned dig_len;
#endif

pj_assert(result->slen >= PJSIP_SHA256STRLEN);

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
md = EVP_get_digestbyname("SHA256");
if (md == NULL) {
return PJ_ENOTSUP;
}
#endif

AUTH_TRACE_((THIS_FILE, "Begin creating digest"));

if ((cred_info->data_type & PASSWD_MASK) == PJSIP_CRED_DATA_PLAIN_PASSWD)
{
/***
*** ha1 = SHA256(username ":" realm ":" password)
***/
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_Init(&pms);
SHA256_Update( &pms, cred_info->username.ptr,
cred_info->username.slen);
Expand All @@ -295,7 +313,18 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
SHA256_Update( &pms, ":", 1);
SHA256_Update( &pms, cred_info->data.ptr, cred_info->data.slen);
SHA256_Final(digest, &pms);

#else
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, cred_info->username.ptr, cred_info->username.slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, realm->ptr, realm->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, cred_info->data.ptr, cred_info->data.slen);

EVP_DigestFinal_ex(mdctx, digest, &dig_len);
EVP_MD_CTX_free(mdctx);
#endif
digestNtoStr(digest, 32, ha1);

} else if ((cred_info->data_type & PASSWD_MASK) == PJSIP_CRED_DATA_DIGEST)
Expand All @@ -319,11 +348,21 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
/***
*** ha2 = SHA256(method ":" req_uri)
***/
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_Init(&pms);
SHA256_Update( &pms, method->ptr, method->slen);
SHA256_Update( &pms, ":", 1);
SHA256_Update( &pms, uri->ptr, uri->slen);
SHA256_Final( digest, &pms);
#else
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, method->ptr, method->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, uri->ptr, uri->slen);
EVP_DigestFinal_ex(mdctx, digest, &dig_len);
EVP_MD_CTX_free(mdctx);
#endif
digestNtoStr(digest, 32, ha2);

AUTH_TRACE_((THIS_FILE, " ha2=%.64s", ha2));
Expand All @@ -335,6 +374,7 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,
*** When qop=auth is used:
*** response = SHA256(ha1 ":" nonce ":" nc ":" cnonce ":" qop ":" ha2)
***/
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA256_Init(&pms);
SHA256_Update( &pms, ha1, PJSIP_SHA256STRLEN);
SHA256_Update( &pms, ":", 1);
Expand All @@ -352,7 +392,26 @@ PJ_DEF(pj_status_t) pjsip_auth_create_digestSHA256(pj_str_t *result,

/* This is the final response digest. */
SHA256_Final(digest, &pms);
#else
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, ha1, PJSIP_SHA256STRLEN);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, nonce->ptr, nonce->slen);
if (qop && qop->slen != 0) {
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, nc->ptr, nc->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, cnonce->ptr, cnonce->slen);
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, qop->ptr, qop->slen);
}
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, ha2, PJSIP_SHA256STRLEN);

EVP_DigestFinal_ex(mdctx, digest, &dig_len);
EVP_MD_CTX_free(mdctx);
#endif
/* Convert digest to string and store in chal->response. */
result->slen = PJSIP_SHA256STRLEN;
digestNtoStr(digest, 32, result->ptr);
Expand Down