#include <openssl/pem.h>
#include <openssl/ec.h>
#include <openssl/err.h>
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+
+#include "rgw/rgw_b64.h"
//If openssl version less than 1.1
#if OPENSSL_VERSION_NUMBER < 269484032
} else
throw rsa_exception("at least one of public or private key need to be present");
}
+
+ rsa(const EVP_MD*(*md)(), const std::string& name) : md(md), alg_name(name)
+ {}
+
+ void setModulusExponentCalcPublicKey(const std::string& modulus, const std::string& exponent)
+ {
+ this->modulus = modulus;
+ this->exponent = exponent;
+ calculatePublicKey();
+ }
+
/**
* Sign jwt data
* \param data The data to sign
std::shared_ptr<EVP_PKEY> pkey;
/// Hash generator
const EVP_MD*(*md)();
+ /// Modulus
+ std::string modulus;
+ /// Exponent
+ std::string exponent;
/// Algorithmname
const std::string alg_name;
+
+ void calculatePublicKey()
+ {
+ std::string n_str = base64_decode_url(modulus);
+ std::string e_str = base64_decode_url(exponent);
+ unsigned char* u_n = (unsigned char *)n_str.c_str();
+ unsigned char* u_e = (unsigned char *)e_str.c_str();
+ BIGNUM *n = BN_bin2bn(u_n, n_str.size(), NULL);
+ BIGNUM *e = BN_bin2bn(u_e, e_str.size(), NULL);
+
+ if (e && n) {
+ EVP_PKEY* pRsaKey = EVP_PKEY_new();
+ RSA* rsa = RSA_new();
+ RSA_set0_key(rsa, n, e, nullptr);
+ EVP_PKEY_assign_RSA(pRsaKey, rsa);
+ std::shared_ptr<EVP_PKEY> p(pRsaKey, EVP_PKEY_free);
+ pkey = p;
+ } else {
+ if (n) BN_free(n);
+ if (e) BN_free(e);
+ throw rsa_exception("Invalid encoding for modulus or exponent\n");
+ }
+ }
+
+ std::string base64_decode_url(const std::string& str) const {
+ std::string s = "====";
+ std::string padded_str = str.length() % 4 == 0 ? str : str + s.substr(0, str.length() % 4);
+ std::replace(padded_str.begin(), padded_str.end(), '_', '/');
+ std::replace(padded_str.begin(), padded_str.end(), '-', '+');
+ return rgw::from_base64(padded_str);
+ }
};
/**
* Base class for ECDSA family of algorithms
explicit rs256(const std::string& public_key, const std::string& private_key = "", const std::string& public_key_password = "", const std::string& private_key_password = "")
: rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha256, "RS256")
{}
+
+ rs256() : rsa(EVP_sha256, "RS256")
+ {}
+
+ rs256& setModulusAndExponent(const std::string& modulus, const std::string& exponent)
+ {
+ rsa::setModulusExponentCalcPublicKey(modulus, exponent);
+ return *this;
+ }
};
/**
* RS384 algorithm
explicit rs384(const std::string& public_key, const std::string& private_key = "", const std::string& public_key_password = "", const std::string& private_key_password = "")
: rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha384, "RS384")
{}
+
+ rs384() : rsa(EVP_sha384, "RS384")
+ {}
+
+ rs384& setModulusAndExponent(const std::string& modulus, const std::string& exponent)
+ {
+ rsa::setModulusExponentCalcPublicKey(modulus, exponent);
+ return *this;
+ }
};
/**
* RS512 algorithm
explicit rs512(const std::string& public_key, const std::string& private_key = "", const std::string& public_key_password = "", const std::string& private_key_password = "")
: rsa(public_key, private_key, public_key_password, private_key_password, EVP_sha512, "RS512")
{}
+
+ rs512() : rsa(EVP_sha512, "RS512")
+ {}
+
+ rs512& setModulusAndExponent(const std::string& modulus, const std::string& exponent)
+ {
+ rsa::setModulusExponentCalcPublicKey(modulus, exponent);
+ return *this;
+ }
};
/**
* ES256 algorithm
return cert_url;
}
+void
+WebTokenEngine::validate_signature_using_n_e(const DoutPrefixProvider* dpp, const jwt::decoded_jwt& decoded, const std::string &algorithm, const std::string& n, const std::string& e) const
+{
+ try {
+ if (algorithm == "RS256") {
+ auto verifier = jwt::verify()
+ .allow_algorithm(jwt::algorithm::rs256().setModulusAndExponent(n,e));
+ verifier.verify(decoded);
+ } else if (algorithm == "RS384") {
+ auto verifier = jwt::verify()
+ .allow_algorithm(jwt::algorithm::rs384().setModulusAndExponent(n,e));
+ verifier.verify(decoded);
+ } else if (algorithm == "RS512") {
+ auto verifier = jwt::verify()
+ .allow_algorithm(jwt::algorithm::rs512().setModulusAndExponent(n,e));
+ verifier.verify(decoded);
+ }
+ } catch (const std::exception& e) {
+ throw std::system_error(EACCES, std::system_category(), std::string("Signature validation using n, e failed: ") + e.what());
+ }
+ ldpp_dout(dpp, 10) << "Verified signature using n and e"<< dendl;
+ return;
+}
+
void
WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::decoded_jwt& decoded, const string& algorithm, const string& iss, const vector<string>& thumbprints, optional_yield y) const
{
throw;
}
} else {
- ldpp_dout(dpp, 0) << "x5c not present" << dendl;
- throw -EINVAL;
+ if (algorithm == "RS256" || algorithm == "RS384" || algorithm == "RS512") {
+ string n, e; //modulus and exponent
+ if (JSONDecoder::decode_json("n", n, &parser) && JSONDecoder::decode_json("e", e, &parser)) {
+ validate_signature_using_n_e(dpp, decoded, algorithm, n, e);
+ return;
+ }
+ ldpp_dout(dpp, 0) << "x5c not present or n, e not present" << dendl;
+ throw std::system_error(EINVAL, std::system_category());
+ } else {
+ throw std::system_error(EINVAL, std::system_category(), "Invalid algorithm: " + algorithm);
+ }
}
} else {
ldpp_dout(dpp, 0) << "Malformed JSON object for keys" << dendl;