1 | /* |
2 | * << Haru Free PDF Library >> -- hpdf_encryptdict.c |
3 | * |
4 | * URL: http://libharu.org |
5 | * |
6 | * Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp> |
7 | * Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org> |
8 | * |
9 | * Permission to use, copy, modify, distribute and sell this software |
10 | * and its documentation for any purpose is hereby granted without fee, |
11 | * provided that the above copyright notice appear in all copies and |
12 | * that both that copyright notice and this permission notice appear |
13 | * in supporting documentation. |
14 | * It is provided "as is" without express or implied warranty. |
15 | * |
16 | */ |
17 | |
18 | #include <time.h> |
19 | #include "hpdf_conf.h" |
20 | #include "hpdf_utils.h" |
21 | #include "hpdf_objects.h" |
22 | #include "hpdf_encryptdict.h" |
23 | #include "hpdf_info.h" |
24 | #ifndef HPDF_UNUSED |
25 | #define HPDF_UNUSED(a) ((void)(a)) |
26 | #endif |
27 | |
28 | HPDF_EncryptDict |
29 | HPDF_EncryptDict_New (HPDF_MMgr mmgr, |
30 | HPDF_Xref xref) |
31 | { |
32 | HPDF_Encrypt attr; |
33 | HPDF_EncryptDict dict; |
34 | |
35 | HPDF_PTRACE((" HPDF_EncryptDict_New\n" )); |
36 | |
37 | dict = HPDF_Dict_New (mmgr); |
38 | if (!dict) |
39 | return NULL; |
40 | |
41 | dict->header.obj_class |= HPDF_OSUBCLASS_ENCRYPT; |
42 | dict->free_fn = HPDF_EncryptDict_OnFree; |
43 | |
44 | attr = HPDF_GetMem (dict->mmgr, sizeof(HPDF_Encrypt_Rec)); |
45 | if (!attr) { |
46 | HPDF_Dict_Free (dict); |
47 | return NULL; |
48 | } |
49 | |
50 | dict->attr = attr; |
51 | HPDF_Encrypt_Init (attr); |
52 | |
53 | if (HPDF_Xref_Add (xref, dict) != HPDF_OK) |
54 | return NULL; |
55 | |
56 | return dict; |
57 | } |
58 | |
59 | |
60 | void |
61 | HPDF_EncryptDict_CreateID (HPDF_EncryptDict dict, |
62 | HPDF_Dict info, |
63 | HPDF_Xref xref) |
64 | { |
65 | HPDF_MD5_CTX ctx; |
66 | HPDF_Encrypt attr = (HPDF_Encrypt)dict->attr; |
67 | |
68 | /* use the result of 'time' function to get random value. |
69 | * when debugging, 'time' value is ignored. |
70 | */ |
71 | #ifndef LIBHPDF_DEBUG |
72 | time_t t = HPDF_TIME (NULL); |
73 | #endif /* LIBHPDF_DEBUG */ |
74 | |
75 | HPDF_MD5Init (&ctx); |
76 | HPDF_UNUSED (xref); |
77 | HPDF_UNUSED (info); |
78 | |
79 | #ifndef LIBHPDF_DEBUG |
80 | HPDF_MD5Update(&ctx, (HPDF_BYTE *)&t, sizeof(t)); |
81 | |
82 | /* create File Identifier from elements of Into dictionary. */ |
83 | if (info) { |
84 | const char *s; |
85 | HPDF_UINT len; |
86 | |
87 | /* Author */ |
88 | s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_AUTHOR); |
89 | if ((len = HPDF_StrLen (s, -1)) > 0) |
90 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len); |
91 | |
92 | /* Creator */ |
93 | s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_CREATOR); |
94 | if ((len = HPDF_StrLen (s, -1)) > 0) |
95 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len); |
96 | |
97 | /* Producer */ |
98 | s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_PRODUCER); |
99 | if ((len = HPDF_StrLen (s, -1)) > 0) |
100 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len); |
101 | |
102 | /* Title */ |
103 | s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_TITLE); |
104 | if ((len = HPDF_StrLen (s, -1)) > 0) |
105 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len); |
106 | |
107 | /* Subject */ |
108 | s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_SUBJECT); |
109 | if ((len = HPDF_StrLen (s, -1)) > 0) |
110 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len); |
111 | |
112 | /* Keywords */ |
113 | s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_KEYWORDS); |
114 | if ((len = HPDF_StrLen (s, -1)) > 0) |
115 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len); |
116 | |
117 | HPDF_MD5Update(&ctx, (const HPDF_BYTE *)&(xref->entries->count), |
118 | sizeof(HPDF_UINT32)); |
119 | |
120 | } |
121 | #endif |
122 | HPDF_MD5Final(attr->encrypt_id, &ctx); |
123 | } |
124 | |
125 | |
126 | HPDF_STATUS |
127 | HPDF_EncryptDict_Prepare (HPDF_EncryptDict dict, |
128 | HPDF_Dict info, |
129 | HPDF_Xref xref) |
130 | { |
131 | HPDF_STATUS ret; |
132 | HPDF_Encrypt attr = (HPDF_Encrypt)dict->attr; |
133 | HPDF_Binary user_key; |
134 | HPDF_Binary owner_key; |
135 | |
136 | HPDF_PTRACE((" HPDF_EncryptDict_Prepare\n" )); |
137 | |
138 | HPDF_EncryptDict_CreateID (dict, info, xref); |
139 | HPDF_Encrypt_CreateOwnerKey (attr); |
140 | HPDF_Encrypt_CreateEncryptionKey (attr); |
141 | HPDF_Encrypt_CreateUserKey (attr); |
142 | |
143 | owner_key = HPDF_Binary_New (dict->mmgr, attr->owner_key, HPDF_PASSWD_LEN); |
144 | if (!owner_key) |
145 | return HPDF_Error_GetCode (dict->error); |
146 | |
147 | if ((ret = HPDF_Dict_Add (dict, "O" , owner_key)) != HPDF_OK) |
148 | return ret; |
149 | |
150 | user_key = HPDF_Binary_New (dict->mmgr, attr->user_key, HPDF_PASSWD_LEN); |
151 | if (!user_key) |
152 | return HPDF_Error_GetCode (dict->error); |
153 | |
154 | if ((ret = HPDF_Dict_Add (dict, "U" , user_key)) != HPDF_OK) |
155 | return ret; |
156 | |
157 | ret += HPDF_Dict_AddName (dict, "Filter" , "Standard" ); |
158 | |
159 | if (attr->mode == HPDF_ENCRYPT_R2) { |
160 | ret += HPDF_Dict_AddNumber (dict, "V" , 1); |
161 | ret += HPDF_Dict_AddNumber (dict, "R" , 2); |
162 | } else if (attr->mode == HPDF_ENCRYPT_R3) { |
163 | ret += HPDF_Dict_AddNumber (dict, "V" , 2); |
164 | ret += HPDF_Dict_AddNumber (dict, "R" , 3); |
165 | ret += HPDF_Dict_AddNumber (dict, "Length" , attr->key_len * 8); |
166 | } |
167 | |
168 | ret += HPDF_Dict_AddNumber (dict, "P" , attr->permission); |
169 | |
170 | if (ret != HPDF_OK) |
171 | return HPDF_Error_GetCode (dict->error); |
172 | |
173 | return HPDF_OK; |
174 | } |
175 | |
176 | |
177 | void |
178 | HPDF_EncryptDict_OnFree (HPDF_Dict obj) |
179 | { |
180 | HPDF_Encrypt attr = (HPDF_Encrypt)obj->attr; |
181 | |
182 | HPDF_PTRACE((" HPDF_EncryptDict_OnFree\n" )); |
183 | |
184 | if (attr) |
185 | HPDF_FreeMem (obj->mmgr, attr); |
186 | } |
187 | |
188 | |
189 | HPDF_STATUS |
190 | HPDF_EncryptDict_SetPassword (HPDF_EncryptDict dict, |
191 | const char *owner_passwd, |
192 | const char *user_passwd) |
193 | { |
194 | HPDF_Encrypt attr = (HPDF_Encrypt)dict->attr; |
195 | |
196 | HPDF_PTRACE((" HPDF_EncryptDict_SetPassword\n" )); |
197 | |
198 | if (HPDF_StrLen(owner_passwd, 2) == 0) |
199 | return HPDF_SetError(dict->error, HPDF_ENCRYPT_INVALID_PASSWORD, 0); |
200 | |
201 | if (owner_passwd && user_passwd && |
202 | HPDF_StrCmp (owner_passwd, user_passwd) == 0) |
203 | return HPDF_SetError(dict->error, HPDF_ENCRYPT_INVALID_PASSWORD, 0); |
204 | |
205 | HPDF_PadOrTrancatePasswd (owner_passwd, attr->owner_passwd); |
206 | HPDF_PadOrTrancatePasswd (user_passwd, attr->user_passwd); |
207 | |
208 | return HPDF_OK; |
209 | } |
210 | |
211 | |
212 | HPDF_BOOL |
213 | HPDF_EncryptDict_Validate (HPDF_EncryptDict dict) |
214 | { |
215 | HPDF_Obj_Header * = (HPDF_Obj_Header *)dict; |
216 | |
217 | HPDF_PTRACE((" HPDF_EncryptDict_Validate\n" )); |
218 | |
219 | if (!dict || !dict->attr) |
220 | return HPDF_FALSE; |
221 | |
222 | if (header->obj_class != (HPDF_OCLASS_DICT | HPDF_OSUBCLASS_ENCRYPT)) |
223 | return HPDF_FALSE; |
224 | |
225 | return HPDF_TRUE; |
226 | } |
227 | |
228 | |
229 | HPDF_Encrypt |
230 | HPDF_EncryptDict_GetAttr (HPDF_EncryptDict dict) |
231 | { |
232 | HPDF_Obj_Header * = (HPDF_Obj_Header *)dict; |
233 | |
234 | HPDF_PTRACE((" HPDF_EncryptDict_GetAttr\n" )); |
235 | |
236 | if (dict && dict->attr && |
237 | (header->obj_class == (HPDF_OCLASS_DICT | HPDF_OSUBCLASS_ENCRYPT))) |
238 | return (HPDF_Encrypt)dict->attr; |
239 | |
240 | return NULL; |
241 | } |
242 | |
243 | |
244 | |