

現在、C++でOpenSSLライブラリを用いて公開鍵暗号方式の暗号化、復号を実装しています。  
しかし、プログラムを実行すると、以下の中の2回目のEVP_PKEY_decryptでSegmentation faultが発生します。  
OSはUbuntu 14.04.3、コンパイラは ~~clang++-3.6または~~ clang++-3.8です。

[code]

    bool decryptData(EVP_PKEY *key, unsigned char *data, size_t datalen, unsigned char **decdata, size_t *declen) {
        int ret;
        EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key, NULL); // 鍵はRSA
    
        if ((ret = EVP_PKEY_decrypt_init(ctx)) != 1) {
            std::cerr << "init: " << ret << std::endl;
            return false;
        }
        if ((ret = EVP_PKEY_decrypt(ctx, NULL, declen, data, datalen)) != 1) { 
            std::cerr << "dec1: " << ret << std::endl;
            return false;
        }
    
        *decdata = (unsigned char *)realloc(*decdata, sizeof(unsigned char *) * *declen);
        //*decdata = (unsigned char *)malloc(sizeof(unsigned char *) * *declen);
        if ((ret = EVP_PKEY_decrypt(ctx, *decdata, declen, data, datalen)) != 1) { // <--
            std::cerr << "dec2: " << ret << std::endl;
            return false;
        }
            return true;
    }
    
[/code]

valgrindで見てみると以下のようになります。

[code]

    ==21343== Invalid read of size 8
    ==21343==    at 0x4EFF421: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
    ==21343==    by 0x4F047B6: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
    ==21343==    by 0x402FC9: decryptData(evp_pkey_st*, unsigned char*, unsigned long, unsigned char**, unsigned long*) (pubkeyenc.h:53)
    ==21343==    by 0x40323E: main (tmp.cpp:27)
    ==21343==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
    
[/code]

decryptData()の引数の変数のアドレスはすべて0でないことを確認したのですが、このようなエラーになるのはどういった原因が考えられるのでしょうか？  
どうぞよろしくお願いします。

* * *

## 追記:

呼び出し側は以下のようなコードで，encryptDataはdecryptData内のdecryptをencryptになっただけです．

[code]

    int main() {
        unsigned char msg[] = "hoge";ただ
        unsigned char *enc = nullptr;
        //unsigned char *enc = NULL;
        size_t *enclen = (size_t *)malloc(sizeof(size_t));
        EVP_PKEY *key = /* 鍵を入れる関数 */
        if (key == nullptr) cerr << "priv key error" << endl;
        if(!(encryptData(key, msg, strlen(reinterpret_cast<char *>(msg)), &enc, enclen))) {
            cerr << "enc error" << endl;
        }else {
            cerr << "enc success" << endl;
        }
    
        unsigned char *decoded = nullptr;
        //unsigned char *decoded = NULL;
        size_t *declen = (size_t *)malloc(sizeof(size_t));
        key = /* 鍵を入れる関数 */
        if (key == nullptr) cerr << "pub key error" << endl;
        if(!(decryptData(key, enc, *enclen, &decoded, declen))) {
            cerr << "dec error" << endl;
        }else {
            cerr << "dec success" << endl;
        }   
    
        free(enclen);
        free(declen);
        if (enc != nullptr) free(enc);
        if (decoded != nullptr) free(decoded);
    
        return 0;
    }
    
[/code]

* * *

## 追記 (2016/12/19):

暗号化に用いる鍵はPEM_read_PrivateKeyを用いて，ssh-
keygenで作成した秘密鍵を利用し，復号に用いる鍵はPEM_read_PUBKEYを用いて，ssh-keygenで作成した公開鍵を利用していました．  
しかし，これらを逆にして公開鍵で暗号化し，秘密鍵で復号したところ問題なくプログラムが動きました．


CC BY-SA 3.0
2016-09-01T19:12:18.190
28639
2016-12-19T06:42:16.543
2016-12-19T06:42:16.543
18671
18671
question
c++ c openssl
EVP_PKEY_decryptにおいてSegmentation faultが発生します


> Address **0x0** is not stack'd, malloc'd or (recently) free'd

なので`nullptr`から値を読み込もうとしています。OpenSSL側のバグの可能性もありますが、たぶん不正な値を渡したのでしょう。

挙げられたコードを手直しして実行してみましたが特に問題なく動作しました。

* * *

なお、`enclen` `declen`は`size_t*`とする必要はありませんし、

[code]

    *decdata = (unsigned char *)realloc(*decdata, sizeof(unsigned char *) * *declen);
    
[/code]

では要求されたメモリ量の８倍のメモリ確保をしています。


CC BY-SA 3.0
2016-09-02T08:49:52.170
28650
2016-09-02T08:49:52.170
4236
28639
answer