diff -ruPN orig/src/network/ssl/qsslcertificate.cpp new/src/network/ssl/qsslcertificate.cpp --- orig/src/network/ssl/qsslcertificate.cpp 2012-03-13 16:05:25.585777631 +0100 +++ new/src/network/ssl/qsslcertificate.cpp 2012-03-14 15:33:01.753715567 +0100 @@ -489,6 +489,10 @@ key.d->dsa = q_EVP_PKEY_get1_DSA(pkey); key.d->algorithm = QSsl::Dsa; key.d->isNull = false; + } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_EC) { + key.d->ec = q_EVP_PKEY_get1_EC_KEY(pkey); + key.d->algorithm = QSsl::Ec; + key.d->isNull = false; } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) { // DH unsupported } else { diff -ruPN orig/src/network/ssl/qssl.cpp new/src/network/ssl/qssl.cpp --- orig/src/network/ssl/qssl.cpp 2012-03-13 16:05:25.585777631 +0100 +++ new/src/network/ssl/qssl.cpp 2012-03-14 15:33:01.754715560 +0100 @@ -70,6 +70,7 @@ \value Rsa The RSA algorithm. \value Dsa The DSA algorithm. + \value Ec The Elliptic Curve algorithm */ /*! diff -ruPN orig/src/network/ssl/qssl.h new/src/network/ssl/qssl.h --- orig/src/network/ssl/qssl.h 2012-03-13 16:05:25.585777631 +0100 +++ new/src/network/ssl/qssl.h 2012-03-14 15:33:01.753715567 +0100 @@ -65,7 +65,8 @@ enum KeyAlgorithm { Rsa, - Dsa + Dsa, + Ec }; enum AlternateNameEntryType { diff -ruPN orig/src/network/ssl/qsslkey.cpp new/src/network/ssl/qsslkey.cpp --- orig/src/network/ssl/qsslkey.cpp 2012-03-13 16:05:25.585777631 +0100 +++ new/src/network/ssl/qsslkey.cpp 2012-03-14 15:33:01.754715560 +0100 @@ -89,6 +89,11 @@ q_DSA_free(dsa); dsa = 0; } + if (ec) { + if (deep) + q_EC_KEY_free(ec); + ec = 0; + } } /*! @@ -127,12 +132,18 @@ : q_PEM_read_bio_RSAPrivateKey(bio, &rsa, 0, phrase); if (rsa && rsa == result) isNull = false; - } else { + } else if (algorithm == QSsl::Dsa) { DSA *result = (type == QSsl::PublicKey) ? q_PEM_read_bio_DSA_PUBKEY(bio, &dsa, 0, phrase) : q_PEM_read_bio_DSAPrivateKey(bio, &dsa, 0, phrase); if (dsa && dsa == result) isNull = false; + } else if (algorithm == QSsl::Ec) { + EC_KEY *result = (type == QSsl::PublicKey) + ? q_PEM_read_bio_EC_PUBKEY(bio, &ec, 0, phrase) + : q_PEM_read_bio_ECPrivateKey(bio, &ec, 0, phrase); + if (ec && ec == result) + isNull = false; } q_BIO_free(bio); @@ -317,8 +328,12 @@ { if (d->isNull) return -1; - return (d->algorithm == QSsl::Rsa) - ? q_BN_num_bits(d->rsa->n) : q_BN_num_bits(d->dsa->p); + switch(d->algorithm) { + case QSsl::Rsa: return q_BN_num_bits(d->rsa->n); + case QSsl::Dsa: return q_BN_num_bits(d->dsa->p); + case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(d->ec)); + default: return -1; + } } /*! @@ -379,7 +394,7 @@ fail = true; } } - } else { + } else if(d->algorithm == QSsl::Dsa) { if (d->type == QSsl::PublicKey) { if (!q_PEM_write_bio_DSA_PUBKEY(bio, d->dsa)) fail = true; @@ -392,6 +407,21 @@ fail = true; } } + } else if(d->algorithm == QSsl::Ec) { + if (d->type == QSsl::PublicKey) { + if (!q_PEM_write_bio_EC_PUBKEY(bio, d->ec)) + fail = true; + } else { + if (!q_PEM_write_bio_ECPrivateKey( + bio, d->ec, + // ### the cipher should be selectable in the API: + passPhrase.isEmpty() ? (const EVP_CIPHER *)0 : q_EVP_des_ede3_cbc(), + (uchar *)passPhrase.data(), passPhrase.size(), 0, 0)) { + fail = true; + } + } + } else { + fail = true; } QByteArray pem; @@ -417,7 +447,12 @@ */ Qt::HANDLE QSslKey::handle() const { - return (d->algorithm == QSsl::Rsa) ? Qt::HANDLE(d->rsa) : Qt::HANDLE(d->dsa); + switch (d->algorithm) { + case QSsl::Rsa: return Qt::HANDLE(d->rsa); + case QSsl::Dsa: return Qt::HANDLE(d->dsa); + case QSsl::Ec: return Qt::HANDLE(d->ec); + default: return Qt::HANDLE(0); + }; } /*! @@ -450,7 +485,7 @@ { debug << "QSslKey(" << (key.type() == QSsl::PublicKey ? "PublicKey" : "PrivateKey") - << ", " << (key.algorithm() == QSsl::Rsa ? "RSA" : "DSA") + << ", " << (key.algorithm() == QSsl::Rsa ? "RSA" : ((key.algorithm() == QSsl::Dsa) ? "DSA" : "EC")) << ", " << key.length() << ')'; return debug; diff -ruPN orig/src/network/ssl/qsslkey_p.h new/src/network/ssl/qsslkey_p.h --- orig/src/network/ssl/qsslkey_p.h 2012-03-13 16:05:25.586777623 +0100 +++ new/src/network/ssl/qsslkey_p.h 2012-03-14 15:33:01.753715567 +0100 @@ -58,6 +58,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -67,6 +68,7 @@ inline QSslKeyPrivate() : rsa(0) , dsa(0) + , ec(0) { clear(); } @@ -88,6 +90,7 @@ QSsl::KeyAlgorithm algorithm; RSA *rsa; DSA *dsa; + EC_KEY* ec; QAtomicInt ref; diff -ruPN orig/src/network/ssl/qsslsocket_openssl.cpp new/src/network/ssl/qsslsocket_openssl.cpp --- orig/src/network/ssl/qsslsocket_openssl.cpp 2012-03-13 16:05:25.586777623 +0100 +++ new/src/network/ssl/qsslsocket_openssl.cpp 2012-03-14 15:33:01.754715560 +0100 @@ -426,8 +426,10 @@ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. if (configuration.privateKey.algorithm() == QSsl::Rsa) q_EVP_PKEY_set1_RSA(pkey, (RSA *)configuration.privateKey.handle()); - else + else if (configuration.privateKey.algorithm() == QSsl::Dsa) q_EVP_PKEY_set1_DSA(pkey, (DSA *)configuration.privateKey.handle()); + else + q_EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY *)configuration.privateKey.handle()); if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) { q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(getErrorsFromOpenSsl())); emit q->error(QAbstractSocket::UnknownSocketError); diff -ruPN orig/src/network/ssl/qsslsocket_openssl_symbols.cpp new/src/network/ssl/qsslsocket_openssl_symbols.cpp --- orig/src/network/ssl/qsslsocket_openssl_symbols.cpp 2012-03-13 16:05:25.585777631 +0100 +++ new/src/network/ssl/qsslsocket_openssl_symbols.cpp 2012-03-14 15:33:01.754715560 +0100 @@ -110,11 +110,14 @@ DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return) DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return) DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return) +DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return) +DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return) DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG) DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG) DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG) DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) +DEFINEFUNC(void, EC_KEY_free, EC_KEY *a, a, return, DUMMYARG) #if OPENSSL_VERSION_NUMBER < 0x00908000L DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, unsigned char **b, b, long c, c, return 0, return) #else // 0.9.8 broke SC and BC by changing this signature. @@ -126,9 +129,11 @@ DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) +DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return) DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return) DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return) +DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return 0, return) DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) @@ -140,13 +145,17 @@ #else DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) #endif DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) +DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG) DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return) DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) @@ -278,8 +287,10 @@ #ifdef SSLEAY_MACROS DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return) DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return) +DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return) DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return) DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return) +DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return) #endif DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG) DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) @@ -683,6 +694,8 @@ RESOLVEFUNC(BIO_read) RESOLVEFUNC(BIO_s_mem) RESOLVEFUNC(BIO_write) + RESOLVEFUNC(EC_KEY_get0_group) + RESOLVEFUNC(EC_GROUP_get_degree) RESOLVEFUNC(BN_num_bits) RESOLVEFUNC(CRYPTO_free) RESOLVEFUNC(CRYPTO_num_locks) @@ -695,9 +708,11 @@ RESOLVEFUNC(EVP_PKEY_assign) RESOLVEFUNC(EVP_PKEY_set1_RSA) RESOLVEFUNC(EVP_PKEY_set1_DSA) + RESOLVEFUNC(EVP_PKEY_set1_EC_KEY) RESOLVEFUNC(EVP_PKEY_free) RESOLVEFUNC(EVP_PKEY_get1_DSA) RESOLVEFUNC(EVP_PKEY_get1_RSA) + RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) RESOLVEFUNC(EVP_PKEY_new) RESOLVEFUNC(EVP_PKEY_type) RESOLVEFUNC(OBJ_nid2sn) @@ -707,16 +722,21 @@ #else RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) + RESOLVEFUNC(PEM_read_bio_ECPrivateKey) RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) + RESOLVEFUNC(PEM_write_bio_ECPrivateKey) #endif RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) RESOLVEFUNC(RAND_seed) RESOLVEFUNC(RAND_status) RESOLVEFUNC(RSA_free) + RESOLVEFUNC(EC_KEY_free) RESOLVEFUNC(sk_free) RESOLVEFUNC(sk_num) RESOLVEFUNC(sk_pop_free) diff -ruPN orig/src/network/ssl/qsslsocket_openssl_symbols_p.h new/src/network/ssl/qsslsocket_openssl_symbols_p.h --- orig/src/network/ssl/qsslsocket_openssl_symbols_p.h 2012-03-13 16:05:25.586777623 +0100 +++ new/src/network/ssl/qsslsocket_openssl_symbols_p.h 2012-03-14 15:33:01.753715567 +0100 @@ -213,11 +213,14 @@ BIO_METHOD *q_BIO_s_mem(); int q_BIO_write(BIO *a, const void *b, int c); int q_BN_num_bits(const BIGNUM *a); +const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k); +int q_EC_GROUP_get_degree(const EC_GROUP* g); int q_CRYPTO_num_locks(); void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int)); void q_CRYPTO_set_id_callback(unsigned long (*a)()); void q_CRYPTO_free(void *a); void q_DSA_free(DSA *a); +void q_EC_KEY_free(EC_KEY *a); #if OPENSSL_VERSION_NUMBER >= 0x00908000L // 0.9.8 broke SC and BC by changing this function's signature. X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c); @@ -230,9 +233,11 @@ int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c); int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); +int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b); void q_EVP_PKEY_free(EVP_PKEY *a); RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a); +EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a); int q_EVP_PKEY_type(int a); EVP_PKEY *q_EVP_PKEY_new(); int q_i2d_X509(X509 *a, unsigned char **b); @@ -246,15 +251,20 @@ #else DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); +EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d, int e, pem_password_cb *f, void *g); int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d, int e, pem_password_cb *f, void *g); +int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); #endif DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d); RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d); +EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b); int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b); +int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); void q_RAND_seed(const void *a, int b); int q_RAND_status(); void q_RSA_free(RSA *a);