2014-10-13 10 views
9

में संदर्भ को मुक्त/आवंटित करने का सही तरीका मैं अपने प्रोग्राम में ओपन एसएसएल का उपयोग कर रहा हूं, एईएस सिफर का उपयोग करके डेटा एन्क्रिप्ट और डिक्रिप्ट करने के लिए। फिलहाल थोड़ी मेमोरी रिसाव है, इसलिए मैं इसे ठीक करने का एक तरीका ढूंढ रहा हूं।ओपनएसएसएल

EVP_CIPHER_CTX_new 

यह examples

लेकिन में OpenSSL विकि पृष्ठ पर था: मेरे एन्क्रिप्ट डिक्रिप्ट दिनचर्या में, मैं संदर्भों तो

EVP_CIPHER_CTX_free(ctx); 

की तरह मुक्त और के द्वारा बनाई गई है! मैन पेज पर, EVP_CIPHER_CTX_cleanup और EVP_CIPHER_CTX_init फ़ंक्शंस का उपयोग करने के लिए एक सुझाव है। तो मूल रूप से उपयोग करने के लिए सही क्या होना चाहिए, EVP_CIPHER_CTX_new/EVP_CIPHER_CTX_free किसी भी तरह से बहिष्कृत है? और EVP_CIPHER_CTX_new/EVP_CIPHER_CTX_free और EVP_CIPHER_CTX_init/EVP_CIPHER_CTX_cleanup के बीच कोई बड़ा अंतर है?

if(!(ctx = EVP_CIPHER_CTX_new())) return -1; 


    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) 
    { 
    EVP_CIPHER_CTX_free(ctx); 
    return -1; 
    } 

    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) 
    { 
    EVP_CIPHER_CTX_free(ctx); 
    return -1; 
    } 
    ciphertext_len = len; 


    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { EVP_CIPHER_CTX_free(ctx); return -1; } 
    ciphertext_len += len; 


    EVP_CIPHER_CTX_free(ctx); 

उत्तर

0

ठीक है, मुझे लगता है कि यह अब साफ़ हो गया है। आप EVP शैली एन्क्रिप्शन/डिक्रिप्शन करते हैं, तो आप की तरह प्रसंग बना सुनिश्चित करें:

EVP_CIPHER_CTX ctx; 
    EVP_CIPHER_CTX_init(&ctx); 

और मुक्त यह इतना की तरह:/मुक्त EVP_CIPHER_CTX_new/EVP_CIPHER_CTX_free का प्रयोग न करें बनाने के लिए

EVP_CIPHER_CTX_cleanup(&ctx); 

संदर्भ, वे बहिष्कृत हैं!

+6

यह मुझे लगता है कि विपरीत है। वास्तव में openssl-1.1.0 EVP_CIPHER_CTX को एक अपारदर्शी प्रकार बनाता है, इसलिए उपरोक्त पहला फॉर्म एक संकलन त्रुटि – pixelbeat

+1

है, इस उत्तर में यह अन्य उत्तरों में बताए गए बिल्कुल पीछे है। कृपया इसे अपडेट या अस्वीकार करें। – rdb

5

आप EVP_EncryptInit अब और उपयोग नहीं करना चाहिए। उस फ़ंक्शन ने स्वचालित रूप से एक विशिष्ट संदर्भ बनाया था, लेकिन यह बाद में जोड़े गए क्रिप्टो इंजन का समर्थन नहीं करता था। EVP_EncryptInit_ex हालांकि स्पष्ट रूप से बताता है कि:

ctx इस फ़ंक्शन को कॉल करने से पहले प्रारंभ किया जाना चाहिए।

इसलिए मुझे लगता है कि आपको EVP_CIPHER_CTX_new का उपयोग करना होगा।

EVP_CIPHER_CTX_free एक और मामला है, ऐसा लगता है कि इसे हटा दिया गया है, मुझे ओपनएसएसएल के मैनुअल पृष्ठों पर इसका कोई उल्लेख नहीं दिख रहा है। एनआईएसटी प्रमाणित कार्यक्षमता के लिए यह अच्छी प्रथा है (और आवश्यक) उपयोग के बाद मुख्य सामग्री और एक सिफर के अन्य राज्य को हटाने के लिए। अन्यथा एक हमलावर स्मृति को स्कैन कर सकता है या बाद के चरण में ओवरफ्लो का उपयोग कर सकता है।

EVP_CIPHER_CTX_free का नाम केवल इंगित करता है कि सीटीएक्स मेमोरी जारी की जानी चाहिए। लेकिन स्मृति को मुक्त करने से यह संकेत नहीं मिलता है कि यह पहले संवेदनशील जानकारी से साफ़ हो जाता है; यह सिर्फ सिस्टम में लौट आया है, जो इसे ओवरराइट करने के लिए कोई दायित्व नहीं है। दूसरी तरफ EVP_CIPHER_CTX_cleanup स्मृति को मुक्त करने से पहले ऐसी जानकारी साफ़ कर देता है (या कम से कम ऐसा करने का एक सभ्य प्रयास करता है, मुझे लगता है)। इसलिए आपको अपनी मुख्य सामग्री प्रदान करने के बाद इस फ़ंक्शन को कॉल करने की आवश्यकता है।

+0

मुझे नहीं लगता कि अपनी स्मृति मुद्दा है, के संदर्भ में है अपने कोड को देख रहा है। आप स्थिर कोड विश्लेषकों जैसे कुछ अन्य चीजों को आजमा सकते हैं। –

8

यदि आप एक सटीक उत्तर चाहते हैं तो सबसे पहले, आपको हमेशा निर्दिष्ट करना चाहिए कि आप किस OpenSSL का उपयोग कर रहे हैं। एफवाईआई 1.0.2 वर्तमान Long Term Support संस्करण है, जबकि 1.1.0 नवीनतम है (सितंबर 2016 में)।

यदि आप 1.1 पढ़ते हैं।0 मैन पेज आप देखेंगे:

EVP_CIPHER_CTX ओपनएसएसएल 1.1.0 में अपारदर्शी बना दिया गया था। नतीजतन, EVP_CIPHER_CTX_reset() दिखाई दिया और EVP_CIPHER_CTX_cleanup() गायब हो गया। EVP_CIPHER_CTX_init() EVP_CIPHER_CTX_reset() के लिए उपनाम के रूप में बनी हुई है।

कम जवाब है: आप EVP_CIPHER_CTX_new का उपयोग करना चाहिए प्रारंभ करने और EVP_CIPHER_CTX_free स्मृति मुक्त करते हैं, संस्करण की परवाह किए बिना, यहाँ क्यों है।

आवंटन:

1.0.2 आदमी पृष्ठों कहते हैं:

EVP_CIPHER_CTX ctx; 
EVP_CIPHER_CTX_init(&ctx); 

और 1.1.0 आदमी पृष्ठों कहते हैं:

EVP_CIPHER_CTX *ctx; 
ctx = EVP_CIPHER_CTX_new(); 

आप EVP_CIPHER_CTX_init की code में को देखें, तो 1.0.2

void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) 
{ 
    memset(ctx, 0, sizeof(EVP_CIPHER_CTX)); 
    /* ctx->cipher=NULL; */ 
} 

EVP_CIPHER_CTX_new है, जबकि:

EVP_CIPHER_CTX *ctx; 
ctx = EVP_CIPHER_CTX_new(); 

1.1.0 यही बात लागू होगी के लिए:

EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) 
{ 
    EVP_CIPHER_CTX *ctx = OPENSSL_malloc(sizeof *ctx); 
    if (ctx) 
     EVP_CIPHER_CTX_init(ctx); 
    return ctx; 
} 

ताकि आप आप अभी भी संदर्भ आरंभ, 1.1.0 उदाहरण की तरह से बेहतर कर रहे हैं।

स्मृति को मुक्त कराने के लिए:

1.0.2 आदमी पृष्ठों:

EVP_CIPHER_CTX_cleanup(&ctx); 

1.1.0 आदमी पृष्ठों:

EVP_CIPHER_CTX_free(ctx); 

लेकिन अगर आप की जाँच code आप देख सकते हैं कि 1.0.2 के लिए:

void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) 
{ 
    if (ctx) { 
     EVP_CIPHER_CTX_cleanup(ctx); 
     OPENSSL_free(ctx); 
    } 
} 

तो आपको हटाने के लिए EVP_CIPHER_CTX_free का उपयोग करना चाहिए। यदि आप किसी अन्य ऑपरेशन के लिए संदर्भ को रीसेट करना चाहते हैं तो EVP_CIPHER_CTX_cleanup (1.0.2) और EVP_CIPHER_CTX_reset (1.1.0) आपके मित्र हैं।

आप mallocmemset और calloc के बारे में उत्सुक हैं, तो यहां एक good explanation

संबंधित मुद्दे