int dssl_decompress( u_char compr_method, void* compr_state, u_char* in_data, uint32_t in_len, u_char* out_data, uint32_t* out_len ) { int rc = DSSL_RC_OK; z_stream * zs = (z_stream*) compr_state; /* right now only DEFLATE method is supported */ if( compr_method != COMPRESSION_DEFLATE ) return NM_ERROR( DSSL_E_UNSUPPORTED_COMPRESSION ); _ASSERT( zs ); zs->next_in = in_data; zs->avail_in = in_len; zs->next_out = out_data; zs->avail_out = *out_len; if( in_len > 0 ) { int zlib_rc = inflate( zs, Z_SYNC_FLUSH ); if( zlib_rc != Z_OK ) { rc = NM_ERROR( DSSL_E_DECOMPRESSION_ERROR ); } } if( rc == DSSL_RC_OK ) { (*out_len) = (*out_len) - zs->avail_out; } return rc; }
int ssl3_alert_decoder( void* decoder_stack, NM_PacketDir dir, u_char* data, uint32_t len, uint32_t* processed ) { dssl_decoder_stack* stack = (dssl_decoder_stack*) decoder_stack; UNUSED_PARAM(dir); if( len != 2 ) return NM_ERROR( NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ) ); if( data[0] == 2 ) { stack->state = SS_FatalAlert; } /* Close notify? */ if( data[1] == 0 ) { stack->state = SS_SeenCloseNotify; } #ifdef NM_TRACE_SSL_RECORD DEBUG_TRACE2( "\nAlert received: %s (%d)", ( (stack->state == SS_FatalAlert) ? "fatal alert" : ((stack->state == SS_SeenCloseNotify) ? "close_notify alert" : "unknown alert")), (int) MAKE_UINT16( data[0], data[1] ) ); #endif (*processed) = len; return DSSL_RC_OK; }
int ssl2_PRF( const u_char* secret, uint32_t secret_len, const u_char* challenge, uint32_t challenge_len, const u_char* conn_id, uint32_t conn_id_len, u_char* out, uint32_t out_len ) { u_char c= '0'; int repeat = 0; int i = 0; const EVP_MD *md5 = NULL; EVP_MD_CTX *ctx; md5 = EVP_md5(); if( !out ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); if( out_len % EVP_MD_size(md5) != 0 ) { return NM_ERROR( DSSL_E_INVALID_PARAMETER ); } repeat = out_len / EVP_MD_size(md5); ctx = EVP_MD_CTX_create(); EVP_MD_CTX_init( ctx ); for( i = 0; i < repeat; i++ ) { EVP_DigestInit_ex( ctx, md5, NULL ); EVP_DigestUpdate( ctx, secret, secret_len ); EVP_DigestUpdate( ctx, &c, 1); c++; /* '0', '1', etc. */ EVP_DigestUpdate( ctx, challenge, challenge_len ); EVP_DigestUpdate( ctx, conn_id, conn_id_len ); EVP_DigestFinal_ex( ctx, out, NULL ); out += EVP_MD_size( md5 ); } EVP_MD_CTX_destroy( ctx ); return DSSL_RC_OK; }
int ssl_detect_client_hello_version( u_char* data, uint32_t len, uint16_t* ver ) { int rc = DSSL_RC_OK; _ASSERT( ver != NULL ); _ASSERT( data != NULL ); /* SSL v2 header can be sent even by never clients */ if( data[0] & 0x80 && len >= 3 && data[2] == SSL2_MT_CLIENT_HELLO ) { *ver = MAKE_UINT16( data[3], data[4] ); } else if ( data[0] == SSL3_RT_HANDSHAKE && len > 11 && data[1] == SSL3_VERSION_MAJOR && data[5] == SSL3_MT_CLIENT_HELLO ) { uint16_t client_hello_ver = MAKE_UINT16( data[9], data[10] ); *ver = MAKE_UINT16( data[1], data[2] ); if( *ver > client_hello_ver ) rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR ); } else { rc = NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION ); } return rc; }
int ssl_detect_server_hello_version( u_char* data, uint32_t len, uint16_t* ver ) { int rc = DSSL_RC_OK; _ASSERT( ver != NULL ); _ASSERT( data != NULL ); if( data[0] & 0x80 && len >= SSL20_SERVER_HELLO_MIN_LEN && data[2] == SSL2_MT_SERVER_HELLO ) { *ver = MAKE_UINT16( data[5], data[6] ); } else if( data[0] == SSL3_RT_HANDSHAKE && len > 11 && data[1] == SSL3_VERSION_MAJOR && data[5] == SSL3_MT_SERVER_HELLO ) { uint16_t sever_hello_ver = MAKE_UINT16( data[9], data[10] ); *ver = MAKE_UINT16( data[1], data[2] ); if( *ver > sever_hello_ver ) rc = NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR ); } else if( data[0] == SSL3_RT_ALERT && len == 7 && data[1] == SSL3_VERSION_MAJOR && MAKE_UINT16( data[3], data[4] ) == 2 ) { /* this is an SSL3 Alert message - the server didn't like this session */ *ver = MAKE_UINT16( data[1], data[2] ); } else { rc = NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION ); } return rc; }
static int ssl3_decode_new_session_ticket(DSSL_Session* sess, u_char* data, uint32_t len ) { uint16_t sz = 0; if(len < 6) return NM_ERROR(DSSL_E_SSL_INVALID_RECORD_LENGTH); sz = MAKE_UINT16(data[4], data[5]); if(len != sz + 6) return NM_ERROR(DSSL_E_SSL_PROTOCOL_ERROR); return ssls_store_new_ticket( sess, data + 6, sz ); }
int tls12_PRF( const EVP_MD *md, const u_char* secret, uint32_t secret_len, const char* label, u_char* random1, uint32_t random1_len, u_char* random2, uint32_t random2_len, u_char *out, uint32_t out_len ) { uint32_t len; uint32_t i; const u_char *S1,*S2; u_char* out_tmp; u_char* seed; uint32_t seed_len; u_char* p; if( !label || !out || out_len == 0 ) { _ASSERT( FALSE); return NM_ERROR( DSSL_E_INVALID_PARAMETER ); } /* 'sha256' is the default for TLS 1.2. * also, do not allow anything less secure... */ if ( !md ) md = EVP_sha256(); else if ( EVP_MD_size( md ) < EVP_MD_size( EVP_sha256() ) ) md = EVP_sha256(); /* allocate a temporary buffer for second output stream */ out_tmp = (u_char*) malloc( out_len ); if( !out_tmp ) return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); /* allocate and initialize the seed */ seed_len = (uint32_t)strlen( label ) + random1_len + random2_len; seed = (u_char*) malloc( seed_len ); if( !seed ) { free( out_tmp ); return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); } p = seed; memcpy( p, label, strlen( label ) ); p+= strlen( label ); memcpy( p, random1, random1_len ); p+= random1_len; memcpy( p, random2, random2_len ); DEBUG_TRACE_BUF("secret", secret, secret_len); DEBUG_TRACE_BUF("seed", seed, seed_len); tls1_P_hash( md, secret, secret_len, seed, seed_len, out_tmp, out_len ); DEBUG_TRACE_BUF("result", out_tmp, out_len); DEBUG_TRACE3( "\nsecret(%d) + seed(%u)=out(%u)\n", secret_len, seed_len, out_len); for( i=0; i < out_len; i++ ) out[i] = out_tmp[i]; free( seed ); free( out_tmp ); return DSSL_RC_OK; }
int ssls_get_decrypt_buffer( DSSL_Session* sess, u_char** data, uint32_t len ) { if(!data || !len ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); if( len > sizeof(sess->env->decrypt_buffer)) { _ASSERT( FALSE ); /*decrypt_buffer is supposed to fit the biggest possible SSL record!*/ return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); } (*data) = sess->env->decrypt_buffer; return DSSL_RC_OK; }
int ssls_get_decompress_buffer( DSSL_Session* sess, u_char** data, uint32_t len ) { if(!data || !len ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); if( len > sizeof(sess->env->decompress_buffer)) { _ASSERT( FALSE ); /*decompressed record can not exceed 2^14 + 1024 bytes !*/ return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); } (*data) = sess->env->decompress_buffer; return DSSL_RC_OK; }
int tls1_PRF( const u_char* secret, uint32_t secret_len, const char* label, u_char* random1, uint32_t random1_len, u_char* random2, uint32_t random2_len, u_char *out, uint32_t out_len ) { uint32_t len; uint32_t i; const u_char *S1,*S2; u_char* out_tmp; u_char* seed; uint32_t seed_len; u_char* p; if( !label || !out || out_len == 0 ) { _ASSERT( FALSE); return NM_ERROR( DSSL_E_INVALID_PARAMETER ); } /* allocate a temporary buffer for second output stream */ out_tmp = (u_char*) malloc( out_len ); if( !out_tmp ) return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); /* allocate and initialize the seed */ seed_len = (uint32_t)strlen( label ) + random1_len + random2_len; seed = (u_char*) malloc( seed_len ); if( !seed ) { free( out_tmp ); return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); } p = seed; memcpy( p, label, strlen( label ) ); p+= strlen( label ); memcpy( p, random1, random1_len ); p+= random1_len; memcpy( p, random2, random2_len ); /* split the secret into halves */ len = (secret_len / 2) + (secret_len % 2); S1 = secret; S2 = secret + secret_len - len; DEBUG_TRACE_BUF("secret", secret, secret_len); DEBUG_TRACE_BUF("seed", seed, seed_len); tls1_P_hash( EVP_md5(), S1, len, seed, seed_len, out, out_len ); tls1_P_hash( EVP_sha1(), S2, len, seed, seed_len, out_tmp, out_len ); for( i=0; i < out_len; i++ ) out[i] ^= out_tmp[i]; DEBUG_TRACE_BUF("result", out, out_len); free( seed ); free( out_tmp ); return DSSL_RC_OK; }
/* ========== SERVER-VERIFY ========== */ static int ssl2_decode_server_verify( DSSL_Session* sess, u_char* data, uint32_t len, uint32_t* processed ) { _ASSERT( processed && data && sess ); if( len != sess->client_challenge_len ) { return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ); } if( memcmp( data, sess->client_random, sess->client_challenge_len ) != 0 ) { return NM_ERROR( DSSL_E_SSL2_BAD_SERVER_VERIFY ); } *processed = len; return DSSL_RC_OK; }
/* ========== CLIENT-FINISHED ========== */ static int ssl2_decode_client_finished( DSSL_Session* sess, u_char* data, uint32_t len, uint32_t* processed ) { _ASSERT( processed && data && sess ); if( len != sess->server_connection_id_len ) { return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ); } if( memcmp( data, sess->server_random, sess->server_connection_id_len ) != 0 ) { return NM_ERROR( DSSL_E_SSL2_BAD_CLIENT_FINISHED ); } *processed = len; return DSSL_RC_OK; }
/* TCP reassembler callback function for SSL sessions */ static int OnNewSSLPacket( struct _TcpStream* stream, DSSL_Pkt* pkt ) { TcpSession* sess = NULL; DSSL_Session* ssl_sess = NULL; u_char* data = NULL; uint32_t len = 0; NM_PacketDir dir = ePacketDirInvalid; int rc = DSSL_RC_OK; _ASSERT( stream ); _ASSERT( pkt ); sess = stream->session; _ASSERT( sess ); ssl_sess = sess->ssl_session; if( !ssl_sess ) { _ASSERT( FALSE ); return NM_ERROR( DSSL_E_UNSPECIFIED_ERROR ); } data = PKT_TCP_PAYLOAD( pkt ); len = pkt->data_len; dir = SessionGetPacketDirection( sess, pkt ); rc = DSSL_SessionProcessData( ssl_sess, dir, data, len ); if( ssl_sess->flags & ( SSF_CLOSE_NOTIFY_RECEIVED | SSF_FATAL_ALERT_RECEIVED ) ) { sess->closing = 1; } return rc; }
int CapEnvSetSSL_ServerInfo( CapEnv* env, struct in_addr* ip_address, uint16_t port, const char* certfile, const char* keyfile, const char* password ) { if( env->ssl_env == NULL ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); return DSSL_EnvSetServerInfo( env->ssl_env, ip_address, port, certfile, keyfile, password ); }
int ssl3_change_cipher_spec_decoder( void* decoder_stack, NM_PacketDir dir, u_char* data, uint32_t len, uint32_t* processed ) { dssl_decoder_stack* stack = (dssl_decoder_stack*) decoder_stack; /* unused parameters */ dir; /* check packet data to comply to CSS protocol */ if( len != 1 ) return NM_ERROR( NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ) ); if(data[0] != 1 ) return NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR ); *processed = 1; return dssl_decoder_stack_flip_cipher( stack ); }
int ssls_lookup_session( DSSL_Session* sess ) { DSSL_SessionKeyData* sess_data = NULL; _ASSERT( sess ); _ASSERT( sess->env ); if( sess->env->session_cache ) { sess_data = dssl_SessionKT_Find( sess->env->session_cache, sess->session_id ); } if( !sess_data ) return NM_ERROR( DSSL_E_SSL_SESSION_NOT_IN_CACHE ); dssl_SessionKT_AddRef( sess_data ); memcpy( sess->master_secret, sess_data->master_secret, SSL3_MASTER_SECRET_SIZE ); sess->master_key_len = sess_data->master_secret_len; if(sess->version == SSL2_VERSION) { memcpy(sess->ssl2_key_arg, sess_data->ssl2_key_arg, SSL2_KEYARG_MAX_LEN ); sess->ssl2_key_arg_len = sess_data->ssl2_key_arg_length; sess->cipher_suite = sess_data->ssl2_cipher_suite; } return DSSL_RC_OK; }
int dssl_decoder_process( dssl_decoder* d, NM_PacketDir dir, u_char* data, uint32_t len ) { uint32_t processed = 0; int rc = DSSL_RC_OK; if( !d->handler ) return NM_ERROR( DSSL_E_NOT_IMPL ); fprintf(stderr, "\ntesting testing: %d", rc); if( d->buff_used_len > 0 ) { rc = dssl_decoder_add_to_buffer( d, data, len ); fprintf(stderr, "\ndssl dssl_decoder_add_to_buffer: %d", rc); if( rc == DSSL_RC_OK ) { data = d->buff; len = d->buff_used_len; } } while( rc == DSSL_RC_OK && processed < len ) { uint32_t p = 0; fprintf(stderr, "\ntesting testing: %d", rc); rc = d->handler( d->handler_data, dir, data + processed, len - processed, &p ); processed += p; fprintf(stderr, "\ntesting testing: %d", rc); /* can't be all ok and no data processed */ if( p == 0 && rc == DSSL_RC_OK ) { rc = NM_ERROR( DSSL_E_UNSPECIFIED_ERROR ); } fprintf(stderr, "\nssl d->handler p==%p rc = %d\n",p, rc); } if( !NM_IS_FAILED( rc ) ) { if( d->buff_used_len > 0 ) { rc = dssl_decoder_shift_buffer( d, processed ); } else if( processed < len ) { rc = dssl_decoder_add_to_buffer( d, data + processed, len - processed ); } } return rc; }
int DSSL_SessionProcessData( DSSL_Session* sess, NM_PacketDir dir, u_char* data, uint32_t len ) { int rc = DSSL_RC_OK; dssl_decoder_stack* dec = NULL; if( dir == ePacketDirInvalid ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); dec = (dir == ePacketDirFromClient) ? &sess->c_dec : &sess->s_dec; if( !sslc_is_decoder_stack_set( dec ) ) { uint16_t ver = 0; int is_client = (dir == ePacketDirFromClient); if( is_client ) { rc = ssl_detect_client_hello_version( data, len, &ver ); } else { rc = ssl_detect_server_hello_version( data, len, &ver ); /* update the client decoder after the server have declared the actual version of the session */ DEBUG_TRACE2("DSSL_SessionProcessData - sess->version: 0x%02X, ver is: 0x%02X\n", sess->version, ver); if( rc == DSSL_RC_OK && sess->version != ver ) { sess->c_dec.version = ver; rc = dssl_decoder_stack_set( &sess->c_dec, sess, ver, 1 ); } ssls_set_session_version( sess, ver ); } if( rc == DSSL_RC_OK ) { dec->version = ver; rc = dssl_decoder_stack_set( dec, sess, ver, is_client ); } } if( rc == DSSL_RC_OK ) rc = dssl_decoder_stack_process( dec, dir, data, len ); /* check if a session with a first-time automapped key failed */ if( NM_IS_FAILED( rc ) && sess->flags & SSF_TEST_SSL_KEY ) { if(sess->event_callback) { (*sess->event_callback)( sess->user_data, eSslMappedKeyFailed, sess->ssl_si ); } DSSL_MoveServerToMissingKeyList( sess->env, sess->ssl_si ); sess->ssl_si = NULL; } if( NM_IS_FAILED( rc ) && sess->error_callback && rc != DSSL_E_SSL_SERVER_KEY_UNKNOWN ) { sess->error_callback( sess->user_data, rc ); } return rc; }
int dssl_compr_init( u_char compr_method, void** compr_state ) { int rc = DSSL_RC_OK; switch( compr_method ) { case 0: break; case COMPRESSION_DEFLATE: { z_stream * zs = (z_stream*) malloc( sizeof(z_stream) ); int err = Z_OK; zs->zalloc = Z_NULL; zs->zfree = Z_NULL; zs->opaque = Z_NULL; zs->next_in = Z_NULL; zs->next_out = Z_NULL; zs->avail_in = 0; zs->avail_out = 0; err = inflateInit(zs); if( err != Z_OK ) { free( zs ); rc = NM_ERROR( DSSL_E_DECOMPRESSION_ERROR ); } else { rc = DSSL_RC_OK; (*compr_state) = zs; } } break; default: rc = NM_ERROR( DSSL_E_UNSUPPORTED_COMPRESSION ); /* unknown compression method */ break; } return rc; }
int ssls_decode_master_secret( DSSL_Session* sess ) { EVP_MD *md; DSSL_CipherSuite* suite = NULL; switch( sess->version ) { case SSL3_VERSION: return ssl3_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); case TLS1_VERSION: return tls1_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); default: DEBUG_TRACE1("ssls_decode_master_secret - version: 0x%02X\n", sess->version); if (sess->version == TLS1_1_VERSION) { DEBUG_TRACE0("ssls_decode_master_secret - supported for 1.1\n"); return tls1_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); } else if (sess->version == TLS1_2_VERSION) { DEBUG_TRACE0("ssls_decode_master_secret - supported for 1.2\n"); /* suite = DSSL_GetSSL3CipherSuite( sess->cipher_suite ); md=EVP_get_digestbyname(suite->digest); */ return tls12_PRF( "SHA256"/*suite->digest*/, sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); } else { DEBUG_TRACE0("ssls_decode_master_secret - DSSL_E_NOT_IMPL\n"); return NM_ERROR( DSSL_E_NOT_IMPL ); } } }
int ssls_store_new_ticket(DSSL_Session* sess, u_char* ticket, uint32_t len) { _ASSERT(sess && ticket && len); if( sess->env->ticket_cache ) { return dssl_SessionTicketTable_Add( sess->env->ticket_cache, sess, ticket, len ); } else { _ASSERT( FALSE ); return NM_ERROR( DSSL_E_UNSPECIFIED_ERROR ); } }
/* First client_hello is a special case, because of SSL v2 compatibility */ int ssl_decode_first_client_hello( DSSL_Session* sess, u_char* data, uint32_t len, uint32_t* processed ) { int rc = DSSL_RC_OK; if( data[0] & 0x80 && len >= 3 && data[2] == SSL2_MT_CLIENT_HELLO ) { int hdrLen = SSL20_CLIENT_HELLO_HDR_LEN; uint32_t recLen = len - hdrLen; rc = ssl2_decode_handshake( sess, ePacketDirFromClient, data + hdrLen, recLen, processed ); if( rc == DSSL_RC_OK ) { if( sess->version >= SSL3_VERSION && sess->version <= TLS1_2_VERSION ) { ssl3_init_handshake_digests( sess ); ssl3_update_handshake_digests( sess, data + hdrLen, recLen ); } *processed += hdrLen; } } else if( data[0] == SSL3_RT_HANDSHAKE && len > 6 && data[1] == SSL3_VERSION_MAJOR && data[5] == SSL3_MT_CLIENT_HELLO ) { uint32_t recLen = 0; u_char* org_data; data += SSL3_HEADER_LEN; recLen = (((int32_t)data[1]) << 16) | (((int32_t)data[2]) << 8) | data[3]; org_data = data; data += SSL3_HANDSHAKE_HEADER_LEN; len -= SSL3_HANDSHAKE_HEADER_LEN; rc = ssl3_decode_client_hello( sess, data, recLen ); if( rc == DSSL_RC_OK ) { *processed = recLen + SSL3_HANDSHAKE_HEADER_LEN + SSL3_HEADER_LEN; ssl3_init_handshake_digests( sess ); ssl3_update_handshake_digests( sess, org_data, recLen + SSL3_HANDSHAKE_HEADER_LEN ); } } else { rc = NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION ); } return rc; }
int ssls_set_session_version( DSSL_Session* sess, uint16_t ver ) { int rc = DSSL_RC_OK; sess->version = ver; switch( ver ) { case SSL3_VERSION: DEBUG_TRACE0("ssls_set_session_version - SSL3_VERSION\n"); sess->decode_finished_proc = ssl3_decode_finished; sess->caclulate_mac_proc = ssl3_calculate_mac; /* convert SSL v2 CHALLENGE to SSL v3+ CLIENT_RANDOM */ if(sess->flags & SSF_SSLV2_CHALLENGE) ssls_convert_v2challenge(sess); break; case TLS1_VERSION: DEBUG_TRACE0("ssls_set_session_version - TLS1_VERSION\n"); sess->decode_finished_proc = tls1_decode_finished; sess->caclulate_mac_proc = tls1_calculate_mac; /* convert SSL v2 CHALLENGE to SSL v3+ CLIENT_RANDOM */ if(sess->flags & SSF_SSLV2_CHALLENGE) ssls_convert_v2challenge(sess); break; case SSL2_VERSION: DEBUG_TRACE0("ssls_set_session_version - SSL2_VERSION\n"); sess->decode_finished_proc = NULL; sess->caclulate_mac_proc = ssl2_calculate_mac; break; case TLS1_1_VERSION: case TLS1_2_VERSION: DEBUG_TRACE0("ssls_set_session_version - TLS1_X_VERSION\n"); sess->decode_finished_proc = tls1_decode_finished; sess->caclulate_mac_proc = tls1_calculate_mac; if(sess->flags & SSF_SSLV2_CHALLENGE) ssls_convert_v2challenge(sess); break; default: DEBUG_TRACE0("ssls_set_session_version - unsupported.. \n"); rc = NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION ); break; } return rc; }
static int realloc_buffer( dssl_decoder* d, uint32_t new_len ) { /* TODO: add CapEnv-scope buffer management */ u_char* new_buff = NULL; _ASSERT( new_len > 0 ); _ASSERT( d->buff_len == 0 || new_len > d->buff_len ); if( d->buff != NULL ) new_buff = (u_char*) realloc( d->buff, new_len ); else new_buff = (u_char*) malloc( new_len ); if( new_buff == NULL ) return NM_ERROR( DSSL_E_OUT_OF_MEMORY ); d->buff_len = new_len; d->buff = new_buff; return DSSL_RC_OK; }
/* ========== SERVER-FINISHED ========== */ static int ssl2_decode_server_finished( DSSL_Session* sess, u_char* data, uint32_t len, uint32_t* processed ) { _ASSERT( processed && data && sess ); if( len > sizeof( sess->session_id ) ) { return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ); } /* set new session ID and add the session to the session cache */ memset( sess->session_id, 0, sizeof(sess->session_id ) ); memcpy( sess->session_id, data, len ); ssls_store_session( sess ); /* handshake is over, time to switch to application data protocol */ sess->c_dec.state = SS_Established; sess->s_dec.state = SS_Established; ssls_handshake_done( sess ); *processed = len; return DSSL_RC_OK; }
int ssl3_PRF( const u_char* secret, uint32_t secret_len, const u_char* random1, uint32_t random1_len, const u_char* random2, uint32_t random2_len, u_char* out, uint32_t out_len ) { MD5_CTX md5; SHA_CTX sha; u_char buf[20]; uint32_t off; u_char i; if( !out ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); for( off=0, i = 1; off < out_len; off+=16, ++i ) { u_char md5_buf[16]; uint32_t cnt; uint32_t j; MD5_Init(&md5); SHA1_Init(&sha); /* salt: A, BB, CCC, ... */ for( j=0; j < i; j++ ) buf[j]='A' + (i-1); SHA1_Update( &sha, buf, i ); if( secret ) SHA1_Update( &sha, secret, secret_len ); SHA1_Update( &sha, random1, random1_len ); SHA1_Update( &sha, random2, random2_len ); SHA1_Final( buf, &sha ); MD5_Update( &md5, secret, secret_len ); MD5_Update( &md5, buf, 20 ); MD5_Final( md5_buf, &md5 ); cnt = out_len - off < 16 ? out_len - off : 16; memcpy( out + off, md5_buf, cnt ); } return DSSL_RC_OK; }
int ssls_decode_master_secret( DSSL_Session* sess ) { switch( sess->version ) { case SSL3_VERSION: return ssl3_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); case TLS1_VERSION: return tls1_PRF( sess->PMS, SSL_MAX_MASTER_KEY_LENGTH, "master secret", sess->client_random, SSL3_RANDOM_SIZE, sess->server_random, SSL3_RANDOM_SIZE, sess->master_secret, sizeof( sess->master_secret ) ); default: return NM_ERROR( DSSL_E_NOT_IMPL ); } }
/*! \fn bool NmHsWidget::loadDocML(HbDocumentLoader &loader) loads layout data and child items from docml file. Must be called after constructor. /return true if loading succeeded, otherwise false. False indicates that object is unusable */ bool NmHsWidget::loadDocML(HbDocumentLoader &loader) { NM_FUNCTION; bool ok(false); loader.load(KNmHsWidgetDocML, &ok); if(ok) { mMainContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetMainContainer)); mWidgetContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetContainer)); mContentContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetContentContainer)); mEmptySpaceContainer = static_cast<HbWidget*> (loader.findWidget(KNmHsWidgetEmptySpaceContainer)); mNoMailsLabel = static_cast<HbLabel*> (loader.findWidget(KNmHsWidgetNoMailsLabel)); mListView = static_cast<HbListView*> (loader.findWidget(KNmHsWidgetMailListView)); if (!mMainContainer || !mWidgetContainer || !mContentContainer || !mEmptySpaceContainer || !mNoMailsLabel || !mListView) { //something failed in documentloader, no point to continue NM_ERROR(1,"NmHsWidget::loadDocML fail @ containers or label"); ok = false; } } return ok; }
int ssls_init_from_tls_ticket( DSSL_Session* sess ) { DSSL_SessionTicketData* ticket_data = NULL; _ASSERT( sess ); _ASSERT( sess->env ); if( sess->env->ticket_cache ) { ticket_data = dssl_SessionTicketTable_Find( sess->env->ticket_cache, sess->session_ticket, sess->session_ticket_len ); } if( !ticket_data ) return NM_ERROR( DSSL_E_SSL_SESSION_TICKET_NOT_CACHED ); memcpy( sess->master_secret, ticket_data->master_secret, SSL3_MASTER_SECRET_SIZE ); sess->master_key_len = SSL3_MASTER_SECRET_SIZE; sess->cipher_suite = ticket_data->cipher_suite; sess->version = ticket_data->protocol_version; sess->compression_method = ticket_data->compression_method; return DSSL_RC_OK; }
/* ========== Server Certificate ========== */ static int ssl3_decode_server_certificate( DSSL_Session* sess, u_char* data, uint32_t len ) { X509 *x=NULL; uint32_t llen = 0; int rc = DSSL_RC_OK; if( !sess ) return NM_ERROR( DSSL_E_INVALID_PARAMETER ); /* TBD: skip server certificate check if SSL key has not yet been mapped for this server */ if( !sess->ssl_si ) return DSSL_RC_OK; if( !sess->ssl_si->pkey ) return NM_ERROR( DSSL_E_UNINITIALIZED_ARGUMENT ); if( len < 3 ) return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH ); llen = MAKE_UINT24( data[0], data[1], data[2] ); data+=3; if( llen + 3 != len || llen < 3 ) return NM_ERROR( DSSL_E_SSL_INVALID_CERTIFICATE_RECORD ); llen = MAKE_UINT24( data[0], data[1], data[2] ); data+=3; if( llen > len ) return NM_ERROR( DSSL_E_SSL_INVALID_CERTIFICATE_LENGTH ); x = d2i_X509( NULL, &data, llen ); if( !x ) { rc = NM_ERROR( DSSL_E_SSL_BAD_CERTIFICATE ); } if( rc == DSSL_RC_OK && !X509_check_private_key(x, ssls_get_session_private_key( sess )) ) { rc = NM_ERROR( DSSL_E_SSL_CERTIFICATE_KEY_MISMATCH ); } if( x ) X509_free( x ); return rc; }