123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- //
- // ECKeyImpl.cpp
- //
- //
- // Library: Crypto
- // Package: EC
- // Module: ECKeyImpl
- //
- // Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
- // and Contributors.
- //
- // SPDX-License-Identifier: BSL-1.0
- //
- #include "Poco/Crypto/ECKeyImpl.h"
- #include "Poco/Crypto/X509Certificate.h"
- #include "Poco/Crypto/PKCS12Container.h"
- #include "Poco/FileStream.h"
- #include "Poco/Format.h"
- #include "Poco/StreamCopier.h"
- #include <sstream>
- #include <openssl/evp.h>
- #if OPENSSL_VERSION_NUMBER >= 0x00908000L
- #include <openssl/bn.h>
- #endif
- namespace Poco {
- namespace Crypto {
- ECKeyImpl::ECKeyImpl(const EVPPKey& key):
- KeyPairImpl("ec", KT_EC_IMPL),
- _pEC(EVP_PKEY_get1_EC_KEY(const_cast<EVP_PKEY*>((const EVP_PKEY*)key)))
- {
- checkEC("ECKeyImpl(const EVPPKey&)", "EVP_PKEY_get1_EC_KEY()");
- }
- ECKeyImpl::ECKeyImpl(const X509Certificate& cert):
- KeyPairImpl("ec", KT_EC_IMPL),
- _pEC(0)
- {
- const X509* pCert = cert.certificate();
- if (pCert)
- {
- EVP_PKEY* pKey = X509_get_pubkey(const_cast<X509*>(pCert));
- if (pKey)
- {
- _pEC = EVP_PKEY_get1_EC_KEY(pKey);
- EVP_PKEY_free(pKey);
- checkEC("ECKeyImpl(const const X509Certificate&)", "EVP_PKEY_get1_EC_KEY()");
- return;
- }
- }
- throw OpenSSLException("ECKeyImpl(const X509Certificate&)");
- }
- ECKeyImpl::ECKeyImpl(const PKCS12Container& cont):
- KeyPairImpl("ec", KT_EC_IMPL),
- _pEC(EVP_PKEY_get1_EC_KEY(cont.getKey()))
- {
- checkEC("ECKeyImpl(const PKCS12Container&)", "EVP_PKEY_get1_EC_KEY()");
- }
- ECKeyImpl::ECKeyImpl(int curve):
- KeyPairImpl("ec", KT_EC_IMPL),
- _pEC(EC_KEY_new_by_curve_name(curve))
- {
- poco_check_ptr(_pEC);
- EC_KEY_set_asn1_flag(_pEC, OPENSSL_EC_NAMED_CURVE);
- if (!(EC_KEY_generate_key(_pEC)))
- throw OpenSSLException("ECKeyImpl(int curve): EC_KEY_generate_key()");
- checkEC("ECKeyImpl(int curve)", "EC_KEY_generate_key()");
- }
- ECKeyImpl::ECKeyImpl(const std::string& publicKeyFile,
- const std::string& privateKeyFile,
- const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
- {
- if (EVPPKey::loadKey(&_pEC, PEM_read_PrivateKey, EVP_PKEY_get1_EC_KEY, privateKeyFile, privateKeyPassphrase))
- {
- checkEC(Poco::format("ECKeyImpl(%s, %s, %s)",
- publicKeyFile, privateKeyFile, privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
- "PEM_read_PrivateKey() or EVP_PKEY_get1_EC_KEY()");
- return; // private key is enough
- }
- // no private key, this must be public key only, otherwise throw
- if (!EVPPKey::loadKey(&_pEC, PEM_read_PUBKEY, EVP_PKEY_get1_EC_KEY, publicKeyFile))
- {
- throw OpenSSLException("ECKeyImpl(const string&, const string&, const string&");
- }
- checkEC(Poco::format("ECKeyImpl(%s, %s, %s)",
- publicKeyFile, privateKeyFile, privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
- "PEM_read_PUBKEY() or EVP_PKEY_get1_EC_KEY()");
- }
- ECKeyImpl::ECKeyImpl(std::istream* pPublicKeyStream,
- std::istream* pPrivateKeyStream,
- const std::string& privateKeyPassphrase): KeyPairImpl("ec", KT_EC_IMPL), _pEC(0)
- {
- if (EVPPKey::loadKey(&_pEC, PEM_read_bio_PrivateKey, EVP_PKEY_get1_EC_KEY, pPrivateKeyStream, privateKeyPassphrase))
- {
- checkEC(Poco::format("ECKeyImpl(stream, stream, %s)",
- privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
- "PEM_read_bio_PrivateKey() or EVP_PKEY_get1_EC_KEY()");
- return; // private key is enough
- }
- // no private key, this must be public key only, otherwise throw
- if (!EVPPKey::loadKey(&_pEC, PEM_read_bio_PUBKEY, EVP_PKEY_get1_EC_KEY, pPublicKeyStream))
- {
- throw OpenSSLException("ECKeyImpl(istream*, istream*, const string&");
- }
- checkEC(Poco::format("ECKeyImpl(stream, stream, %s)",
- privateKeyPassphrase.empty() ? privateKeyPassphrase : std::string("***")),
- "PEM_read_bio_PUBKEY() or EVP_PKEY_get1_EC_KEY()");
- }
- ECKeyImpl::~ECKeyImpl()
- {
- freeEC();
- }
- void ECKeyImpl::checkEC(const std::string& method, const std::string& func) const
- {
- if (!_pEC) throw OpenSSLException(Poco::format("%s: %s", method, func));
- if (!EC_KEY_check_key(_pEC))
- throw OpenSSLException(Poco::format("%s: EC_KEY_check_key()", method));
- }
- void ECKeyImpl::freeEC()
- {
- if (_pEC)
- {
- EC_KEY_free(_pEC);
- _pEC = 0;
- }
- }
- int ECKeyImpl::size() const
- {
- int sz = -1;
- EVP_PKEY* pKey = EVP_PKEY_new();
- if (pKey && EVP_PKEY_set1_EC_KEY(pKey, _pEC))
- {
- sz = EVP_PKEY_bits(pKey);
- EVP_PKEY_free(pKey);
- return sz;
- }
- throw OpenSSLException("ECKeyImpl::size()");
- }
- int ECKeyImpl::groupId() const
- {
- if (_pEC)
- {
- const EC_GROUP* ecGroup = EC_KEY_get0_group(_pEC);
- if (ecGroup)
- {
- return EC_GROUP_get_curve_name(ecGroup);
- }
- else
- {
- throw OpenSSLException("ECKeyImpl::groupName()");
- }
- }
- throw NullPointerException("ECKeyImpl::groupName() => _pEC");
- }
- std::string ECKeyImpl::getCurveName(int nid)
- {
- std::string curveName;
- size_t len = EC_get_builtin_curves(NULL, 0);
- EC_builtin_curve* pCurves =
- (EC_builtin_curve*) OPENSSL_malloc(sizeof(EC_builtin_curve) * len);
- if (!pCurves) return curveName;
- if (!EC_get_builtin_curves(pCurves, len))
- {
- OPENSSL_free(pCurves);
- return curveName;
- }
- if (-1 == nid) nid = pCurves[0].nid;
- const int bufLen = 128;
- char buf[bufLen];
- std::memset(buf, 0, bufLen);
- OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
- curveName = buf;
- OPENSSL_free(pCurves);
- return curveName;
- }
- int ECKeyImpl::getCurveNID(std::string& name)
- {
- std::string curveName;
- size_t len = EC_get_builtin_curves(NULL, 0);
- EC_builtin_curve* pCurves =
- (EC_builtin_curve*)OPENSSL_malloc(static_cast<int>(sizeof(EC_builtin_curve) * len));
- if (!pCurves) return -1;
- if (!EC_get_builtin_curves(pCurves, len))
- {
- OPENSSL_free(pCurves);
- return -1;
- }
- int nid = -1;
- const int bufLen = 128;
- char buf[bufLen];
- if (name.empty())
- {
- std::memset(buf, 0, bufLen);
- OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(nid), 0);
- name = buf;
- nid = pCurves[0].nid;
- }
- else
- {
- for (int i = 0; i < len; ++i)
- {
- std::memset(buf, 0, bufLen);
- OBJ_obj2txt(buf, bufLen, OBJ_nid2obj(pCurves[i].nid), 0);
- if (strncmp(name.c_str(), buf, name.size() > bufLen ? bufLen : name.size()) == 0)
- {
- nid = pCurves[i].nid;
- break;
- }
- }
- }
- OPENSSL_free(pCurves);
- return nid;
- }
- bool ECKeyImpl::hasCurve(const std::string& name)
- {
- std::string tmp(name);
- return (-1 != getCurveNID(tmp));
- }
- } } // namespace Poco::Crypto
|