Bonjour à tous, Désolé de venir avec un problème pas tout à fait Debian. J'essaye de m'inscrire sur les listes de diffusion OpenSSL depuis plusieurs jours sans aucun retour. Je pense que des lecteurs ont déjà été confrontés au problème.
J'utilise OpenSSL (3.3.1) pour chiffrer des messages et les déchiffrer. J'observe un comportement que je ne comprends pas. Je n'utilise qu'un chiffrement de type AES256-ECB (donc le chiffrement d'un bloc ne dépend que du bloc en question. Je sais, ce n'est pas bien, mais le périphérique en face est un microcontrôleur qui cause en 4G et qui possède très peu de mémoire). Lorsque mon périphérique parle à mon serveur Debian, mon programme plante méchamment lors de l'appel à la fonction EVP_CipherFinal_ex(). Que fais-je ? Je crée un contexte, je l'initialise avec la clef et tout ce qui va bien puis je chiffre : if ((contexte = EVP_CIPHER_CTX_new()) == NULL) { return(NULL); } EVP_CIPHER_CTX_reset(contexte); longueur_bloc_de_chiffrement = EVP_CIPHER_block_size(type_chiffrement); if (EVP_CipherInit_ex(contexte, type_chiffrement, NULL, clef, vecteur_initialisation, (encodage == d_vrai) ? 1 : 0) != 1) { EVP_CIPHER_CTX_free(contexte); return(NULL); } nombre_blocs = longueur_message / longueur_bloc_de_chiffrement; if ((longueur_message % longueur_bloc_de_chiffrement) != 0) { nombre_blocs++; } (*longueur_message_chiffre) = nombre_blocs * longueur_bloc_de_chiffrement; printf("longueur_message_chiffre = %lld\n", (*longueur_message_chiffre)); // On prévoit une zone de garde pour EVP_CipherFinal_ex() en // espérant // qu'il ne faille pas plus qu'une longueur de bloc de chiffrement. // Méchant hack en raison d'un comportement étrange de // EVP_CipherFinal_ex(). if ((message_chiffre = malloc(((size_t) ((*longueur_message_chiffre) + longueur_bloc_de_chiffrement)) * sizeof(unsigned char))) == NULL) { EVP_CIPHER_CTX_free(contexte); return(NULL); } printf("longueur_message = %d\n", (int) longueur_message); if (EVP_CipherUpdate(contexte, message_chiffre, &longueur_message_1, message, (int) longueur_message) != 1) { free(message_chiffre); EVP_CIPHER_CTX_free(contexte); return(NULL); } printf("longueur_message_1 = %d\n", longueur_message_1); if (EVP_CipherFinal_ex(contexte, message_chiffre + longueur_message_1, &longueur_message_2) != 1) { free(message_chiffre); EVP_CIPHER_CTX_free(contexte); return(NULL); } printf("longueur_message_2 = %d\n", longueur_message_2); (*longueur_message_chiffre) = longueur_message_1 + longueur_message_2; // Mise à jour du vecteur d'initialisation EVP_CIPHER_CTX_get_updated_iv(contexte, vecteur_initialisation, (size_t) EVP_CIPHER_iv_length(type_chiffrement)); EVP_CIPHER_CTX_free(contexte); Cette routine est appelée pour chiffrer et pour déchiffrer. Je ne mets pas tout le code, ça n'a pas beaucoup d'intérêt. Maintenant, mon problème. Le code AES256 utilise des blocs de 16 octets. Si je chiffre un message de 15 octets, j'obtiens un message chiffré de 16 octets. Normal. longueur_message_chiffre = 16 longueur_message = 15 longueur_message_1 = 0 longueur_message_2 = 16 Ainsi, EVP_CipherUpdate() ne fait rien (aucun bloc entier) et le chiffrement est effectué par EVP_CipherFinal_ex(). Si maintenant je cherche à chiffrer un message de 16 octets, voici ce qui sort : longueur_message_chiffre = 16 longueur_message = 16 longueur_message_1 = 16 longueur_message_2 = 16 => longueur_message_chiffre donne la longueur nécessaire au chiffrement du message. La longueur effectivement renvoyée est longueur_message_1+longueur_message_2 soit ici 32 ! Si je comprends bien, EVP_CipherUpdate() chiffre un bloc de 16 octets. Mais pourquoi EVP_CipherFinal_ex() rajoute-t-il un autre bloc de 16 octets ? J'obtiens un message de 32 octets alors que seuls les 16 premiers sont signifiants. Dans mon cas, j'obtiens : "?r\xF1\xF0-\x89\x83]\xD3\xEE\xF0bj\xE2\xB7\x9E\xE34\xF2\xD2f \xF6w\x02\x14\x0DbS\xD5\x01\x1A" alors que seul "?r\xF1\xF0-\x89\x83]\xD3\xEE\xF0bj\xE2\xB7\x9E" contient le message chiffré (le formalisme est le suivant : les caractères affichables sont directement affichés, les autres sont \x + octet en hexadécimal). Le problème est aussi que je suis capable de déchiffrer le message complet "?r\xF1\xF0-\x89\x83]\xD3\xEE\xF0bj\xE2\xB7\x9E\xE34\xF2\xD2f \xF6w\x02\x14\x0DbS\xD5\x01\x1A" en une chaîne de 16 octets (qui est bien le message envoyé). En revanche, si je tente le déchiffrement des seuls 16 premiers octets, EVP_CipherFinal_ex() renvoie une erreur. Je ne comprends pas mon erreur. Quelqu'un a-t-il déjà été confronté à ce problème ? J'ai trouvé des tas d'exemples sur internet, mais, à chaque fois, EVP_CipherFinal_ex() est appelé. Je prends tout avis, tout pointeur sur une documentation compréhensible (celle d'OpenSSL est un peu... touffue). Merci de votre lecture, JKB
signature.asc
Description: OpenPGP digital signature