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
HPDF_EncryptDict_New(HPDF_MMgr mmgr,HPDF_Xref xref)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
HPDF_EncryptDict_CreateID(HPDF_EncryptDict dict,HPDF_Dict info,HPDF_Xref xref)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
HPDF_EncryptDict_Prepare(HPDF_EncryptDict dict,HPDF_Dict info,HPDF_Xref xref)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
HPDF_EncryptDict_OnFree(HPDF_Dict obj)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
HPDF_EncryptDict_SetPassword(HPDF_EncryptDict dict,const char * owner_passwd,const char * user_passwd)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
HPDF_EncryptDict_Validate(HPDF_EncryptDict dict)213 HPDF_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 
229 HPDF_Encrypt
HPDF_EncryptDict_GetAttr(HPDF_EncryptDict dict)230 HPDF_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