Libgourou

Libgourou Git Source Tree

Root/src/libgourou.cpp

1/*
2 Copyright 2021 Grégory Soutadé
3
4 This file is part of libgourou.
5
6 libgourou is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 libgourou is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with libgourou. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include <arpa/inet.h>
21#include <sys/time.h>
22#include <time.h>
23#include <vector>
24
25#include <uPDFParser.h>
26
27#include <libgourou.h>
28#include <libgourou_common.h>
29#include <libgourou_log.h>
30
31#define LOCAL_ADEPT_DIR "./.adept"
32
33#define ASN_NONE 0x00
34#define ASN_NS_TAG 0x01
35#define ASN_CHILD 0x02
36#define ASN_END_TAG 0x03
37#define ASN_TEXT 0x04
38#define ASN_ATTRIBUTE 0x05
39
40namespace gourou
41{
42 GOUROU_LOG_LEVEL logLevel = LG_LOG_WARN;
43 const std::string DRMProcessor::VERSION = LIBGOUROU_VERSION;
44
45 DRMProcessor::DRMProcessor(DRMProcessorClient* client):client(client), device(0), user(0)
46 {
47if (!client)
48 EXCEPTION(GOUROU_INVALID_CLIENT, "DRMProcessorClient is NULL");
49 }
50
51 DRMProcessor::DRMProcessor(DRMProcessorClient* client,
52 const std::string& deviceFile, const std::string& activationFile,
53 const std::string& deviceKeyFile):
54client(client), device(0), user(0)
55 {
56if (!client)
57 EXCEPTION(GOUROU_INVALID_CLIENT, "DRMProcessorClient is NULL");
58
59device = new Device(this, deviceFile, deviceKeyFile);
60user = new User(this, activationFile);
61
62if (user->getDeviceFingerprint() != "" &&
63 (*device)["fingerprint"] != user->getDeviceFingerprint())
64 EXCEPTION(GOUROU_DEVICE_DOES_NOT_MATCH, "User and device fingerprint does not match");
65 }
66
67 DRMProcessor::~DRMProcessor()
68 {
69if (device) delete device;
70if (user) delete user;
71 }
72
73 DRMProcessor* DRMProcessor::createDRMProcessor(DRMProcessorClient* client, bool randomSerial, std::string dirName,
74 const std::string& hobbes, const std::string& ACSServer)
75 {
76DRMProcessor* processor = new DRMProcessor(client);
77
78if (dirName == "")
79 dirName = getDefaultAdeptDir();
80
81Device* device = Device::createDevice(processor, dirName, hobbes, randomSerial);
82processor->device = device;
83
84User* user = User::createUser(processor, dirName, ACSServer);
85processor->user = user;
86
87return processor;
88 }
89
90
91 void DRMProcessor::pushString(void* sha_ctx, const std::string& string)
92 {
93int length = string.length();
94uint16_t nlength = htons(length);
95char c;
96
97if (logLevel >= LG_LOG_TRACE)
98 printf("%02x %02x ", ((uint8_t*)&nlength)[0], ((uint8_t*)&nlength)[1]);
99
100client->digestUpdate(sha_ctx, (unsigned char*)&nlength, sizeof(nlength));
101
102for(int i=0; i<length; i++)
103{
104 c = string[i];
105 client->digestUpdate(sha_ctx, (unsigned char*)&c, 1);
106 if (logLevel >= LG_LOG_TRACE)
107printf("%c", c);
108}
109if (logLevel >= LG_LOG_TRACE)
110 printf("\n");
111 }
112
113 void DRMProcessor::pushTag(void* sha_ctx, uint8_t tag)
114 {
115client->digestUpdate(sha_ctx, &tag, sizeof(tag));
116if (logLevel >= LG_LOG_TRACE)
117 printf("%02x ", tag);
118 }
119
120 void DRMProcessor::hashNode(const pugi::xml_node& root, void *sha_ctx, std::map<std::string,std::string> nsHash)
121 {
122switch(root.type())
123{
124case pugi::node_element:
125{
126 std::string name = root.name();
127
128 // Look for "xmlns[:]" attribute
129 for (pugi::xml_attribute_iterator ait = root.attributes_begin();
130 ait != root.attributes_end(); ++ait)
131 {
132std::string attrName(ait->name());
133
134if (attrName.find("xmlns") == 0)
135{
136 std::string ns("GENERICNS");
137 // Compound xmlns:Name attribute
138 if (attrName.find(':') != std::string::npos)
139ns = attrName.substr(attrName.find(':')+1);
140
141 nsHash[ns] = ait->value();
142 // Don't break here because we may multiple xmlns definitions
143 // break;
144}
145 }
146
147 // Remove namespace from tag
148 // If we have a namespace for the first time, put it to hash
149 if (name.find(':') != std::string::npos)
150 {
151size_t nsIndex = name.find(':');
152std::string nodeNS = name.substr(0, nsIndex);
153
154pushTag(sha_ctx, ASN_NS_TAG);
155pushString(sha_ctx, nsHash[nodeNS]);
156
157name = name.substr(nsIndex+1);
158 }
159 // Global xmlns, always send to hash
160 else if (nsHash.find("GENERICNS") != nsHash.end())
161 {
162pushTag(sha_ctx, ASN_NS_TAG);
163pushString(sha_ctx, nsHash["GENERICNS"]);
164 }
165
166 pushString(sha_ctx, name);
167
168 std::vector<std::string> attributes;
169 pugi::xml_attribute attr;
170
171 for (attr = root.first_attribute();
172 attr; attr = attr.next_attribute())
173 {
174if (std::string(attr.name()).find("xmlns") != std::string::npos)
175 continue;
176
177attributes.push_back(attr.name());
178 }
179
180 // Attributes must be handled in alphabetical order
181 std::sort(attributes.begin(), attributes.end());
182
183 std::vector<std::string>::iterator attributesIt;
184 for(attributesIt = attributes.begin();
185attributesIt != attributes.end();
186attributesIt++)
187 {
188attr = root.attribute(attributesIt->c_str());
189
190pushTag(sha_ctx, ASN_ATTRIBUTE);
191pushString(sha_ctx, "");
192
193pushString(sha_ctx, attr.name());
194pushString(sha_ctx, attr.value());
195 }
196
197 pushTag(sha_ctx, ASN_CHILD);
198
199 for (pugi::xml_node child : root.children())
200hashNode(child, sha_ctx, nsHash);
201
202 pushTag(sha_ctx, ASN_END_TAG);
203
204 break;
205}
206case pugi::node_pcdata:
207{
208 std::string trimmed = root.value();
209 trimmed = trim(trimmed);
210
211 if (trimmed.length())
212 {
213pushTag(sha_ctx, ASN_TEXT);
214pushString(sha_ctx, trimmed);
215 }
216
217 break;
218}
219default:
220 break;
221}
222 }
223
224 void DRMProcessor::hashNode(const pugi::xml_node& root, unsigned char* sha_out)
225 {
226void* sha_ctx = client->createDigest("SHA1");
227
228std::map<std::string, std::string> nsHash;
229
230hashNode(root, sha_ctx, nsHash);
231
232client->digestFinalize(sha_ctx, sha_out);
233
234dumpBuffer(gourou::LG_LOG_DEBUG, "\nSHA OUT : ", sha_out, SHA1_LEN);
235 }
236
237 void DRMProcessor::signNode(pugi::xml_node& rootNode)
238 {
239// Compute hash
240unsigned char sha_out[SHA1_LEN];
241
242hashNode(rootNode, sha_out);
243
244// Sign with private key
245unsigned char res[RSA_KEY_SIZE];
246ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
247std::string pkcs12 = user->getPKCS12();
248ByteArray privateRSAKey = ByteArray::fromBase64(pkcs12);
249
250client->RSAPrivateEncrypt(privateRSAKey.data(), privateRSAKey.length(),
251 RSAInterface::RSA_KEY_PKCS12, deviceKey.toBase64().data(),
252 sha_out, sizeof(sha_out), res);
253
254dumpBuffer(gourou::LG_LOG_DEBUG, "Sig : ", res, sizeof(res));
255
256std::string signature = ByteArray(res, sizeof(res)).toBase64();
257appendTextElem(rootNode, "adept:signature", signature);
258 }
259
260 void DRMProcessor::addNonce(pugi::xml_node& root)
261 {
262/*
263 r4 = tp->time
264 r3 = 0
265 r2 = tm->militime
266 r0 = 0x6f046000
267 r1 = 0x388a
268
269 r3 += high(r4*1000)
270 r2 += low(r4*1000)
271
272 r0 += r2
273 r1 += r3
274 */
275struct timeval tv;
276gettimeofday(&tv, 0);
277uint32_t nonce32[2] = {0x6f046000, 0x388a};
278#ifdef STATIC_NONCE
279uint64_t bigtime = 0xAA001122BBCCAAULL;
280#else
281uint64_t bigtime = tv.tv_sec*1000;
282#endif
283nonce32[0] += (bigtime & 0xFFFFFFFF) + (tv.tv_usec/1000);
284nonce32[1] += ((bigtime >> 32) & 0xFFFFFFFF);
285
286ByteArray nonce((const unsigned char*)&nonce32, sizeof(nonce32));
287uint32_t tmp = 0;
288nonce.append((const unsigned char*)&tmp, sizeof(tmp));
289appendTextElem(root, "adept:nonce", nonce.toBase64().data());
290
291time_t _time = time(0) + 10*60; // Cur time + 10 minutes
292struct tm* tm_info = gmtime(&_time);
293char buffer[32];
294
295strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", tm_info);
296appendTextElem(root, "adept:expiration", buffer);
297 }
298
299 ByteArray DRMProcessor::sendRequest(const std::string& URL, const std::string& POSTdata, const char* contentType, std::map<std::string, std::string>* responseHeaders, int fd, bool resume)
300 {
301if (contentType == 0)
302 contentType = "";
303std::string reply = client->sendHTTPRequest(URL, POSTdata, contentType, responseHeaders, fd, resume);
304
305if (fd) return ByteArray();
306
307pugi::xml_document replyDoc;
308replyDoc.load_buffer(reply.c_str(), reply.length());
309
310pugi::xml_node root = replyDoc.first_child();
311if (std::string(root.name()) == "error")
312{
313 EXCEPTION(GOUROU_ADEPT_ERROR, root.attribute("data").value());
314}
315
316return ByteArray(reply);
317 }
318
319 ByteArray DRMProcessor::sendRequest(const pugi::xml_document& document, const std::string& url)
320 {
321StringXMLWriter xmlWriter;
322document.save(xmlWriter, " ");
323std::string xmlStr = xmlWriter.getResult();
324
325return sendRequest(url, xmlStr, (const char*)"application/vnd.adobe.adept+xml");
326 }
327
328 void DRMProcessor::buildAuthRequest(pugi::xml_document& authReq)
329 {
330pugi::xml_node decl = authReq.append_child(pugi::node_declaration);
331decl.append_attribute("version") = "1.0";
332
333pugi::xml_node root = authReq.append_child("adept:credentials");
334root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
335
336appendTextElem(root, "adept:user", user->getUUID());
337
338ByteArray deviceKey(device->getDeviceKey(), Device::DEVICE_KEY_SIZE);
339unsigned char* pkcs12 = 0;
340unsigned int pkcs12Length;
341ByteArray pkcs12Cert = ByteArray::fromBase64(user->getPKCS12());
342
343client->extractCertificate(pkcs12Cert.data(), pkcs12Cert.length(),
344 RSAInterface::RSA_KEY_PKCS12, deviceKey.toBase64().data(),
345 &pkcs12, &pkcs12Length);
346ByteArray privateCertificate(pkcs12, pkcs12Length);
347free(pkcs12);
348
349appendTextElem(root, "adept:certificate", privateCertificate.toBase64());
350appendTextElem(root, "adept:licenseCertificate", user->getProperty("//adept:licenseCertificate"));
351appendTextElem(root, "adept:authenticationCertificate", user->getProperty("//adept:authenticationCertificate"));
352 }
353
354 void DRMProcessor::buildInitLicenseServiceRequest(pugi::xml_document& initLicReq, std::string operatorURL)
355 {
356pugi::xml_node decl = initLicReq.append_child(pugi::node_declaration);
357decl.append_attribute("version") = "1.0";
358
359pugi::xml_node root = initLicReq.append_child("adept:licenseServiceRequest");
360root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
361root.append_attribute("identity") = "user";
362
363appendTextElem(root, "adept:operatorURL", operatorURL);
364addNonce(root);
365appendTextElem(root, "adept:user", user->getUUID());
366
367signNode(root);
368 }
369
370 void DRMProcessor::doOperatorAuth(std::string operatorURL)
371 {
372pugi::xml_document authReq;
373buildAuthRequest(authReq);
374std::string authURL = operatorURL;
375unsigned int fulfillPos = authURL.rfind("Fulfill");
376if (fulfillPos == (authURL.size() - (sizeof("Fulfill")-1)))
377 authURL = authURL.substr(0, fulfillPos-1);
378ByteArray replyData = sendRequest(authReq, authURL + "/Auth");
379
380pugi::xml_document initLicReq;
381std::string activationURL = user->getProperty("//adept:activationURL");
382buildInitLicenseServiceRequest(initLicReq, authURL);
383sendRequest(initLicReq, activationURL + "/InitLicenseService");
384 }
385
386 void DRMProcessor::operatorAuth(std::string operatorURL)
387 {
388pugi::xpath_node_set operatorList = user->getProperties("//adept:operatorURL");
389
390for (pugi::xpath_node_set::const_iterator operatorIt = operatorList.begin();
391 operatorIt != operatorList.end(); ++operatorIt)
392{
393 std::string value = operatorIt->node().first_child().value();
394 if (trim(value) == operatorURL)
395 {
396GOUROU_LOG(DEBUG, "Already authenticated to operator " << operatorURL);
397return;
398 }
399}
400
401doOperatorAuth(operatorURL);
402
403// Add new operatorURL to list
404pugi::xml_document activationDoc;
405user->readActivation(activationDoc);
406
407pugi::xml_node root;
408pugi::xpath_node xpathRes = activationDoc.select_node("//adept:operatorURLList");
409
410// Create adept:operatorURLList if it doesn't exists
411if (!xpathRes)
412{
413 xpathRes = activationDoc.select_node("/activationInfo");
414 root = xpathRes.node();
415 root = root.append_child("adept:operatorURLList");
416 root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
417
418 appendTextElem(root, "adept:user", user->getUUID());
419}
420else
421 root = xpathRes.node();
422
423appendTextElem(root, "adept:operatorURL", operatorURL);
424
425user->updateActivationFile(activationDoc);
426 }
427
428 void DRMProcessor::buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq)
429 {
430pugi::xml_node decl = fulfillReq.append_child(pugi::node_declaration);
431decl.append_attribute("version") = "1.0";
432
433pugi::xml_node root = fulfillReq.append_child("adept:fulfill");
434root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
435
436appendTextElem(root, "adept:user", user->getUUID());
437appendTextElem(root, "adept:device", user->getDeviceUUID());
438appendTextElem(root, "adept:deviceType", (*device)["deviceType"]);
439
440root.append_copy(acsmDoc.first_child());
441
442pugi::xml_node targetDevice = root.append_child("adept:targetDevice");
443appendTextElem(targetDevice, "adept:softwareVersion", (*device)["hobbes"]);
444appendTextElem(targetDevice, "adept:clientOS", (*device)["clientOS"]);
445appendTextElem(targetDevice, "adept:clientLocale", (*device)["clientLocale"]);
446appendTextElem(targetDevice, "adept:clientVersion", (*device)["deviceClass"]);
447appendTextElem(targetDevice, "adept:deviceType", (*device)["deviceType"]);
448appendTextElem(targetDevice, "adept:fingerprint", (*device)["fingerprint"]);
449
450pugi::xml_node activationToken = targetDevice.append_child("adept:activationToken");
451appendTextElem(activationToken, "adept:user", user->getUUID());
452appendTextElem(activationToken, "adept:device", user->getDeviceUUID());
453 }
454
455 void DRMProcessor::fetchLicenseServiceCertificate(const std::string& licenseURL,
456 const std::string& operatorURL)
457 {
458if (user->getLicenseServiceCertificate(licenseURL) != "")
459 return;
460
461std::string licenseServiceInfoReq = operatorURL + "/LicenseServiceInfo?licenseURL=" + licenseURL;
462
463ByteArray replyData;
464replyData = sendRequest(licenseServiceInfoReq);
465
466pugi::xml_document licenseServicesDoc;
467licenseServicesDoc.load_buffer(replyData.data(), replyData.length());
468
469// Add new license certificate
470pugi::xml_document activationDoc;
471user->readActivation(activationDoc);
472
473pugi::xml_node root;
474pugi::xpath_node xpathRes = activationDoc.select_node("//adept:licenseServices");
475
476// Create adept:licenseServices if it doesn't exists
477if (!xpathRes)
478{
479 xpathRes = activationDoc.select_node("/activationInfo");
480 root = xpathRes.node();
481 root = root.append_child("adept:licenseServices");
482 root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
483}
484else
485 root = xpathRes.node();
486
487root = root.append_child("adept:licenseServiceInfo");
488
489std::string certificate = extractTextElem(licenseServicesDoc,
490 "/licenseServiceInfo/certificate");
491
492appendTextElem(root, "adept:licenseURL", licenseURL);
493appendTextElem(root, "adept:certificate", certificate);
494
495user->updateActivationFile(activationDoc);
496 }
497
498 FulfillmentItem* DRMProcessor::fulfill(const std::string& ACSMFile)
499 {
500if (!user->getPKCS12().length())
501 EXCEPTION(FF_NOT_ACTIVATED, "Device not activated");
502
503pugi::xml_document acsmDoc;
504
505if (!acsmDoc.load_file(ACSMFile.c_str(), pugi::parse_ws_pcdata_single|pugi::parse_escapes, pugi::encoding_utf8))
506 EXCEPTION(FF_INVALID_ACSM_FILE, "Invalid ACSM file " << ACSMFile);
507
508// Could be an server internal error
509pugi::xml_node rootNode = acsmDoc.first_child();
510if (std::string(rootNode.name()) == "error")
511{
512 EXCEPTION(FF_SERVER_INTERNAL_ERROR, rootNode.attribute("data").value());
513}
514
515GOUROU_LOG(INFO, "Fulfill " << ACSMFile);
516
517// Build req file
518pugi::xml_document fulfillReq;
519
520buildFulfillRequest(acsmDoc, fulfillReq);
521pugi::xpath_node root = fulfillReq.select_node("//adept:fulfill");
522rootNode = root.node();
523
524// Remove HMAC
525pugi::xpath_node xpathRes = fulfillReq.select_node("//hmac");
526
527if (!xpathRes)
528 EXCEPTION(FF_NO_HMAC_IN_ACSM_FILE, "hmac tag not found in ACSM file");
529
530pugi::xml_node hmacNode = xpathRes.node();
531pugi::xml_node hmacParentNode = hmacNode.parent();
532
533hmacParentNode.remove_child(hmacNode);
534
535signNode(rootNode);
536
537// Add removed HMAC
538appendTextElem(hmacParentNode, hmacNode.name(), hmacNode.first_child().value());
539
540pugi::xpath_node node = acsmDoc.select_node("//operatorURL");
541if (!node)
542 EXCEPTION(FF_NO_OPERATOR_URL, "OperatorURL not found in ACSM document");
543
544std::string operatorURL = node.node().first_child().value();
545operatorURL = trim(operatorURL);
546std::string fulfillURL = operatorURL + "/Fulfill";
547
548operatorAuth(fulfillURL);
549
550ByteArray replyData;
551
552try
553{
554 replyData = sendRequest(fulfillReq, fulfillURL);
555}
556catch (gourou::Exception& e)
557{
558 /*
559 Operator requires authentication even if it's already in
560 our operator list
561 */
562 std::string errorMsg(e.what());
563 if (e.getErrorCode() == GOUROU_ADEPT_ERROR &&
564errorMsg.find("E_ADEPT_DISTRIBUTOR_AUTH") != std::string::npos)
565 {
566doOperatorAuth(fulfillURL);
567replyData = sendRequest(fulfillReq, fulfillURL);
568 }
569 else
570 {
571throw e;
572 }
573}
574
575pugi::xml_document fulfillReply;
576
577fulfillReply.load_string((const char*)replyData.data());
578
579std::string licenseURL = extractTextElem(fulfillReply, "//licenseToken/licenseURL");
580
581fetchLicenseServiceCertificate(licenseURL, operatorURL);
582
583return new FulfillmentItem(fulfillReply, user);
584 }
585
586 DRMProcessor::ITEM_TYPE DRMProcessor::download(FulfillmentItem* item, std::string path, bool resume)
587 {
588ITEM_TYPE res = EPUB;
589
590if (!item)
591 EXCEPTION(DW_NO_ITEM, "No item");
592
593std::map<std::string, std::string> headers;
594
595int fd = createNewFile(path, !resume);
596
597sendRequest(item->getDownloadURL(), "", 0, &headers, fd, resume);
598
599close(fd);
600
601GOUROU_LOG(INFO, "Download into " << path);
602
603ByteArray rightsStr(item->getRights());
604
605if (item->getMetadata("format").find("application/pdf") != std::string::npos)
606 res = PDF;
607
608if (headers.count("Content-Type") &&
609 headers["Content-Type"].find("application/pdf") != std::string::npos)
610 res = PDF;
611
612if (res == EPUB)
613{
614 void* handler = client->zipOpen(path);
615 client->zipWriteFile(handler, "META-INF/rights.xml", rightsStr);
616 client->zipClose(handler);
617}
618else if (res == PDF)
619{
620 uPDFParser::Parser parser;
621 bool EBXHandlerFound = false;
622
623 try
624 {
625GOUROU_LOG(DEBUG, "Parse PDF");
626parser.parse(path);
627 }
628 catch(std::invalid_argument& e)
629 {
630GOUROU_LOG(ERROR, "Invalid PDF");
631return res;
632 }
633
634 std::vector<uPDFParser::Object*> objects = parser.objects();
635 std::vector<uPDFParser::Object*>::reverse_iterator it;
636
637 for(it = objects.rbegin(); it != objects.rend(); it++)
638 {
639// Update EBX_HANDLER with rights
640if ((*it)->hasKey("Filter") && (**it)["Filter"]->str() == "/EBX_HANDLER")
641{
642 EBXHandlerFound = true;
643 uPDFParser::Object* ebx = (*it)->clone();
644 (*ebx)["ADEPT_ID"] = new uPDFParser::String(item->getResource());
645 (*ebx)["EBX_BOOKID"] = new uPDFParser::String(item->getResource());
646 ByteArray zipped;
647 client->deflate(rightsStr, zipped);
648 (*ebx)["ADEPT_LICENSE"] = new uPDFParser::String(zipped.toBase64());
649 parser.addObject(ebx);
650 break;
651}
652 }
653
654 if (EBXHandlerFound)
655parser.write(path, true);
656 else
657 {
658EXCEPTION(DW_NO_EBX_HANDLER, "EBX_HANDLER not found");
659 }
660}
661
662return res;
663 }
664
665 void DRMProcessor::buildSignInRequest(pugi::xml_document& signInRequest,
666 const std::string& adobeID, const std::string& adobePassword,
667 const std::string& authenticationCertificate)
668 {
669pugi::xml_node decl = signInRequest.append_child(pugi::node_declaration);
670decl.append_attribute("version") = "1.0";
671pugi::xml_node signIn = signInRequest.append_child("adept:signIn");
672signIn.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
673std::string loginMethod = user->getLoginMethod();
674
675if (adobeID == "anonymous")
676 signIn.append_attribute("method") = "anonymous";
677else if (loginMethod.size())
678 signIn.append_attribute("method") = loginMethod.c_str();
679else
680 signIn.append_attribute("method") = "AdobeID";
681
682unsigned char encryptedSignInData[RSA_KEY_SIZE];
683const unsigned char* deviceKey = device->getDeviceKey();
684
685ByteArray _authenticationCertificate = ByteArray::fromBase64(authenticationCertificate);
686
687// Build buffer <deviceKey> <len username> <username> <len password> <password>
688ByteArray ar(deviceKey, Device::DEVICE_KEY_SIZE);
689ar.append((unsigned char)adobeID.length());
690ar.append(adobeID);
691ar.append((unsigned char)adobePassword.length());
692ar.append(adobePassword);
693
694// Encrypt with authentication certificate (public part)
695client->RSAPublicEncrypt(_authenticationCertificate.data(),
696 _authenticationCertificate.length(),
697 RSAInterface::RSA_KEY_X509,
698 ar.data(), ar.length(), encryptedSignInData);
699
700ar = ByteArray(encryptedSignInData, sizeof(encryptedSignInData));
701appendTextElem(signIn, "adept:signInData", ar.toBase64());
702
703// Generate Auth key and License Key
704void* rsaAuth = client->generateRSAKey(RSA_KEY_SIZE_BITS);
705void* rsaLicense = client->generateRSAKey(RSA_KEY_SIZE_BITS);
706
707std::string serializedData = serializeRSAPublicKey(rsaAuth);
708appendTextElem(signIn, "adept:publicAuthKey", serializedData);
709serializedData = serializeRSAPrivateKey(rsaAuth);
710appendTextElem(signIn, "adept:encryptedPrivateAuthKey", serializedData.data());
711
712serializedData = serializeRSAPublicKey(rsaLicense);
713appendTextElem(signIn, "adept:publicLicenseKey", serializedData.data());
714serializedData = serializeRSAPrivateKey(rsaLicense);
715appendTextElem(signIn, "adept:encryptedPrivateLicenseKey", serializedData.data());
716
717client->destroyRSAHandler(rsaAuth);
718client->destroyRSAHandler(rsaLicense);
719 }
720
721 void DRMProcessor::signIn(const std::string& adobeID, const std::string& adobePassword)
722 {
723pugi::xml_document signInRequest;
724std::string authenticationCertificate = user->getAuthenticationCertificate();
725
726buildSignInRequest(signInRequest, adobeID, adobePassword, authenticationCertificate);
727
728GOUROU_LOG(INFO, "SignIn " << adobeID);
729
730std::string signInURL = user->getProperty("//adept:authURL");
731signInURL += "/SignInDirect";
732
733ByteArray credentials = sendRequest(signInRequest, signInURL);
734
735pugi::xml_document credentialsDoc;
736if (!credentialsDoc.load_buffer(credentials.data(), credentials.length()))
737 EXCEPTION(SIGN_INVALID_CREDENTIALS, "Invalid credentials reply");
738
739struct adeptWalker: pugi::xml_tree_walker
740{
741 void changeName(pugi::xml_node& node)
742 {
743std::string name = std::string("adept:") + node.name();
744node.set_name(name.c_str());
745 }
746
747 bool begin(pugi::xml_node& node)
748 {
749changeName(node);
750return true;
751 }
752
753 virtual bool for_each(pugi::xml_node& node)
754 {
755if (node.type() == pugi::node_element)
756 changeName(node);
757return true; // continue traversal
758 }
759} adeptWalker;
760
761pugi::xml_node credentialsNode = credentialsDoc.first_child();
762
763if (std::string(credentialsNode.name()) != "credentials")
764 EXCEPTION(SIGN_INVALID_CREDENTIALS, "Invalid credentials reply");
765
766pugi::xpath_node encryptedPrivateLicenseKey = credentialsNode.select_node("encryptedPrivateLicenseKey");
767const char* privateKeyData = encryptedPrivateLicenseKey.node().first_child().value();
768ByteArray privateKeyDataStr = ByteArray::fromBase64(privateKeyData);
769ByteArray privateKey = decryptWithDeviceKey(privateKeyDataStr.data(), privateKeyDataStr.length());
770credentialsNode.remove_child(encryptedPrivateLicenseKey.node());
771appendTextElem(credentialsNode, "privateLicenseKey", privateKey.toBase64().data());
772
773// Add "adept:" prefix to all nodes
774credentialsNode.remove_attribute("xmlns");
775credentialsNode.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
776credentialsNode.traverse(adeptWalker);
777
778appendTextElem(credentialsNode, "adept:authenticationCertificate", authenticationCertificate.data());
779
780pugi::xml_document activationDoc;
781user->readActivation(activationDoc);
782pugi::xml_node activationInfo = activationDoc.select_node("activationInfo").node();
783activationInfo.append_copy(credentialsNode);
784
785user->updateActivationFile(activationDoc);
786 }
787
788 void DRMProcessor::buildActivateReq(pugi::xml_document& activateReq)
789 {
790pugi::xml_node decl = activateReq.append_child(pugi::node_declaration);
791decl.append_attribute("version") = "1.0";
792
793pugi::xml_node root = activateReq.append_child("adept:activate");
794root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
795root.append_attribute("requestType") = "initial";
796
797appendTextElem(root, "adept:fingerprint", (*device)["fingerprint"]);
798appendTextElem(root, "adept:deviceType", (*device)["deviceType"]);
799appendTextElem(root, "adept:clientOS", (*device)["clientOS"]);
800appendTextElem(root, "adept:clientLocale", (*device)["clientLocale"]);
801appendTextElem(root, "adept:clientVersion", (*device)["deviceClass"]);
802
803pugi::xml_node targetDevice = root.append_child("adept:targetDevice");
804appendTextElem(targetDevice, "adept:softwareVersion", (*device)["hobbes"]);
805appendTextElem(targetDevice, "adept:clientOS", (*device)["clientOS"]);
806appendTextElem(targetDevice, "adept:clientLocale", (*device)["clientLocale"]);
807appendTextElem(targetDevice, "adept:clientVersion", (*device)["deviceClass"]);
808appendTextElem(targetDevice, "adept:deviceType", (*device)["deviceType"]);
809appendTextElem(targetDevice, "adept:fingerprint", (*device)["fingerprint"]);
810
811addNonce(root);
812
813appendTextElem(root, "adept:user", user->getUUID());
814 }
815
816 void DRMProcessor::activateDevice()
817 {
818pugi::xml_document activateReq;
819
820GOUROU_LOG(INFO, "Activate device");
821
822buildActivateReq(activateReq);
823
824pugi::xml_node root = activateReq.select_node("adept:activate").node();
825
826signNode(root);
827
828pugi::xml_document activationDoc;
829user->readActivation(activationDoc);
830
831std::string activationURL = user->getProperty("//adept:activationURL");
832activationURL += "/Activate";
833
834ByteArray reply = sendRequest(activateReq, activationURL);
835
836pugi::xml_document activationToken;
837activationToken.load_buffer(reply.data(), reply.length());
838
839root = activationDoc.select_node("activationInfo").node();
840root.append_copy(activationToken.first_child());
841user->updateActivationFile(activationDoc);
842 }
843
844 void DRMProcessor::buildReturnReq(pugi::xml_document& returnReq, const std::string& loanID, const std::string& operatorURL)
845 {
846pugi::xml_node decl = returnReq.append_child(pugi::node_declaration);
847decl.append_attribute("version") = "1.0";
848
849pugi::xml_node root = returnReq.append_child("adept:loanReturn");
850root.append_attribute("xmlns:adept") = ADOBE_ADEPT_NS;
851
852appendTextElem(root, "adept:user", user->getUUID());
853appendTextElem(root, "adept:device", user->getDeviceUUID());
854appendTextElem(root, "adept:loan", loanID);
855
856addNonce(root);
857signNode(root);
858 }
859
860 std::string DRMProcessor::getDefaultAdeptDir(void)
861 {
862#ifndef DEFAULT_ADEPT_DIR
863const char* user = getenv("USER");
864
865if (user && user[0])
866{
867 return std::string("/home/") + user + std::string("/.config/adept/");
868}
869else
870 return LOCAL_ADEPT_DIR;
871#else
872return DEFAULT_ADEPT_DIR "/";
873#endif
874 }
875
876 void DRMProcessor::returnLoan(const std::string& loanID, const std::string& operatorURL)
877 {
878pugi::xml_document returnReq;
879
880GOUROU_LOG(INFO, "Return loan " << loanID);
881
882buildReturnReq(returnReq, loanID, operatorURL);
883
884sendRequest(returnReq, operatorURL + "/LoanReturn");
885 }
886
887 ByteArray DRMProcessor::encryptWithDeviceKey(const unsigned char* data, unsigned int len)
888 {
889const unsigned char* deviceKey = device->getDeviceKey();
890unsigned int outLen;
891int remain = 0;
892if ((len % 16))
893 remain = 16 - (len%16);
894int encrypted_data_len = 16 + len + remain; // IV + data + pad
895unsigned char* encrypted_data = new unsigned char[encrypted_data_len];
896
897// Generate IV in front
898client->randBytes(encrypted_data, 16);
899
900client->encrypt(CryptoInterface::ALGO_AES, CryptoInterface::CHAIN_CBC,
901deviceKey, 16, encrypted_data, 16,
902data, len,
903encrypted_data+16, &outLen);
904
905ByteArray res(encrypted_data, outLen+16);
906
907delete[] encrypted_data;
908
909return res;
910 }
911
912 /* First 16 bytes of data is IV for CBC chaining */
913 ByteArray DRMProcessor::decryptWithDeviceKey(const unsigned char* data, unsigned int len)
914 {
915unsigned int outLen;
916const unsigned char* deviceKey = device->getDeviceKey();
917unsigned char* decrypted_data = new unsigned char[len-16];
918
919client->decrypt(CryptoInterface::ALGO_AES, CryptoInterface::CHAIN_CBC,
920deviceKey, 16, data, 16,
921data+16, len-16,
922decrypted_data, &outLen);
923
924ByteArray res(decrypted_data, outLen);
925
926delete[] decrypted_data;
927
928return res;
929 }
930
931 std::string DRMProcessor::serializeRSAPublicKey(void* rsa)
932 {
933unsigned char* data = 0;
934unsigned int len;
935
936client->extractRSAPublicKey(rsa, &data, &len);
937
938ByteArray res(data, len);
939
940free(data);
941
942return res.toBase64();
943 }
944
945 std::string DRMProcessor::serializeRSAPrivateKey(void* rsa)
946 {
947unsigned char* data = 0;
948unsigned int len;
949
950client->extractRSAPrivateKey(rsa, &data, &len);
951
952ByteArray res = encryptWithDeviceKey(data, len);
953
954free(data);
955
956return res.toBase64();
957 }
958
959 void DRMProcessor::exportPrivateLicenseKey(std::string path)
960 {
961int fd = open(path.c_str(), O_CREAT|O_TRUNC|O_WRONLY, S_IRWXU);
962int ret;
963
964if (fd <= 0)
965 EXCEPTION(GOUROU_FILE_ERROR, "Unable to open " << path);
966
967ByteArray privateLicenseKey = ByteArray::fromBase64(user->getPrivateLicenseKey());
968/* In adobekey.py, we get base64 decoded data [26:] */
969ret = write(fd, privateLicenseKey.data()+26, privateLicenseKey.length()-26);
970close(fd);
971if (ret != (int)(privateLicenseKey.length()-26))
972{
973 EXCEPTION(gourou::GOUROU_FILE_ERROR, "Error writing " << path);
974}
975 }
976
977 int DRMProcessor::getLogLevel() {return (int)gourou::logLevel;}
978 void DRMProcessor::setLogLevel(int logLevel) {gourou::logLevel = (GOUROU_LOG_LEVEL)logLevel;}
979
980 /**
981 * RSA Key can be over encrypted with AES128-CBC if keyType attribute is set
982 * remainder = keyType % 16
983 * Key = SHA256(keyType)[remainder*2:remainder*2+(16-remainder)] || SHA256(keyType)[16-remainder:16]
984 * IV = DeviceID ^ FulfillmentId ^ VoucherId
985 *
986 * @return Base64 encoded decrypted key
987 */
988 std::string DRMProcessor::encryptedKeyFirstPass(pugi::xml_document& rightsDoc, const std::string& encryptedKey, const std::string& keyType)
989 {
990unsigned char digest[32], key[16], iv[16];
991unsigned int dataOutLength;
992std::string id;
993
994client->digest("SHA256", (unsigned char*)keyType.c_str(), keyType.size(), digest);
995
996dumpBuffer(gourou::LG_LOG_DEBUG, "SHA of KeyType : ", digest, sizeof(digest));
997
998long nonce = std::stol(keyType);
999int remainder = nonce % 16;
1000
1001memcpy(key, &digest[remainder*2], 16-remainder);
1002memcpy(&key[16-remainder], &digest[remainder], remainder);
1003
1004id = extractTextElem(rightsDoc, "/adept:rights/licenseToken/device");
1005if (id == "")
1006 EXCEPTION(DRM_ERR_ENCRYPTION_KEY_FP, "Device id not found in rights.xml");
1007ByteArray deviceId = ByteArray::fromHex(extractIdFromUUID(id));
1008unsigned char* _deviceId = deviceId.data();
1009
1010id = extractTextElem(rightsDoc, "/adept:rights/licenseToken/fulfillment");
1011if (id == "")
1012 EXCEPTION(DRM_ERR_ENCRYPTION_KEY_FP, "Fulfillment id not found in rights.xml");
1013ByteArray fulfillmentId = ByteArray::fromHex(extractIdFromUUID(id));
1014unsigned char* _fulfillmentId = fulfillmentId.data();
1015
1016id = extractTextElem(rightsDoc, "/adept:rights/licenseToken/voucher");
1017if (id == "")
1018 EXCEPTION(DRM_ERR_ENCRYPTION_KEY_FP, "Voucher id not found in rights.xml");
1019ByteArray voucherId = ByteArray::fromHex(extractIdFromUUID(id));
1020unsigned char* _voucherId = voucherId.data();
1021
1022if (deviceId.size() < sizeof(iv) || fulfillmentId.size() < sizeof(iv) || voucherId.size() < sizeof(iv))
1023 EXCEPTION(DRM_ERR_ENCRYPTION_KEY_FP, "One id has a bad length");
1024
1025for(unsigned int i=0; i<sizeof(iv); i++)
1026 iv[i] = _deviceId[i] ^ _fulfillmentId[i] ^ _voucherId[i];
1027
1028dumpBuffer(gourou::LG_LOG_DEBUG, "First pass key : ", key, sizeof(key));
1029dumpBuffer(gourou::LG_LOG_DEBUG, "First pass IV : ", iv, sizeof(iv));
1030
1031ByteArray arrayEncryptedKey = ByteArray::fromBase64(encryptedKey);
1032unsigned char* clearRSAKey = new unsigned char[arrayEncryptedKey.size()];
1033
1034client->decrypt(CryptoInterface::ALGO_AES, CryptoInterface::CHAIN_CBC,
1035(const unsigned char*)key, (unsigned int)sizeof(key),
1036(const unsigned char*)iv, (unsigned int)sizeof(iv),
1037(const unsigned char*)arrayEncryptedKey.data(), arrayEncryptedKey.size(),
1038(unsigned char*)clearRSAKey, &dataOutLength);
1039
1040dumpBuffer(gourou::LG_LOG_DEBUG, "\nDecrypted key : ", clearRSAKey, dataOutLength);
1041
1042/* Last block could be 0x10*16 which is OpenSSL padding, remove it if it's the case */
1043bool skipLastLine = true;
1044for(unsigned int i=dataOutLength-16; i<dataOutLength; i++)
1045{
1046 if (clearRSAKey[i] != 0x10)
1047 {
1048skipLastLine = false;
1049break;
1050 }
1051}
1052
1053ByteArray res(clearRSAKey, (skipLastLine)?dataOutLength-16:dataOutLength);
1054
1055delete[] clearRSAKey;
1056
1057return res.toBase64();
1058 }
1059
1060 void DRMProcessor::decryptADEPTKey(pugi::xml_document& rightsDoc, unsigned char* decryptedKey, const unsigned char* encryptionKey, unsigned encryptionKeySize)
1061 {
1062unsigned char rsaKey[RSA_KEY_SIZE];
1063
1064std::string user = extractTextElem(rightsDoc, "/adept:rights/licenseToken/user");
1065
1066if (!encryptionKey)
1067{
1068 if (this->user->getUUID() != user)
1069 {
1070EXCEPTION(DRM_INVALID_USER, "This book has been downloaded for another user (" << user << ")");
1071 }
1072
1073 std::string encryptedKey = extractTextElem(rightsDoc, "/adept:rights/licenseToken/encryptedKey");
1074 std::string keyType = extractTextAttribute(rightsDoc, "/adept:rights/licenseToken/encryptedKey", "keyType", false);
1075
1076 if (keyType != "")
1077encryptedKey = encryptedKeyFirstPass(rightsDoc, encryptedKey, keyType);
1078
1079 if (encryptedKey.size() != 172)
1080EXCEPTION(DRM_INVALID_KEY_SIZE, "Invalid encrypted key size (" << encryptedKey.size() << "). DRM version not supported");
1081
1082 ByteArray arrayEncryptedKey = ByteArray::fromBase64(encryptedKey);
1083
1084 std::string privateKeyData = this->user->getPrivateLicenseKey();
1085 ByteArray privateRSAKey = ByteArray::fromBase64(privateKeyData);
1086
1087 dumpBuffer(gourou::LG_LOG_DEBUG, "To decrypt : ", arrayEncryptedKey.data(), arrayEncryptedKey.length());
1088
1089 client->RSAPrivateDecrypt(privateRSAKey.data(), privateRSAKey.length(),
1090 RSAInterface::RSA_KEY_PKCS8, "",
1091 arrayEncryptedKey.data(), arrayEncryptedKey.length(), rsaKey);
1092
1093 dumpBuffer(gourou::LG_LOG_DEBUG, "Decrypted : ", rsaKey, sizeof(rsaKey));
1094
1095 if (rsaKey[0] != 0x00 || rsaKey[1] != 0x02 ||
1096rsaKey[RSA_KEY_SIZE-16-1] != 0x00)
1097EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Unable to retrieve encryption key");
1098
1099 memcpy(decryptedKey, &rsaKey[sizeof(rsaKey)-16], 16);
1100}
1101else
1102{
1103 GOUROU_LOG(DEBUG, "Use provided encryption key");
1104 if (encryptionKeySize != 16)
1105EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Provided encryption key must be 16 bytes");
1106
1107 memcpy(decryptedKey, encryptionKey, encryptionKeySize);
1108}
1109 }
1110
1111 void DRMProcessor::removeEPubDRM(const std::string& filenameIn, const std::string& filenameOut,
1112 const unsigned char* encryptionKey, unsigned encryptionKeySize)
1113 {
1114ByteArray zipData;
1115bool removeEncryptionXML = true;
1116void* zipHandler = client->zipOpen(filenameOut);
1117
1118client->zipReadFile(zipHandler, "META-INF/rights.xml", zipData);
1119pugi::xml_document rightsDoc;
1120rightsDoc.load_string((const char*)zipData.data());
1121
1122unsigned char decryptedKey[16];
1123
1124decryptADEPTKey(rightsDoc, decryptedKey, encryptionKey, encryptionKeySize);
1125
1126client->zipReadFile(zipHandler, "META-INF/encryption.xml", zipData);
1127pugi::xml_document encryptionDoc;
1128encryptionDoc.load_string((const char*)zipData.data());
1129
1130pugi::xpath_node_set nodeSet = encryptionDoc.select_nodes("//EncryptedData");
1131
1132for (pugi::xpath_node_set::const_iterator it = nodeSet.begin();
1133 it != nodeSet.end(); ++it)
1134{
1135 pugi::xml_node encryptionMethod = it->node().child("EncryptionMethod");
1136 pugi::xml_node cipherReference = it->node().child("CipherData").child("CipherReference");
1137
1138 std::string encryptionType = encryptionMethod.attribute("Algorithm").value();
1139 std::string encryptedFile = cipherReference.attribute("URI").value();
1140
1141 if (encryptionType == "")
1142 {
1143EXCEPTION(DRM_MISSING_PARAMETER, "Missing Algorithm attribute in encryption.xml");
1144 }
1145 else if (encryptionType == "http://www.w3.org/2001/04/xmlenc#aes128-cbc")
1146 {
1147if (encryptedFile == "")
1148{
1149 EXCEPTION(DRM_MISSING_PARAMETER, "Missing URI attribute in encryption.xml");
1150}
1151
1152GOUROU_LOG(DEBUG, "Encrypted file " << encryptedFile);
1153
1154client->zipReadFile(zipHandler, encryptedFile, zipData, false);
1155
1156unsigned char* _data = zipData.data();
1157ByteArray clearData(zipData.length()-16+1, true); /* Reserve 1 byte for 'Z' */
1158unsigned char* _clearData = clearData.data();
1159gourou::ByteArray inflateData(true);
1160unsigned int dataOutLength;
1161
1162client->decrypt(CryptoInterface::ALGO_AES, CryptoInterface::CHAIN_CBC,
1163decryptedKey, sizeof(decryptedKey), /* Key */
1164_data, 16, /* IV */
1165&_data[16], zipData.length()-16,
1166_clearData, &dataOutLength);
1167
1168// Add 'Z' at the end, done in ineptepub.py
1169_clearData[dataOutLength] = 'Z';
1170clearData.resize(dataOutLength+1);
1171
1172try
1173{
1174 client->inflate(clearData, inflateData);
1175 client->zipWriteFile(zipHandler, encryptedFile, inflateData);
1176}
1177catch(gourou::Exception& e)
1178{
1179 if (e.getErrorCode() == CLIENT_ZIP_ERROR)
1180 {
1181GOUROU_LOG(ERROR, e.what() << std::endl << "Skip file " << encryptedFile);
1182 }
1183 else
1184throw e;
1185}
1186
1187it->node().parent().remove_child(it->node());
1188 }
1189 else
1190 {
1191GOUROU_LOG(WARN, "Unsupported encryption algorithm " << encryptionType << ", for file " << encryptedFile);
1192removeEncryptionXML = false;
1193 }
1194}
1195
1196client->zipDeleteFile(zipHandler, "META-INF/rights.xml");
1197if (removeEncryptionXML)
1198 client->zipDeleteFile(zipHandler, "META-INF/encryption.xml");
1199else
1200{
1201 StringXMLWriter xmlWriter;
1202 encryptionDoc.save(xmlWriter, " ");
1203 std::string xmlStr = xmlWriter.getResult();
1204 ByteArray ba(xmlStr);
1205 client->zipWriteFile(zipHandler, "META-INF/encryption.xml", ba);
1206}
1207
1208client->zipClose(zipHandler);
1209 }
1210
1211 void DRMProcessor::generatePDFObjectKey(int version,
1212 const unsigned char* masterKey, unsigned int masterKeyLength,
1213 int objectId, int objectGenerationNumber,
1214 unsigned char* keyOut)
1215 {
1216switch(version)
1217{
1218case 4:
1219 ByteArray toHash(masterKey, masterKeyLength);
1220 uint32_t _objectId = objectId;
1221 uint32_t _objectGenerationNumber = objectGenerationNumber;
1222 toHash.append((const unsigned char*)&_objectId, 3); // Fill 3 bytes
1223 toHash.append((const unsigned char*)&_objectGenerationNumber, 2); // Fill 2 bytes
1224
1225 client->digest("md5", toHash.data(), toHash.length(), keyOut);
1226 break;
1227}
1228 }
1229
1230 void DRMProcessor::removePDFDRM(const std::string& filenameIn, const std::string& filenameOut,
1231 const unsigned char* encryptionKey, unsigned encryptionKeySize)
1232 {
1233uPDFParser::Parser parser;
1234bool EBXHandlerFound = false;
1235
1236if (filenameIn == filenameOut)
1237{
1238 EXCEPTION(DRM_IN_OUT_EQUALS, "PDF IN must be different of PDF OUT");
1239}
1240
1241try
1242{
1243 GOUROU_LOG(DEBUG, "Parse PDF");
1244 parser.parse(filenameIn);
1245}
1246catch(std::invalid_argument& e)
1247{
1248 GOUROU_LOG(ERROR, "Invalid PDF");
1249 return;
1250}
1251
1252uPDFParser::Integer* ebxVersion;
1253std::vector<uPDFParser::Object*> objects = parser.objects();
1254std::vector<uPDFParser::Object*>::iterator it;
1255std::vector<uPDFParser::Object*>::reverse_iterator rIt;
1256unsigned char decryptedKey[16];
1257int ebxId;
1258
1259for(rIt = objects.rbegin(); rIt != objects.rend(); rIt++)
1260{
1261 // Update EBX_HANDLER with rights
1262 if ((*rIt)->hasKey("Filter") && (**rIt)["Filter"]->str() == "/EBX_HANDLER")
1263 {
1264EBXHandlerFound = true;
1265uPDFParser::Object* ebx = *rIt;
1266
1267ebxVersion = (uPDFParser::Integer*)(*ebx)["V"];
1268if (ebxVersion->value() != 4)
1269{
1270 EXCEPTION(DRM_VERSION_NOT_SUPPORTED, "EBX encryption version not supported " << ebxVersion->value());
1271}
1272
1273if (!(ebx->hasKey("ADEPT_LICENSE")))
1274{
1275 EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "No ADEPT_LICENSE found");
1276}
1277
1278uPDFParser::String* licenseObject = (uPDFParser::String*)(*ebx)["ADEPT_LICENSE"];
1279
1280std::string value = licenseObject->value();
1281// Pad with '='
1282while ((value.size() % 4))
1283 value += "=";
1284ByteArray zippedData = ByteArray::fromBase64(value);
1285
1286if (zippedData.size() == 0)
1287 EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Invalid ADEPT_LICENSE");
1288
1289ByteArray rightsStr;
1290client->inflate(zippedData, rightsStr);
1291
1292pugi::xml_document rightsDoc;
1293rightsDoc.load_string((const char*)rightsStr.data());
1294
1295decryptADEPTKey(rightsDoc, decryptedKey, encryptionKey, encryptionKeySize);
1296
1297ebxId = ebx->objectId();
1298
1299break;
1300 }
1301}
1302
1303if (!EBXHandlerFound)
1304{
1305 EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "EBX_HANDLER not found");
1306}
1307
1308for(it = objects.begin(); it != objects.end(); it++)
1309{
1310 uPDFParser::Object* object = *it;
1311
1312 if (object->objectId() == ebxId)
1313 {
1314// object->deleteKey("Filter");
1315continue;
1316 }
1317
1318 // Should not decrypt XRef stream
1319 if (object->hasKey("Type") && (*object)["Type"]->str() == "/XRef")
1320 {
1321GOUROU_LOG(DEBUG, "XRef stream at " << object->offset());
1322continue;
1323 }
1324
1325 GOUROU_LOG(DEBUG, "Obj " << object->objectId());
1326
1327 unsigned char tmpKey[sizeof(decryptedKey)];
1328
1329 generatePDFObjectKey(ebxVersion->value(),
1330 decryptedKey, sizeof(decryptedKey),
1331 object->objectId(), object->generationNumber(),
1332 tmpKey);
1333
1334 uPDFParser::Dictionary& dictionary = object->dictionary();
1335 std::map<std::string, uPDFParser::DataType*>& dictValues = dictionary.value();
1336 std::map<std::string, uPDFParser::DataType*>::iterator dictIt;
1337 std::map<std::string, uPDFParser::DataType*> decodedStrings;
1338 std::string string;
1339
1340 /* Parse dictionary */
1341 for (dictIt = dictValues.begin(); dictIt != dictValues.end(); dictIt++)
1342 {
1343uPDFParser::DataType* dictData = dictIt->second;
1344if (dictData->type() == uPDFParser::DataType::STRING)
1345{
1346 string = ((uPDFParser::String*) dictData)->unescapedValue();
1347
1348 unsigned char* encryptedData = (unsigned char*)string.c_str();
1349 unsigned int dataLength = string.size();
1350 unsigned char* clearData = new unsigned char[dataLength];
1351 unsigned int dataOutLength;
1352
1353 GOUROU_LOG(DEBUG, "Decrypt string " << dictIt->first << " " << dataLength);
1354
1355 client->decrypt(CryptoInterface::ALGO_RC4, CryptoInterface::CHAIN_ECB,
1356 tmpKey, sizeof(tmpKey), /* Key */
1357 NULL, 0, /* IV */
1358 encryptedData, dataLength,
1359 clearData, &dataOutLength);
1360
1361 decodedStrings[dictIt->first] = new uPDFParser::String(
1362std::string((const char*)clearData, dataOutLength));
1363
1364 delete[] clearData;
1365}
1366 }
1367
1368 for (dictIt = decodedStrings.begin(); dictIt != decodedStrings.end(); dictIt++)
1369dictionary.replace(dictIt->first, dictIt->second);
1370
1371 std::vector<uPDFParser::DataType*>::iterator datasIt;
1372 std::vector<uPDFParser::DataType*>& datas = object->data();
1373 uPDFParser::Stream* stream;
1374
1375 for (datasIt = datas.begin(); datasIt != datas.end(); datasIt++)
1376 {
1377if ((*datasIt)->type() != uPDFParser::DataType::STREAM)
1378 continue;
1379
1380stream = (uPDFParser::Stream*) (*datasIt);
1381unsigned char* encryptedData = stream->data();
1382unsigned int dataLength = stream->dataLength();
1383unsigned char* clearData = new unsigned char[dataLength];
1384unsigned int dataOutLength;
1385
1386GOUROU_LOG(DEBUG, "Decrypt stream id " << object->objectId() << ", size " << stream->dataLength());
1387
1388client->decrypt(CryptoInterface::ALGO_RC4, CryptoInterface::CHAIN_ECB,
1389tmpKey, sizeof(tmpKey), /* Key */
1390NULL, 0, /* IV */
1391encryptedData, dataLength,
1392clearData, &dataOutLength);
1393
1394stream->setData(clearData, dataOutLength, true);
1395if (dataOutLength != dataLength)
1396 GOUROU_LOG(DEBUG, "New size " << dataOutLength);
1397 }
1398}
1399
1400uPDFParser::Object& trailer = parser.getTrailer();
1401trailer.deleteKey("Encrypt");
1402
1403parser.write(filenameOut);
1404 }
1405
1406 void DRMProcessor::removeDRM(const std::string& filenameIn, const std::string& filenameOut,
1407 ITEM_TYPE type, const unsigned char* encryptionKey, unsigned encryptionKeySize)
1408 {
1409if (type == PDF)
1410 removePDFDRM(filenameIn, filenameOut, encryptionKey, encryptionKeySize);
1411else
1412 removeEPubDRM(filenameIn, filenameOut, encryptionKey, encryptionKeySize);
1413 }
1414}

Archive Download this file