gs: backport aes support for pdf-1.6

This commit is contained in:
cinap_lenrek 2015-02-20 00:21:45 +01:00
parent 13508a99a8
commit 0b016a77e4
14 changed files with 564 additions and 119 deletions

View file

@ -641,7 +641,7 @@ pdfdict begin
% of the objects in sthe stream and place them into the Objects % of the objects in sthe stream and place them into the Objects
% array. % array.
% Stack: savepos objpos obj# objectstream# % Stack: savepos objpos obj# objectstream#
resolveobjectstream resolveobjectstream
resolved? { % If object has already been resolved ... resolved? { % If object has already been resolved ...
exch pop % Remove object pos from stack. exch pop % Remove object pos from stack.
} { } {

View file

@ -39,6 +39,12 @@ pdfdict begin
currentdict end /ArcfourDecode filter currentdict end /ArcfourDecode filter
} bind def } bind def
/aesdecodefilter {
1 dict begin
/Key exch def
currentdict end /AESDecode filter
} bind def
% <ciphertext> <key> arc4decode <plaintext> % <ciphertext> <key> arc4decode <plaintext>
/arc4decode { /arc4decode {
%(key: ) print dup == (ct: ) print 1 index == %(key: ) print dup == (ct: ) print 1 index ==
@ -49,6 +55,22 @@ pdfdict begin
} ifelse } ifelse
} bind def } 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 { /md5 {
16 string dup /MD5Encode filter dup 4 3 roll writestring closefile 16 string dup /MD5Encode filter dup 4 3 roll writestring closefile
} bind def } bind def
@ -294,18 +316,38 @@ def
% put into a stream dictionary). % put into a stream dictionary).
/computeobjkey % <object#> <generation#> computeobjkey <keystring> /computeobjkey % <object#> <generation#> computeobjkey <keystring>
{ {
exch Trailer /Encrypt oget /V oget 5 eq {
FileKey length 5 add string % Encrypt version 5 doesn't use object keys; everything is
dup 0 FileKey putinterval % encrypted with the file key.
exch pop pop FileKey
% stack: gen# string obj# } {
2 copy 255 and FileKey length exch put exch
2 copy -8 bitshift 255 and FileKey length 1 add exch put FileKey length 5 add string
2 copy -16 bitshift 255 and FileKey length 2 add exch put dup 0 FileKey putinterval
pop exch exch
2 copy 255 and FileKey length 3 add exch put % stack: gen# string obj#
2 copy -8 bitshift 255 and FileKey length 4 add exch put 2 copy 255 and FileKey length exch put
pop md5 0 FileKey length 5 add 2 index length .min getinterval 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 } bind def
% As .pdfrun, but decrypt strings with key <key>. % As .pdfrun, but decrypt strings with key <key>.
@ -351,17 +393,31 @@ def
{ % R < 4 --> encrypted strings { % R < 4 --> encrypted strings
pop 1 index arc4decode % Decrypt string pop 1 index arc4decode % Decrypt string
PDFDEBUG { (%Decrypted: ) print dup == flush } if PDFDEBUG { (%Decrypted: ) print dup == flush } if
} { % Else R = 4 } { % Else R &gt;= 4
/StrF knownoget % Get StrF (if present) /StrF knownoget % Get StrF (if present)
{ % If StrF is present ... { % If StrF is present ...
/Identity eq not % Check if StrF != Identity dup /Identity eq not % Check if StrF != Identity
{ 1 index arc4decode % Decrypt string { /StdCF eq
PDFDEBUG { (%Decrypted: ) print dup == flush } if { Trailer /Encrypt oget /CF knownoget {
} /StdCF oget /CFM oget
if % If StrF != identity dup /AESV2 eq exch /AESV3 eq or
} } {
if % If StrF is known //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 ifelse % Ifelse R < 4
} }
if % If = stringtype if % If = stringtype
@ -384,49 +440,55 @@ def
2 copy computeobjkey dup 4 1 roll 2 copy computeobjkey dup 4 1 roll
PDFfile exch resolveopdict .decpdfrun PDFfile exch resolveopdict .decpdfrun
dup dup dup 5 2 roll 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. { % Use loop to provide an exitable context.
xcheck exch type /dicttype eq and % Check if executable dictionary xcheck exch type /dicttype eq and % Check if executable dictionary
not { % If object is not ... not { % If object is not ...
pop pop % ignore object pop pop % ignore object
exit % Exit 'loop' context exit % Exit 'loop' context
} if % If not possible stream } if % If not possible stream
% Starting with PDF 1.4 (R = 3), there are some extra features % Starting with PDF 1.4 (R = 3), there are some extra features
% which control encryption of streams. The EncryptMetadata entry % which control encryption of streams. The EncryptMetadata entry
% in the Encrypt dict controls the encryption of metadata streams. % in the Encrypt dict controls the encryption of metadata streams.
Trailer /Encrypt oget % Get encryption dictionary Trailer /Encrypt oget % Get encryption dictionary
dup /R oget dup 3 lt % Only PDF 1.4 and higher has options 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 pop pop /StreamKey exch put % Insert StreamKey in dictionary
exit % Exit 'loop' context exit % Exit 'loop' context
} if } 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) 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 not % Check if EncryptMetadata = false
{ % if false we need to check the stream type { % if false we need to check the stream type
3 index /Type knownoget % Get stream type (if present) 3 index /Type knownoget % Get stream type (if present)
not { //null } if % If type not present use fake name not { //null } if % If type not present use fake name
/Metadata eq % Check if the type is Metadata /Metadata eq % Check if the type is Metadata
{ pop pop pop pop % Type == Metadata --> no encryption { pop pop pop pop % Type == Metadata --&gt; no encryption
exit % Exit 'loop' context exit % Exit 'loop' context
} if } if
} if } if
% PDF 1.5 encryption (R == 4) has selectable encryption handlers. 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 % 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 % we need to decrypt the stream. stack: object object key R Encrypt
exch 4 lt % Check for less than PDF 1.5 exch 4 lt % Check for less than PDF 1.5
{ pop /StreamKey exch put % Insert StreamKey in dictionary { 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 } if
% Check if the stream encryption handler (StmF) == Identity.
/StmF knownoget % Get StmF (if present) /StmF knownoget % Get StmF (if present)
not { /Identity } if % If StmF not present default = Identity not { /Identity } if % If StmF not present default = Identity
/Identity eq % Check if StmF == Identity /Identity eq % Check if StmF == Identity
{ pop pop % Identity --> no encryption { pop pop % Identity --&gt; no encryption
exit % Exit 'loop' context exit % Exit 'loop' context
} if } 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 /StreamKey exch put % Insert StreamKey into dictionary
exit % Exit 'loop' context, never loop exit % Exit 'loop' context, never loop
} loop % End of loop exitable context } loop % End of loop exitable context
@ -441,16 +503,22 @@ def
/pdf_decrypt_stream /pdf_decrypt_stream
{ 3 index /StreamKey known % Check if the file is encrypted { 3 index /StreamKey known % Check if the file is encrypted
{ {
exch exch
% Stack: readdata? dict parms filternames file/string % Stack: readdata? dict parms filternames file/string
3 index /Length oget 3 index /StreamKey get
dup 0 eq { Trailer /Encrypt oget
% Handle Length=0 case specially to avoid SubFileDecode semantics dup /StmF knownoget
pop pop () { % stack: key Encrypt StmF
} { exch /CF knownoget {
() /SubFileDecode filter exch oget /CFM oget % stack: key StmF-CFM
} ifelse dup /AESV2 eq exch /AESV3 eq or
3 index /StreamKey get arc4decodefilter } { pop //false } ifelse
{ aesdecodefilter } % install the requested filter
{ arc4decodefilter }
ifelse
}
{ pop arc4decodefilter } % fallback for no StmF
ifelse
exch exch
} if } if
} bind def } bind def

View file

@ -412,11 +412,10 @@ pdfdict begin
( **** Warning: wrong generation: ) ( **** Warning: wrong generation: )
} ifelse } ifelse
2 index =string cvs concatstrings ( ) concatstrings % put obj # 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 pdfformaterror % Output warning message
} { % Else QUIET ... } if
pop % Pop generation umber 0 eq
} ifelse false % Return false if gen # not match
} ifelse } ifelse
} bind def } bind def
/R { % <object#> <generation#> R <object> /R { % <object#> <generation#> R <object>
@ -642,7 +641,7 @@ pdfdict begin
% of the objects in sthe stream and place them into the Objects % of the objects in sthe stream and place them into the Objects
% array. % array.
% Stack: savepos objpos obj# objectstream# % Stack: savepos objpos obj# objectstream#
resolveobjectstream resolveobjectstream
resolved? { % If object has already been resolved ... resolved? { % If object has already been resolved ...
exch pop % Remove object pos from stack. exch pop % Remove object pos from stack.
} { } {

View file

@ -25,6 +25,8 @@ pdfdict begin
% Patch in an obsolete variable used by some third-party software. % Patch in an obsolete variable used by some third-party software.
/#? false def /#? false def
/NoVerifyXref true def
% Test whether the current output device handles pdfmark. % Test whether the current output device handles pdfmark.
/.writepdfmarkdict 1 dict dup /pdfmark null put readonly def /.writepdfmarkdict 1 dict dup /pdfmark null put readonly def
/.writepdfmarks { % - .writepdfmarks <bool> /.writepdfmarks { % - .writepdfmarks <bool>

View file

@ -39,6 +39,12 @@ pdfdict begin
currentdict end /ArcfourDecode filter currentdict end /ArcfourDecode filter
} bind def } bind def
/aesdecodefilter {
1 dict begin
/Key exch def
currentdict end /AESDecode filter
} bind def
% <ciphertext> <key> arc4decode <plaintext> % <ciphertext> <key> arc4decode <plaintext>
/arc4decode { /arc4decode {
%(key: ) print dup == (ct: ) print 1 index == %(key: ) print dup == (ct: ) print 1 index ==
@ -49,6 +55,22 @@ pdfdict begin
} ifelse } ifelse
} bind def } 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 { /md5 {
16 string dup /MD5Encode filter dup 4 3 roll writestring closefile 16 string dup /MD5Encode filter dup 4 3 roll writestring closefile
} bind def } bind def
@ -294,18 +316,38 @@ def
% put into a stream dictionary). % put into a stream dictionary).
/computeobjkey % <object#> <generation#> computeobjkey <keystring> /computeobjkey % <object#> <generation#> computeobjkey <keystring>
{ {
exch Trailer /Encrypt oget /V oget 5 eq {
FileKey length 5 add string % Encrypt version 5 doesn't use object keys; everything is
dup 0 FileKey putinterval % encrypted with the file key.
exch pop pop FileKey
% stack: gen# string obj# } {
2 copy 255 and FileKey length exch put exch
2 copy -8 bitshift 255 and FileKey length 1 add exch put FileKey length 5 add string
2 copy -16 bitshift 255 and FileKey length 2 add exch put dup 0 FileKey putinterval
pop exch exch
2 copy 255 and FileKey length 3 add exch put % stack: gen# string obj#
2 copy -8 bitshift 255 and FileKey length 4 add exch put 2 copy 255 and FileKey length exch put
pop md5 0 FileKey length 5 add 2 index length .min getinterval 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 } bind def
% As .pdfrun, but decrypt strings with key <key>. % As .pdfrun, but decrypt strings with key <key>.
@ -351,17 +393,31 @@ def
{ % R < 4 --> encrypted strings { % R < 4 --> encrypted strings
pop 1 index arc4decode % Decrypt string pop 1 index arc4decode % Decrypt string
PDFDEBUG { (%Decrypted: ) print dup == flush } if PDFDEBUG { (%Decrypted: ) print dup == flush } if
} { % Else R = 4 } { % Else R &gt;= 4
/StrF knownoget % Get StrF (if present) /StrF knownoget % Get StrF (if present)
{ % If StrF is present ... { % If StrF is present ...
/Identity eq not % Check if StrF != Identity dup /Identity eq not % Check if StrF != Identity
{ 1 index arc4decode % Decrypt string { /StdCF eq
PDFDEBUG { (%Decrypted: ) print dup == flush } if { Trailer /Encrypt oget /CF knownoget {
} /StdCF oget /CFM oget
if % If StrF != identity dup /AESV2 eq exch /AESV3 eq or
} } {
if % If StrF is known //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 ifelse % Ifelse R < 4
} }
if % If = stringtype if % If = stringtype
@ -384,49 +440,55 @@ def
2 copy computeobjkey dup 4 1 roll 2 copy computeobjkey dup 4 1 roll
PDFfile exch resolveopdict .decpdfrun PDFfile exch resolveopdict .decpdfrun
dup dup dup 5 2 roll 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. { % Use loop to provide an exitable context.
xcheck exch type /dicttype eq and % Check if executable dictionary xcheck exch type /dicttype eq and % Check if executable dictionary
not { % If object is not ... not { % If object is not ...
pop pop % ignore object pop pop % ignore object
exit % Exit 'loop' context exit % Exit 'loop' context
} if % If not possible stream } if % If not possible stream
% Starting with PDF 1.4 (R = 3), there are some extra features % Starting with PDF 1.4 (R = 3), there are some extra features
% which control encryption of streams. The EncryptMetadata entry % which control encryption of streams. The EncryptMetadata entry
% in the Encrypt dict controls the encryption of metadata streams. % in the Encrypt dict controls the encryption of metadata streams.
Trailer /Encrypt oget % Get encryption dictionary Trailer /Encrypt oget % Get encryption dictionary
dup /R oget dup 3 lt % Only PDF 1.4 and higher has options 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 pop pop /StreamKey exch put % Insert StreamKey in dictionary
exit % Exit 'loop' context exit % Exit 'loop' context
} if } 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) 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 not % Check if EncryptMetadata = false
{ % if false we need to check the stream type { % if false we need to check the stream type
3 index /Type knownoget % Get stream type (if present) 3 index /Type knownoget % Get stream type (if present)
not { //null } if % If type not present use fake name not { //null } if % If type not present use fake name
/Metadata eq % Check if the type is Metadata /Metadata eq % Check if the type is Metadata
{ pop pop pop pop % Type == Metadata --> no encryption { pop pop pop pop % Type == Metadata --&gt; no encryption
exit % Exit 'loop' context exit % Exit 'loop' context
} if } if
} if } if
% PDF 1.5 encryption (R == 4) has selectable encryption handlers. 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 % 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 % we need to decrypt the stream. stack: object object key R Encrypt
exch 4 lt % Check for less than PDF 1.5 exch 4 lt % Check for less than PDF 1.5
{ pop /StreamKey exch put % Insert StreamKey in dictionary { 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 } if
% Check if the stream encryption handler (StmF) == Identity.
/StmF knownoget % Get StmF (if present) /StmF knownoget % Get StmF (if present)
not { /Identity } if % If StmF not present default = Identity not { /Identity } if % If StmF not present default = Identity
/Identity eq % Check if StmF == Identity /Identity eq % Check if StmF == Identity
{ pop pop % Identity --> no encryption { pop pop % Identity --&gt; no encryption
exit % Exit 'loop' context exit % Exit 'loop' context
} if } 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 /StreamKey exch put % Insert StreamKey into dictionary
exit % Exit 'loop' context, never loop exit % Exit 'loop' context, never loop
} loop % End of loop exitable context } loop % End of loop exitable context
@ -441,16 +503,22 @@ def
/pdf_decrypt_stream /pdf_decrypt_stream
{ 3 index /StreamKey known % Check if the file is encrypted { 3 index /StreamKey known % Check if the file is encrypted
{ {
exch exch
% Stack: readdata? dict parms filternames file/string % Stack: readdata? dict parms filternames file/string
3 index /Length oget 3 index /StreamKey get
dup 0 eq { Trailer /Encrypt oget
% Handle Length=0 case specially to avoid SubFileDecode semantics dup /StmF knownoget
pop pop () { % stack: key Encrypt StmF
} { exch /CF knownoget {
() /SubFileDecode filter exch oget /CFM oget % stack: key StmF-CFM
} ifelse dup /AESV2 eq exch /AESV3 eq or
3 index /StreamKey get arc4decodefilter } { pop //false } ifelse
{ aesdecodefilter } % install the requested filter
{ arc4decodefilter }
ifelse
}
{ pop arc4decodefilter } % fallback for no StmF
ifelse
exch exch
} if } if
} bind def } bind def

View file

@ -64,7 +64,8 @@ BIN=/$objtype/bin
TARG=gs TARG=gs
OFILES=\ OFILES=\
obj/gs.$O\ obj/gs.$O\
`{sed 's#^./obj/(.*)\.o .*#obj/\1.$O#' src/ld.tr >[2] /dev/null | sort} `{sed 's#^./obj/(.*)\.o .*#obj/\1.$O#' src/ld.tr >[2] /dev/null | sort} \
/$objtype/lib/ape/libcrypto.a
# The first driver is the default. # The first driver is the default.
DRIVERS=\ DRIVERS=\

View file

@ -287,6 +287,7 @@ psfile_("gs_cff.ps",9)
#ifdef oper_ #ifdef oper_
oper_(zfmd5_op_defs) oper_(zfmd5_op_defs)
oper_(zfarc4_op_defs) oper_(zfarc4_op_defs)
oper_(zfaes_op_defs)
#endif #endif
#ifdef psfile_ #ifdef psfile_
psfile_("gs_mgl_e.ps",11) psfile_("gs_mgl_e.ps",11)

View file

@ -287,6 +287,7 @@ psfile_("gs_cff.ps",9)
#ifdef oper_ #ifdef oper_
oper_(zfmd5_op_defs) oper_(zfmd5_op_defs)
oper_(zfarc4_op_defs) oper_(zfarc4_op_defs)
oper_(zfaes_op_defs)
#endif #endif
#ifdef psfile_ #ifdef psfile_
psfile_("gs_mgl_e.ps",11) psfile_("gs_mgl_e.ps",11)

View file

@ -1289,6 +1289,13 @@ $(PSD)farc4.dev : $(INT_MAK) $(ECHOGS_XE) $(farc4_) $(GLD)sarc4.dev
$(ADDMOD) $(PSD)farc4 -include $(GLD)sarc4 $(ADDMOD) $(PSD)farc4 -include $(GLD)sarc4
$(ADDMOD) $(PSD)farc4 -oper zfarc4 $(ADDMOD) $(PSD)farc4 -oper zfarc4
# AES cipher filter
faes4_=$(PSOBJ)zfaes.$(OBJ)
$(PSD)faes.dev : $(INT_MAK) $(ECHOGS_XE) $(faes_) $(GLD)saes.dev
$(SETMOD) $(PSD)faes $(faes_)
$(ADDMOD) $(PSD)faes -include $(GLD)saes
$(ADDMOD) $(PSD)faes -oper zfaes
$(PSOBJ)zfarc4.$(OBJ) : $(PSSRC)zfarc4.c $(OP) $(memory__h)\ $(PSOBJ)zfarc4.$(OBJ) : $(PSSRC)zfarc4.c $(OP) $(memory__h)\
$(gsstruct_h) $(ialloc_h) $(idict_h) $(ifilter_h)\ $(gsstruct_h) $(ialloc_h) $(idict_h) $(ifilter_h)\
$(sarc4_h) $(stream_h) $(strimpl_h) $(sarc4_h) $(stream_h) $(strimpl_h)

View file

@ -285,6 +285,8 @@
./obj/md5.o \ ./obj/md5.o \
./obj/zfarc4.o \ ./obj/zfarc4.o \
./obj/sarc4.o \ ./obj/sarc4.o \
./obj/zfaes.o \
./obj/saes.o \
./obj/zicc.o \ ./obj/zicc.o \
./obj/gsicc.o \ ./obj/gsicc.o \
./obj/icc.o \ ./obj/icc.o \

View file

@ -475,6 +475,7 @@ sjpeg_h=$(GLSRC)sjpeg.h
slzwx_h=$(GLSRC)slzwx.h slzwx_h=$(GLSRC)slzwx.h
smd5_h=$(GLSRC)smd5.h $(md5_h) smd5_h=$(GLSRC)smd5.h $(md5_h)
sarc4_h=$(GLSRC)sarc4.h $(scommon_h) sarc4_h=$(GLSRC)sarc4.h $(scommon_h)
saes_h=$(GLSRC)saes.h $(scommon_h)
sjbig2_h=$(GLSRC)sjbig2.h $(stdint__h) $(scommon_h) sjbig2_h=$(GLSRC)sjbig2.h $(stdint__h) $(scommon_h)
sjpx_h=$(GLSRC)sjpx.h $(scommon_h) sjpx_h=$(GLSRC)sjpx.h $(scommon_h)
spdiffx_h=$(GLSRC)spdiffx.h spdiffx_h=$(GLSRC)spdiffx.h
@ -1370,6 +1371,16 @@ $(GLOBJ)sarc4.$(OBJ) : $(GLSRC)sarc4.c $(AK) $(memory__h)\
$(gserror_h) $(gserrors_h) $(sarc4_h) $(strimpl_h) $(gserror_h) $(gserrors_h) $(sarc4_h) $(strimpl_h)
$(GLCC) $(GLO_)sarc4.$(OBJ) $(C_) $(GLSRC)sarc4.c $(GLCC) $(GLO_)sarc4.$(OBJ) $(C_) $(GLSRC)sarc4.c
# -------------- AES cipher filter --------------- #
saes_=$(GLOBJ)saes.$(OBJ)
$(GLD)saes.dev : $(LIB_MAK) $(ECHOGS_XE) $(saes_)
$(SETMOD) $(GLD)saes $(saes_)
$(GLOBJ)saes.$(OBJ) : $(GLSRC)saes.c $(AK) $(memory__h)\
$(gserror_h) $(gserrors_h) $(saes_h) $(strimpl_h)
$(GLCC) $(GLO_)saes.$(OBJ) $(C_) $(GLSRC)saes.c
# ---------------- JBIG2 compression filter ---------------- # # ---------------- JBIG2 compression filter ---------------- #
sjbig2_=$(GLOBJ)sjbig2.$(OBJ) sjbig2_=$(GLOBJ)sjbig2.$(OBJ)

160
sys/src/cmd/gs/src/saes.c Normal file
View file

@ -0,0 +1,160 @@
/* Copyright (C) 2001-2012 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
Refer to licensing information at http://www.artifex.com or contact
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
/* AES filter implementation */
#include "memory_.h"
#include "gserrors.h"
#include "gserror.h"
#include "strimpl.h"
#include "saes.h"
/* stream implementation */
private_st_aes_state(); /* creates a gc object for our state,
defined in saes.h */
/* Store a key in our crypt context */
int
s_aes_set_key(stream_aes_state * state, const unsigned char *key,
int keylength)
{
if ( (keylength < 1) || (keylength > SAES_MAX_KEYLENGTH) )
return_error(gs_error_rangecheck);
if (key == NULL)
return_error(gs_error_invalidaccess);
/* we can't set the key here because the interpreter's
filter implementation wants to duplicate our state
after the zfaes.c binding calls us. So stash it now
and handle it in our process method. */
memcpy(state->key, key, keylength);
state->keylength = keylength;
/* return successfully */
return 0;
}
/* Specify whether the plaintext stream uses RFC 1423-style padding
* (allowing it to be an arbitrary length), or is unpadded (and must
* therefore be a multiple of 16 bytes long). */
void
s_aes_set_padding(stream_aes_state *state, int use_padding)
{
state->use_padding = use_padding;
}
/* initialize our state object. */
static int
s_aes_init(stream_state *ss)
{
stream_aes_state *const state = (stream_aes_state *) ss;
/* clear the flags so we know we're at the start of a stream */
state->initialized = 0;
memset(&state->aes, 0, sizeof(state->aes));
return 0;
}
/* release our private storage */
static void
s_aes_release(stream_state *)
{
}
/* (de)crypt a section of text--the procedure is the same
* in each direction. see strimpl.h for return codes.
*/
static int
s_aes_process(stream_state * ss, stream_cursor_read * pr,
stream_cursor_write * pw, bool last)
{
stream_aes_state *const state = (stream_aes_state *) ss;
const unsigned char *limit;
const long in_size = pr->limit - pr->ptr;
const long out_size = pw->limit - pw->ptr;
unsigned char temp[16];
int status = 0;
/* figure out if we're going to run out of space */
if (in_size > out_size) {
limit = pr->ptr + out_size;
status = 1; /* need more output space */
} else {
limit = pr->limit;
status = last ? EOFC : 0; /* need more input */
}
if (state->keylength < 1 || state->keylength > SAES_MAX_KEYLENGTH)
return ERRC;
if (!state->initialized) {
memset(&state->aes, 0, sizeof(state->aes));
AES_set_decrypt_key(state->key, state->keylength*8, &state->aes);
/* read the initialization vector from the first 16 bytes */
if (in_size < 16) return 0; /* get more data */
memcpy(state->iv, pr->ptr + 1, 16);
state->initialized = 1;
pr->ptr += 16;
}
/* decrypt available blocks */
while (pr->ptr + 16 <= limit) {
AES_cbc_encrypt(pr->ptr + 1, temp, 16, &state->aes, state->iv, AES_DECRYPT);
pr->ptr += 16;
if (last && pr->ptr == pr->limit) {
/* we're on the last block; unpad if necessary */
int pad;
if (state->use_padding) {
/* we are using RFC 1423-style padding, so the last byte of the
plaintext gives the number of bytes to discard */
pad = temp[15];
if (pad < 1 || pad > 16) {
/* Bug 692343 - don't error here, just warn. Take padding to be
* zero. This may give us a stream that's too long - preferable
* to the alternatives. */
pad = 0;
}
} else {
/* not using padding */
pad = 0;
}
memcpy(pw->ptr + 1, temp, 16 - pad);
pw->ptr += 16 - pad;
return EOFC;
}
memcpy(pw->ptr + 1, temp, 16);
pw->ptr += 16;
}
/* if we got to the end of the file without triggering the padding
check, the input must not have been a multiple of 16 bytes long.
complain. */
if (status == EOFC)
return 0;
return status;
}
/* stream template */
const stream_template s_aes_template = {
&st_aes_state, s_aes_init,
s_aes_process, 16, 16,
s_aes_release
};

63
sys/src/cmd/gs/src/saes.h Normal file
View file

@ -0,0 +1,63 @@
/* Copyright (C) 2001-2012 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
Refer to licensing information at http://www.artifex.com or contact
Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael,
CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
/* Stream wrapper for the AES cypher implementation */
/* Requires scommon.h; strimpl.h if any templates are referenced */
#ifndef saes_INCLUDED
# define saes_INCLUDED
#include "scommon.h"
#include <openssl/aes.h>
/* maximum supported key length in bytes */
#define SAES_MAX_KEYLENGTH 32
/* AES is a symmetric block cipher so we share the stream states.
The internal cypher state is all held in the ctx pointer */
struct stream_aes_state_s
{
stream_state_common; /* a define from scommon.h */
unsigned char key[SAES_MAX_KEYLENGTH];
unsigned int keylength;
unsigned char iv[16]; /* CBC initialization vector */
int initialized; /* whether we're set up */
int use_padding; /* are we using RFC 1423-style padding? */
AES_KEY aes;
};
#ifndef stream_aes_state_DEFINED
#define stream_aes_state_DEFINED
typedef struct stream_aes_state_s stream_aes_state;
#endif
int s_aes_set_key(stream_aes_state * state,
const unsigned char *key, int keylength);
void s_aes_set_padding(stream_aes_state *state, int use_padding);
/* state declaration macro;
should be updated for the aes_context finalization */
#define private_st_aes_state() \
gs_private_st_simple(st_aes_state, stream_aes_state, "aes filter state")
extern const stream_template s_aes_template;
/* (de)crypt a section of text in a buffer -- the procedure is the same
* in each direction. see strimpl.h for return codes.
*/
int s_aes_process_buffer(stream_aes_state *ss, byte *buf, int buf_size);
#endif /* saes_INCLUDED */

View file

@ -0,0 +1,62 @@
/* Copyright (C) 2001 Artifex Software, Inc. All rights reserved.
This software is provided AS-IS with no warranty, either express or
implied.
This software is distributed under license and may not be copied,
modified or distributed except as expressly authorized under the terms
of the license contained in the file LICENSE in this distribution.
For more information about licensing, please refer to
http://www.ghostscript.com/licensing/. For information on
commercial licensing, go to http://www.artifex.com/licensing/ or
contact Artifex Software, Inc., 101 Lucas Valley Road #110,
San Rafael, CA 94903, U.S.A., +1(415)492-9861.
*/
/* this is the ps interpreter interface to the aescbc cipher filter
used in PDF decryption. */
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
#include "gsstruct.h"
#include "ialloc.h"
#include "idict.h"
#include "stream.h"
#include "strimpl.h"
#include "ifilter.h"
#include "saes.h"
/* <source> <dict> aes/filter <file> */
private int
z_aes_d(i_ctx_t * i_ctx_p)
{
os_ptr op = osp; /* i_ctx_p->op_stack.stack.p defined in osstack.h */
ref *sop = NULL;
stream_aes_state state;
/* extract the key from the parameter dictionary */
check_type(*op, t_dictionary);
check_dict_read(*op);
if (dict_find_string(op, "Key", &sop) <= 0)
return_error(e_rangecheck);
s_aes_set_key(&state, sop->value.const_bytes, r_size(sop));
/* we pass npop=0, since we've no arguments left to consume */
/* we pass 0 instead of the usual rspace(sop) will allocate storage for
filter state from the same memory pool as the stream it's coding. this
causes no trouble because we maintain no pointers */
return filter_read(i_ctx_p, 0, &s_aes_template,
(stream_state *) & state, 0);
}
/* match the above routines to their postscript filter names
this is how our 'private' routines get called externally */
const op_def zfaes_op_defs[] = {
op_def_begin_filter(),
{"2AESDecode", z_aes_d},
op_def_end(0)
};