#include #include "util.h" #include #include #include "Log.h" #include "Crypto.h" #include "Family.h" namespace i2p { namespace data { Families::Families () { } Families::~Families () { } void Families::LoadCertificate (const std::string& filename) { SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ()); int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) { SSL * ssl = SSL_new (ctx); X509 * cert = SSL_get_certificate (ssl); if (cert) { std::shared_ptr verifier; // extract issuer name char name[100]; X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); char * cn = strstr (name, "CN="); if (cn) { cn += 3; char * family = strstr (cn, ".family"); if (family) family[0] = 0; } auto pkey = X509_get_pubkey (cert); int keyType = EVP_PKEY_type(pkey->type); switch (keyType) { case EVP_PKEY_DSA: // TODO: break; case EVP_PKEY_EC: { EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); if (ecKey) { auto group = EC_KEY_get0_group (ecKey); if (group) { int curve = EC_GROUP_get_curve_name (group); if (curve == NID_X9_62_prime256v1) { uint8_t signingKey[64]; BIGNUM * x = BN_new(), * y = BN_new(); EC_POINT_get_affine_coordinates_GFp (group, EC_KEY_get0_public_key (ecKey), x, y, NULL); i2p::crypto::bn2buf (x, signingKey, 32); i2p::crypto::bn2buf (y, signingKey + 32, 32); BN_free (x); BN_free (y); verifier = std::make_shared(signingKey); } else LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); } EC_KEY_free (ecKey); } break; } default: LogPrint (eLogWarning, "Family: Certificate key type ", keyType, " is not supported"); } EVP_PKEY_free (pkey); if (verifier && cn) m_SigningKeys[cn] = verifier; } SSL_free (ssl); } else LogPrint (eLogError, "Family: Can't open certificate file ", filename); SSL_CTX_free (ctx); } void Families::LoadCertificates () { boost::filesystem::path familyDir = i2p::util::filesystem::GetCertificatesDir() / "family"; if (!boost::filesystem::exists (familyDir)) return; int numCertificates = 0; boost::filesystem::directory_iterator end; // empty for (boost::filesystem::directory_iterator it (familyDir); it != end; ++it) { if (boost::filesystem::is_regular_file (it->status()) && it->path ().extension () == ".crt") { LoadCertificate (it->path ().string ()); numCertificates++; } } if (numCertificates > 0) LogPrint (eLogInfo, "Family: ", numCertificates, " certificates loaded"); } bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, const char * signature, const char * key) { uint8_t buf[50], signatureBuf[64]; size_t len = family.length (), signatureLen = strlen (signature); memcpy (buf, family.c_str (), len); memcpy (buf + len, (const uint8_t *)ident, 32); len += 32; Base64ToByteStream (signature, signatureLen, signatureBuf, 64); auto it = m_SigningKeys.find (family); if (it != m_SigningKeys.end ()) return it->second->Verify (buf, len, signatureBuf); // TODO: process key return true; } } }