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

@ -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,6 +316,11 @@ def
% put into a stream dictionary).
/computeobjkey % <object#> <generation#> computeobjkey <keystring>
{
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
@ -305,7 +332,22 @@ def
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
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,14 +393,28 @@ def
{ % R < 4 --> encrypted strings
pop 1 index arc4decode % Decrypt string
PDFDEBUG { (%Decrypted: ) print dup == flush } if
} { % Else R = 4
} { % Else R &gt;= 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
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
}
if % If StrF != identity
{ 1 index arc4decode }
ifelse % If StrF != StdCF
PDFDEBUG { (%Decrypted: ) print dup //== exec flush } if
}
{ pop }
ifelse % If StrF != identity
}
if % If StrF is known
}
@ -396,34 +452,40 @@ def
% 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
} if
% 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
{ 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
% 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
} 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
/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
{ pop pop % Identity --&gt; no encryption
exit % Exit 'loop' context
} if
% If we get here then we need to decrypt the stream.
@ -443,14 +505,20 @@ def
{
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
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

View file

@ -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>

View file

@ -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>

View file

@ -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,6 +316,11 @@ def
% put into a stream dictionary).
/computeobjkey % <object#> <generation#> computeobjkey <keystring>
{
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
@ -305,7 +332,22 @@ def
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
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,14 +393,28 @@ def
{ % R < 4 --> encrypted strings
pop 1 index arc4decode % Decrypt string
PDFDEBUG { (%Decrypted: ) print dup == flush } if
} { % Else R = 4
} { % Else R &gt;= 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
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
}
if % If StrF != identity
{ 1 index arc4decode }
ifelse % If StrF != StdCF
PDFDEBUG { (%Decrypted: ) print dup //== exec flush } if
}
{ pop }
ifelse % If StrF != identity
}
if % If StrF is known
}
@ -396,34 +452,40 @@ def
% 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
} if
% 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
{ 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
% 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
} 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
/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
{ pop pop % Identity --&gt; no encryption
exit % Exit 'loop' context
} if
% If we get here then we need to decrypt the stream.
@ -443,14 +505,20 @@ def
{
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
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

View file

@ -64,7 +64,8 @@ BIN=/$objtype/bin
TARG=gs
OFILES=\
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.
DRIVERS=\

View file

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

View file

@ -287,6 +287,7 @@ psfile_("gs_cff.ps",9)
#ifdef oper_
oper_(zfmd5_op_defs)
oper_(zfarc4_op_defs)
oper_(zfaes_op_defs)
#endif
#ifdef psfile_
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 -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)\
$(gsstruct_h) $(ialloc_h) $(idict_h) $(ifilter_h)\
$(sarc4_h) $(stream_h) $(strimpl_h)

View file

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

View file

@ -475,6 +475,7 @@ sjpeg_h=$(GLSRC)sjpeg.h
slzwx_h=$(GLSRC)slzwx.h
smd5_h=$(GLSRC)smd5.h $(md5_h)
sarc4_h=$(GLSRC)sarc4.h $(scommon_h)
saes_h=$(GLSRC)saes.h $(scommon_h)
sjbig2_h=$(GLSRC)sjbig2.h $(stdint__h) $(scommon_h)
sjpx_h=$(GLSRC)sjpx.h $(scommon_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)
$(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 ---------------- #
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)
};