forked from soutade/libgourou
v0.2 Fix a lot of things :
* add common method signNode() and addNonde() * Try to auth to operator if not already set * Fix an error in ADEPT protocol : attributes must be hashed in alphabetical order, not in reverse one * Update DRMProcessorClient
This commit is contained in:
parent
7adc6a0fc1
commit
0e90b89382
|
@ -173,6 +173,20 @@ namespace gourou
|
||||||
* @param keyOutLength Length of result
|
* @param keyOutLength Length of result
|
||||||
*/
|
*/
|
||||||
virtual void extractRSAPrivateKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength) = 0;
|
virtual void extractRSAPrivateKey(void* handler, unsigned char** keyOut, unsigned int* keyOutLength) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extract certificate from PKCS12 blob
|
||||||
|
*
|
||||||
|
* @param RSAKey RSA key in binary form
|
||||||
|
* @param RSAKeyLength RSA key length
|
||||||
|
* @param keyType Key type
|
||||||
|
* @param password Optional password for RSA PKCS12 certificate
|
||||||
|
* @param certOut Result certificate
|
||||||
|
* @param certOutLength Result certificate length
|
||||||
|
*/
|
||||||
|
virtual void extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength,
|
||||||
|
const RSA_KEY_TYPE keyType, const std::string& password,
|
||||||
|
unsigned char** certOut, unsigned int* certOutLength) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CryptoInterface
|
class CryptoInterface
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
#define ACS_SERVER "http://adeactivate.adobe.com/adept"
|
#define ACS_SERVER "http://adeactivate.adobe.com/adept"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LIBGOUROU_VERSION "0.1.1"
|
#define LIBGOUROU_VERSION "0.2"
|
||||||
|
|
||||||
namespace gourou
|
namespace gourou
|
||||||
{
|
{
|
||||||
|
@ -184,6 +184,11 @@ namespace gourou
|
||||||
void pushTag(void* sha_ctx, uint8_t tag);
|
void pushTag(void* sha_ctx, uint8_t tag);
|
||||||
void hashNode(const pugi::xml_node& root, void *sha_ctx, std::map<std::string,std::string> nsHash);
|
void hashNode(const pugi::xml_node& root, void *sha_ctx, std::map<std::string,std::string> nsHash);
|
||||||
void hashNode(const pugi::xml_node& root, unsigned char* sha_out);
|
void hashNode(const pugi::xml_node& root, unsigned char* sha_out);
|
||||||
|
std::string signNode(const pugi::xml_node& rootNode);
|
||||||
|
void addNonce(pugi::xml_node& root);
|
||||||
|
void buildAuthRequest(pugi::xml_document& authReq);
|
||||||
|
void buildInitLicenseServiceRequest(pugi::xml_document& initLicReq, std::string operatorURL);
|
||||||
|
void operatorAuth(std::string operatorURL);
|
||||||
void buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq);
|
void buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq);
|
||||||
void buildActivateReq(pugi::xml_document& activateReq);
|
void buildActivateReq(pugi::xml_document& activateReq);
|
||||||
ByteArray sendFulfillRequest(const pugi::xml_document& document, const std::string& url);
|
ByteArray sendFulfillRequest(const pugi::xml_document& document, const std::string& url);
|
||||||
|
|
|
@ -70,6 +70,11 @@ namespace gourou
|
||||||
*/
|
*/
|
||||||
std::string getProperty(const std::string property);
|
std::string getProperty(const std::string property);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get all nodes with property name
|
||||||
|
*/
|
||||||
|
pugi::xpath_node_set getProperties(const std::string property);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create activation.xml and devicesalt files if they did not exists
|
* @brief Create activation.xml and devicesalt files if they did not exists
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <libgourou.h>
|
#include <libgourou.h>
|
||||||
#include <libgourou_common.h>
|
#include <libgourou_common.h>
|
||||||
|
@ -156,13 +157,28 @@ namespace gourou
|
||||||
|
|
||||||
pushString(sha_ctx, name);
|
pushString(sha_ctx, name);
|
||||||
|
|
||||||
// Must be parsed in reverse order
|
std::vector<std::string> attributes;
|
||||||
for (pugi::xml_attribute attr = root.last_attribute();
|
pugi::xml_attribute attr;
|
||||||
attr; attr = attr.previous_attribute())
|
|
||||||
|
for (attr = root.first_attribute();
|
||||||
|
attr; attr = attr.next_attribute())
|
||||||
{
|
{
|
||||||
if (std::string(attr.name()).find("xmlns") != std::string::npos)
|
if (std::string(attr.name()).find("xmlns") != std::string::npos)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
attributes.push_back(attr.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attributes must be handled in alphabetical order
|
||||||
|
std::sort(attributes.begin(), attributes.end());
|
||||||
|
|
||||||
|
std::vector<std::string>::iterator attributesIt;
|
||||||
|
for(attributesIt = attributes.begin();
|
||||||
|
attributesIt != attributes.end();
|
||||||
|
attributesIt++)
|
||||||
|
{
|
||||||
|
attr = root.attribute(attributesIt->c_str());
|
||||||
|
|
||||||
pushTag(sha_ctx, ASN_ATTRIBUTE);
|
pushTag(sha_ctx, ASN_ATTRIBUTE);
|
||||||
pushString(sha_ctx, "");
|
pushString(sha_ctx, "");
|
||||||
|
|
||||||
|
@ -213,8 +229,73 @@ namespace gourou
|
||||||
for(int i=0; i<(int)SHA1_LEN; i++)
|
for(int i=0; i<(int)SHA1_LEN; i++)
|
||||||
printf("%02x ", sha_out[i]);
|
printf("%02x ", sha_out[i]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DRMProcessor::signNode(const pugi::xml_node& rootNode)
|
||||||
|
{
|
||||||
|
// Compute hash
|
||||||
|
unsigned char sha_out[SHA1_LEN];
|
||||||
|
|
||||||
|
hashNode(rootNode, sha_out);
|
||||||
|
|
||||||
|
// Sign with private key
|
||||||
|
unsigned char res[RSA_KEY_SIZE];
|
||||||
|
ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
|
||||||
|
std::string pkcs12 = user->getPKCS12();
|
||||||
|
ByteArray privateRSAKey = ByteArray::fromBase64(pkcs12);
|
||||||
|
|
||||||
|
client->RSAPrivateEncrypt(privateRSAKey.data(), privateRSAKey.length(),
|
||||||
|
RSAInterface::RSA_KEY_PKCS12, deviceKey.toBase64().data(),
|
||||||
|
sha_out, sizeof(sha_out), res);
|
||||||
|
if (logLevel >= DEBUG)
|
||||||
|
{
|
||||||
|
printf("Sig : ");
|
||||||
|
for(int i=0; i<(int)sizeof(res); i++)
|
||||||
|
printf("%02x ", res[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArray signature(res, sizeof(res));
|
||||||
|
|
||||||
|
return signature.toBase64();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DRMProcessor::addNonce(pugi::xml_node& root)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
r4 = tp->time
|
||||||
|
r3 = 0
|
||||||
|
r2 = tm->militime
|
||||||
|
r0 = 0x6f046000
|
||||||
|
r1 = 0x388a
|
||||||
|
|
||||||
|
r3 += high(r4*1000)
|
||||||
|
r2 += low(r4*1000)
|
||||||
|
|
||||||
|
r0 += r2
|
||||||
|
r1 += r3
|
||||||
|
*/
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, 0);
|
||||||
|
uint32_t nonce32[2] = {0x6f046000, 0x388a};
|
||||||
|
uint64_t bigtime = tv.tv_sec*1000;
|
||||||
|
nonce32[0] += (bigtime & 0xFFFFFFFF) + (tv.tv_usec/1000);
|
||||||
|
nonce32[1] += ((bigtime >> 32) & 0xFFFFFFFF);
|
||||||
|
|
||||||
|
ByteArray nonce((const unsigned char*)&nonce32, sizeof(nonce32));
|
||||||
|
uint32_t tmp = 0;
|
||||||
|
nonce.append((const unsigned char*)&tmp, sizeof(tmp));
|
||||||
|
appendTextElem(root, "adept:nonce", nonce.toBase64().data());
|
||||||
|
|
||||||
|
time_t _time = time(0) + 10*60; // Cur time + 10 minutes
|
||||||
|
struct tm* tm_info = localtime(&_time);
|
||||||
|
char buffer[32];
|
||||||
|
|
||||||
|
strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", tm_info);
|
||||||
|
appendTextElem(root, "adept:expiration", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
ByteArray DRMProcessor::sendRequest(const std::string& URL, const std::string& POSTdata, const char* contentType)
|
ByteArray DRMProcessor::sendRequest(const std::string& URL, const std::string& POSTdata, const char* contentType)
|
||||||
{
|
{
|
||||||
|
@ -243,6 +324,102 @@ namespace gourou
|
||||||
return sendRequest(url, xmlStr, (const char*)"application/vnd.adobe.adept+xml");
|
return sendRequest(url, xmlStr, (const char*)"application/vnd.adobe.adept+xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DRMProcessor::buildAuthRequest(pugi::xml_document& authReq)
|
||||||
|
{
|
||||||
|
pugi::xml_node decl = authReq.append_child(pugi::node_declaration);
|
||||||
|
decl.append_attribute("version") = "1.0";
|
||||||
|
|
||||||
|
pugi::xml_node root = authReq.append_child("adept:credentials");
|
||||||
|
root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
|
||||||
|
|
||||||
|
appendTextElem(root, "adept:user", user->getUUID());
|
||||||
|
|
||||||
|
ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
|
||||||
|
unsigned char* pkcs12 = 0;
|
||||||
|
unsigned int pkcs12Length;
|
||||||
|
ByteArray pkcs12Cert = ByteArray::fromBase64(user->getPKCS12());
|
||||||
|
|
||||||
|
client->extractCertificate(pkcs12Cert.data(), pkcs12Cert.length(),
|
||||||
|
RSAInterface::RSA_KEY_PKCS12, deviceKey.toBase64().data(),
|
||||||
|
&pkcs12, &pkcs12Length);
|
||||||
|
ByteArray privateCertificate(pkcs12, pkcs12Length);
|
||||||
|
free(pkcs12);
|
||||||
|
|
||||||
|
appendTextElem(root, "adept:certificate", privateCertificate.toBase64());
|
||||||
|
appendTextElem(root, "adept:licenseCertificate", user->getProperty("//adept:licenseCertificate"));
|
||||||
|
appendTextElem(root, "adept:authenticationCertificate", user->getProperty("//adept:authenticationCertificate"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DRMProcessor::buildInitLicenseServiceRequest(pugi::xml_document& initLicReq, std::string operatorURL)
|
||||||
|
{
|
||||||
|
pugi::xml_node decl = initLicReq.append_child(pugi::node_declaration);
|
||||||
|
decl.append_attribute("version") = "1.0";
|
||||||
|
|
||||||
|
pugi::xml_node root = initLicReq.append_child("adept:licenseServiceRequest");
|
||||||
|
root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
|
||||||
|
root.append_attribute("identity") = "user";
|
||||||
|
|
||||||
|
appendTextElem(root, "adept:operatorURL", operatorURL);
|
||||||
|
addNonce(root);
|
||||||
|
appendTextElem(root, "adept:user", user->getUUID());
|
||||||
|
|
||||||
|
std::string signature = signNode(root);
|
||||||
|
appendTextElem(root, "adept:signature", signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DRMProcessor::operatorAuth(std::string operatorURL)
|
||||||
|
{
|
||||||
|
pugi::xpath_node_set operatorList = user->getProperties("//adept:operatorURL");
|
||||||
|
|
||||||
|
for (pugi::xpath_node_set::const_iterator operatorIt = operatorList.begin();
|
||||||
|
operatorIt != operatorList.end(); ++operatorIt)
|
||||||
|
{
|
||||||
|
std::string value = operatorIt->node().first_child().value();
|
||||||
|
if (trim(value) == operatorURL)
|
||||||
|
{
|
||||||
|
GOUROU_LOG(DEBUG, "Already authenticated to operator " << operatorURL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pugi::xml_document authReq;
|
||||||
|
buildAuthRequest(authReq);
|
||||||
|
std::string authURL = operatorURL;
|
||||||
|
int fulfillPos = authURL.rfind("Fulfill");
|
||||||
|
if (fulfillPos == ((int)authURL.size() - 7))
|
||||||
|
authURL = authURL.substr(0, fulfillPos-1);
|
||||||
|
ByteArray replyData = sendRequest(authReq, authURL + "/Auth");
|
||||||
|
|
||||||
|
pugi::xml_document initLicReq;
|
||||||
|
std::string activationURL = user->getProperty("//adept:activationURL");
|
||||||
|
buildInitLicenseServiceRequest(initLicReq, authURL);
|
||||||
|
sendRequest(initLicReq, activationURL + "/InitLicenseService");
|
||||||
|
|
||||||
|
// Add new operatorURL to list
|
||||||
|
pugi::xml_document activationDoc;
|
||||||
|
user->readActivation(activationDoc);
|
||||||
|
|
||||||
|
pugi::xml_node root;
|
||||||
|
pugi::xpath_node xpathRes = activationDoc.select_node("//adept:operatorURLList");
|
||||||
|
|
||||||
|
// Create adept:operatorURLList if it doesn't exists
|
||||||
|
if (!xpathRes)
|
||||||
|
{
|
||||||
|
xpathRes = activationDoc.select_node("/activationInfo");
|
||||||
|
root = xpathRes.node();
|
||||||
|
root = root.append_child("adept:operatorURLList");
|
||||||
|
root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
|
||||||
|
|
||||||
|
appendTextElem(root, "adept:user", user->getUUID());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
root = xpathRes.node();
|
||||||
|
|
||||||
|
appendTextElem(root, "adept:operatorURL", operatorURL);
|
||||||
|
|
||||||
|
user->updateActivationFile(activationDoc);
|
||||||
|
}
|
||||||
|
|
||||||
void DRMProcessor::buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq)
|
void DRMProcessor::buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq)
|
||||||
{
|
{
|
||||||
pugi::xml_node decl = fulfillReq.append_child(pugi::node_declaration);
|
pugi::xml_node decl = fulfillReq.append_child(pugi::node_declaration);
|
||||||
|
@ -281,7 +458,7 @@ namespace gourou
|
||||||
EXCEPTION(FF_INVALID_ACSM_FILE, "Invalid ACSM file " << ACSMFile);
|
EXCEPTION(FF_INVALID_ACSM_FILE, "Invalid ACSM file " << ACSMFile);
|
||||||
|
|
||||||
GOUROU_LOG(INFO, "Fulfill " << ACSMFile);
|
GOUROU_LOG(INFO, "Fulfill " << ACSMFile);
|
||||||
|
|
||||||
// Build req file
|
// Build req file
|
||||||
pugi::xml_document fulfillReq;
|
pugi::xml_document fulfillReq;
|
||||||
|
|
||||||
|
@ -300,36 +477,12 @@ namespace gourou
|
||||||
|
|
||||||
hmacParentNode.remove_child(hmacNode);
|
hmacParentNode.remove_child(hmacNode);
|
||||||
|
|
||||||
// Compute hash
|
std::string signature = signNode(rootNode);
|
||||||
unsigned char sha_out[SHA1_LEN];
|
|
||||||
|
|
||||||
hashNode(rootNode, sha_out);
|
|
||||||
|
|
||||||
// Sign with private key
|
|
||||||
unsigned char res[RSA_KEY_SIZE];
|
|
||||||
ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
|
|
||||||
std::string pkcs12 = user->getPKCS12();
|
|
||||||
ByteArray privateRSAKey = ByteArray::fromBase64(pkcs12);
|
|
||||||
|
|
||||||
client->RSAPrivateEncrypt(privateRSAKey.data(), privateRSAKey.length(),
|
|
||||||
RSAInterface::RSA_KEY_PKCS12, deviceKey.toBase64().data(),
|
|
||||||
sha_out, sizeof(sha_out), res);
|
|
||||||
if (logLevel >= DEBUG)
|
|
||||||
{
|
|
||||||
printf("Sig : ");
|
|
||||||
for(int i=0; i<(int)sizeof(res); i++)
|
|
||||||
printf("%02x ", res[i]);
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add removed HMAC
|
// Add removed HMAC
|
||||||
appendTextElem(hmacParentNode, hmacNode.name(), hmacNode.first_child().value());
|
appendTextElem(hmacParentNode, hmacNode.name(), hmacNode.first_child().value());
|
||||||
|
|
||||||
// Add base64 encoded signature
|
appendTextElem(rootNode, "adept:signature", signature);
|
||||||
ByteArray signature(res, sizeof(res));
|
|
||||||
std::string b64Signature = signature.toBase64();
|
|
||||||
|
|
||||||
appendTextElem(rootNode, "adept:signature", b64Signature);
|
|
||||||
|
|
||||||
pugi::xpath_node node = acsmDoc.select_node("//operatorURL");
|
pugi::xpath_node node = acsmDoc.select_node("//operatorURL");
|
||||||
if (!node)
|
if (!node)
|
||||||
|
@ -338,6 +491,8 @@ namespace gourou
|
||||||
std::string operatorURL = node.node().first_child().value();
|
std::string operatorURL = node.node().first_child().value();
|
||||||
operatorURL = trim(operatorURL) + "/Fulfill";
|
operatorURL = trim(operatorURL) + "/Fulfill";
|
||||||
|
|
||||||
|
operatorAuth(operatorURL);
|
||||||
|
|
||||||
ByteArray replyData = sendRequest(fulfillReq, operatorURL);
|
ByteArray replyData = sendRequest(fulfillReq, operatorURL);
|
||||||
|
|
||||||
pugi::xml_document fulfillReply;
|
pugi::xml_document fulfillReply;
|
||||||
|
@ -508,37 +663,7 @@ namespace gourou
|
||||||
appendTextElem(targetDevice, "adept:deviceType", (*device)["deviceType"]);
|
appendTextElem(targetDevice, "adept:deviceType", (*device)["deviceType"]);
|
||||||
appendTextElem(targetDevice, "adept:fingerprint", (*device)["fingerprint"]);
|
appendTextElem(targetDevice, "adept:fingerprint", (*device)["fingerprint"]);
|
||||||
|
|
||||||
/*
|
addNonce(root);
|
||||||
r4 = tp->time
|
|
||||||
r3 = 0
|
|
||||||
r2 = tm->militime
|
|
||||||
r0 = 0x6f046000
|
|
||||||
r1 = 0x388a
|
|
||||||
|
|
||||||
r3 += high(r4*1000)
|
|
||||||
r2 += low(r4*1000)
|
|
||||||
|
|
||||||
r0 += r2
|
|
||||||
r1 += r3
|
|
||||||
*/
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, 0);
|
|
||||||
uint32_t nonce32[2] = {0x6f046000, 0x388a};
|
|
||||||
uint64_t bigtime = tv.tv_sec*1000;
|
|
||||||
nonce32[0] += (bigtime & 0xFFFFFFFF) + (tv.tv_usec/1000);
|
|
||||||
nonce32[1] += ((bigtime >> 32) & 0xFFFFFFFF);
|
|
||||||
|
|
||||||
ByteArray nonce((const unsigned char*)&nonce32, sizeof(nonce32));
|
|
||||||
uint32_t tmp = 0;
|
|
||||||
nonce.append((const unsigned char*)&tmp, sizeof(tmp));
|
|
||||||
appendTextElem(root, "adept:nonce", nonce.toBase64().data());
|
|
||||||
|
|
||||||
time_t _time = time(0) + 10*60; // Cur time + 10 minutes
|
|
||||||
struct tm* tm_info = localtime(&_time);
|
|
||||||
char buffer[32];
|
|
||||||
|
|
||||||
strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", tm_info);
|
|
||||||
appendTextElem(root, "adept:expiration", buffer);
|
|
||||||
|
|
||||||
appendTextElem(root, "adept:user", user->getUUID());
|
appendTextElem(root, "adept:user", user->getUUID());
|
||||||
}
|
}
|
||||||
|
@ -550,29 +675,13 @@ namespace gourou
|
||||||
GOUROU_LOG(INFO, "Activate device");
|
GOUROU_LOG(INFO, "Activate device");
|
||||||
|
|
||||||
buildActivateReq(activateReq);
|
buildActivateReq(activateReq);
|
||||||
|
|
||||||
// Compute hash
|
|
||||||
unsigned char sha_out[SHA1_LEN];
|
|
||||||
|
|
||||||
pugi::xml_node root = activateReq.select_node("adept:activate").node();
|
pugi::xml_node root = activateReq.select_node("adept:activate").node();
|
||||||
hashNode(root, sha_out);
|
|
||||||
|
|
||||||
// Sign with private key
|
std::string signature = signNode(root);
|
||||||
ByteArray RSAKey = ByteArray::fromBase64(user->getPKCS12());
|
|
||||||
unsigned char res[RSA_KEY_SIZE];
|
|
||||||
ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
|
|
||||||
|
|
||||||
client->RSAPrivateEncrypt(RSAKey.data(), RSAKey.length(), RSAInterface::RSA_KEY_PKCS12,
|
|
||||||
deviceKey.toBase64().c_str(),
|
|
||||||
sha_out, sizeof(sha_out),
|
|
||||||
res);
|
|
||||||
|
|
||||||
// Add base64 encoded signature
|
|
||||||
ByteArray signature(res, sizeof(res));
|
|
||||||
std::string b64Signature = signature.toBase64();
|
|
||||||
|
|
||||||
root = activateReq.select_node("adept:activate").node();
|
root = activateReq.select_node("adept:activate").node();
|
||||||
appendTextElem(root, "adept:signature", b64Signature);
|
appendTextElem(root, "adept:signature", signature);
|
||||||
|
|
||||||
pugi::xml_document activationDoc;
|
pugi::xml_document activationDoc;
|
||||||
user->readActivation(activationDoc);
|
user->readActivation(activationDoc);
|
||||||
|
|
|
@ -110,6 +110,11 @@ namespace gourou {
|
||||||
return trim(res);
|
return trim(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pugi::xpath_node_set User::getProperties(const std::string property)
|
||||||
|
{
|
||||||
|
return activationDoc.select_nodes(property.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
User* User::createUser(DRMProcessor* processor, const std::string& dirName, const std::string& ACSServer)
|
User* User::createUser(DRMProcessor* processor, const std::string& dirName, const std::string& ACSServer)
|
||||||
{
|
{
|
||||||
struct stat _stat;
|
struct stat _stat;
|
||||||
|
|
|
@ -213,6 +213,25 @@ void DRMProcessorClientImpl::extractRSAPrivateKey(void* handler, unsigned char**
|
||||||
EVP_PKEY_free(evpKey);
|
EVP_PKEY_free(evpKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DRMProcessorClientImpl::extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength,
|
||||||
|
const RSA_KEY_TYPE keyType, const std::string& password,
|
||||||
|
unsigned char** certOut, unsigned int* certOutLength)
|
||||||
|
{
|
||||||
|
PKCS12 * pkcs12;
|
||||||
|
EVP_PKEY* pkey = 0;
|
||||||
|
X509* cert = 0;
|
||||||
|
STACK_OF(X509)* ca;
|
||||||
|
|
||||||
|
pkcs12 = d2i_PKCS12(NULL, &RSAKey, RSAKeyLength);
|
||||||
|
if (!pkcs12)
|
||||||
|
EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));
|
||||||
|
PKCS12_parse(pkcs12, password.c_str(), &pkey, &cert, &ca);
|
||||||
|
|
||||||
|
*certOutLength = i2d_X509(cert, certOut);
|
||||||
|
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
}
|
||||||
|
|
||||||
/* Crypto interface */
|
/* Crypto interface */
|
||||||
void DRMProcessorClientImpl::AESEncrypt(CHAINING_MODE chaining,
|
void DRMProcessorClientImpl::AESEncrypt(CHAINING_MODE chaining,
|
||||||
const unsigned char* key, unsigned int keyLength,
|
const unsigned char* key, unsigned int keyLength,
|
||||||
|
|
|
@ -63,6 +63,9 @@ class DRMProcessorClientImpl : public gourou::DRMProcessorClient
|
||||||
|
|
||||||
virtual void extractRSAPublicKey(void* RSAKeyHandler, unsigned char** keyOut, unsigned int* keyOutLength);
|
virtual void extractRSAPublicKey(void* RSAKeyHandler, unsigned char** keyOut, unsigned int* keyOutLength);
|
||||||
virtual void extractRSAPrivateKey(void* RSAKeyHandler, unsigned char** keyOut, unsigned int* keyOutLength);
|
virtual void extractRSAPrivateKey(void* RSAKeyHandler, unsigned char** keyOut, unsigned int* keyOutLength);
|
||||||
|
virtual void extractCertificate(const unsigned char* RSAKey, unsigned int RSAKeyLength,
|
||||||
|
const RSA_KEY_TYPE keyType, const std::string& password,
|
||||||
|
unsigned char** certOut, unsigned int* certOutLength);
|
||||||
|
|
||||||
/* Crypto interface */
|
/* Crypto interface */
|
||||||
virtual void AESEncrypt(CHAINING_MODE chaining,
|
virtual void AESEncrypt(CHAINING_MODE chaining,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user