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 | #ifndef _LIBGOUROU_H_␊ |
21 | #define _LIBGOUROU_H_␊ |
22 | ␊ |
23 | #include "bytearray.h"␊ |
24 | #include "device.h"␊ |
25 | #include "user.h"␊ |
26 | #include "fulfillment_item.h"␊ |
27 | #include "drmprocessorclient.h"␊ |
28 | ␊ |
29 | #include <pugixml.hpp>␊ |
30 | #include <stdint.h>␊ |
31 | ␊ |
32 | #ifndef HOBBES_DEFAULT_VERSION␊ |
33 | #define HOBBES_DEFAULT_VERSION "10.0.4"␊ |
34 | #endif␊ |
35 | ␊ |
36 | #ifndef ACS_SERVER␊ |
37 | #define ACS_SERVER "http://adeactivate.adobe.com/adept"␊ |
38 | #endif␊ |
39 | ␊ |
40 | #define LIBGOUROU_VERSION "0.8.1"␊ |
41 | ␊ |
42 | namespace gourou␊ |
43 | {␊ |
44 | /**␊ |
45 | * @brief Main class that handle all ADEPTS functions (fulfill, download, signIn, activate)␊ |
46 | */␊ |
47 | class DRMProcessor␊ |
48 | {␊ |
49 | public:␊ |
50 | ␊ |
51 | ␉static const std::string VERSION;␊ |
52 | ␊ |
53 | ␉enum ITEM_TYPE { EPUB=0, PDF };␊ |
54 | ␉/**␊ |
55 | ␉ * @brief Main constructor. To be used once all is configured (user has signedIn, device is activated)␊ |
56 | ␉ *␊ |
57 | ␉ * @param client Client processor␊ |
58 | ␉ * @param deviceFile Path of device.xml␊ |
59 | ␉ * @param activationFile Path of activation.xml␊ |
60 | ␉ * @param deviceKeyFile Path of devicesalt␊ |
61 | ␉ */␊ |
62 | DRMProcessor(DRMProcessorClient* client, const std::string& deviceFile, const std::string& activationFile, const std::string& deviceKeyFile);␊ |
63 | ␉␊ |
64 | ␉~DRMProcessor();␊ |
65 | ␊ |
66 | ␉/**␊ |
67 | ␉ * @brief Fulfill ACSM file to server in order to retrieve ePub fulfillment item␊ |
68 | ␉ *␊ |
69 | ␉ * @param ACSMFile Path of ACSMFile␊ |
70 | ␉ *␊ |
71 | ␉ * @return a FulfillmentItem if all is OK␊ |
72 | ␉ */␊ |
73 | ␉FulfillmentItem* fulfill(const std::string& ACSMFile);␊ |
74 | ␊ |
75 | ␉/**␊ |
76 | ␉ * @brief Once fulfilled, ePub file needs to be downloaded.␊ |
77 | ␉ * During this operation, DRM information is added into downloaded file␊ |
78 | ␉ *␊ |
79 | ␉ * @param item Item from fulfill() method␊ |
80 | ␉ * @param path Output file path ␊ |
81 | ␉ * @param resume false if target file should be truncated, true to try resume download␊ |
82 | ␉ *␊ |
83 | ␉ * @return Type of downloaded item␊ |
84 | ␉ */␊ |
85 | ␉ITEM_TYPE download(FulfillmentItem* item, std::string path, bool resume=false);␊ |
86 | ␊ |
87 | ␉/**␊ |
88 | ␉ * @brief SignIn into ACS Server (required to activate device)␊ |
89 | ␉ * ␊ |
90 | ␉ * @param adobeID AdobeID username␊ |
91 | ␉ * @param adobePassword Adobe password␊ |
92 | ␉ */␊ |
93 | ␉void signIn(const std::string& adobeID, const std::string& adobePassword);␊ |
94 | ␊ |
95 | ␉/**␊ |
96 | ␉ * @brief Activate newly created device (user must have successfuly signedIn before)␊ |
97 | ␉ */␊ |
98 | ␉void activateDevice();␊ |
99 | ␊ |
100 | ␉/**␊ |
101 | ␉ * @brief Return loaned book to server␊ |
102 | ␉ *␊ |
103 | ␉ * @param loanID Loan ID received during fulfill␊ |
104 | ␉ * @param operatorURL URL of operator that loans this book␊ |
105 | ␉ */␊ |
106 | ␉void returnLoan(const std::string& loanID, const std::string& operatorURL);␊ |
107 | ␊ |
108 | ␉/**␊ |
109 | ␉ * @brief Return default ADEPT directory (ie /home/<user>/.config/adept)␊ |
110 | ␉ */␉ ␊ |
111 | ␉static std::string getDefaultAdeptDir(void);␊ |
112 | ␉␊ |
113 | ␉/**␊ |
114 | ␉ * @brief Create a new ADEPT environment (device.xml, devicesalt and activation.xml).␊ |
115 | ␉ *␊ |
116 | ␉ * @param client Client processor␊ |
117 | ␉ * @param randomSerial Always generate a new device (or not)␊ |
118 | ␉ * @param dirName Directory where to put generated files (.adept)␊ |
119 | ␉ * @param hobbes Override hobbes default version␊ |
120 | ␉ * @param ACSServer Override main ACS server (default adeactivate.adobe.com)␊ |
121 | ␉ */␊ |
122 | static DRMProcessor* createDRMProcessor(DRMProcessorClient* client,␊ |
123 | ␉␉␉␉␉␉bool randomSerial=false, std::string dirName=std::string(""),␊ |
124 | ␉␉␉␉␉␉const std::string& hobbes=std::string(HOBBES_DEFAULT_VERSION),␊ |
125 | ␉␉␉␉␉␉const std::string& ACSServer=ACS_SERVER);␊ |
126 | ␊ |
127 | ␉/**␊ |
128 | ␉ * @brief Get current log level␊ |
129 | ␉ */␊ |
130 | ␉static int getLogLevel();␊ |
131 | ␊ |
132 | ␉/**␊ |
133 | ␉ * @brief Set log level (higher number for verbose output)␊ |
134 | ␉ */␊ |
135 | ␉static void setLogLevel(int logLevel);␊ |
136 | ␊ |
137 | ␉/**␊ |
138 | ␉ * Functions used internally, should not be called by user␊ |
139 | ␉ */␊ |
140 | ␊ |
141 | ␉/**␊ |
142 | ␉ * @brief Send HTTP (GET or POST) request␊ |
143 | ␉ *␊ |
144 | ␉ * @param URL HTTP URL␊ |
145 | ␉ * @param POSTData POST data if needed, if not set, a GET request is done␊ |
146 | ␉ * @param contentType Optional content type of POST Data␊ |
147 | ␉ * @param responseHeaders Optional Response headers of HTTP request␊ |
148 | ␉ * @param fd Optional File descriptor to write received data␊ |
149 | ␉ * @param resume false if target file should be truncated, true to try resume download (works only in combination of a valid fd)␊ |
150 | ␉ *␊ |
151 | ␉ * @return data of HTTP response␊ |
152 | ␉ */␊ |
153 | ␉ByteArray sendRequest(const std::string& URL, const std::string& POSTData=std::string(), const char* contentType=0, std::map<std::string, std::string>* responseHeaders=0, int fd=0, bool resume=false);␊ |
154 | ␊ |
155 | ␉/**␊ |
156 | ␉ * @brief Send HTTP POST request to URL with document as POSTData␊ |
157 | ␉ */␊ |
158 | ␉ByteArray sendRequest(const pugi::xml_document& document, const std::string& url);␊ |
159 | ␊ |
160 | ␉/**␊ |
161 | ␉ * @brief In place encrypt data with private device key␊ |
162 | ␉ */␊ |
163 | ␉ByteArray encryptWithDeviceKey(const unsigned char* data, unsigned int len);␊ |
164 | ␊ |
165 | ␉/**␊ |
166 | ␉ * @brief In place decrypt data with private device key␊ |
167 | ␉ */␊ |
168 | ␉ByteArray decryptWithDeviceKey(const unsigned char* data, unsigned int len);␊ |
169 | ␊ |
170 | ␉/**␊ |
171 | ␉ * @brief Return base64 encoded value of RSA public key␊ |
172 | ␉ */␊ |
173 | ␉std::string serializeRSAPublicKey(void* rsa);␊ |
174 | ␊ |
175 | ␉/**␊ |
176 | ␉ * @brief Return base64 encoded value of RSA private key encrypted with private device key␊ |
177 | ␉ */␊ |
178 | ␉std::string serializeRSAPrivateKey(void* rsa);␊ |
179 | ␊ |
180 | ␉/**␊ |
181 | ␉ * @brief Export clear private license key into path␊ |
182 | ␉ */␊ |
183 | ␉void exportPrivateLicenseKey(std::string path);␊ |
184 | ␉␊ |
185 | ␉/**␊ |
186 | ␉ * @brief Get current user␊ |
187 | ␉ */␊ |
188 | ␉User* getUser() { return user; }␊ |
189 | ␊ |
190 | ␉/**␊ |
191 | ␉ * @brief Get current device␊ |
192 | ␉ */␊ |
193 | ␉Device* getDevice() { return device; }␊ |
194 | ␊ |
195 | ␉/**␊ |
196 | ␉ * @brief Get current client␊ |
197 | ␉ */␊ |
198 | ␉DRMProcessorClient* getClient() { return client; }␊ |
199 | ␉␉␊ |
200 | ␉/**␊ |
201 | ␉ * @brief Remove ADEPT DRM␊ |
202 | ␉ * Warning: for PDF format, filenameIn must be different than filenameOut␊ |
203 | ␉ *␊ |
204 | ␉ * @param filenameIn Input file (with ADEPT DRM)␊ |
205 | ␉ * @param filenameOut Output file (without ADEPT DRM)␊ |
206 | ␉ * @param type Type of file (ePub or PDF)␊ |
207 | ␉ * @param encryptionKey Optional encryption key, do not try to decrypt the one inside input file␊ |
208 | ␉ * @param encryptionKeySize Size of encryption key (if provided)␊ |
209 | ␉ */␊ |
210 | ␉void removeDRM(const std::string& filenameIn, const std::string& filenameOut, ITEM_TYPE type, const unsigned char* encryptionKey=0, unsigned encryptionKeySize=0);␊ |
211 | ␉␊ |
212 | private:␊ |
213 | ␉gourou::DRMProcessorClient* client;␊ |
214 | gourou::Device* device;␊ |
215 | gourou::User* user;␊ |
216 | ␉␊ |
217 | DRMProcessor(DRMProcessorClient* client);␊ |
218 | ␉␊ |
219 | ␉void pushString(void* sha_ctx, const std::string& string);␊ |
220 | ␉void pushTag(void* sha_ctx, uint8_t tag);␊ |
221 | ␉void hashNode(const pugi::xml_node& root, void *sha_ctx, std::map<std::string,std::string> nsHash);␊ |
222 | ␉void hashNode(const pugi::xml_node& root, unsigned char* sha_out);␊ |
223 | ␉void signNode(pugi::xml_node& rootNode);␊ |
224 | ␉void addNonce(pugi::xml_node& root);␊ |
225 | ␉void buildAuthRequest(pugi::xml_document& authReq);␊ |
226 | ␉void buildInitLicenseServiceRequest(pugi::xml_document& initLicReq, std::string operatorURL);␊ |
227 | ␉void doOperatorAuth(std::string operatorURL);␊ |
228 | ␉void operatorAuth(std::string operatorURL);␊ |
229 | ␉void buildFulfillRequest(pugi::xml_document& acsmDoc, pugi::xml_document& fulfillReq);␊ |
230 | ␉void buildActivateReq(pugi::xml_document& activateReq);␊ |
231 | ␉void buildReturnReq(pugi::xml_document& returnReq, const std::string& loanID, const std::string& operatorURL);␊ |
232 | ␉ByteArray sendFulfillRequest(const pugi::xml_document& document, const std::string& url);␊ |
233 | ␉void buildSignInRequest(pugi::xml_document& signInRequest, const std::string& adobeID, const std::string& adobePassword, const std::string& authenticationCertificate);␊ |
234 | ␉void fetchLicenseServiceCertificate(const std::string& licenseURL,␊ |
235 | ␉␉␉␉␉ const std::string& operatorURL);␊ |
236 | ␉std::string encryptedKeyFirstPass(pugi::xml_document& rightsDoc, const std::string& encryptedKey, const std::string& keyType);␊ |
237 | ␉void decryptADEPTKey(pugi::xml_document& rightsDoc, unsigned char* decryptedKey, const unsigned char* encryptionKey=0, unsigned encryptionKeySize=0);␊ |
238 | ␉void removeEPubDRM(const std::string& filenameIn, const std::string& filenameOut, const unsigned char* encryptionKey, unsigned encryptionKeySize);␊ |
239 | ␉void generatePDFObjectKey(int version,␊ |
240 | ␉␉␉␉ const unsigned char* masterKey, unsigned int masterKeyLength,␊ |
241 | ␉␉␉␉ int objectId, int objectGenerationNumber,␊ |
242 | ␉␉␉␉ unsigned char* keyOut);␊ |
243 | ␉void removePDFDRM(const std::string& filenameIn, const std::string& filenameOut, const unsigned char* encryptionKey, unsigned encryptionKeySize);␊ |
244 | };␊ |
245 | }␊ |
246 | ␊ |
247 | #endif␊ |