OpenSSL. Probleme multi-plateforme Win/Linux 32/64

Fermé
philou06450 - Modifié par philou06450 le 20/12/2016 à 12:29
philou06450 Messages postés 5 Date d'inscription mardi 20 décembre 2016 Statut Membre Dernière intervention 4 janvier 2017 - 4 janv. 2017 à 16:27
Bonjour à tous.

Je suis entrain de m'arracher les cheveux avec DSA_Verify.
Contexte :
3 plateformes. Seven 32 bits / Seven 64 bits / Linux 64 bits.
Pour chacune de ces plateformes j'ai un tout petit main de test injectant dans DSA_Verify, le hash, le DSA (p, q, r, clef_pub) et la signature (Ces paramètres sont identiques sur les 3 plateformes, sous la forme de tableau simple).
En 32 bits, ma signature est ok
En 64 bits, la fonction sort en erreur sous seven, et sous linux elle est KO.

Je ne suis pas spécialiste en crypto, mais en toute logique il ne doit pas y avoir d’influence lié à la plateforme, au 32/64 bits, voir même à la version d'OpenSSL. Quelque chose, gros comme une maison, m’échappe, mais je ne vois pas quoi.

Je rajouterai que la problématique du type de donnée 'sensible' unsigned long (32bits sous windows 32/64) et (64 sous linux 64) a été gommé par l'utilisation d'affection explicite.

error:0A071066:lib(10):func(113):reason(102)

Le code est à disposition pour qui a une idée géniale.

A voir également:

3 réponses

[Dal] Messages postés 6204 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 27 février 2025 1 101
Modifié par [Dal] le 20/12/2016 à 14:40
Salut,

Pas d'idée géniale, mais sans le code (et toutes les plateformes que tu testes), de toutes façons, on ne peut pas reproduire ton problème.

Pour ton message d'erreur, je suppose que tu l'obtiens avec ERR_error_string()... il n'est pas très explicite. Vois si tu as des messages plus "humains" en appelant préalalblement SSL_load_error_strings() (si tu ne l'as pas déjà fait) et essaye aussi avec ERR_lib_error_string(), ERR_func_error_string() et ERR_reason_error_string()

Sinon, une piste :

DSA_verify() utilise LibTomMath, qui essaye bien de détecter si l'architecture est 64 bits ou pas, et peut-être qu'elle n'y arrive pas dans ton cas.

https://github.com/paiq/dsa_verify/blob/master/mp_math.h#L36

La bibliothèque se fonde sur le fait que
#if defined(__x86_64__)
soit vérifié pour mettre un
#define MP_64BIT
.

Ce symbole "__x86_64__" est définit par le compilateur (si ton compilateur est 64bits, n'est-ce pas). Avec gcc, tu peux le vérifier en générant la liste des #define, par exemple comme cela :

sous Linux :
echo | gcc -E -dM - | sort | less

sous Windows:
crée un fichier vide, par exemple toto.h, puis fais :
gcc -dM toto.h

Tu pourrais aussi tester en essayant de forcer un peu les choses en définissant MP_64BIT, mais si "__x86_64__" ne fait pas partie de tes définitions, tu as peut-être l'origine de ton problème.

Enfin sur ce que tu dis :

Je rajouterai que la problématique du type de donnée 'sensible' unsigned long (32bits sous windows 32/64) et (64 sous linux 64) a été gommé par l'utilisation d'affection explicite.

Je n'ai pas compris de quelle "affection explicite" tu parles.

Le prototype de DSA_verify est :

int    DSA_verify(int type, const unsigned char *dgst, int len,
               unsigned char *sigbuf, int siglen, DSA *dsa);

et tu ne devrais passer que des données de ces types à cette fonction.

Dal
0
philou06450 Messages postés 5 Date d'inscription mardi 20 décembre 2016 Statut Membre Dernière intervention 4 janvier 2017
20 déc. 2016 à 15:43
Merci Dal

mon compilo linux est bien 64bits
sous seven je n'ai pas encore vérifié mais comme j'utilise VS2013, d'un coté je suis en x86 de l'autre en x64


ci-dessous le main...(7) pour linux virer tchar


#include <stdio.h>
#include <tchar.h>
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>

#include <openssl/dsa.h>
#include <openssl/sha.h>

unsigned long dsa_p[32] = {
3811852759, 926649948, 2135774737, 1262601905,
1351636205, 2484862582, 519248036, 1626119556,
1184646062, 294631062, 2549550002, 3147470844,
4154665630, 1914777489, 1168880028, 67789018,
4054198124, 155739334, 3239472924, 629582299,
3043782693, 1762446732, 3206420649, 864427097,
151017452, 1581737565, 190555228, 2827061896,
997252281, 3039591181, 1194997035, 2435025315
};

unsigned long dsa_q[5] = {
2288297, 3218350423, 922783001, 3201946821, 3756889991 };

unsigned long dsa_g[32] = {
2032178000, 2297111264, 864729554, 718824603,
562315409, 4189660788, 1627495526, 3142496757,
876794508, 4290028694, 241957513, 639223573,
1272884139, 27367265, 2464374154, 3191768853,
3378816242, 2454241671, 1995845717, 2209543142,
2361862845, 1168247003, 1408284205, 3603575928,
4207068206, 4016281136, 2240572078, 2902652898,
3673088755, 373773416, 1408678609, 210747117
};

unsigned long pulClefPublique[] = {
1406887592, 2231013855, 1214468519, 89716016,
2983760192, 2899919399, 443441104, 205478390,
3095919601, 1102263977, 1909516063, 2399102550,
2927693062, 1091127790, 242048208, 2790027052,
597195458, 3228378404, 853469933, 1830894158,
4050012554, 3007645684, 912129534, 1936682052,
1417975566, 3658201153, 3908365181, 1140355707,
297788173, 1078708393, 2676829823, 638575751
};

unsigned char pucAuthenticator[] = {
0x30, 0x2D, 0x02, 0x15, 0x00, 0xDD, 0x15, 0x49, 0x98, 0x51, 0x49, 0x14, 0x4C, 0xA9, 0xE8, 0xFF,
0x18, 0x44, 0x34, 0x31, 0x25, 0x0A, 0x10, 0x19, 0xAF, 0x02, 0x14, 0x04, 0x95, 0x56, 0x35, 0xDA,
0x6B, 0x27, 0x40, 0x1C, 0x20, 0x30, 0xB0, 0xF3, 0xAD, 0x23, 0xF7, 0x27, 0x17, 0x7A, 0xAE
};

unsigned char sha[] = {
0x10, 0xB2, 0x3B, 0xE3, 0xB3, 0x2C, 0x51, 0x85, 0x69, 0xAC, 0x66, 0xDC, 0xB0, 0x50, 0x00, 0xB1,
0x0C, 0x19, 0xF6, 0x9F
};

int _tmain(int argc, _TCHAR* argv[])
{
BIGNUM *xPremP;
BIGNUM *xPremQ;
BIGNUM *xPremG;
BIGNUM *xPub = NULL;
DSA *dsa = NULL;
int i, retour;
unsigned char dgst[128] = "";

dsa = DSA_new();
if (dsa == NULL)
{
printf("erreur DSA_new\n");
}
else
{
xPremP = (BIGNUM*)calloc(1, sizeof(BIGNUM));
xPremP->d = (BN_ULONG*)calloc(32, sizeof(BN_ULONG));
xPremP->top = 32;
xPremP->dmax = 32;
xPremP->neg = 0;
xPremP->flags = 1;
for (i = 0; i < 32; i++)
xPremP->d[i] = dsa_p[i];

xPremQ = (BIGNUM*)calloc(1, sizeof(BIGNUM));
xPremQ->d = (BN_ULONG*)calloc(5, sizeof(BN_ULONG));
xPremQ->top = 5;
xPremQ->dmax = 5;
xPremQ->neg = 0;
xPremQ->flags = 1;
for (i = 0; i < 5; i++)
xPremQ->d[i] = dsa_q[i];

xPremG = (BIGNUM*)calloc(1, sizeof(BIGNUM));
xPremG->d = (BN_ULONG*)calloc(32, sizeof(BN_ULONG));
xPremG->top = 32;
xPremG->dmax = 32;
xPremG->neg = 0;
xPremG->flags = 1;
for (i = 0; i < 32; i++)
xPremG->d[i] = dsa_g[i];

/* Copie des paramètres P, Q et G dans la structure DSA */
dsa->p = xPremP;
dsa->q = xPremQ;
dsa->g = xPremG;

/* Clef publique */
xPub = (BIGNUM*)calloc(1, sizeof(BIGNUM));
xPub->d = (BN_ULONG*)calloc(32, sizeof(BN_ULONG));
xPub->top = 32;
xPub->dmax = 32;
xPub->neg = 0;
xPub->flags = 1;
for (i = 0; i < 32; i++)
xPub->d[i] = pulClefPublique[i];

/* On copie la clef privée dans la structure DSA */
dsa->pub_key = xPub;

/* Vérification de la signature */
int iSize = sizeof(pucAuthenticator);
retour = DSA_verify(0, sha, 20, pucAuthenticator, iSize, dsa);

if (retour == 1) /* signature OK */
{
printf("pbAuthenticatorValide : %s", "TRUE");
}
else if (retour == 0) /* signature incorrecte */
{
printf("pbAuthenticatorValide : %s", "FALSE");
}
else /* erreur */
{
char szBuffer[256];
unsigned long ulError = ERR_get_error();

ERR_error_string(ulError, szBuffer);
printf("pbAuthenticatorValide : %s - %lx - %s", "ECHEC", ulError, ERR_error_string(ulError, szBuffer));
}

// la libération mémoires
dsa->pub_key = NULL;
dsa->p = NULL;
dsa->q = NULL;
dsa->g = NULL;

if (xPremP->d != NULL)
free(xPremP->d);
xPremP->d = NULL;
if (xPremP != NULL)
free(xPremP);
xPremP = NULL;

if (xPremQ->d != NULL)
free(xPremQ->d);
xPremQ->d = NULL;
if (xPremQ != NULL)
free(xPremQ);
xPremQ = NULL;

if (xPremG->d != NULL)
free(xPremG->d);
xPremG->d = NULL;
if (xPremG != NULL)
free(xPremG);
xPremG = NULL;

if (xPub->d != NULL)
free(xPub->d);
xPub->d = NULL;
if (xPub != NULL)
free(xPub);
xPub = NULL;

/* Libération de la structure DSA */
if (dsa != NULL)
DSA_free(dsa);
dsa = NULL;
}
}
0
philou06450 Messages postés 5 Date d'inscription mardi 20 décembre 2016 Statut Membre Dernière intervention 4 janvier 2017
20 déc. 2016 à 16:19
Re,
Après avoir appelé SSL_load_error_strings()
j'ai comme erreur : bad q value.....
0
[Dal] Messages postés 6204 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 27 février 2025 1 101
Modifié par [Dal] le 21/12/2016 à 09:58
As-tu vérifié si ton Visual Studio est-ce qu'il définit "__x86_64__" comme je te demandais de le faire sur les compilateurs que tu utilises ?

Selon cette page https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?redirectedfrom=MSDN&view=msvc-160&viewFallbackFrom=vs-2019 il semblerait que ce soit plutôt "_WIN64" dans leur cas...


Dal
0
philou06450 Messages postés 5 Date d'inscription mardi 20 décembre 2016 Statut Membre Dernière intervention 4 janvier 2017 > [Dal] Messages postés 6204 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 27 février 2025
21 déc. 2016 à 10:43
avec un petit #ifdef...

MP_64BIT n'est pas défini
__x86_64__ n'est pas défini
_WIN64 est défini

est les deux premiers semble indépendant. le positionnement de l'un ne change pas l'autre. Et n'a pas d'influance sur le résultat.
0
philou06450 Messages postés 5 Date d'inscription mardi 20 décembre 2016 Statut Membre Dernière intervention 4 janvier 2017
21 déc. 2016 à 09:35
Re

Je vais reformuler ma question (une question bien posée...)

Avec mes p, q, r, clef privé et clef publique en 32bits j'ai signé un message, que j'arrive à vérifier avec openSSL en 32bits (je n'ai pas fais l'essai sous linux 32bits, mais cela devrait marcher).
Cryptologiquement parlant peut-on reprendre les p, q, r, clef publique 32bits, + message + auth, les injecter dans un openSSL en 64bits afin de vérifier la signature ?
Il me semble impensable que cela ne puisse pas se faire.

Merci
0
philou06450 Messages postés 5 Date d'inscription mardi 20 décembre 2016 Statut Membre Dernière intervention 4 janvier 2017
4 janv. 2017 à 16:27
Bon, le problème est réglé...
Sur certain forum, on suggérait de mettre en place une appli 32 bits linké avec openssl32bits, et de la soliciter via IPC depuis l'appli 64bits...un peu tiré par le cheveux mais qui aurait été mon recours ultime si je n'avais pas trouvé.
Alors :
Les 4 paramètres (p, q, g, pub) du DSA qui sont chez moi N 32bits MAIS ce sont en fait 4 entiers 1024bits (je ne suis pas expert crypto )...

Du coup, les transferts qui se faisait :

for (i = 0; i < 32; i++)
xPub->d[i] = pulClefPublique[i];

doivent être fait :

for (i = 0; i < 32; i=i+2)
{
xPub->d[i/2] = pulClefPublique[i+1];
xPub->d[i/2] =<< 32;
xPub->d[i/2] += pulClefPublique[i];
}

idem pour les tailles => 16

Voilou...
0