summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2005-03-03 03:28:17 +0100
committerTor Andersson <tor@ghostscript.com>2005-03-03 03:28:17 +0100
commitb52684f74f105429ca7a3da862e1999764a9063d (patch)
treea9a9c7b2adcd255e99f325f47ac172e1238e78b0
parentee7063d6e2f22d6ceac6bb15b6589e4165bb5f57 (diff)
downloadmupdf-b52684f74f105429ca7a3da862e1999764a9063d.tar.xz
check owner password
-rw-r--r--include/mupdf/syntax.h2
-rw-r--r--mupdf/crypt.c91
2 files changed, 75 insertions, 18 deletions
diff --git a/include/mupdf/syntax.h b/include/mupdf/syntax.h
index c25dcb01..54eafa9e 100644
--- a/include/mupdf/syntax.h
+++ b/include/mupdf/syntax.h
@@ -54,6 +54,8 @@ struct pdf_crypt_s
fz_error *pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id);
fz_error *pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj *id);
fz_error *pdf_setpassword(pdf_crypt *crypt, char *pw);
+fz_error *pdf_setuserpassword(pdf_crypt *crypt, char *pw, int pwlen);
+fz_error *pdf_setownerpassword(pdf_crypt *crypt, char *pw, int pwlen);
fz_error *pdf_cryptstream(fz_filter **fp, pdf_crypt *crypt, int oid, int gid);
void pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid);
void pdf_dropcrypt(pdf_crypt *crypt);
diff --git a/mupdf/crypt.c b/mupdf/crypt.c
index d0cf1084..2732256e 100644
--- a/mupdf/crypt.c
+++ b/mupdf/crypt.c
@@ -35,13 +35,12 @@ static void voodoo19(unsigned char *data, int ndata, unsigned char *key, int nke
}
}
-static void padpassword(unsigned char *buf, char *pw)
+static void padpassword(unsigned char *buf, char *pw, int pwlen)
{
- int len = strlen(pw);
- if (len > 32)
- len = 32;
- memcpy(buf, pw, len);
- memcpy(buf + len, padding, 32 - len);
+ if (pwlen > 32)
+ pwlen = 32;
+ memcpy(buf, pw, pwlen);
+ memcpy(buf + pwlen, padding, 32 - pwlen);
}
/*
@@ -62,7 +61,7 @@ pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id)
if (m != 1 && m != 2)
return fz_throw("unsupported encryption: %d", m);
- crypt = fz_malloc(sizeof(pdf_crypt));
+ crypt = fz_malloc(sizeof(pdf_crypt));
if (!crypt)
return fz_outofmem;
@@ -141,7 +140,7 @@ createobjkey(pdf_crypt *crypt, unsigned oid, unsigned gid, unsigned char *key)
fz_md5init(&md5);
fz_md5update(&md5, crypt->key, crypt->n);
-
+
message[0] = oid & 0xFF;
message[1] = (oid >> 8) & 0xFF;
message[2] = (oid >> 16) & 0xFF;
@@ -158,14 +157,14 @@ createobjkey(pdf_crypt *crypt, unsigned oid, unsigned gid, unsigned char *key)
* Algorithm 3.2 Computing an encryption key
*/
static void
-createkey(pdf_crypt *crypt, char *userpw)
+createkey(pdf_crypt *crypt, char *userpw, int pwlen)
{
unsigned char buf[32];
fz_md5 md5;
/* Step 1 + 2 */
fz_md5init(&md5);
- padpassword(buf, userpw);
+ padpassword(buf, userpw, pwlen);
fz_md5update(&md5, buf, 32);
/* Step 3 */
@@ -203,7 +202,7 @@ createowner(pdf_crypt *crypt, char *userpw, char *ownerpw)
/* Step 1 + 2 */
if (strlen(ownerpw) == 0)
ownerpw = userpw;
- padpassword(buf, ownerpw);
+ padpassword(buf, ownerpw, strlen(ownerpw));
fz_md5init(&md5);
fz_md5update(&md5, buf, 32);
fz_md5final(&md5, key);
@@ -216,7 +215,7 @@ createowner(pdf_crypt *crypt, char *userpw, char *ownerpw)
fz_arc4init(&arc4, key, crypt->n);
/* Step 5 */
- padpassword(buf, userpw);
+ padpassword(buf, userpw, strlen(ownerpw));
/* Step 6 */
fz_arc4encrypt(&arc4, buf, buf, 32);
@@ -234,21 +233,21 @@ createowner(pdf_crypt *crypt, char *userpw, char *ownerpw)
* Algorithm 3.5 Computing the U value (rev 3)
*/
static void
-createuser(pdf_crypt *crypt, char *userpw)
+createuser(pdf_crypt *crypt, char *userpw, int pwlen)
{
unsigned char key[16];
fz_arc4 arc4;
fz_md5 md5;
if (crypt->r == 2) {
- createkey(crypt, userpw);
+ createkey(crypt, userpw, pwlen);
fz_arc4init(&arc4, crypt->key, crypt->n);
fz_arc4encrypt(&arc4, crypt->u, padding, 32);
}
if (crypt->r == 3) {
/* Step 1 */
- createkey(crypt, userpw);
+ createkey(crypt, userpw, pwlen);
/* Step 2 */
fz_md5init(&md5);
@@ -293,7 +292,7 @@ pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj
crypt->r = crypt->n == 5 ? 2 : 3;
createowner(crypt, userpw, ownerpw);
- createuser(crypt, userpw);
+ createuser(crypt, userpw, strlen(userpw));
error = fz_packobj(&crypt->encrypt,
"<< /Filter /Standard "
@@ -320,14 +319,27 @@ pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj
/*
* Algorithm 3.6 Checking the user password
*/
+
+fz_error *
+pdf_setpassword(pdf_crypt *crypt, char *pw)
+{
+ fz_error *error = pdf_setuserpassword(crypt, pw, strlen(pw));
+ if (error)
+ {
+ fz_droperror(error);
+ error = pdf_setownerpassword(crypt, pw, strlen(pw));
+ }
+ return error;
+}
+
fz_error *
-pdf_setpassword(pdf_crypt *crypt, char *userpw)
+pdf_setuserpassword(pdf_crypt *crypt, char *userpw, int pwlen)
{
unsigned char saved[32];
unsigned char test[32];
memcpy(saved, crypt->u, 32);
- createuser(crypt, userpw);
+ createuser(crypt, userpw, pwlen);
memcpy(test, crypt->u, 32);
memcpy(crypt->u, saved, 32);
@@ -337,6 +349,49 @@ pdf_setpassword(pdf_crypt *crypt, char *userpw)
return nil;
}
+fz_error *
+pdf_setownerpassword(pdf_crypt *crypt, char *ownerpw, int pwlen)
+{
+ unsigned char buf[32];
+ unsigned char key[16];
+ fz_arc4 arc4;
+ fz_md5 md5;
+
+ /* Step 1 + 2 */
+ padpassword(buf, ownerpw, pwlen);
+ fz_md5init(&md5);
+ fz_md5update(&md5, buf, 32);
+ fz_md5final(&md5, key);
+
+ /* Step 3 (rev 3 only) */
+ if (crypt->r == 3)
+ voodoo50(key, crypt->n);
+
+ /* Step 4 */
+ fz_arc4init(&arc4, key, crypt->n);
+
+ if (crypt->r == 2) {
+ fz_arc4encrypt(&arc4, buf, crypt->o, 32);
+ }
+
+ if (crypt->r == 3) {
+ unsigned char keyxor[16];
+ int i;
+ int k;
+
+ memcpy(buf, crypt->o, 32);
+
+ for(i = 19; i >= 0; --i) {
+ for(k = 0; k < crypt->keylen; ++k)
+ keyxor[k] = key[k] ^ i;
+ fz_arc4init(&arc4, keyxor, crypt->keylen);
+ fz_arc4encrypt(&arc4, buf, buf, 32);
+ }
+ }
+
+ return pdf_setuserpassword(crypt, buf, 32);
+}
+
/*
* Recursively (and destructively!) de/encrypt all strings in obj
*/