static int ssl_decrypt_record( dssl_decoder_stack* stack, u_char* data, uint32_t len, u_char** out, uint32_t* out_len, int *buffer_aquired ) { u_char* buf = NULL; uint32_t buf_len = len; int rc = DSSL_RC_OK; int block_size; const EVP_CIPHER* c = NULL; _ASSERT( stack ); _ASSERT( stack->sess ); _ASSERT( stack->cipher ); rc = ssls_get_decrypt_buffer( stack->sess, &buf, buf_len ); if( rc != DSSL_RC_OK ) return rc; *buffer_aquired = 1; c = EVP_CIPHER_CTX_cipher( stack->cipher ); block_size = EVP_CIPHER_block_size( c ); DEBUG_TRACE3( "using cipher %s (mode=%u, block=%u)\n", EVP_CIPHER_name(c), stack->sess->cipher_mode, block_size ); if( block_size != 1 ) { if( len == 0 || (len % block_size) != 0 ) { return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } } DEBUG_TRACE_BUF("encrypted", data, len); if ( EVP_CIPH_GCM_MODE == stack->sess->cipher_mode || EVP_CIPH_CCM_MODE == stack->sess->cipher_mode ) { if ( len < EVP_GCM_TLS_EXPLICIT_IV_LEN ) { return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } if ( EVP_CIPH_GCM_MODE == stack->sess->cipher_mode ) { /* set 'explicit_nonce' part from message bytes */ rc = EVP_CIPHER_CTX_ctrl(stack->cipher, EVP_CTRL_GCM_SET_IV_INV, EVP_GCM_TLS_EXPLICIT_IV_LEN, data); } else { /* 4 bytes write_iv, 8 bytes explicit_nonce, 4 bytes counter */ u_char ccm_nonce[EVP_GCM_TLS_TAG_LEN] = { 0 }; rc = EVP_CIPHER_CTX_ctrl(stack->cipher, EVP_CTRL_CCM_GET_TAG, sizeof(ccm_nonce), ccm_nonce); if( rc != DSSL_RC_OK ) return rc; /* overwrite exlicit_nonce part with packet data */ memcpy(ccm_nonce + 1 + EVP_GCM_TLS_FIXED_IV_LEN, data, EVP_GCM_TLS_EXPLICIT_IV_LEN); rc = EVP_CIPHER_CTX_ctrl(stack->cipher, EVP_CTRL_CCM_SET_TAG, sizeof(ccm_nonce), ccm_nonce); if( rc != DSSL_RC_OK ) return rc; } data += EVP_GCM_TLS_EXPLICIT_IV_LEN; len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; } rc = EVP_Cipher(stack->cipher, buf, data, len ); buf_len = len; /* strip the padding */ if( block_size != 1 ) { if( buf[len-1] >= buf_len - 1 ) return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); buf_len -= buf[len-1] + 1; } DEBUG_TRACE_BUF("decrypted", buf, buf_len); /* ignore auth tag, which is 16 (for CCM/GCM) or 8 (for CCM-8) bytes */ if ( EVP_CIPH_GCM_MODE == stack->sess->cipher_mode || EVP_CIPH_CCM_MODE == stack->sess->cipher_mode ) { if (NULL == stack->sess->dssl_cipher_suite->extra_info) buf_len -= EVP_GCM_TLS_TAG_LEN; else buf_len -= (size_t)stack->sess->dssl_cipher_suite->extra_info; } *out = buf; *out_len = buf_len; return DSSL_RC_OK; }
static int ssl_decrypt_record( dssl_decoder_stack* stack, u_char* data, uint32_t len, u_char** out, uint32_t* out_len, int *buffer_aquired,int *block_size ) { u_char* buf = NULL; uint32_t buf_len = len; int rc = DSSL_RC_OK; const EVP_CIPHER* c = NULL; int func_ret = 0; int i = 0; DEBUG_TRACE3("ssl_decrypt_record - len: %d, out_len: %d, buffer_aquired: %d\n", len, *out_len, buffer_aquired); _ASSERT( stack ); _ASSERT( stack->sess ); _ASSERT( stack->cipher ); rc = ssls_get_decrypt_buffer( stack->sess, &buf, buf_len ); DEBUG_TRACE1("ssl_decrypt_record - calling ssls_get_decrypt_buffer ended. ret: %d\n", rc); // test //memset(buf, 0x77, DSSL_MAX_COMPRESSED_LENGTH); /* for (i = 0; i < 128; i++) { printf("ssl_decrypt_record(1) - buf[%d]: 0x%02X, data: 0x%02X\n", i, buf[i], data[i]); } */ if( rc != DSSL_RC_OK ) return rc; *buffer_aquired = 1; c = EVP_CIPHER_CTX_cipher( stack->cipher ); *block_size = EVP_CIPHER_block_size( c ); DEBUG_TRACE1("ssl_decrypt_record - calling EVP_CIPHER_block_size ended. ret: %d\n", *block_size); if( *block_size != 1 ) { if( len == 0 || (len % *block_size) != 0 ) { DEBUG_TRACE0("ssl_decrypt_record - DSSL_E_SSL_DECRYPTION_ERROR(after EVP_CIPHER_block_size)\n"); return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } } func_ret = EVP_Cipher(stack->cipher, buf, data, len ); DEBUG_TRACE1("ssl_decrypt_record - calling EVP_Cipher ret: %d\n", func_ret); buf_len = len; DEBUG_TRACE1("ssl_decrypt_record - buf_len: %d\n", buf_len); /* for (i = 0; i < 128; i++) { printf("ssl_decrypt_record(2) - buf[%d]: 0x%02X, data: 0x%02X\n", i, buf[i], data[i]); } */ /* strip the padding */ if( *block_size > 1 ) { if( buf[len-1] >= buf_len - 1 ) { DEBUG_TRACE0("ssl_decrypt_record - DSSL_E_SSL_DECRYPTION_ERROR(after EVP_Cipher)\n"); return NM_ERROR( DSSL_E_SSL_DECRYPTION_ERROR ); } buf_len -= buf[len-1] + 1; } *out = buf; *out_len = buf_len; return DSSL_RC_OK; }