diff options
author | André Klitzing <aklitzing@gmail.com> | 2014-11-18 10:18:18 +0100 |
---|---|---|
committer | André Klitzing <aklitzing@gmail.com> | 2015-01-18 10:18:43 +0100 |
commit | 962ea5690cb9351822c30da534ecae7aeeba667d (patch) | |
tree | c3fef960ae04c61bd55426cc05c7a910b8b48f52 /src/network/ssl/qsslkey_openssl.cpp | |
parent | a6a865e24999bf878f6f80341b7fc14f2b67a05e (diff) |
Add elliptic curve support to QSsl
Add possibility to get length and other information of EC based
certificates. Also it is possible to parse those public/private
keys from PEM and DER encoded files.
Based on patch by Remco Bloemen
[ChangeLog][QtNetwork][SSL/TLS support] It is now possible to
parse elliptic curve certificates.
Change-Id: I4b11f726296aecda89c3cbd195d7c817ae6fc47b
Task-number: QTBUG-18972
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/network/ssl/qsslkey_openssl.cpp')
-rw-r--r-- | src/network/ssl/qsslkey_openssl.cpp | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index e4d30ff229..ee4e8efa7c 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -70,6 +70,13 @@ void QSslKeyPrivate::clear(bool deep) q_DSA_free(dsa); dsa = 0; } +#ifndef OPENSSL_NO_EC + if (ec) { + if (deep) + q_EC_KEY_free(ec); + ec = 0; + } +#endif if (opaque) { if (deep) q_EVP_PKEY_free(opaque); @@ -99,6 +106,16 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey) return true; } +#ifndef OPENSSL_NO_EC + else if (pkey->type == EVP_PKEY_EC) { + isNull = false; + algorithm = QSsl::Ec; + type = QSsl::PrivateKey; + ec = q_EC_KEY_dup(q_EVP_PKEY_get1_EC_KEY(pkey)); + + return true; + } +#endif else { // Unknown key type. This could be handled as opaque, but then // we'd eventually leak memory since we wouldn't be able to free @@ -138,12 +155,20 @@ void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhra : 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; +#ifndef OPENSSL_NO_EC + } 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; +#endif } q_BIO_free(bio); @@ -154,8 +179,14 @@ int QSslKeyPrivate::length() const if (isNull || algorithm == QSsl::Opaque) return -1; - return (algorithm == QSsl::Rsa) - ? q_BN_num_bits(rsa->n) : q_BN_num_bits(dsa->p); + switch (algorithm) { + case QSsl::Rsa: return q_BN_num_bits(rsa->n); + case QSsl::Dsa: return q_BN_num_bits(dsa->p); +#ifndef OPENSSL_NO_EC + case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(ec)); +#endif + default: return -1; + } } QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const @@ -182,7 +213,7 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const fail = true; } } - } else { + } else if (algorithm == QSsl::Dsa) { if (type == QSsl::PublicKey) { if (!q_PEM_write_bio_DSA_PUBKEY(bio, dsa)) fail = true; @@ -195,6 +226,23 @@ QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const fail = true; } } +#ifndef OPENSSL_NO_EC + } else if (algorithm == QSsl::Ec) { + if (type == QSsl::PublicKey) { + if (!q_PEM_write_bio_EC_PUBKEY(bio, ec)) + fail = true; + } else { + if (!q_PEM_write_bio_ECPrivateKey( + bio, 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; + } + } +#endif + } else { + fail = true; } QByteArray pem; @@ -216,6 +264,10 @@ Qt::HANDLE QSslKeyPrivate::handle() const return Qt::HANDLE(rsa); case QSsl::Dsa: return Qt::HANDLE(dsa); +#ifndef OPENSSL_NO_EC + case QSsl::Ec: + return Qt::HANDLE(ec); +#endif default: return Qt::HANDLE(NULL); } |