2017-10-01 5 views
2

私はSignalのlibsignalライブラリで遊んでいます。小さなおもちゃプログラムをコンパイルして実行する方法を推測しています。しかし、私は最初に立ち往生しています。私は、後でライブラリで使用される関数へのポインタを変数に設定しなければならないことを理解しています。また、ライブラリのテストで複製するものを複製しようとしていても、テストと私のコード、そしてなぜ私のプログラムが実行時に失敗するかを示します。私が使用していたコードは、次のいずれかです。アサーション - 関数のポインタに失敗しました

#include <stdlib> 
#include <signal/signal_protocol.h> 
#include <signal/key_helper.h> 
#include <openssl/rand.h> 

int random(uint8_t *data, size_t len, void *user_data) 
{ 
    if(RAND_bytes(data, len)) { 
     return 0; 
    } 
    else { 
     return SG_ERR_UNKNOWN; 
    } 
} 

int main(int argc, char **argv) { 
    signal_crypto_provider provider = { 
      .random_func = random 
      /*.hmac_sha256_init_func = HMAC_CTX_new, 
      .hmac_sha256_update_func = HMAC_Update, 
      .hmac_sha256_final_func = HMAC_Final, 
      .hmac_sha256_cleanup_func = HMAC_CTX_free, 
      .sha512_digest_init_func = SHA512_Init, 
      .sha512_digest_update_func = SHA512_Update, 
      .sha512_digest_final_func = SHA512_Final, 
      .sha512_digest_cleanup_func = EVP_MD_CTX_free, 
      .encrypt_func = EVP_aes_256_cbc, 
      .decrypt_func = EVP_aes_256_cbc, 
      .user_data = 0*/ 
    }; 

    signal_context *global_context; 
    signal_context_create(&global_context, 0); 
    signal_context_set_crypto_provider(global_context, &provider); 
    //signal_context_set_locking_functions(global_context, lock_function, 
    //unlock_function); 


    ratchet_identity_key_pair *identity_key_pair; 
    uint32_t registration_id; 
    signal_protocol_key_helper_pre_key_list_node *pre_keys_head; 
    session_signed_pre_key *signed_pre_key; 


    signal_protocol_key_helper_generate_identity_key_pair(
     &identity_key_pair, 
     global_context 
    ); 

    exit(EXIT_SUCCESS); 

} 

プログラムがsignal_protocol_key_helper_generate_identity_key_pairに達したときに問題が発生します。私は次の関数で終わった、図書室を通って行くと、それが作る呼び出しを次のよう:失敗

int signal_crypto_random(signal_context *context, uint8_t *data, size_t len) 
{ 
    assert(context); 
    assert(context->crypto_provider.random_func); 
    return context->crypto_provider.random_func(data, len, context->crypto_provider.user_data); 
} 

アサーションは私に次のエラーを与えて、第二いずれかになります。

signal_crypto_random: Assertion `context->crypto_provider.random_func' failed. 

のみ私が考えることができる説明は、私がC言語で新しいものであると考えることができるということです。何とかポインタが以前に指定した関数を指していないということです。この推測が正しい場合、なぜこれが起こるのですか?

テストコードを確認し、それを自分のコードと比較すると、私のプログラムが失敗する重要な違いは何か分かりません。デバッグするとき、変数は正しい内容を持つように見えます。

Variable contents

ありがとうございます。 signal_context_set_crypto_provider()


test-common.c

void setup_test_crypto_provider(signal_context *context) 
{ 
    signal_crypto_provider provider = { 
      .random_func = test_random_generator, 
      .hmac_sha256_init_func = test_hmac_sha256_init, 
      .hmac_sha256_update_func = test_hmac_sha256_update, 
      .hmac_sha256_final_func = test_hmac_sha256_final, 
      .hmac_sha256_cleanup_func = test_hmac_sha256_cleanup, 
      .sha512_digest_init_func = test_sha512_digest_init, 
      .sha512_digest_update_func = test_sha512_digest_update, 
      .sha512_digest_final_func = test_sha512_digest_final, 
      .sha512_digest_cleanup_func = test_sha512_digest_cleanup, 
      .encrypt_func = test_encrypt, 
      .decrypt_func = test_decrypt, 
      .user_data = 0 
    }; 

    signal_context_set_crypto_provider(context, &provider); 
} 

test-common-openssl.c

int test_random_generator(uint8_t *data, size_t len, void *user_data) 
{ 
    if(RAND_bytes(data, len)) { 
     return 0; 
    } 
    else { 
     return SG_ERR_UNKNOWN; 
    } 
} 
+0

そして 'signal_context_set_crypto_provider()'の戻りコードは何ですか? –

+0

-22は 'SG_ERR_INVAL'を表します。ちょっと、あなた。この関数は、 'hmac_sha'関数のどれもが' provider'変数に指定されていなければ、そのエラーを返します。 – MikelAlejoBR

+0

はい、確かに。だから私は私の質問をしました。私の答えは下記をご覧ください。 –

答えて

2

チェックあり:

if(!crypto_provider 
     || !crypto_provider->hmac_sha256_init_func 
     || !crypto_provider->hmac_sha256_update_func 
     || !crypto_provider->hmac_sha256_final_func 
     || !crypto_provider->hmac_sha256_cleanup_func) { 
    return SG_ERR_INVAL; 
} 

だから、答えはあなたがそれらのcallbを離れることができないということです未設定なので、何もコンテキストにコピーされず、最終的にassert()が発生します。

私は、テストコードが戻りコードをチェックしない理由を理解していますが、実動コードではエラーを監視するために戻り値をチェックする必要があります。

+0

プロダクションコードだけでなく、これらのプレイテストについてもアドバイスをします。私は、エラーチェックを忘れて、すぐに進んでいく方が早いと思っていました。ご協力ありがとうございました。 – MikelAlejoBR

+1

ええ、マクロが便利になるかもしれません。ループ本体と 'if((ret = _call)!= 0)'と 'printf()'の 'int ret;'で 'do {} while(0);'に 'CHECK_RET(_call)それに応じて。同じような場所で使うだけです。 –

+0

このコードスニペットありがとうございます。それは確かに便利になるだろう:) – MikelAlejoBR

関連する問題