2016-02-09 2 views
1

J'ai un programme qui fonctionne depuis un certain temps déjà sous SUSE Linux Enterprise Server. Récemment, il a été déplacé sur un système OpenSUSE 13.2 et un problème a été rencontré. Le programme s'interface avec un tiers et les données sont reçues dans notre programme où le bloc de données se compose de certaines informations d'en-tête et de données cryptées AES. À l'aide de la bibliothèque OpenSSL libcrypto, nous avons réussi l'interface avec ce système sous SLES. Cependant, sous OpenSUSE, nous voyons toujours une erreur où la fin des données déchiffrées contient des données parasites. J'ai identifié où le problème se produit et j'ai un travail à faire, mais en regardant le code, je ne vois pas pourquoi il y aurait un problème.Garbage caractères lors du décryptage avec memcpy sur OpenSUSE 13.2

J'ai créé un programme de test qui simule le problème. Le programme de test fonctionne correctement sous SUSE Linux Enterprise Server 11 et Red Hat 7.2 Enterprise Linux mais échoue sur OpenSUSE 13.2 en utilisant différents niveaux de version des bibliothèques OpenSSL. Sous SLES et Red Hat, les données décryptées sont renvoyées correctement. Sous OpenSUSE, la plupart des données sont décryptées proprement, sauf pour les déchets qui apparaissent vers la fin du bloc de données. Le bloc de données retourné est correct, puis contient quelques déchets, puis se termine correctement. Le code pour mon exemple de programme est ci-dessous, mais la ligne à l'origine du problème est un memcpy() où je déplace les données chiffrées à l'avant du bloc de données pour le traitement. La ligne dans mon exemple de programme est ci-dessous:

// Generates Garbage 
    memcpy(encbuf, encbuf+100, enclen);     

Si je déplace les données cryptées au tampon temporaire avant de passer au début de la encbuf, les ordures ne sont pas générés.

// This does not generate garbage 
    memcpy(tmpbuf, encbuf+100, enclen);     
    memcpy(encbuf, tmpbuf, enclen);     

Mon programme exemple un tampon défini de texte clair, encrypte en utilisant une clé et IV et décrypte ensuite et affiche le résultat. Code condensé est la suivante:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <unistd.h>  
#include <time.h>  
#include <fcntl.h>  
#include <sys/types.h> 

#include <openssl/evp.h> 

#define EVP_DECRYPT 0 
#define EVP_ENCRYPT 1 

char clrbuf[100000]; 
char encbuf[100000]; 
char tmpbuf[100000]; 
int clrlen;   
int enclen;   

char enckey[1024];  
unsigned char enciv[16]; 

main() 
{ 
    int rc; 

    // Set clear text to 50 lines of text 
    sprintf(clrbuf,             
     "0001this is a test this is a test this is a test this is a test\n" \ 
     "0002this is a test this is a test this is a test this is a test\n" \ 
     "0003this is a test this is a test this is a test this is a test\n" \ 
     // etc etc etc………………. 
     "0048this is a test this is a test this is a test this is a test\n" \ 
     "0049this is a test this is a test this is a test this is a test\n" \ 
     "0050this is a test this is a test this is a test this is a test\n" 

    sprintf(enckey, "this is the key this is the key "); 
    sprintf(enciv, "123456789"); 

    // Encrypt the data and simulate a 100 byte header by returning encrypted data 100 bytes into the data block 
    // 
    memcpy(encbuf, "Some header stuff that will need to be removed", 46); 
    rc = evp_aes256_cbc(clrbuf, strlen(clrbuf), encbuf+100, &enclen, enckey, enciv, EVP_ENCRYPT);     

    // Now remove the header by shifting the encrypted data to the start of the data block and decrypt 
    // This is where doing the memcpy() as coded in OpenSUSE results in garbage at the end of clrbuf 
    // but everything is returned correctly in SLES and Red Hat 
    // 
    // This work fines on all OSes: 
    //   memcpy(tmpbuf, encbuf+100, enclen);     
    //   memcpy(encbuf, tmpbuf, enclen);     

    memcpy(encbuf, encbuf+100, enclen);     
    rc = evp_aes256_cbc(encbuf, enclen, clrbuf, &clrlen, enckey, enciv, EVP_DECRYPT); 

    printf("Decrypt: rc=%d EncLen=%d ClrLen=%d\n", rc, enclen, clrlen); 
    printf("Data:\n\n<\n%s\n>\n\n", clrbuf);        
} 

/****************************************************************************/ 

evp_aes256_cbc(char *InBuf, int InLen, char *OutBuf, int OutLen, char *Key, char *IV, int EncryptFlag)    
{                    
    EVP_CIPHER_CTX ctx;               
    int padlen;                 

    EVP_CIPHER_CTX_init(&ctx);             

    if (! EVP_CipherInit_ex(&ctx, EVP_aes_256_cbc(), NULL, Key, IV, EncryptFlag)) 
     return(0);                 

    if (! EVP_CipherUpdate(&ctx, OutBuf, OutLen, InBuf, InLen)) 
     return(0);            

    if (! EVP_CipherFinal_ex(&ctx, OutBuf+(*OutLen), &padlen)) 
     return(0);            

    *OutLen = *OutLen + padlen;         

    EVP_CIPHER_CTX_cleanup(&ctx);        

    return(1);             
}                

sur SLES et Red Hat, la sortie finale ressemble:

0046this ​​est un test ceci est un test ceci est un test ceci est un test
0047this est un test c'est un test c'est un test c'est un test
0048c'est un test c'est un test c'est un test c'est un test c'est un test
0049c'est un test c'est un test c'est un test c'est un test
0050c'est un test c'est un test ceci est un test ceci est un test

sur openSUSE, sortie finale peut ressembler à:

0046this ​​est un test ceci est un test ceci est un test ceci est un test
0047this est un test c'est un test ceci est un test c'est un test
0048ceci est un test c'est un tes╧┬S_úReÅ▌
| τZk╠½çP≥ii≡w╙p▓8ª'MêÅt▒g {Y ¥ ΩEô¬ ⌡n} ⌐ * ╘¿μ2└╠LS4 = Qüü├; ~ ╕Ç < ╗^¿ßD0┤T.OQΣq # ≈
0050c'est un test ceci est un test c'est un test c'est un test

Des pensées?

Merci

+0

Rembourrage raté? – Asaph

Répondre

1
// Generates Garbage 
memcpy(encbuf, encbuf+100, enclen); 

tampons Chevauchement et memcpy est un comportement non défini dans C/C++. Utilisez memmove à la place. On dirait que vous avez une version de la glibc qui peut être mémorisée en avant ou en arrière. Dans votre cas, vous exécutez sur un processeur qui a passé HAS_FAST_COPY_BACKWARD.

Voici un rapport de bogue classique pour le problème: Strange sound on mp3 flash website. Mais rien d'Adobe ne devrait vous surprendre. Il y a une raison pour laquelle ils sont connus pour les logiciels les moins sécurisés de la planète.

En outre, si vous exécutez votre binaire sous Valgrind, l'outil marque parfois le code avec le problème. Je me souviens avoir vu Valgrind le signaler pour le Crypto++ library:

size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking) 
{ 
    // Avoid passing NULL pointer to memcpy. Using memmove due to 
    // Valgrind finding on overlapping buffers. 
    size_t copied = 0; 
    if (m_buf && begin) 
    { 
     copied = STDMIN(length, SaturatingSubtract(m_size, m_total)); 
     memmove(m_buf+m_total, begin, copied); 
    } 
    m_total += copied; 
    return length - copied; 
} 
0

réponse fournie par une autre source:

devraient utiliser memmove() plutôt que memcpy() en raison du chevauchement de la mémoire.