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
28HPDF_EncryptDict
29HPDF_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
60void
61HPDF_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
126HPDF_STATUS
127HPDF_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
177void
178HPDF_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
189HPDF_STATUS
190HPDF_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
212HPDF_BOOL
213HPDF_EncryptDict_Validate (HPDF_EncryptDict dict)
214{
215 HPDF_Obj_Header *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
229HPDF_Encrypt
230HPDF_EncryptDict_GetAttr (HPDF_EncryptDict dict)
231{
232 HPDF_Obj_Header *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