summaryrefslogtreecommitdiff
path: root/sys/src/cmd/gs/lib
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-02-20 00:21:45 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2015-02-20 00:21:45 +0100
commit0b016a77e42dfc33df4d46bdd4c817fa3ed5ac90 (patch)
treeb1c26f5712a9724de0fd276e86b119b2365a80ee /sys/src/cmd/gs/lib
parent13508a99a8955b98609ec7dcbf5f57069179a4de (diff)
gs: backport aes support for pdf-1.6
Diffstat (limited to 'sys/src/cmd/gs/lib')
-rw-r--r--sys/src/cmd/gs/lib/pdf_base.ps9
-rw-r--r--sys/src/cmd/gs/lib/pdf_main.ps2
-rw-r--r--sys/src/cmd/gs/lib/pdf_sec.ps180
3 files changed, 130 insertions, 61 deletions
diff --git a/sys/src/cmd/gs/lib/pdf_base.ps b/sys/src/cmd/gs/lib/pdf_base.ps
index 710e15c79..f969b883a 100644
--- a/sys/src/cmd/gs/lib/pdf_base.ps
+++ b/sys/src/cmd/gs/lib/pdf_base.ps
@@ -412,11 +412,10 @@ pdfdict begin
( **** Warning: wrong generation: )
} ifelse
2 index =string cvs concatstrings ( ) concatstrings % put obj #
- exch =string cvs concatstrings ( R\n) concatstrings % put gen #
+ 1 index =string cvs concatstrings ( R\n) concatstrings % put gen #
pdfformaterror % Output warning message
- } { % Else QUIET ...
- pop % Pop generation umber
- } ifelse false % Return false if gen # not match
+ } if
+ 0 eq
} ifelse
} bind def
/R { % <object#> <generation#> R <object>
@@ -642,7 +641,7 @@ pdfdict begin
% of the objects in sthe stream and place them into the Objects
% array.
% Stack: savepos objpos obj# objectstream#
- resolveobjectstream
+ resolveobjectstream
resolved? { % If object has already been resolved ...
exch pop % Remove object pos from stack.
} {
diff --git a/sys/src/cmd/gs/lib/pdf_main.ps b/sys/src/cmd/gs/lib/pdf_main.ps
index c4c352085..12ee8e6fc 100644
--- a/sys/src/cmd/gs/lib/pdf_main.ps
+++ b/sys/src/cmd/gs/lib/pdf_main.ps
@@ -25,6 +25,8 @@ pdfdict begin
% Patch in an obsolete variable used by some third-party software.
/#? false def
+/NoVerifyXref true def
+
% Test whether the current output device handles pdfmark.
/.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
/.writepdfmarks { % - .writepdfmarks <bool>
diff --git a/sys/src/cmd/gs/lib/pdf_sec.ps b/sys/src/cmd/gs/lib/pdf_sec.ps
index d982a740e..7a4cb1a03 100644
--- a/sys/src/cmd/gs/lib/pdf_sec.ps
+++ b/sys/src/cmd/gs/lib/pdf_sec.ps
@@ -39,6 +39,12 @@ pdfdict begin
currentdict end /ArcfourDecode filter
} bind def
+/aesdecodefilter {
+ 1 dict begin
+ /Key exch def
+ currentdict end /AESDecode filter
+} bind def
+
% <ciphertext> <key> arc4decode <plaintext>
/arc4decode {
%(key: ) print dup == (ct: ) print 1 index ==
@@ -49,6 +55,22 @@ pdfdict begin
} ifelse
} bind def
+/aesdecode {
+ 1 index length 0 eq {
+ pop
+ } {
+ 1 index length string 3 1 roll
+
+ % If our second argument is a dictionary, it's the full set
+ % of decoding options (including the key); pass it directly
+ % to the AESDecode filter. Otherwise, it's just the key, so
+ % call aesdecodefilter to construct the dictionary.
+ dup type /dicttype eq { /AESDecode filter } { aesdecodefilter } ifelse
+
+ exch readstring pop
+ } ifelse
+} bind def
+
/md5 {
16 string dup /MD5Encode filter dup 4 3 roll writestring closefile
} bind def
@@ -294,18 +316,38 @@ def
% put into a stream dictionary).
/computeobjkey % <object#> <generation#> computeobjkey <keystring>
{
- exch
- FileKey length 5 add string
- dup 0 FileKey putinterval
- exch
- % stack: gen# string obj#
- 2 copy 255 and FileKey length exch put
- 2 copy -8 bitshift 255 and FileKey length 1 add exch put
- 2 copy -16 bitshift 255 and FileKey length 2 add exch put
- pop exch
- 2 copy 255 and FileKey length 3 add exch put
- 2 copy -8 bitshift 255 and FileKey length 4 add exch put
- pop md5 0 FileKey length 5 add 2 index length .min getinterval
+ Trailer /Encrypt oget /V oget 5 eq {
+ % Encrypt version 5 doesn't use object keys; everything is
+ % encrypted with the file key.
+ pop pop FileKey
+ } {
+ exch
+ FileKey length 5 add string
+ dup 0 FileKey putinterval
+ exch
+ % stack: gen# string obj#
+ 2 copy 255 and FileKey length exch put
+ 2 copy -8 bitshift 255 and FileKey length 1 add exch put
+ 2 copy -16 bitshift 255 and FileKey length 2 add exch put
+ pop exch
+ 2 copy 255 and FileKey length 3 add exch put
+ 2 copy -8 bitshift 255 and FileKey length 4 add exch put
+ pop
+ % this step is for the AES cipher only
+ Trailer /Encrypt oget
+ dup /StmF knownoget {
+ exch /CF knownoget {
+ exch oget /CFM oget /AESV2 eq {
+ (sAlT) concatstrings
+ } if
+ } {
+ pop
+ } ifelse
+ } {
+ pop
+ } ifelse
+ md5 0 FileKey length 5 add 2 index length .min getinterval
+ } ifelse
} bind def
% As .pdfrun, but decrypt strings with key <key>.
@@ -351,17 +393,31 @@ def
{ % R < 4 --> encrypted strings
pop 1 index arc4decode % Decrypt string
PDFDEBUG { (%Decrypted: ) print dup == flush } if
- } { % Else R = 4
- /StrF knownoget % Get StrF (if present)
- { % If StrF is present ...
- /Identity eq not % Check if StrF != Identity
- { 1 index arc4decode % Decrypt string
- PDFDEBUG { (%Decrypted: ) print dup == flush } if
- }
- if % If StrF != identity
- }
- if % If StrF is known
- }
+ } { % Else R &gt;= 4
+ /StrF knownoget % Get StrF (if present)
+ { % If StrF is present ...
+ dup /Identity eq not % Check if StrF != Identity
+ { /StdCF eq
+ { Trailer /Encrypt oget /CF knownoget {
+ /StdCF oget /CFM oget
+ dup /AESV2 eq exch /AESV3 eq or
+ } {
+ //false
+ } ifelse { % Decrypt string
+ 1 index aesdecode
+ } {
+ 1 index arc4decode
+ } ifelse
+ }
+ { 1 index arc4decode }
+ ifelse % If StrF != StdCF
+ PDFDEBUG { (%Decrypted: ) print dup //== exec flush } if
+ }
+ { pop }
+ ifelse % If StrF != identity
+ }
+ if % If StrF is known
+ }
ifelse % Ifelse R < 4
}
if % If = stringtype
@@ -384,49 +440,55 @@ def
2 copy computeobjkey dup 4 1 roll
PDFfile exch resolveopdict .decpdfrun
dup dup dup 5 2 roll
- % stack: object object key object object
+ % stack: object object key object object
{ % Use loop to provide an exitable context.
xcheck exch type /dicttype eq and % Check if executable dictionary
not { % If object is not ...
pop pop % ignore object
exit % Exit 'loop' context
} if % If not possible stream
- % Starting with PDF 1.4 (R = 3), there are some extra features
- % which control encryption of streams. The EncryptMetadata entry
- % in the Encrypt dict controls the encryption of metadata streams.
+ % Starting with PDF 1.4 (R = 3), there are some extra features
+ % which control encryption of streams. The EncryptMetadata entry
+ % in the Encrypt dict controls the encryption of metadata streams.
Trailer /Encrypt oget % Get encryption dictionary
dup /R oget dup 3 lt % Only PDF 1.4 and higher has options
- { % R < 3 --> all streams encrypted
+ { % R &lt; 3 --&gt; all streams encrypted
pop pop /StreamKey exch put % Insert StreamKey in dictionary
- exit % Exit 'loop' context
+ exit % Exit 'loop' context
} if
- % Check EncryptMeta. stack: object object key Encrypt R
+ % Check EncryptMeta. stack: object object key Encrypt R
exch dup /EncryptMetadata knownoget % Get EncryptMetadata (if present)
- not { true } if % If not present default = true
+ not { //true } if % If not present default = true
not % Check if EncryptMetadata = false
- { % if false we need to check the stream type
- 3 index /Type knownoget % Get stream type (if present)
- not { //null } if % If type not present use fake name
- /Metadata eq % Check if the type is Metadata
- { pop pop pop pop % Type == Metadata --> no encryption
- exit % Exit 'loop' context
+ { % if false we need to check the stream type
+ 3 index /Type knownoget % Get stream type (if present)
+ not { //null } if % If type not present use fake name
+ /Metadata eq % Check if the type is Metadata
+ { pop pop pop pop % Type == Metadata --&gt; no encryption
+ exit % Exit 'loop' context
} if
} if
- % PDF 1.5 encryption (R == 4) has selectable encryption handlers. If
- % this is not PDF 1.5 encryption (R < 4) then we are done checking and
- % we need to decrypt the stream. stack: object object key R Encrypt
+ % PDF 1.5 encryption (R == 4) has selectable encryption handlers. If
+ % this is not PDF 1.5 encryption (R &lt; 4) then we are done checking and
+ % we need to decrypt the stream. stack: object object key R Encrypt
exch 4 lt % Check for less than PDF 1.5
{ pop /StreamKey exch put % Insert StreamKey in dictionary
- exit % Exit 'loop' context
+ exit % Exit 'loop' context
+ } if
+ % Check if the stream encryption handler (StmF) == Identity.
+ PDFDEBUG {
+ Trailer /Encrypt oget /CF knownoget {
+ /StdCF oget /CFM oget
+ (Encrypt StmF is StdCF with CFM ) print =
+ } if
} if
- % Check if the stream encryption handler (StmF) == Identity.
/StmF knownoget % Get StmF (if present)
not { /Identity } if % If StmF not present default = Identity
- /Identity eq % Check if StmF == Identity
- { pop pop % Identity --> no encryption
- exit % Exit 'loop' context
+ /Identity eq % Check if StmF == Identity
+ { pop pop % Identity --&gt; no encryption
+ exit % Exit 'loop' context
} if
- % If we get here then we need to decrypt the stream.
+ % If we get here then we need to decrypt the stream.
/StreamKey exch put % Insert StreamKey into dictionary
exit % Exit 'loop' context, never loop
} loop % End of loop exitable context
@@ -441,16 +503,22 @@ def
/pdf_decrypt_stream
{ 3 index /StreamKey known % Check if the file is encrypted
{
- exch
- % Stack: readdata? dict parms filternames file/string
- 3 index /Length oget
- dup 0 eq {
- % Handle Length=0 case specially to avoid SubFileDecode semantics
- pop pop ()
- } {
- () /SubFileDecode filter
- } ifelse
- 3 index /StreamKey get arc4decodefilter
+ exch
+ % Stack: readdata? dict parms filternames file/string
+ 3 index /StreamKey get
+ Trailer /Encrypt oget
+ dup /StmF knownoget
+ { % stack: key Encrypt StmF
+ exch /CF knownoget {
+ exch oget /CFM oget % stack: key StmF-CFM
+ dup /AESV2 eq exch /AESV3 eq or
+ } { pop //false } ifelse
+ { aesdecodefilter } % install the requested filter
+ { arc4decodefilter }
+ ifelse
+ }
+ { pop arc4decodefilter } % fallback for no StmF
+ ifelse
exch
} if
} bind def