2012-06-19 10 views
14

Tengo dificultades para ejecutar un servidor M2Crypto SSLSer con cifras de clasificación EXPORT.Cifrados EXP (ORT) y M2Crypto/OpenSSL

Las cifras de BAJO/MEDIO/ALTO funcionan sin ningún problema, pero EXPORT simplemente no lo hará. Además, cuando OpenSSL se ejecuta en un modo de servidor desde una línea de comando, acepta cifras de clasificación EXPORT sin ningún problema.

Entonces, me falta algo o hay un problema en un módulo M2Crypto. Cualquier ayuda es apreciada.

código de Python utilizados (ssl-server.py) tiene el siguiente aspecto:

import M2Crypto 
import socket 

CERTFILE = "dummy_cert.pem" 
KEYFILE = "dummy_key.pem" 
PROTOCOL = "sslv3" 
HOST = "0.0.0.0" 
PORT = 4433 

def main(): 
    print "[i] Initializing context ..." 
    ctx = M2Crypto.SSL.Context(protocol=PROTOCOL, weak_crypto=True) 
    ctx.load_cert_chain(certchainfile=CERTFILE, keyfile=KEYFILE) 
    ctx.set_options(M2Crypto.m2.SSL_OP_ALL) 
    ctx.set_cipher_list("ALL") 

    print "[i] Initializing socket ..." 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.bind((HOST, PORT)) 
    sock.listen(1) 
    conn, addr = sock.accept() 

    print "[i] SSL handshake ..." 
    ssl_conn = M2Crypto.SSL.Connection(ctx=ctx, sock=conn) 
    ssl_conn.setup_ssl() 
    try: 
     ssl_conn_res = ssl_conn.accept_ssl() 
    except Exception, ex: 
     print "[x] SSL connection failed: '%s'" % str(ex) 
    else: 
     if ssl_conn_res == 1: 
      print "[i] SSL connection accepted" 
     else: 
      print "[x] SSL handshake failed: '%s'" % ssl_conn.ssl_get_error(ssl_conn_res) 

if __name__ == "__main__": 
    main() 

Los síntomas son:

$ uname -a 
Linux XYZ 2.6.38-15-generiC#59-Ubuntu SMP Fri Apr 27 16:03:32 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux 

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu 
DISTRIB_RELEASE=11.04 
DISTRIB_CODENAME=natty 
DISTRIB_DESCRIPTION="Ubuntu 11.04" 

$ python -c "import M2Crypto;print M2Crypto.version_info" 
(0, 20, 1) 

$ openssl version 
OpenSSL 0.9.8o 01 Jun 2010 

1) NOT OK 
SERVER (terminal 1): $ python ssl-server.py 
CLIENT (terminal 2): $ openssl s_client -connect localhost:4433 -cipher EXPORT 
CONNECTED(00000003) 
28131:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:602: 

2) OK 
SERVER (terminal 1): $ openssl s_server -cert dummy_cert.pem -key dummy_key.pem -ssl3 -no_tls1 -no_ssl2 -cipher EXPORT 
CLIENT (terminal 2): $ openssl s_client -connect localhost:4433 -cipher EXPORT 
CONNECTED(00000003) 
depth=0 C = BE, CN = www.example.com 
verify error:num=20:unable to get local issuer certificate 
verify return:1 
depth=0 C = BE, CN = www.example.com 
verify error:num=27:certificate not trusted 
verify return:1 
depth=0 C = BE, CN = www.example.com 
verify error:num=21:unable to verify the first certificate 
verify return:1 
--- 
Certificate chain 
0 s:/C=BE/CN=www.example.com 
    i:/C=BE/CN=test-ca 
--- 
Server certificate 
-----BEGIN CERTIFICATE----- 
... 
-----END CERTIFICATE----- 
subject=/C=BE/CN=www.example.com 
issuer=/C=BE/CN=test-ca 
--- 
No client certificate CA names sent 
--- 
SSL handshake has read 1141 bytes and written 242 bytes 
--- 
New, TLSv1/SSLv3, Cipher is EXP-EDH-RSA-DES-CBC-SHA 
Server public key is 1024 bit 
Secure Renegotiation IS supported 
Compression: zlib compression 
Expansion: zlib compression 
SSL-Session: 
    Protocol : SSLv3 
    Cipher : EXP-EDH-RSA-DES-CBC-SHA 
    Session-ID: B052D5D5A436F9A0B9D3FB24F2E32A8A06A0B6828230621C4CFAEB82A0A9AE0C 
    Session-ID-ctx: 
    Master-Key:  47F6E3720D06518B961FE389F13BCDE42C37F703099ABBB9B3DA35383C420F519D4F4773D35E470CF6FF7BB243B29069 
    Key-Arg : None 
    PSK identity: None 
    PSK identity hint: None 
    SRP username: None 
    Compression: 1 (zlib compression) 
    Start Time: 1340644713 
    Timeout : 300 (sec) 
    Verify return code: 21 (unable to verify the first certificate) 
--- 

contenido de un dummy_cert.pem es el siguiente:

-----BEGIN CERTIFICATE----- 
MIICkTCCAfqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJCRTEQ 
MA4GA1UEAxMHdGVzdC1jYTAeFw0xMjA1MDYwODQyNDlaFw0yMjA1MDMwODQyNDla 
MCcxCzAJBgNVBAYTAkJFMRgwFgYDVQQDEw93d3cuZXhhbXBsZS5jb20wgZ8wDQYJ 
KoZIhvcNAQEBBQADgY0AMIGJAoGBAL7OBv9wRwtNjN984XSy22/rw6tHM6Lq/Ccf 
NoHKbqwC+PsxgmgJJiGBGewrzBR42toqHJi7EjHhuvrgqV9s2duPQBAANh7tzY1h 
6VekrwhIIt4o1h0F2KB16VXA8s918d+8pRGt2T11GUh/QT3m9yY1VzqdIBeAfklC 
ET6ncPK/AgMBAAGjgdQwgdEwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAw 
KwYJYIZIAYb4QgENBB4WHFRpbnlDQSBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD 
VR0OBBYEFNGQArEZPKprJTn7A64qEFfl0m4xME8GA1UdIwRIMEaAFFuITOUJlGrJ 
9lKufs8cm1MpwXrroSOkITAfMQswCQYDVQQGEwJCRTEQMA4GA1UEAxMHdGVzdC1j 
YYIJALimgW7YUgdrMAkGA1UdEgQCMAAwCQYDVR0RBAIwADANBgkqhkiG9w0BAQUF 
AAOBgQDWh8A0eBxI9XHy68xdjFsk2oerJeV6qqlcmtPZgz3GlarRcWcKsRJOyLLL 
dCOe7tY5isWQAoLt6XALzDWjbQkTJnxBaKHif1MIikuajaYKT7LA1MvFn50Qrm6n 
f9hG7gvdTpm1rlPcs0qibp1vJVubkU51mT6JT4UnLfeVIjtL7Q== 
-----END CERTIFICATE----- 

contenido de un dummy_key.pem es el siguiente:

-----BEGIN RSA PRIVATE KEY----- 
MIICXgIBAAKBgQC+zgb/cEcLTYzffOF0sttv68OrRzOi6vwnHzaBym6sAvj7MYJo 
CSYhgRnsK8wUeNraKhyYuxIx4br64KlfbNnbj0AQADYe7c2NYelXpK8ISCLeKNYd 
BdigdelVwPLPdfHfvKURrdk9dRlIf0E95vcmNVc6nSAXgH5JQhE+p3DyvwIDAQAB 
AoGBAIZldIRkP4Z0n2+j9OJQQUS6Wl7AjlyJDAc6cxhE0GOUzG+S1foVx6f92ZaC 
2wLoha75zp691fkQuLWRnXu7nk9QwxQdOppKijIPHdL2cYtUc9UCedN5rExjpcOP 
4Hjwf17YOxK2J0zzmG1djTBB47BKGUedSQ7E1QxGcrESS2XxAkEA+6ey2jy8etWi 
QmCdJJIxXwKRVHCmt5LVwj+IOk/u3sr1AGfBm7spKGU3boCiFt4FmjGMax7B9r/e 
zPaMb34guwJBAMIZX7Vv5gfjvWtgp6pyE/UkjRSOKBpuy9gyiqtLBJwehj/qsBqr 
O6tFmjMFiudVusnVSrEFGAPLV52xf0U4580CQQDkEQ1UH2spX2dYBLslo6A+3NLc 
1eMhx18WVgGd50cyfnkfzuh1vF8GjwR3jvhXBQvKvFDn284pU6YV1vNbL9F1AkEA 
o2CwSwyRV3q+6i9Fchbr7aCCkBbIctdoBeclCeHvU2nuHsbwzMHtS9EeZmv365kh 
zNoYMMDU4fy7FyVct2ua0QJASXtIwYKZ2CAP+lAQqfh+knRRqtqdLt4Lt0mpML5m 
UtsECS8frKeF3mynXfsyRkvC8F2WFiJVJ3+D+y3zYNGlZg== 
-----END RSA PRIVATE KEY----- 

actualización: en el nivel bajo de paquetes handshake parece ser el mismo, salvo que el campo random[32] hacer esto aún más extraña.

volcado SSL (ssldump -a -A -H -i lo) para ambos casos se puede encontrar aquí:

http://pastebin.com/YuC7d8zg (caso NO OK)

http://pastebin.com/U6YGQmv9 (OK caso)

+0

Su PKI no se ha configurado correctamente, su caso OK solo muestra una conexión SSL anónima, lo que no debe permitirse. Su servidor no envía ningún certificado al cliente. Tenga en cuenta que la depuración a través de las pilas SSL es un poco demasiado para este foro; a menudo contiene muchas iteraciones try/test/retry que realmente no se pueden representar bien stackoverflow, y tienden a tomar mucho tiempo. –

+0

Estamos tratando de reproducir ese caso OK (openssl s_server) programáticamente con M2Crypto. PKI es irrelevante aquí. En el caso de OK, el cifrado EXPORT se elige mientras que en M2Crypto no. La cosa es que todo funciona correctamente con BAJO, MEDIO y ALTO, pero no con EXPORTACIÓN. – stamparm

+0

Solo me preguntaba por qué querría usar los códigos de EXPORTACIÓN en primer lugar. [Se consideran suficientemente débiles como para haber sido prohibidos en TLS 1.1] (http://tools.ietf.org/html/rfc4346#appendix-A.5) (finalizado hace 6 años): "* Los clientes de TLS 1.1 DEBEN consultar que el servidor no eligió uno de estos conjuntos de cifrado durante el protocolo de enlace. * " – Bruno

Respuesta

5

necesitaba los siguientes dos ajustes a la secuencia de comandos de Python para que funcione con la exportación de cifrado:

PROTOCOL = "sslv23" 
... 
    print "[i] Initializing context ..." 
    ctx = M2Crypto.SSL.Context(protocol=PROTOCOL, weak_crypto=True) 
    ctx.load_cert_chain(certchainfile=CERTFILE, keyfile=KEYFILE) 
    ctx.set_options(M2Crypto.m2.SSL_OP_ALL) 
    ctx.set_tmp_rsa(M2Crypto.RSA.gen_key(512, 65537)) 
    ctx.set_cipher_list("ALL") 

es decir:

  1. Use SSLv23 como identificador de protocolo (modo compatible SSLv2/v3). No estoy seguro de por qué es necesario en este caso, pero parece que no funciona de otra manera.
  2. Establezca una clave RSA temporaria y efímera en el contexto usando set_tmp_rsa(). Esto es necesario porque con cifras de exportación, la clave RSA (1024 bits) proporcionada solo se utiliza para la autenticación (firma), mientras que una clave RSA temporal de 512 bits limitada a la exportación se utiliza para la confidencialidad (cifrado). OpenSSL requiere que configure esta clave en el contexto (consulte documentation of SSL_set_tmp_rsa()).

Extrañamente, también funciona en modo de sólo SSLv2 (usando -ssl2 en openssl s_client cuando se prueba) sin establecer una clave temporal RSA (llamado a la set_tmp_rsa comentado en el guión). No tengo ni idea de porqué.

En general, algunas suites de cifrado requieren que se agreguen claves especiales al contexto, p. suites que usan DH (parámetros de grupo) o ECDH (curva). Para ver exactamente qué se usa para cada conjunto de cifrado, openssl ciphers -v puede ser útil, por ejemplo.:

% openssl ciphers -v EXPORT 
EXP-EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH(512) Au=RSA Enc=DES(40) Mac=SHA1 export 
EXP-EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH(512) Au=DSS Enc=DES(40) Mac=SHA1 export 
EXP-ADH-DES-CBC-SHA  SSLv3 Kx=DH(512) Au=None Enc=DES(40) Mac=SHA1 export 
EXP-DES-CBC-SHA   SSLv3 Kx=RSA(512) Au=RSA Enc=DES(40) Mac=SHA1 export 
EXP-RC2-CBC-MD5   SSLv3 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export 
EXP-RC2-CBC-MD5   SSLv2 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export 
EXP-ADH-RC4-MD5   SSLv3 Kx=DH(512) Au=None Enc=RC4(40) Mac=MD5 export 
EXP-RC4-MD5    SSLv3 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export 
EXP-RC4-MD5    SSLv2 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export 

EDITAR en Respone a la pregunta sobre DSS conjuntos de cifrado:

DSS/DSA de cifrado necesitan parámetros DH, y por supuesto un/certificado de servidor basado DSA DSS en lugar de (sólo) una RSA uno. Esto es cierto no solo para las suites de cifrado de exportación, sino también para todas las suites que usan DSS/DSA para la autenticidad. DSS/DSA solo puede utilizarse, por diseño, para firmas, no para el cifrado, a fin de permitir la exportación a países que no son de confianza. Debido a que DSS/DSA solo se puede usar para firmas, se necesita un intercambio efímero de claves Diffie-Hellman para establecer una clave de sesión compartida. Eso es lo que significa el EDH en la suite de cifrado. Para configurar los parámetros DH, usaría los equivalentes M2Crypto de la API OpenSSL SSL_set_tmp_dh().

Tenga en cuenta que OpenSSL permite cargar un certificado/par de llaves RSA y DSA/DSS en el mismo contexto SSL.

+0

Hola, Daniel. Gracias por su respuesta. Todavía hay una (sub) pregunta relacionada para aclarar todo esto. El cifrado "EXP-EDH-DSS-DES-CBC-SHA" necesita probablemente DSS params para ser configurado pero no podemos encontrar la función apropiada dentro de M2Crypto/OpenSSL para hacerlo (como set_tmp_rsa() y/o set_tmp_dh() se usan en otros casos). Sería grandioso si tú (u otra persona) pudieras indicarnos en la dirección correcta cómo hacerlo. – stamparm

+0

Necesita configurar parámetros DH para suites de cifrado DSS, consulte mi edición anterior. Y, por supuesto, un certificado de servidor DSS, no (solo) uno de RSA. –

+0

Muchas gracias Daniel. Tu respuesta fue de gran ayuda – stamparm

Cuestiones relacionadas