# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: address@hidden # target_branch: http://bzr.savannah.gnu.org/r/pdf/libgnupdf/branches\ # /trunk/ # testament_sha1: 824f2d06074bd562233b2f7a99b1d928ca250201 # timestamp: 2008-12-25 16:51:26 +0100 # base_revision_id: address@hidden # # Begin patch === modified file 'ChangeLog' --- ChangeLog 2008-12-10 20:45:27 +0000 +++ ChangeLog 2008-12-25 15:49:31 +0000 @@ -1,3 +1,72 @@ +2008-12-25 David Vazquez + + * doc/gnupdf.texi (Stream Types): Crypt filters added. + + * src/base/pdf-stm-f-aesv2.c: Adjust to use new crypt module functions. + + * src/base/pdf-stm-f-md5.c: Same. + +2008-12-23 David Vazquez + + * doc/gnupdf-tsd.texi: Updated. + + * torture/unit/base/crypt/pdf-crypt-cipher-setkey.c (test_pdf_crypt_cipher_setkey): New tests. + + * torture/unit/base/crypt/pdf-crypt-cipher-decrypt.c: New tests. + + * torture/unit/base/crypt/pdf-crypt-md-write.c (test_pdf_crypt_md_write): New tests. + + * doc/gnupdf.texi (Encryption): Updated. + + * src/base/pdf-crypt-c-aesv2.c: Incremental encryption support added. + + * src/base/pdf-crypt-c-v2.c: Same. + + * src/base/pdf-crypt.h: Same. + +2008-12-20 David Vazquez + + * src/base/pdf-crypt.h (pdf_crypt_md_hash): Minor bug fixed. + + * src/base/pdf-stm-buffer.c (pdf_stm_buffer_resize): New function. + +2008-12-15 David Vazquez + + * doc/gnupdf-tsd.texi (pdf_crypt_md_hash) + (Message digest functions): Updated. + + * torture/unit/base/crypt/pdf-crypt-md-hash.c: New tests. + + * src/base/pdf-crypt.h (pdf_crypt_md_new): The *MD argument should + is the last argument. + +2008-12-14 David Vazquez + + * src/base/MANIFEST.wiki: Updated. + + * src/base/pdf-stm-f-aesv2.c: New file + + * src/base/pdf-stm-f-v2.c: New file + + * src/base/pdf-stm-f-md5.c: New file + + * src/base/pdf-crypt-c-aesv2.c (pdf_crypt_cipher_aesv2_decrypt): + Check padding size is lesser than AESV2_BLKSIZE. + + * torture/unit/base/crypt/pdf-crypt-cipher-decrypt.c: New test. + +2008-12-11 David Vazquez + + * torture/unit/base/stm/pdf-stm-read.c: New test. + + * doc/gnupdf-tsd.texi (pdf_crypt_cipher_encrypt): New test documentation. + (pdf_stm_write): New tests documentation. + + * torture/unit/base/crypt/pdf-crypt-cipher-encrypt.c: New test + + * torture/unit/base/crypt/pdf-crypt-cipher-decrypt.c: Change + `pdf_crypt_cipher_decrypt_001' ciphered buffer and key. + 2008-12-10 Jose E. Marchesi * torture/unit/runtests.c (main): Dont set the CK_FORK variable, === modified file 'doc/gnupdf-tsd.texi' --- doc/gnupdf-tsd.texi 2008-12-02 23:18:59 +0000 +++ doc/gnupdf-tsd.texi 2008-12-25 15:49:31 +0000 @@ -920,6 +920,16 @@ @end table @end deffn address@hidden Test pdf_stm_read_011 +Create a memory-based reading stream and attach a cipher filter +decoder to it. address@hidden @strong address@hidden Success condition +The decoded data should be correct. address@hidden table address@hidden deffn + + @node pdf_stm_read_char @subsubsection pdf_stm_read_char @@ -1058,6 +1068,49 @@ @end deffn address@hidden Test pdf_stm_write_008 +Create a memory-based writing stream and attach an V2 filter without parameters. address@hidden @strong address@hidden Success condition +The installation of the filter should fail. address@hidden table address@hidden deffn + address@hidden Test pdf_stm_write_009 +Create a memory-based writing stream and attach a V2 cipher filter to +encode it. address@hidden @strong address@hidden Success condition +The encoded data should be correct. address@hidden table address@hidden deffn + address@hidden Test pdf_stm_write_010 +Create a memory-based writing stream and attach an AESV2 cipher filter to +encode it. address@hidden @strong address@hidden Success condition +The encoded data should be correct. address@hidden table address@hidden deffn + address@hidden Test pdf_stm_write_011 +Create a memory-based writing stream and attach an MD5 filter to +encode it. address@hidden @strong address@hidden Success condition +The encoded data should be correct. address@hidden table address@hidden deffn + address@hidden Test pdf_stm_write_012 +Create a memory-based writing stream and attach an AESv2 cipher filter to +encode it. address@hidden @strong address@hidden Success condition +The encoded data should be correct. address@hidden table address@hidden deffn @node Text Module @@ -6063,12 +6116,11 @@ * pdf_crypt_cipher_new:: * pdf_crypt_cipher_destroy:: * pdf_crypt_cipher_setkey:: -* pdf_crypt_cipher_encrypt_size:: -* pdf_crypt_cipher_decrypt_size:: * pdf_crypt_cipher_encrypt:: * pdf_crypt_cipher_decrypt:: * pdf_crypt_md_new:: -* pdf_crypt_md_hash:: +* pdf_crypt_md_write:: +* pdf_crypt_md_read:: * pdf_crypt_md_destroy:: @end menu @@ -6116,83 +6168,9 @@ @end deffn address@hidden pdf_crypt_cipher_encrypt_size address@hidden pdf_crypt_cipher_encrypt_size - address@hidden Test pdf_crypt_cipher_encrypt_size_001 -Get the ciphered buffer size for an empty input buffer (AESV2). address@hidden @strong address@hidden Success condition -Returns 32 address@hidden table address@hidden deffn - address@hidden Test pdf_crypt_cipher_encrypt_size_002 -Get the ciphered buffer size for a 15 bytes buffer (AESV2). address@hidden @strong address@hidden Success condition -Returns 32 address@hidden table address@hidden deffn - address@hidden Test pdf_crypt_cipher_encrypt_size_003 -Get the ciphered buffer size for an empty buffer (V2). address@hidden @strong address@hidden Success condition -Returns 0 address@hidden table address@hidden deffn - address@hidden Test pdf_crypt_cipher_encrypt_size_004 -Get the ciphered buffer size for a 15 bytes buffer in a (V2). address@hidden @strong address@hidden Success condition -Returns 15 address@hidden table address@hidden deffn - - @node pdf_crypt_cipher_setkey @subsubsection pdf_crypt_cipher_setkey address@hidden Test pdf_crypt_cipher_setkey_001 -Try set a empty key for a cipher (AESV2). address@hidden @strong address@hidden Success condition -Returns PDF_EBADDATA address@hidden table address@hidden deffn - - address@hidden Test pdf_crypt_cipher_setkey_001 -Set a key for a cipher (AESV2). address@hidden @strong address@hidden Success condition -Returns PDF_OK address@hidden table address@hidden deffn - - - - address@hidden pdf_crypt_cipher_decrypt_size address@hidden pdf_crypt_cipher_decrypt_size - address@hidden Test pdf_crypt_cipher_decrypt_size_001 address@hidden @strong -Get the plain buffer size for a 32 bytes ciphered buffer (AESV2). address@hidden Success condition -Returns 0 address@hidden table address@hidden deffn - address@hidden Test pdf_crypt_cipher_decrypt_size_002 address@hidden @strong -Get the plain buffer size for a 15 bytes ciphered buffer (V2). address@hidden Success condition -Returns 15 address@hidden table address@hidden deffn @node pdf_crypt_cipher_encrypt @@ -6208,9 +6186,17 @@ @deffn Test pdf_crypt_cipher_encrypt_002 @table @strong -Encrypt an empty buffer (V2). address@hidden Success condition -Returns PDF_OK +Encrypt an ciphered buffer (AESV2). address@hidden Success condition +The output data should be correct. address@hidden table address@hidden deffn + address@hidden Test pdf_crypt_cipher_encrypt_003 address@hidden @strong +Encrypt an ciphered buffer incrementally (AESV2). address@hidden Success condition +The output data should be correct. @end table @end deffn @@ -6220,9 +6206,9 @@ @deffn Test pdf_crypt_cipher_decrypt_001 @table @strong -Decrypt an ciphered empty buffer (AESV2). +Decrypt an ciphered buffer (AESV2). @item Success condition -Returns PDF_OK and the length of output buffer is zero. +The output data should be correct. @end table @end deffn @@ -6234,6 +6220,22 @@ @end table @end deffn address@hidden Test pdf_crypt_cipher_decrypt_003 address@hidden @strong +Decrypt an ciphered buffer (AESV2). address@hidden Success condition +The output data should be correct. address@hidden table address@hidden deffn + address@hidden Test pdf_crypt_cipher_decrypt_004 address@hidden @strong +Decrypt an ciphered buffer incrementally (AESV2). address@hidden Success condition +The output data should be correct. address@hidden table address@hidden deffn + @node pdf_crypt_md_new @subsubsection pdf_crypt_md_new @@ -6247,10 +6249,22 @@ @end deffn address@hidden pdf_crypt_md_hash address@hidden pdf_crypt_md_hash - address@hidden Test pdf_crypt_md_hash_001 address@hidden pdf_crypt_md_write address@hidden pdf_crypt_md_write + address@hidden Test pdf_crypt_md_write_001 address@hidden @strong +Pass an empty message. address@hidden Success condition +Returns PDF_OK. address@hidden table address@hidden deffn + + address@hidden pdf_crypt_md_read address@hidden pdf_crypt_md_read + address@hidden Test pdf_crypt_md_read_001 @table @strong Compute the md5 of an empty buffer. @item Success condition @@ -6258,6 +6272,23 @@ @end table @end deffn address@hidden Test pdf_crypt_md_read_002 address@hidden @strong +Compute the md5 checksum of a string. address@hidden Success condition +The output data should be correct. address@hidden table address@hidden deffn + address@hidden Test pdf_crypt_md_read_003 address@hidden @strong +Compute the md5 checksum of a string. address@hidden Success condition +The output data should be correct. address@hidden table address@hidden deffn + + @node pdf_crypt_md_destroy @subsubsection pdf_crypt_md_destroy === modified file 'doc/gnupdf.texi' --- doc/gnupdf.texi 2008-12-01 23:55:12 +0000 +++ doc/gnupdf.texi 2008-12-25 15:49:31 +0000 @@ -307,6 +307,8 @@ *p = 666; @end example @end table + + @end deftypefun @deftypefun void pdf_dealloc (const void address@hidden) @@ -3436,6 +3438,16 @@ Flate (zlib) decoder. @item PDF_STM_FILTER_JBIG2_DEC JBIG2 decoder. address@hidden PDF_STM_FILTER_AESV2_ENC +AESV2 encoder. address@hidden PDF_STM_FILTER_AESV2_DEC +AESV2 decoder. address@hidden PDF_STM_FILTER_V2_ENC +V2 encoder. address@hidden PDF_STM_FILTER_V2_ENC +V2 decoder. address@hidden PDF_STM_FILTER_MD5_ENC +MD5 encoder. @end table @end deftp @@ -8130,7 +8142,7 @@ @table @code @item PDF_OK The operation was successfully performed and the current position in address@hidden was set to @var{pos}. address@hidden was set to @var{pos}. @end table This callback is called by the @code{pdf_fsys_file_set_pos} file @@ -8338,7 +8350,8 @@ * Initializating the module:: * Creating and destroying Ciphers:: * Encryption and decryption:: -* Message digest functions:: +* Message digest functions:: +* Utilities:: @end menu @node Initializating the module @@ -8376,6 +8389,7 @@ @end table @end deftypefun + @node Creating and destroying Ciphers @subsection Creating and destroying Ciphers @@ -8507,67 +8521,6 @@ @end table @end deftypefun address@hidden pdf_size_t pdf_crypt_cipher_encrypt_size (pdf_crypt_cipher_t @var{cipher}, pdf_char_t address@hidden, pdf_size_t @var{in_size}) - -Compute the size for the output buffer in address@hidden function for the given parameters. - address@hidden @strong address@hidden Parameters address@hidden @var address@hidden cipher -A cipher. address@hidden in -A pointer to the buffer which will be encrypted. address@hidden in_size -The length of the buffer in bytes. address@hidden table address@hidden Returns -The size of a valid output buffer in @code{pdf_crypt_cipher_encrypt} -function for this parameters. address@hidden Usage example address@hidden -pdf_crypt_cipher_t cipher; -pdf_size_t size; -pdf_char_t in[16]; - -/* ...prepare the cipher... */ -size = pdf_crypt_cipher_encrypt_size (cipher, in, sizeof (in)); address@hidden example address@hidden table address@hidden deftypefun - address@hidden pdf_size_t pdf_crypt_cipher_decrypt_size (pdf_crypt_cipher_t @var{cipher}, pdf_char_t address@hidden, pdf_size_t @var{in_size}) - -Compute the size for a valid output buffer in address@hidden function for the given parameters. - address@hidden @strong address@hidden Parameters address@hidden @var address@hidden cipher -A cipher. address@hidden in -A pointer to the buffer which will be decrypted. address@hidden in_size -The length of the buffer in bytes. address@hidden table address@hidden Returns -The size of a valid output buffer in @code{pdf_crypt_cipher_encrypt} -function for this parameters. address@hidden Usage example address@hidden -pdf_crypt_cipher_t cipher; -pdf_size_t size; -pdf_char_t *in; -pdf_size_t in_size; - -/* ...prepare the cipher... */ -size = pdf_crypt_cipher_decrypt_size (cipher, in, in_size); address@hidden example address@hidden table address@hidden deftypefun - @deftypefun pdf_status_t pdf_crypt_cipher_encrypt (pdf_crypt_cipher_t @var{cipher}, pdf_char_t address@hidden, pdf_size_t @var{out_size}, pdf_char_t address@hidden, pdf_size_t @var{in_size}, pdf_size_t address@hidden) @@ -8586,7 +8539,9 @@ @item in A pointer to input buffer. @item in_size -The length of the input buffer in bytes. I must be greater than zero. +The length of the input buffer in bytes. I must be greater than +zero. Some algorithms requires than IN_SIZE to be multiple of a fixed +integer. @item result_size A pointer where it will put the real size of the output buffer. This size will be lesser or equal than out_size. @@ -8693,7 +8648,7 @@ address@hidden pdf_status_t pdf_crypt_md_new (pdf_crypt_md_t address@hidden, enum pdf_crypt_md_algo_e @var{algo}) address@hidden pdf_status_t pdf_crypt_md_new (enum pdf_crypt_md_algo_e @var{algo}, pdf_crypt_md_t address@hidden) Create a message-digest descriptor for an algorithm. @@ -8730,19 +8685,15 @@ address@hidden pdf_status_t pdf_crypt_md_hash (pdf_crypt_md_t @var{md}, pdf_char_t address@hidden, pdf_size_t @var{out_size}, pdf_char_t address@hidden, pdf_size_t @var{in_size}) address@hidden pdf_status_t pdf_crypt_md_write (pdf_crypt_md_t @var{md}, pdf_char_t address@hidden, pdf_size_t @var{in_size}) -Compute the message-digest for a given buffer. +Pass a buffer to the message-digest handler in order to compute its digest. @table @strong @item Parameters @table @var @item md A message-digest descriptor. address@hidden out -A pointer to output buffer. address@hidden out_size -The size of output buffer in bytes. @item in A pointer to the input buffer. @item in_size @@ -8759,7 +8710,6 @@ @item Usage example @example pdf_crypt_md_t md; -pdf_char_t out[16]; pdf_char_t *in; pdf_size_t in_size; pdf_status_t st; @@ -8768,17 +8718,61 @@ pdf_crypt_md_new (&md, PDF_CRYPT_MD_MD5); -st = pdf_crypt_md_hash (md, out, sizeof(out), in, in_size); - -if (st != PDF_OK) address@hidden - /* Error */ address@hidden - -pdf_crypt_md_destroy (md); address@hidden example address@hidden table address@hidden deftypefun +st = pdf_crypt_md_hash (md, in, in_size); + +if (st != PDF_OK) address@hidden + /* Error */ address@hidden + +pdf_crypt_md_destroy (md); address@hidden example address@hidden table address@hidden deftypefun + + + address@hidden pdf_status_t pdf_crypt_md_read (pdf_crypt_md_t @var{md}, pdf_char_t address@hidden, pdf_size_t @var{out_size}) + +Read the computed digest value from a message-digest descriptor. + address@hidden @strong address@hidden Parameters address@hidden @var address@hidden md +A message-digest descriptor. address@hidden table address@hidden Returns +A PDF status value: address@hidden @code address@hidden PDF_OK +Operation successful address@hidden PDF_EBADDATA +Bad parameter. The size of the output buffer is wrong. address@hidden table address@hidden Usage example address@hidden +pdf_crypt_md_t md; +pdf_char_t *out; +pdf_size_t out_size; +pdf_status_t st; + +pdf_crypt_md_new (&md, PDF_CRYPT_MD_MD5); + +/* ...Write the buffer into descriptor here... */ + +st = pdf_crypt_md_read (md, out, out_size); + +if (st != PDF_OK) address@hidden + /* Error */ address@hidden + +pdf_crypt_md_destroy (md); address@hidden example address@hidden table address@hidden deftypefun + @deftypefun pdf_status_t pdf_crypt_md_destroy (pdf_crypt_md_t @var{md}) @@ -8814,6 +8808,36 @@ @end deftypefun address@hidden Utilities address@hidden Utilities + address@hidden pdf_status_t pdf_crypt_nonce (pdf_crypt_char_t address@hidden, pdf_size_t @var{size}) + +Fill a buffer with random bytes. + address@hidden @strong address@hidden Parameters address@hidden @var address@hidden buffer +Buffer which be filled. address@hidden size +Size of the buffer in bytes. address@hidden table address@hidden Returns +A PDF status value: address@hidden @code address@hidden PDF_OK +Operation successful address@hidden table address@hidden Usage example address@hidden +pdf_char_t buffer[16]; + +pdf_crypt_nonce (buffer, sizeof(buffer)); address@hidden example address@hidden table address@hidden deftypefun + @node Object Layer === modified file 'src/Makefile.am' --- src/Makefile.am 2008-11-30 20:15:05 +0000 +++ src/Makefile.am 2008-12-25 15:49:31 +0000 @@ -44,7 +44,10 @@ base/pdf-stm-filter.h base/pdf-stm-filter.c \ base/pdf-stm-f-null.h base/pdf-stm-f-null.c \ base/pdf-stm-f-ahex.h base/pdf-stm-f-ahex.c \ - base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c + base/pdf-stm-f-rl.h base/pdf-stm-f-rl.c \ + base/pdf-stm-f-v2.h base/pdf-stm-f-v2.c \ + base/pdf-stm-f-aesv2.h base/pdf-stm-f-aesv2.c \ + base/pdf-stm-f-md5.h base/pdf-stm-f-md5.c if ZLIB STM_MODULE_SOURCES += base/pdf-stm-f-flate.c base/pdf-stm-f-flate.h === modified file 'src/base/MANIFEST.wiki' --- src/base/MANIFEST.wiki 2008-11-26 21:53:10 +0000 +++ src/base/MANIFEST.wiki 2008-12-21 17:39:51 +0000 @@ -16,6 +16,9 @@ ; '''pdf-stm-f-null.h''', '''pdf-stm-f-null.c''' ; '''pdf-stm-f-pred.h''', '''pdf-stm-f-pred.c''' ; '''pdf-stm-f-rl.h''', '''pdf-stm-f-rl.c''' +; '''pdf-stm-f-aesv2.h''', '''pdf-stm-f-aesv2.c''' +; '''pdf-stm-f-v2.h''', '''pdf-stm-f-v2.c''' +; '''pdf-stm-f-md.h''', '''pdf-stm-f-md.c''' : [[PDF:Standard_Filters|Implementation of the PDF standard filters]]. ; '''pdf-stm-file.h''', '''pdf-stm-file.c''' === modified file 'src/base/pdf-crypt-c-aesv2.c' --- src/base/pdf-crypt-c-aesv2.c 2008-11-29 16:21:37 +0000 +++ src/base/pdf-crypt-c-aesv2.c 2008-12-23 18:08:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 15:58:15 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-23 18:47:26 davazp" * * File: pdf-crypt.c * Date: Fri Feb 22 21:05:05 2008 @@ -32,38 +32,49 @@ #include #include + #define AESV2_BLKSIZE 16 /* Size of a block in AES128 */ +struct aesv2_state_s +{ + gcry_cipher_hd_t cipher; + pdf_bool_t first_block; +}; + +typedef struct aesv2_state_s * aesv2_state_t; + + /* Creation and destruction of aesv2 ciphers */ pdf_status_t -pdf_crypt_cipher_aesv2_new (void ** cipher) +pdf_crypt_cipher_aesv2_new (void ** out) { - gcry_cipher_hd_t * hd; - - hd = pdf_alloc (sizeof (gcry_cipher_hd_t)); - - if (hd != NULL) + aesv2_state_t state; + + state = pdf_alloc (sizeof(struct aesv2_state_s)); + + if (state != NULL) { gcry_error_t err; - err = gcry_cipher_open (hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0); - + err = gcry_cipher_open (&state->cipher, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0); + state->first_block = PDF_TRUE; + if (err == GPG_ERR_NO_ERROR) { - *cipher = hd; + *out = state; return PDF_OK; } else { - pdf_dealloc (hd); + pdf_dealloc (state); return PDF_ERROR; } } else { - pdf_dealloc (hd); + pdf_dealloc (state); return PDF_ENOMEM; } @@ -73,11 +84,11 @@ pdf_status_t -pdf_crypt_cipher_aesv2_destroy (void * cipher) +pdf_crypt_cipher_aesv2_destroy (void * _state) { - gcry_cipher_hd_t * hd = cipher; - gcry_cipher_close (*hd); - pdf_dealloc (cipher); + aesv2_state_t state = _state; + gcry_cipher_close (state->cipher); + pdf_dealloc (state); return PDF_OK; } @@ -86,12 +97,12 @@ /* Encryption and decryption functions */ pdf_status_t -pdf_crypt_cipher_aesv2_setkey (void * cipher, +pdf_crypt_cipher_aesv2_setkey (void * _state, pdf_char_t *key, pdf_size_t size) { - gcry_cipher_hd_t * hd = cipher; + aesv2_state_t state = _state; - if (gcry_cipher_setkey (*hd, key, size) == GPG_ERR_NO_ERROR) + if (gcry_cipher_setkey (state->cipher, key, size) == GPG_ERR_NO_ERROR) return PDF_OK; else return PDF_EBADDATA; @@ -99,101 +110,115 @@ -pdf_size_t -pdf_crypt_cipher_aesv2_encrypt_size (void * cipher, - pdf_char_t *in, pdf_size_t in_size) -{ - return in_size + 2*AESV2_BLKSIZE - (in_size % AESV2_BLKSIZE); -} - - - -pdf_size_t -pdf_crypt_cipher_aesv2_decrypt_size (void * cipher, - pdf_char_t *in, pdf_size_t in_size) -{ - if (in_size < 2*AESV2_BLKSIZE) - { - PDF_DEBUG_BASE ("Invalid input buffer size"); - return 0; - } - else - { - return in_size <= 2*AESV2_BLKSIZE ? 0: in_size - 2*AESV2_BLKSIZE; - } -} - - - -pdf_status_t -pdf_crypt_cipher_aesv2_encrypt (void * cipher, - pdf_char_t *out, pdf_size_t out_size, - pdf_char_t *in, pdf_size_t in_size, - pdf_size_t *result_size) -{ - gcry_cipher_hd_t * hd = cipher; - pdf_size_t buffer_size; - pdf_size_t iv_size = AESV2_BLKSIZE; - pdf_size_t content_size = in_size; - pdf_size_t padding_size; - pdf_char_t * buffer = out; - pdf_char_t * iv = &buffer[0]; - pdf_char_t * content = &buffer[iv_size]; - pdf_char_t * padding = &buffer[iv_size + content_size]; - - buffer_size = pdf_crypt_cipher_aesv2_encrypt_size (cipher, in, in_size); - - if (out_size < buffer_size) - return PDF_ERROR; - - padding_size = buffer_size - iv_size - content_size; - - gcry_create_nonce (iv, iv_size); - memcpy (content, in, in_size); - memset (padding, padding_size, padding_size); - - gcry_cipher_setiv (*hd, iv, iv_size); - if (gcry_cipher_encrypt (*hd, content, content_size + padding_size, NULL, 0) != GPG_ERR_NO_ERROR) - { - return PDF_ERROR; - } - - *result_size = buffer_size; - - return PDF_OK; -} - - - -pdf_status_t -pdf_crypt_cipher_aesv2_decrypt (void * cipher, - pdf_char_t *out, pdf_size_t out_size, - pdf_char_t *in, pdf_size_t in_size, - pdf_size_t *result_size) -{ - gcry_cipher_hd_t * hd = cipher; - pdf_size_t buffer_size = in_size; - pdf_size_t iv_size = AESV2_BLKSIZE; - pdf_size_t content_size; - pdf_size_t padding_size; - pdf_char_t * buffer = in; - pdf_char_t * iv = &buffer[0]; - pdf_char_t * content = &buffer[iv_size]; - - gcry_cipher_setiv (*hd, iv, iv_size); - if (gcry_cipher_decrypt (*hd, content, buffer_size - iv_size, NULL, 0) != GPG_ERR_NO_ERROR) - { - return PDF_ERROR; - } - - padding_size = content[buffer_size - iv_size - 1]; - content_size = buffer_size - iv_size - padding_size; - - memcpy (out, content, content_size); - - *result_size = content_size; - - return PDF_OK; -} +pdf_status_t +pdf_crypt_cipher_aesv2_encrypt (void * _state, + pdf_char_t *out, pdf_size_t out_size, + pdf_char_t *in, pdf_size_t in_size, + pdf_size_t *result_size) +{ + aesv2_state_t state = _state; + pdf_char_t * output; + pdf_size_t output_size; + pdf_char_t * input; + pdf_size_t input_size; + + if (in_size < AESV2_BLKSIZE || in_size % AESV2_BLKSIZE != 0) + return PDF_EBADDATA; + + if (out_size < in_size) + return PDF_EBADDATA; + + /* If we are at first block, then we have found the IV vector */ + if (state->first_block == PDF_TRUE) + { + pdf_char_t * iv = in; + gcry_cipher_setiv (state->cipher, iv, AESV2_BLKSIZE); + input = in + AESV2_BLKSIZE; + input_size = in_size - AESV2_BLKSIZE; + + memcpy (out, iv, AESV2_BLKSIZE); + + output = out + AESV2_BLKSIZE; + output_size = out_size - AESV2_BLKSIZE; + + state->first_block = PDF_FALSE; + } + else + { + output = out; + output_size = out_size; + input = in; + input_size = in_size; + } + + if (gcry_cipher_encrypt (state->cipher, output, output_size, input, input_size) != GPG_ERR_NO_ERROR) + { + return PDF_ERROR; + } + + if (result_size != NULL) + *result_size = in_size; + + return PDF_OK; +} + + + + +pdf_status_t +pdf_crypt_cipher_aesv2_decrypt (void * _state, + pdf_char_t *out, pdf_size_t out_size, + pdf_char_t *in, pdf_size_t in_size, + pdf_size_t *result_size) +{ + aesv2_state_t state = _state; + pdf_char_t * output; + pdf_size_t output_size; + pdf_char_t * input; + pdf_size_t input_size; + + if (in_size < AESV2_BLKSIZE || in_size % AESV2_BLKSIZE != 0) + return PDF_EBADDATA; + + if (out_size < in_size) + return PDF_EBADDATA; + + /* If we are at first block, then we have found the IV vector */ + if (state->first_block == PDF_TRUE) + { + pdf_char_t * iv = in; + gcry_cipher_setiv (state->cipher, iv, AESV2_BLKSIZE); + input = in + AESV2_BLKSIZE; + input_size = in_size - AESV2_BLKSIZE; + + memcpy (out, iv, AESV2_BLKSIZE); + + output = out + AESV2_BLKSIZE; + output_size = out_size - AESV2_BLKSIZE; + + state->first_block = PDF_FALSE; + } + else + { + output = out; + output_size = out_size; + input = in; + input_size = in_size; + } + + if (gcry_cipher_decrypt (state->cipher, output, output_size, input, input_size) != GPG_ERR_NO_ERROR) + { + return PDF_ERROR; + } + + if (result_size != NULL) + *result_size = in_size; + + return PDF_OK; +} + + + + /* End of pdf-crypt-c-aesv2.c */ === modified file 'src/base/pdf-crypt-c-v2.c' --- src/base/pdf-crypt-c-v2.c 2008-11-29 16:21:37 +0000 +++ src/base/pdf-crypt-c-v2.c 2008-12-23 18:08:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 16:00:51 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-23 18:02:38 davazp" * * File: pdf-crypt.c * Date: Fri Feb 22 21:05:05 2008 @@ -97,24 +97,6 @@ } - -pdf_size_t -pdf_crypt_cipher_v2_encrypt_size (void * cipher, - pdf_char_t *in, pdf_size_t in_size) -{ - return in_size; -} - - -pdf_size_t -pdf_crypt_cipher_v2_decrypt_size (void * cipher, - pdf_char_t *in, pdf_size_t in_size) -{ - return in_size; -} - - - pdf_status_t pdf_crypt_cipher_v2_encrypt (void * cipher, pdf_char_t *out, pdf_size_t out_size, @@ -125,7 +107,8 @@ if (gcry_cipher_encrypt (*hd, out, out_size, in, in_size) == GPG_ERR_NO_ERROR) { - *result_size = in_size; + if (result_size != NULL) + *result_size = in_size; return PDF_OK; } else @@ -146,7 +129,8 @@ if (gcry_cipher_decrypt (*hd, out, out_size, in, in_size) == GPG_ERR_NO_ERROR) { - *result_size = in_size; + if (result_size != NULL) + *result_size = in_size; return PDF_OK; } else === modified file 'src/base/pdf-crypt.h' --- src/base/pdf-crypt.h 2008-11-29 16:21:37 +0000 +++ src/base/pdf-crypt.h 2008-12-23 18:08:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 16:01:38 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-23 17:13:24 davazp" * * File: pdf-crypt.c * Date: Fri Feb 22 21:05:05 2008 @@ -32,7 +32,7 @@ #include #include #include - +#include /* BEGIN PUBLIC */ @@ -59,10 +59,6 @@ pdf_status_t (*setkey) (void * cipher, pdf_char_t *key, pdf_size_t size); - pdf_size_t (*encrypt_size) (void * cipher, pdf_char_t *in, pdf_size_t in_size); - - pdf_size_t (*decrypt_size) (void * cipher, pdf_char_t *in, pdf_size_t in_size); - pdf_status_t (*encrypt) (void * cipher, pdf_char_t *out, pdf_size_t out_size, pdf_char_t *in, pdf_size_t in_size, @@ -81,8 +77,6 @@ struct pdf_crypt_cipher_s { pdf_crypt_cipher_algo_t algo; - pdf_char_t * key; - pdf_size_t key_size; void * raw; }; @@ -99,6 +93,8 @@ pdf_status_t pdf_crypt_init (void); +pdf_status_t pdf_crypt_nonce (pdf_char_t * buffer, pdf_size_t size); + pdf_status_t pdf_crypt_cipher_new (enum pdf_crypt_cipher_algo_e algorithm, pdf_crypt_cipher_t *cipher); @@ -106,12 +102,6 @@ pdf_char_t *key, pdf_size_t size); -pdf_size_t pdf_crypt_cipher_encrypt_size (pdf_crypt_cipher_t cipher, - pdf_char_t *in, pdf_size_t in_size); - -pdf_size_t pdf_crypt_cipher_decrypt_size (pdf_crypt_cipher_t cipher, - pdf_char_t *in, pdf_size_t in_size); - pdf_status_t pdf_crypt_cipher_encrypt (pdf_crypt_cipher_t cipher, pdf_char_t *out, pdf_size_t out_size, @@ -129,11 +119,14 @@ pdf_status_t pdf_crypt_cipher_destroy (pdf_crypt_cipher_t cipher); -pdf_status_t pdf_crypt_md_new (pdf_crypt_md_t *md, enum pdf_crypt_md_algo_e algo); - -pdf_status_t pdf_crypt_md_hash (pdf_crypt_md_t md, - pdf_char_t *out, pdf_size_t out_size, - pdf_char_t *in, pdf_size_t in_size); +pdf_status_t pdf_crypt_md_new (enum pdf_crypt_md_algo_e algo, pdf_crypt_md_t *md); + +pdf_status_t pdf_crypt_md_write (pdf_crypt_md_t md, + pdf_char_t *in, pdf_size_t in_size); + +pdf_status_t pdf_crypt_md_read (pdf_crypt_md_t md, + pdf_char_t *out, pdf_size_t out_size); + pdf_status_t pdf_crypt_md_destroy (pdf_crypt_md_t hd); @@ -191,6 +184,15 @@ EXTERN_INLINE pdf_status_t +pdf_crypt_nonce (pdf_char_t * buffer, pdf_size_t size) +{ + gcry_create_nonce (buffer, size); + return PDF_OK; +} + + + +EXTERN_INLINE pdf_status_t pdf_crypt_cipher_new (enum pdf_crypt_cipher_algo_e algorithm, pdf_crypt_cipher_t *cipher) { @@ -206,8 +208,6 @@ { cipher_algo->new = pdf_crypt_cipher_aesv2_new; cipher_algo->setkey = pdf_crypt_cipher_aesv2_setkey; - cipher_algo->encrypt_size = pdf_crypt_cipher_aesv2_encrypt_size; - cipher_algo->decrypt_size = pdf_crypt_cipher_aesv2_decrypt_size; cipher_algo->encrypt = pdf_crypt_cipher_aesv2_encrypt; cipher_algo->decrypt = pdf_crypt_cipher_aesv2_decrypt; cipher_algo->destroy = pdf_crypt_cipher_aesv2_destroy; @@ -217,8 +217,6 @@ { cipher_algo->new = pdf_crypt_cipher_v2_new; cipher_algo->setkey = pdf_crypt_cipher_v2_setkey; - cipher_algo->encrypt_size = pdf_crypt_cipher_v2_encrypt_size; - cipher_algo->decrypt_size = pdf_crypt_cipher_v2_decrypt_size; cipher_algo->encrypt = pdf_crypt_cipher_v2_encrypt; cipher_algo->decrypt = pdf_crypt_cipher_v2_decrypt; cipher_algo->destroy = pdf_crypt_cipher_v2_destroy; @@ -234,10 +232,8 @@ if (cipher_algo->new (&(*cipher)->raw) == PDF_OK) { - (*cipher)->algo = cipher_algo; - (*cipher)->key = NULL; - (*cipher)->key_size = 0; - status = PDF_OK; + (*cipher)->algo = cipher_algo; + status = PDF_OK; } else status = PDF_ERROR; @@ -250,34 +246,7 @@ pdf_crypt_cipher_setkey (pdf_crypt_cipher_t cipher, pdf_char_t *key, pdf_size_t size) { - pdf_status_t status; - - status = cipher->algo->setkey (cipher->raw, key, size); - - if (status == PDF_OK) - { - cipher->key = pdf_alloc (size); - cipher->key_size = size; - memcpy (cipher->key, key, size); - } - - return status; -} - - -EXTERN_INLINE pdf_size_t -pdf_crypt_cipher_encrypt_size (pdf_crypt_cipher_t cipher, - pdf_char_t *in, pdf_size_t in_size) -{ - return cipher->algo->encrypt_size (cipher->raw, in, in_size); -} - - -EXTERN_INLINE pdf_size_t -pdf_crypt_cipher_decrypt_size (pdf_crypt_cipher_t cipher, - pdf_char_t *in, pdf_size_t in_size) -{ - return cipher->algo->decrypt_size (cipher->raw, in, in_size); + return cipher->algo->setkey (cipher->raw, key, size); } @@ -287,7 +256,6 @@ pdf_char_t *in, pdf_size_t in_size, pdf_size_t *result_size) { - cipher->algo->setkey (cipher->raw, cipher->key, cipher->key_size); return cipher->algo->encrypt (cipher->raw, out, out_size, in, in_size, result_size); } @@ -298,7 +266,6 @@ pdf_char_t *in, pdf_size_t in_size, pdf_size_t *result_size) { - cipher->algo->setkey (cipher->raw, cipher->key, cipher->key_size); return cipher->algo->decrypt (cipher->raw, out, out_size, in, in_size, result_size); } @@ -308,11 +275,9 @@ { pdf_status_t ret; - pdf_dealloc (cipher->key); ret = cipher->algo->destroy (cipher->raw); pdf_dealloc (cipher->algo); pdf_dealloc (cipher); - return ret; } @@ -321,58 +286,84 @@ EXTERN_INLINE pdf_status_t -pdf_crypt_md_new (pdf_crypt_md_t *md, enum pdf_crypt_md_algo_e algo) +pdf_crypt_md_new (enum pdf_crypt_md_algo_e algo, pdf_crypt_md_t *_md) { - *md = pdf_alloc (sizeof(struct pdf_crypt_md_s)); + pdf_crypt_md_t md; + gcry_md_hd_t * raw; + pdf_status_t ret; + + md = pdf_alloc (sizeof(struct pdf_crypt_md_s)); if (algo == PDF_CRYPT_MD_MD5) { - (*md)->raw = pdf_alloc (sizeof(gcry_md_hd_t)); + raw = pdf_alloc (sizeof(gcry_md_hd_t)); - if (gcry_md_open ((*md)->raw, GCRY_MD_MD5, 0) == GPG_ERR_NO_ERROR) - { - return PDF_OK; - } + if (gcry_md_open (raw, GCRY_MD_MD5, 0) == GPG_ERR_NO_ERROR) + { + md->raw = raw; + *_md = md; + ret = PDF_OK; + } else - { - pdf_dealloc ((*md)->raw); - return PDF_ERROR; - } + { + gcry_md_close (*raw); + ret = PDF_ERROR; + } } else { - return PDF_EBADDATA; + ret = PDF_EBADDATA; } + + return ret; } EXTERN_INLINE pdf_status_t -pdf_crypt_md_hash (pdf_crypt_md_t md, - pdf_char_t *out, pdf_size_t out_size, - pdf_char_t *in, pdf_size_t in_size) +pdf_crypt_md_write (pdf_crypt_md_t md, + pdf_char_t *in, pdf_size_t in_size) { gcry_md_hd_t * gcry_md = md->raw; - register pdf_size_t i; - - for (i = 0; i < in_size; i++) - { - gcry_md_putc (*gcry_md, in[i]); - } - + gcry_md_write (*gcry_md, in, in_size); + return PDF_OK; +} + + +EXTERN_INLINE pdf_status_t +pdf_crypt_md_read (pdf_crypt_md_t md, + pdf_char_t *out, pdf_size_t out_size) +{ + gcry_md_hd_t * gcry_md = md->raw; + pdf_size_t required_size = gcry_md_get_algo_dlen (GCRY_MD_MD5); + + if (out_size < required_size) + return PDF_EBADDATA; + if (gcry_md_final (*gcry_md) != GPG_ERR_NO_ERROR) { return PDF_ERROR; } else { - gcry_md_read (*gcry_md, GCRY_MD_MD5); - gcry_md_close (*gcry_md); + void * hash; + + hash = gcry_md_read (*gcry_md, GCRY_MD_MD5); + + if (hash == NULL) + return PDF_ERROR; + else + { + memcpy (out, hash, required_size); + } + + gcry_md_reset (*gcry_md); return PDF_OK; } } + EXTERN_INLINE pdf_status_t pdf_crypt_md_destroy (pdf_crypt_md_t md) { === modified file 'src/base/pdf-stm-buffer.c' --- src/base/pdf-stm-buffer.c 2008-10-04 12:31:11 +0000 +++ src/base/pdf-stm-buffer.c 2008-12-21 17:39:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/10/04 14:26:53 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-20 15:48:31 davazp" * * File: pdf-stm-buffer.c * Date: Wed Jul 23 23:28:59 2008 @@ -25,6 +25,7 @@ #include #include +#include pdf_stm_buffer_t pdf_stm_buffer_new (pdf_size_t size) @@ -64,6 +65,20 @@ return ((buffer->wp - buffer->rp) == 0); } + +pdf_status_t +pdf_stm_buffer_resize (pdf_stm_buffer_t buffer, pdf_size_t newsize) +{ + if (pdf_realloc (buffer->data, newsize) != PDF_OK) + return PDF_ENOMEM; + + buffer->size = newsize; + buffer->rp = PDF_MIN (buffer->rp, newsize); + buffer->wp = PDF_MIN (buffer->wp, newsize); + return PDF_OK; +} + + pdf_status_t pdf_stm_buffer_rewind (pdf_stm_buffer_t buffer) { === modified file 'src/base/pdf-stm-buffer.h' --- src/base/pdf-stm-buffer.h 2008-11-29 16:21:37 +0000 +++ src/base/pdf-stm-buffer.h 2008-12-21 17:39:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 15:14:38 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-20 15:48:34 davazp" * * File: pdf-stm-buffer.h * Date: Wed Jun 18 20:34:23 2008 @@ -49,6 +49,7 @@ pdf_bool_t pdf_stm_buffer_full_p (pdf_stm_buffer_t buffer); pdf_bool_t pdf_stm_buffer_eob_p (pdf_stm_buffer_t buffer); +pdf_status_t pdf_stm_buffer_resize (pdf_stm_buffer_t buffer, pdf_size_t newsize); pdf_status_t pdf_stm_buffer_rewind (pdf_stm_buffer_t buffer); #endif /* !PDF_STM_BUFFER_H */ === added file 'src/base/pdf-stm-f-aesv2.c' --- src/base/pdf-stm-f-aesv2.c 1970-01-01 00:00:00 +0000 +++ src/base/pdf-stm-f-aesv2.c 2008-12-25 15:49:31 +0000 @@ -0,0 +1,333 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-25 16:37:22 davazp" + * + * File: pdf-stm-f-aesv2.c + * Date: Sun Dec 14 20:13:53 2008 + * + * GNU PDF Library - AESV2 stream filter + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include +#include + +#define AESV2_CACHE_SIZE 16 + + +/* Internal state */ +struct pdf_stm_f_aesv2_s +{ + pdf_crypt_cipher_t cipher; + pdf_stm_buffer_t in_cache; + pdf_stm_buffer_t out_cache; +}; +typedef struct pdf_stm_f_aesv2_s * pdf_stm_f_aesv2_t; + + +/* Encryption and decryption */ +enum pdf_stm_f_aesv2_mode_e + { + PDF_STM_F_AESV2_MODE_ENCODE, + PDF_STM_F_AESV2_MODE_DECODE + }; +typedef enum pdf_stm_f_aesv2_mode_e pdf_stm_f_aesv2_mode_t; + + + +static inline pdf_status_t +pdf_stm_f_aesv2_init (pdf_hash_t params, void **state) +{ + pdf_status_t ret; + pdf_stm_f_aesv2_t filter_state; + + filter_state = pdf_alloc (sizeof (struct pdf_stm_f_aesv2_s)); + + if (filter_state == NULL) + { + ret = PDF_ENOMEM; + } + else if (state == NULL) + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + else + { + pdf_char_t * key; + pdf_size_t * keysize; + pdf_crypt_cipher_t cipher; + + /* We demand all parameters are present */ + if ((( pdf_hash_key_p (params, "Key") == PDF_TRUE)) + && pdf_hash_key_p (params, "KeySize") == PDF_TRUE) + { + pdf_hash_search (params, "Key", (const void **)&key); + pdf_hash_search (params, "KeySize", (const void **)&keysize); + + if (pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher) == PDF_OK + && pdf_crypt_cipher_setkey (cipher, key, *keysize) == PDF_OK) + { + filter_state->cipher = cipher; + + /* Initialize cache buffers */ + filter_state->in_cache = pdf_stm_buffer_new (AESV2_CACHE_SIZE); + filter_state->out_cache = pdf_stm_buffer_new (AESV2_CACHE_SIZE); + + if (filter_state->in_cache == NULL || filter_state->out_cache == NULL) + { + ret = PDF_ERROR; + } + else + { + ret = PDF_OK; + *state = filter_state; + } + } + else + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + } + else + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + } + + return ret; +} + + + + +static inline pdf_status_t +pdf_stm_f_aesv2_apply (pdf_stm_f_aesv2_mode_t mode, + pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + pdf_stm_f_aesv2_t filter_state = state; + pdf_crypt_cipher_t cipher = filter_state->cipher; + pdf_stm_buffer_t in_cache = filter_state->in_cache; + pdf_stm_buffer_t out_cache = filter_state->out_cache; + + while(1) + { + pdf_size_t in_size; + pdf_size_t out_size; + pdf_size_t in_cache_size; + pdf_size_t out_cache_size; + pdf_size_t bytes_to_read; + pdf_size_t bytes_to_write; + + /* Read bytes from IN and fill IN_CACHE*/ + in_size = in->wp - in->rp; + in_cache_size = in_cache->size - in_cache->wp; + bytes_to_read = PDF_MIN (in_size, in_cache_size); + + memcpy (in_cache->data + in_cache->wp, + in->data + in->rp, + bytes_to_read); + + in_cache->wp += bytes_to_read; + in->rp += bytes_to_read; + + + /* If we cannot fill all IN_CACHE... */ + if (!pdf_stm_buffer_full_p (in_cache)) + { + if (finish_p && mode == PDF_STM_F_AESV2_MODE_DECODE + && in_cache->wp > 0) + return PDF_ERROR; + + /* ...pad the cache if we have reached EOD */ + if (finish_p + && !pdf_stm_buffer_full_p (in_cache) + && mode == PDF_STM_F_AESV2_MODE_ENCODE) + { + pdf_size_t padding; + padding = in_cache->size - in_cache->wp; + + memset (in_cache->data + in_cache->wp, + padding, + padding); + + in_cache->wp += padding; + } + else + { + if (pdf_stm_buffer_eob_p (out_cache)) + return PDF_ENINPUT; /* ...ask more input */ + } + } + + + /* If OUT_CACHE is empty and IN_CACHE is full, then it is ready + to be processed. */ + if (pdf_stm_buffer_full_p (in_cache) && pdf_stm_buffer_eob_p (out_cache)) + { + switch (mode) + { + case PDF_STM_F_AESV2_MODE_ENCODE: + pdf_crypt_cipher_encrypt (cipher, + out_cache->data, + out_cache->size, + in_cache->data, + in_cache->size, + NULL); + break; + + case PDF_STM_F_AESV2_MODE_DECODE: + pdf_crypt_cipher_decrypt (cipher, + out_cache->data, + out_cache->size, + in_cache->data, + in_cache->size, + NULL); + break; + + default: /* not reached */ + break; + } + + /* Both cache are full now */ + pdf_stm_buffer_rewind (in_cache); + out_cache->wp = out_cache->size; + } + + + /* When we are decrypting data, we need know what block is the + last. If both IN and IN_CACHE are empty, then OUT_CACHE could + hold it. So, we ask more input to we make sure.*/ + if (mode == PDF_STM_F_AESV2_MODE_DECODE + && pdf_stm_buffer_eob_p (in) && pdf_stm_buffer_eob_p (in_cache)) + { + /* When we know it is the last, remove the padding. */ + if (finish_p) + { + pdf_size_t padding; + padding = out_cache->data[out_cache->size - 1]; + + if (padding > AESV2_CACHE_SIZE) + return PDF_ERROR; + + out_cache->wp = out_cache->size - padding; + } + else + return PDF_ENINPUT; + } + + + /* Finally, we fill the OUT buffer */ + out_size = out->size - out->wp; + out_cache_size = out_cache->wp - out_cache->rp; + bytes_to_write = PDF_MIN (out_size, out_cache_size); + + memcpy (out->data + out->wp, + out_cache->data + out_cache->rp, + bytes_to_write); + + out_cache->rp += bytes_to_write; + out->wp += bytes_to_write; + + + if (finish_p) + { + return PDF_EEOF; + } + else if (pdf_stm_buffer_full_p (out)) + { + return PDF_ENOUTPUT; + } + else + { + pdf_stm_buffer_rewind (out_cache); + } + } +} + + + +static inline pdf_status_t +pdf_stm_f_aesv2_dealloc_state (void *state) +{ + pdf_stm_f_aesv2_t filter_state = state; + pdf_crypt_cipher_destroy (filter_state->cipher); + pdf_stm_buffer_destroy (filter_state->in_cache); + pdf_stm_buffer_destroy (filter_state->out_cache); + pdf_dealloc (state); + return PDF_OK; +} + + + + +/* Encode filter */ + +pdf_status_t +pdf_stm_f_aesv2enc_init (pdf_hash_t params, void **state) +{ + return pdf_stm_f_aesv2_init (params, state); +} + +pdf_status_t +pdf_stm_f_aesv2enc_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + return pdf_stm_f_aesv2_apply (PDF_STM_F_AESV2_MODE_ENCODE, + params, state, in, out, finish_p); +} + +pdf_status_t +pdf_stm_f_aesv2enc_dealloc_state (void *state) +{ + return pdf_stm_f_aesv2_dealloc_state (state); +} + + + +/* Decode filter */ + +pdf_status_t +pdf_stm_f_aesv2dec_init (pdf_hash_t params, void **state) +{ + return pdf_stm_f_aesv2_init (params, state); +} + + +pdf_status_t +pdf_stm_f_aesv2dec_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + return pdf_stm_f_aesv2_apply (PDF_STM_F_AESV2_MODE_DECODE, + params, state, in, out, finish_p); +} + + +pdf_status_t +pdf_stm_f_aesv2dec_dealloc_state (void *state) +{ + return pdf_stm_f_aesv2_dealloc_state (state); +} + + + +/* End of pdf_stm_f_aesv2.c */ === added file 'src/base/pdf-stm-f-aesv2.h' --- src/base/pdf-stm-f-aesv2.h 1970-01-01 00:00:00 +0000 +++ src/base/pdf-stm-f-aesv2.h 2008-12-21 17:39:51 +0000 @@ -0,0 +1,65 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-14 20:32:40 davazp" + * + * File: pdf-stm-f-aesv2.h + * Date: Fri Dec 5 16:58:49 2008 + * + * GNU PDF Library - AESv2 stream filter + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PDF_STM_F_AESV2_H +#define PDF_STM_F_AESV2_H + +#include +#include +#include +#include +#include +#include +#include + + +pdf_status_t pdf_stm_f_aesv2enc_init (pdf_hash_t params, + void **state); + +pdf_status_t pdf_stm_f_aesv2enc_apply (pdf_hash_t params, + void *state, + pdf_stm_buffer_t in, + pdf_stm_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_aesv2enc_dealloc_state (void *state); + + +pdf_status_t pdf_stm_f_aesv2dec_init (pdf_hash_t params, + void **state); + +pdf_status_t pdf_stm_f_aesv2dec_apply (pdf_hash_t params, + void *state, + pdf_stm_buffer_t in, + pdf_stm_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_aesv2dec_dealloc_state (void *state); + + + +#endif /* PDF_STM_F_AESV2_H */ + +/* End of pdf_stm_f_aesv2.h */ === added file 'src/base/pdf-stm-f-md5.c' --- src/base/pdf-stm-f-md5.c 1970-01-01 00:00:00 +0000 +++ src/base/pdf-stm-f-md5.c 2008-12-25 15:49:31 +0000 @@ -0,0 +1,151 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-25 00:13:01 davazp" + * + * File: pdf-stm-f-md5.c + * Date: Fri Dec 5 16:40:50 2008 + * + * GNU PDF Library - Message-digest stream filter + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#define MD5_OUTPUT_SIZE 16 + + + +/* Internal state */ +struct pdf_stm_f_md5_s +{ + pdf_crypt_md_t md; + pdf_stm_buffer_t cache; +}; +typedef struct pdf_stm_f_md5_s * pdf_stm_f_md5_t; + + + +pdf_status_t +pdf_stm_f_md5enc_init (pdf_hash_t params, void **state) +{ + pdf_status_t ret; + pdf_stm_f_md5_t filter_state; + + filter_state = pdf_alloc (sizeof (struct pdf_stm_f_md5_s)); + + if (filter_state == NULL) + { + ret = PDF_ENOMEM; + } + else if (state == NULL) + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + else + { + pdf_crypt_md_t md; + + if (pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md) == PDF_OK) + { + filter_state->md = md; + filter_state->cache = pdf_stm_buffer_new (MD5_OUTPUT_SIZE); + + if (filter_state->cache == NULL) + { + pdf_dealloc (filter_state); + ret = PDF_ERROR; + } + else + { + *state = filter_state; + ret = PDF_OK; + } + } + else + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + } + return ret; +} + + + +pdf_status_t +pdf_stm_f_md5enc_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + pdf_stm_f_md5_t filter_state = state; + pdf_stm_buffer_t cache = filter_state->cache; + pdf_size_t in_size; + pdf_status_t ret; + + in_size = in->wp - in->rp; + + pdf_crypt_md_write (filter_state->md, in->data, in_size); + in->rp += in_size; + ret = PDF_ENINPUT; + + if (finish_p == PDF_TRUE) + { + pdf_size_t bytes_to_write; + pdf_size_t cache_size; + pdf_size_t out_size; + + if (pdf_stm_buffer_eob_p (cache)) + { + /* If we have reached the end, read the hash value in cache */ + pdf_crypt_md_read (filter_state->md, cache->data, cache->size); + cache->wp = cache->size; + } + + out_size = out->size - out->wp; + cache_size = cache->wp - cache->rp; + bytes_to_write = PDF_MIN (out_size, cache_size); + + memcpy (out->data, cache->data + cache->rp, bytes_to_write); + + cache->rp += bytes_to_write; + out->wp += bytes_to_write; + + if (out_size < cache_size) + ret = PDF_ENOUTPUT; + else + ret = PDF_EEOF; + } + + return ret; +} + + + +pdf_status_t +pdf_stm_f_md5enc_dealloc_state (void *state) +{ + pdf_stm_f_md5_t filter_state = state; + pdf_crypt_md_destroy (filter_state->md); + pdf_stm_buffer_destroy (filter_state->cache); + pdf_dealloc (state); + return PDF_OK; +} + + + +/* End of pdf_stm_f_md5.c */ === added file 'src/base/pdf-stm-f-md5.h' --- src/base/pdf-stm-f-md5.h 1970-01-01 00:00:00 +0000 +++ src/base/pdf-stm-f-md5.h 2008-12-21 17:39:51 +0000 @@ -0,0 +1,63 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-15 17:53:17 davazp" + * + * File: pdf-stm-f-md5.h + * Date: Fri Dec 5 16:38:39 2008 + * + * GNU PDF Library - MD5 stream filter + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PDF_STM_F_MD5_H +#define PDF_STM_F_MD5_H + +#include +#include +#include +#include +#include +#include +#include + + +/* Internal state of cipher filter */ + +struct pdf_stm_f_md_s +{ + void *md; +}; + + +/* Filter API implementation */ + +pdf_status_t pdf_stm_f_md5enc_init (pdf_hash_t params, + void **state); + +pdf_status_t pdf_stm_f_md5enc_apply (pdf_hash_t params, + void *state, + pdf_stm_buffer_t in, + pdf_stm_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_md5enc_dealloc_state (void *state); + + + +#endif /* PDF_STM_F_MD5_H */ + +/* End of pdf_stm_f_md5.h */ === added file 'src/base/pdf-stm-f-v2.c' --- src/base/pdf-stm-f-v2.c 1970-01-01 00:00:00 +0000 +++ src/base/pdf-stm-f-v2.c 2008-12-25 15:49:31 +0000 @@ -0,0 +1,222 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-24 22:58:05 davazp" + * + * File: pdf-stm-f-v2.c + * Date: Tue Jul 10 23:44:00 2007 + * + * GNU PDF Library - V2 stream filter + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + + +/* Internal state */ +struct pdf_stm_f_v2_s +{ + pdf_crypt_cipher_t cipher; +}; +typedef struct pdf_stm_f_v2_s * pdf_stm_f_v2_t; + + +/* Encryption and decryption */ +enum pdf_stm_f_v2_mode_e +{ + PDF_STM_F_V2_MODE_ENCODE, + PDF_STM_F_V2_MODE_DECODE +}; +typedef enum pdf_stm_f_v2_mode_e pdf_stm_f_v2_mode_t; + + + +static inline pdf_status_t +pdf_stm_f_v2_init (pdf_hash_t params, void **state) +{ + pdf_status_t ret; + pdf_stm_f_v2_t filter_state; + + filter_state = pdf_alloc (sizeof (struct pdf_stm_f_v2_s)); + + if (filter_state == NULL) + { + ret = PDF_ENOMEM; + } + else if (state == NULL) + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + else + { + pdf_char_t * key; + pdf_size_t * keysize; + pdf_crypt_cipher_t cipher; + + /* We demand all parameters are present */ + if ((( pdf_hash_key_p (params, "Key") == PDF_TRUE)) + && pdf_hash_key_p (params, "KeySize") == PDF_TRUE) + { + pdf_hash_search (params, "Key", (const void **)&key); + pdf_hash_search (params, "KeySize", (const void **)&keysize); + + if (pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher) == PDF_OK + && pdf_crypt_cipher_setkey (cipher, key, *keysize) == PDF_OK) + { + filter_state->cipher = cipher; + *state = filter_state; + ret = PDF_OK; + } + else + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + } + else + { + pdf_dealloc (filter_state); + ret = PDF_EBADDATA; + } + } + + return ret; +} + + +static inline pdf_status_t +pdf_stm_f_v2_apply (pdf_stm_f_v2_mode_t mode, + pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + pdf_stm_f_v2_t filter_state = state; + + pdf_size_t in_size; + pdf_size_t out_size; + pdf_size_t bytes_to_copy; + pdf_size_t written; + pdf_status_t ret; + + in_size = in->wp - in->rp; + out_size = out->size - out->wp; + + bytes_to_copy = PDF_MIN(out_size, in_size); + + if (bytes_to_copy != 0) + { + if (mode == PDF_STM_F_V2_MODE_ENCODE) + { + pdf_crypt_cipher_encrypt (filter_state->cipher, + out->data, + out_size, + in->data, + in_size, + &written); + } + else if (mode == PDF_STM_F_V2_MODE_DECODE) + { + pdf_crypt_cipher_decrypt (filter_state->cipher, + out->data, + out_size, + in->data, + in_size, + &written); + } + else + { + /* This point should not be reached. */ + } + + in->rp += bytes_to_copy; + out->wp += written; + } + + if (in_size > out_size) + { + /* We need more room in the output buffer */ + ret = PDF_ENOUTPUT; + } + else + { + /* We can process more input */ + ret = PDF_ENINPUT; + } + + return ret; +} + + +static inline pdf_status_t +pdf_stm_f_v2_dealloc_state (void *state) +{ + pdf_stm_f_v2_t filter_state = state; + pdf_crypt_cipher_destroy (filter_state->cipher); + pdf_dealloc (state); + return PDF_OK; +} + + + +/* Encode filter */ + +pdf_status_t +pdf_stm_f_v2enc_init (pdf_hash_t params, void **state) +{ + return pdf_stm_f_v2_init (params, state); +} + +pdf_status_t +pdf_stm_f_v2enc_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + return pdf_stm_f_v2_apply (PDF_STM_F_V2_MODE_ENCODE, + params, state, in, out, finish_p); +} + +pdf_status_t +pdf_stm_f_v2enc_dealloc_state (void *state) +{ + return pdf_stm_f_v2_dealloc_state (state); +} + + +/* Decode filter */ + +pdf_status_t +pdf_stm_f_v2dec_init (pdf_hash_t params, void **state) +{ + return pdf_stm_f_v2_init (params, state); +} + + +pdf_status_t +pdf_stm_f_v2dec_apply (pdf_hash_t params, void *state, pdf_stm_buffer_t in, + pdf_stm_buffer_t out, pdf_bool_t finish_p) +{ + return pdf_stm_f_v2_apply (PDF_STM_F_V2_MODE_DECODE, + params, state, in, out, finish_p); +} + + +pdf_status_t +pdf_stm_f_v2dec_dealloc_state (void *state) +{ + return pdf_stm_f_v2_dealloc_state (state); +} + + +/* End of pdf_stm_f_v2.c */ === added file 'src/base/pdf-stm-f-v2.h' --- src/base/pdf-stm-f-v2.h 1970-01-01 00:00:00 +0000 +++ src/base/pdf-stm-f-v2.h 2008-12-21 17:39:51 +0000 @@ -0,0 +1,67 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-14 20:16:02 davazp" + * + * File: pdf-stm-f-v2.h + * Date: Fri Dec 5 16:58:49 2008 + * + * GNU PDF Library - V2 stream filter + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PDF_STM_F_V2_H +#define PDF_STM_F_V2_H + +#include +#include +#include +#include +#include +#include +#include + + +/* Filter API implementation */ + +pdf_status_t pdf_stm_f_v2enc_init (pdf_hash_t params, + void **state); + +pdf_status_t pdf_stm_f_v2enc_apply (pdf_hash_t params, + void *state, + pdf_stm_buffer_t in, + pdf_stm_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_v2enc_dealloc_state (void *state); + + +pdf_status_t pdf_stm_f_v2dec_init (pdf_hash_t params, + void **state); + +pdf_status_t pdf_stm_f_v2dec_apply (pdf_hash_t params, + void *state, + pdf_stm_buffer_t in, + pdf_stm_buffer_t out, + pdf_bool_t finish_p); + +pdf_status_t pdf_stm_f_v2dec_dealloc_state (void *state); + + + +#endif /* PDF_STM_F_V2_H */ + +/* End of pdf_stm_f_v2.h */ === modified file 'src/base/pdf-stm-filter.c' --- src/base/pdf-stm-filter.c 2008-12-08 19:03:28 +0000 +++ src/base/pdf-stm-filter.c 2008-12-25 15:49:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/12/08 20:02:37 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-24 02:35:06 davazp" * * File: pdf-stm-filter.c * Date: Thu Jun 12 22:13:31 2008 @@ -101,6 +101,7 @@ new->impl.dealloc_state_fn = pdf_stm_f_rldec_dealloc_state; break; } + #if defined(HAVE_LIBZ) case PDF_STM_FILTER_FLATE_ENC: { @@ -117,6 +118,42 @@ break; } #endif /* HAVE_LIBZ */ + case PDF_STM_FILTER_V2_ENC: + { + new->impl.init_fn = pdf_stm_f_v2enc_init; + new->impl.apply_fn = pdf_stm_f_v2enc_apply; + new->impl.dealloc_state_fn = pdf_stm_f_v2enc_dealloc_state; + break; + } + case PDF_STM_FILTER_V2_DEC: + { + new->impl.init_fn = pdf_stm_f_v2dec_init; + new->impl.apply_fn = pdf_stm_f_v2dec_apply; + new->impl.dealloc_state_fn = pdf_stm_f_v2dec_dealloc_state; + break; + } + case PDF_STM_FILTER_AESV2_ENC: + { + new->impl.init_fn = pdf_stm_f_aesv2enc_init; + new->impl.apply_fn = pdf_stm_f_aesv2enc_apply; + new->impl.dealloc_state_fn = pdf_stm_f_aesv2enc_dealloc_state; + break; + } + case PDF_STM_FILTER_AESV2_DEC: + { + new->impl.init_fn = pdf_stm_f_aesv2dec_init; + new->impl.apply_fn = pdf_stm_f_aesv2dec_apply; + new->impl.dealloc_state_fn = pdf_stm_f_aesv2dec_dealloc_state; + break; + } + case PDF_STM_FILTER_MD5_ENC: + { + new->impl.init_fn = pdf_stm_f_md5enc_init; + new->impl.apply_fn = pdf_stm_f_md5enc_apply; + new->impl.dealloc_state_fn = pdf_stm_f_md5enc_dealloc_state; + break; + } + #if defined(HAVE_JBIG2DEC) case PDF_STM_FILTER_JBIG2_DEC: { @@ -126,6 +163,7 @@ break; } #endif /* HAVE_JBIG2DEC */ + default: { /* Shall not be reached, but makes the compiler happy */ === modified file 'src/base/pdf-stm-filter.h' --- src/base/pdf-stm-filter.h 2008-11-29 16:21:37 +0000 +++ src/base/pdf-stm-filter.h 2008-12-25 15:49:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 15:10:34 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-24 02:35:52 davazp" * * File: pdf-stm-filter.h * Date: Thu Jun 12 22:05:06 2008 @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #if defined(HAVE_LIBZ) # include @@ -56,6 +59,11 @@ PDF_STM_FILTER_RL_DEC, PDF_STM_FILTER_FLATE_ENC, PDF_STM_FILTER_FLATE_DEC, + PDF_STM_FILTER_AESV2_ENC, + PDF_STM_FILTER_AESV2_DEC, + PDF_STM_FILTER_V2_ENC, + PDF_STM_FILTER_V2_DEC, + PDF_STM_FILTER_MD5_ENC, PDF_STM_FILTER_JBIG2_DEC }; === modified file 'torture/unit/Makefile.am' --- torture/unit/Makefile.am 2008-12-02 20:28:39 +0000 +++ torture/unit/Makefile.am 2008-12-23 18:08:31 +0000 @@ -166,13 +166,13 @@ TEST_SUITE_CRYPT = base/crypt/pdf-crypt-init.c \ base/crypt/pdf-crypt-cipher-new.c \ + base/crypt/pdf-crypt-cipher-setkey.c \ base/crypt/pdf-crypt-cipher-destroy.c \ - base/crypt/pdf-crypt-cipher-encrypt-size.c \ - base/crypt/pdf-crypt-cipher-decrypt-size.c \ base/crypt/pdf-crypt-cipher-encrypt.c \ base/crypt/pdf-crypt-cipher-decrypt.c \ base/crypt/pdf-crypt-md-new.c \ - base/crypt/pdf-crypt-md-hash.c \ + base/crypt/pdf-crypt-md-write.c \ + base/crypt/pdf-crypt-md-read.c \ base/crypt/pdf-crypt-md-destroy.c TEST_SUITE_ALLOC = base/alloc/pdf-alloc.c \ === removed file 'torture/unit/base/crypt/pdf-crypt-cipher-decrypt-size.c' --- torture/unit/base/crypt/pdf-crypt-cipher-decrypt-size.c 2008-10-03 16:08:19 +0000 +++ torture/unit/base/crypt/pdf-crypt-cipher-decrypt-size.c 1970-01-01 00:00:00 +0000 @@ -1,87 +0,0 @@ -/* -*- mode: C -*- Time-stamp: "08/09/20 14:43:38 jemarch" - * - * File: pdf-crypt-cipher-decrypt-size.c - * Date: Wed Mar 12 12:43:00 2008 - * - * GNU PDF Library - Unit tests for pdf_crypt_cipher_decrypt_size - * - */ - -/* Copyright (C) 2008 Free Software Foundation, Inc. */ - -/* This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include -#include -#include - - -/* - * Test: pdf_crypt_cipher_decrypt_size_001 - * Description: - * Get the plain buffer size for a 32 bytes ciphered buffer (AESV2). - * Success condition: - * Returns 0 - */ -START_TEST (pdf_crypt_cipher_decrypt_size_001) -{ - pdf_crypt_cipher_t cipher; - pdf_crypt_init(); - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); - fail_if (pdf_crypt_cipher_decrypt_size (cipher, NULL, 32) != 0); - pdf_crypt_cipher_destroy (cipher); -} -END_TEST - - -/* - * Test: pdf_crypt_cipher_decrypt_size_003 - * Description: - * Get the plain buffer size for a 15 bytes ciphered buffer (V2). - * Success condition: - * Returns 15 - */ -START_TEST (pdf_crypt_cipher_decrypt_size_002) -{ - pdf_crypt_cipher_t cipher; - pdf_crypt_init(); - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); - fail_if (pdf_crypt_cipher_decrypt_size (cipher, NULL, 15) != 15); - pdf_crypt_cipher_destroy (cipher); -} -END_TEST - - - -/* - * Test case creation function - */ -TCase * -test_pdf_crypt_cipher_decrypt_size (void) -{ - TCase *tc = tcase_create("pdf_crypt_cipher_decrypt_size"); - - tcase_add_test(tc, pdf_crypt_cipher_decrypt_size_001); - tcase_add_test(tc, pdf_crypt_cipher_decrypt_size_002); - - return tc; -} - - -/* End of pdf-crypt-cipher-decrypt-size.c */ - === modified file 'torture/unit/base/crypt/pdf-crypt-cipher-decrypt.c' --- torture/unit/base/crypt/pdf-crypt-cipher-decrypt.c 2008-11-29 16:21:37 +0000 +++ torture/unit/base/crypt/pdf-crypt-cipher-decrypt.c 2008-12-23 18:08:31 +0000 @@ -1,26 +1,27 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 16:04:36 jemarch" - * +/* + * -*- mode: C -*- Time-stamp: "2008-12-23 18:57:09 davazp" + * * File: pdf-crypt-cipher-decrypt.c * Date: Wed Mar 12 12:43:00 2008 - * + * * GNU PDF Library - Unit tests for pdf_crypt_cipher_decrypt - * - */ - -/* Copyright (C) 2008 Free Software Foundation, Inc. */ - -/* This program is free software: you can redistribute it and/or modify + * + * + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . + * */ #include @@ -34,57 +35,66 @@ /* * Test: pdf_crypt_cipher_decrypt_001 * Description: - * Decrypt an ciphered empty buffer (AESV2). + * Decrypt an ciphered buffer (AEV2). * Success condition: - * Returns 0. + * The ouput data should be correct. */ START_TEST (pdf_crypt_cipher_decrypt_001) { pdf_crypt_cipher_t cipher; - pdf_char_t *plain; - pdf_size_t plain_size; - - pdf_char_t ciphered[] = { - 0xa6, 0x14, 0x2e, 0x8a, - 0x51, 0x84, 0x84, 0x2a, - 0xf0, 0x4d, 0xc8, 0x37, - 0x23, 0x8b, 0xc6, 0xf0, - 0x3a, 0x30, 0x0f, 0xcc, - 0xb1, 0x04, 0x05, 0x47, - 0x99, 0xf4, 0x0e, 0xed, - 0x6f, 0xdf, 0xc5, 0x20 - }; - - pdf_char_t key[] = - { - 0x29, 0xfd, 0x08, 0x08, - 0x05, 0x00, 0x00, 0x00, - 0x18, 0x92, 0xe7, 0xbf, - 0xab, 0x17, 0x08, 0x08 - }; - + + pdf_char_t out[32]; + + pdf_char_t key[16] = + { + 0x06, 0xa9, 0x21, 0x40, + 0x36, 0xb8, 0xa1, 0x5b, + 0x51, 0x2e, 0x03, 0xd5, + 0x34, 0x12, 0x00, 0x06 + }; + + pdf_char_t plain[] = + { + 0x3d, 0xaf, 0xba, 0x42, /* iv vector */ + 0x9d, 0x9e, 0xb4, 0x30, + 0xb4, 0x22, 0xda, 0x80, + 0x2c, 0x9f, 0xac, 0x41, + + 'S', 'i', 'n', 'g', /* plain text */ + 'l', 'e', ' ', 'b', + 'l', 'o', 'c', 'k', + ' ', 'm', 's', 'g', + }; + + pdf_char_t ciphered[] = + { + 0x3d, 0xaf, 0xba, 0x42, /* iv vector */ + 0x9d, 0x9e, 0xb4, 0x30, + 0xb4, 0x22, 0xda, 0x80, + 0x2c, 0x9f, 0xac, 0x41, + + 0xe3, 0x53, 0x77, 0x9c, /* ciphered */ + 0x10, 0x79, 0xae, 0xb8, + 0x27, 0x08, 0x94, 0x2d, + 0xbe, 0x77, 0x18, 0x1a + }; + pdf_crypt_init(); pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); - plain_size = pdf_crypt_cipher_decrypt_size (cipher, ciphered, sizeof(ciphered)); - plain = pdf_alloc (plain_size); - - fail_if (pdf_crypt_cipher_decrypt (cipher, - plain, plain_size, - ciphered, sizeof(ciphered), - &plain_size) != PDF_OK); - fail_if (plain_size != 0); + fail_if (pdf_crypt_cipher_decrypt (cipher, out, sizeof(out), ciphered, sizeof(ciphered), NULL) != PDF_OK); + fail_if (memcmp (out, plain, sizeof(out)) != 0); - pdf_dealloc (plain); pdf_crypt_cipher_destroy (cipher); } END_TEST + /* * Test: pdf_crypt_cipher_decrypt_002 * Description: @@ -96,7 +106,7 @@ START_TEST (pdf_crypt_cipher_decrypt_002) { pdf_crypt_cipher_t cipher; - pdf_char_t *plain; + pdf_char_t plain[16]; pdf_size_t plain_size; pdf_char_t * ciphered; @@ -109,16 +119,148 @@ pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); pdf_crypt_cipher_setkey (cipher, NULL, 0); - plain_size = pdf_crypt_cipher_decrypt_size (cipher, ciphered, ciphered_size); - plain = pdf_alloc (plain_size); - fail_if (pdf_crypt_cipher_decrypt (cipher, - plain, plain_size, + plain, sizeof(plain), ciphered, ciphered_size, &plain_size) != PDF_OK); fail_if (plain_size != 0); - - pdf_dealloc (plain); + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + + + + +/* + * Test: pdf_crypt_cipher_decrypt_003 + * Description: + * Decrypt an ciphered buffer (AEV2). + * Success condition: + * The ouput data should be correct. + */ + +START_TEST (pdf_crypt_cipher_decrypt_003) +{ + pdf_crypt_cipher_t cipher; + + pdf_char_t out[80]; + + pdf_char_t key[16] = + { + 0x56, 0xe4, 0x7a, 0x38, + 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, + 0xba, 0x29, 0x03, 0x49 + }; + + pdf_char_t plain[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf + }; + + pdf_char_t ciphered[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e, + 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa, + 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6, + 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e, + 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf, + 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad, + 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d, + 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55, + }; + + pdf_crypt_init(); + + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); + pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); + + fail_if (pdf_crypt_cipher_decrypt (cipher, out, sizeof(out), ciphered, sizeof(ciphered), NULL) != PDF_OK); + fail_if (memcmp (out, plain, sizeof(out)) != 0); + + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + + + +/* + * Test: pdf_crypt_cipher_decrypt_004 + * Description: + * Decrypt an ciphered buffer incrementally (AEV2). + * Success condition: + * The ouput data should be correct. + */ + +START_TEST (pdf_crypt_cipher_decrypt_004) +{ + pdf_crypt_cipher_t cipher; + + pdf_char_t out[80]; + + pdf_char_t key[16] = + { + 0x56, 0xe4, 0x7a, 0x38, + 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, + 0xba, 0x29, 0x03, 0x49 + }; + + pdf_char_t plain[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf + }; + + pdf_char_t ciphered[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e, + 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa, + 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6, + 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e, + 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf, + 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad, + 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d, + 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55, + }; + + pdf_crypt_init(); + + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); + pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); + fail_if (pdf_crypt_cipher_decrypt (cipher, out + 00, 16, ciphered + 00, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_decrypt (cipher, out + 16, 16, ciphered + 16, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_decrypt (cipher, out + 32, 16, ciphered + 32, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_decrypt (cipher, out + 48, 16, ciphered + 48, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_decrypt (cipher, out + 64, 16, ciphered + 64, 16, NULL) != PDF_OK); + + fail_if (memcmp (out, plain, sizeof(out)) != 0); + pdf_crypt_cipher_destroy (cipher); } END_TEST @@ -135,6 +277,8 @@ TCase *tc = tcase_create("pdf_crypt_cipher_decrypt"); tcase_add_test(tc, pdf_crypt_cipher_decrypt_001); tcase_add_test(tc, pdf_crypt_cipher_decrypt_002); + tcase_add_test(tc, pdf_crypt_cipher_decrypt_003); + tcase_add_test(tc, pdf_crypt_cipher_decrypt_004); return tc; } === removed file 'torture/unit/base/crypt/pdf-crypt-cipher-encrypt-size.c' --- torture/unit/base/crypt/pdf-crypt-cipher-encrypt-size.c 2008-10-03 16:08:19 +0000 +++ torture/unit/base/crypt/pdf-crypt-cipher-encrypt-size.c 1970-01-01 00:00:00 +0000 @@ -1,125 +0,0 @@ -/* -*- mode: C -*- Time-stamp: "2008-09-09 04:07:52 david" - * - * File: pdf-crypt-cipher-encrypt-size.c - * Date: Wed Mar 12 12:43:00 2008 - * - * GNU PDF Library - Unit tests for pdf_crypt_cipher_encrypt_size - * - */ - -/* Copyright (C) 2008 Free Software Foundation, Inc. */ - -/* This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include -#include -#include - - -/* - * Test: pdf_crypt_cipher_encrypt_size_001 - * Description: - * Get the ciphered buffer size for an empty input buffer (AESV2). - * Success condition: - * Returns 32 - */ -START_TEST (pdf_crypt_cipher_encrypt_size_001) -{ - pdf_crypt_cipher_t cipher; - pdf_crypt_init(); - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); - fail_if (pdf_crypt_cipher_encrypt_size (cipher, NULL, 0) != 32); - pdf_crypt_cipher_destroy (cipher); -} -END_TEST - - -/* - * Test: pdf_crypt_cipher_encrypt_size_002 - * Description: - * Get the ciphered buffer size for a 15 bytes buffer (AESV2). - * Success condition: - * Returns 32 - */ -START_TEST (pdf_crypt_cipher_encrypt_size_002) -{ - pdf_crypt_cipher_t cipher; - pdf_crypt_init(); - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); - fail_if (pdf_crypt_cipher_encrypt_size (cipher, NULL, 15) != 32); - pdf_crypt_cipher_destroy (cipher); - -} -END_TEST - - -/* - * Test: pdf_crypt_cipher_encrypt_size_003 - * Description: - * Get the ciphered buffer size for a empty buffer (V2). - * Success condition: - * Returns 0 - */ -START_TEST (pdf_crypt_cipher_encrypt_size_003) -{ - pdf_crypt_cipher_t cipher; - pdf_crypt_init(); - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); - fail_if (pdf_crypt_cipher_encrypt_size (cipher, NULL, 0) != 0); - pdf_crypt_cipher_destroy (cipher); -} -END_TEST - - - -/* - * Test: pdf_crypt_cipher_encrypt_size_004 - * Description: - * Get the ciphered buffer size for a 15 bytes buffer (V2). - * Success condition: - * Returns 15 - */ -START_TEST (pdf_crypt_cipher_encrypt_size_004) -{ - pdf_crypt_cipher_t cipher; - pdf_crypt_init(); - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); - fail_if (pdf_crypt_cipher_encrypt_size (cipher, NULL, 15) != 15); - pdf_crypt_cipher_destroy (cipher); -} -END_TEST - - - - -/* - * Test case creation function - */ -TCase * -test_pdf_crypt_cipher_encrypt_size (void) -{ - TCase *tc = tcase_create("pdf_crypt_cipher_encrypt_size"); - tcase_add_test(tc, pdf_crypt_cipher_encrypt_size_001); - tcase_add_test(tc, pdf_crypt_cipher_encrypt_size_002); - tcase_add_test(tc, pdf_crypt_cipher_encrypt_size_003); - tcase_add_test(tc, pdf_crypt_cipher_encrypt_size_004); - return tc; -} - - -/* End of pdf-crypt-cipher-encrypt-size.c */ === modified file 'torture/unit/base/crypt/pdf-crypt-cipher-encrypt.c' --- torture/unit/base/crypt/pdf-crypt-cipher-encrypt.c 2008-11-29 16:21:37 +0000 +++ torture/unit/base/crypt/pdf-crypt-cipher-encrypt.c 2008-12-23 18:08:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/11/29 16:04:01 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-23 19:02:55 davazp" * * File: pdf-crypt-cipher-encrypt.c * Date: Wed Mar 12 12:43:00 2008 @@ -34,70 +34,175 @@ /* * Test: pdf_crypt_cipher_encrypt_001 * Description: - * Encrypt a empty buffer (AESV2). + * Encrypt a buffer (V2). * Success condition: - * Returns PDF_OK + * Encrypted data should be correct. */ START_TEST (pdf_crypt_cipher_encrypt_001) { pdf_crypt_cipher_t cipher; - pdf_char_t *out; - pdf_char_t *in; + pdf_char_t out[14]; pdf_size_t out_size; + pdf_char_t in[14] = "Attack at dawn"; /* not trailing '\0' */ pdf_size_t in_size; - pdf_char_t key[16]; /* unintialized data */ + pdf_char_t key[6] = "Secret"; /* not trailing '\0' */ + + pdf_char_t ciphered[] = + { + 0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B, + 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5 + }; - in_size = 0; - pdf_crypt_init(); + + in_size = sizeof(in); + out_size = in_size; - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); - pdf_crypt_cipher_setkey (cipher, key, in_size); - out_size = pdf_crypt_cipher_encrypt_size (cipher, in, in_size); - - out = pdf_alloc (out_size); + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); + pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); fail_if (pdf_crypt_cipher_encrypt (cipher, out, out_size, in, in_size, &out_size) != PDF_OK); + fail_if (memcmp (out, ciphered, out_size) != 0); - pdf_dealloc (out); pdf_crypt_cipher_destroy (cipher); } END_TEST - /* * Test: pdf_crypt_cipher_encrypt_002 * Description: - * Encrypt a empty buffer (V2). + * Encrypt an ciphered buffer (AEV2). * Success condition: - * Returns PDF_OK + * The ouput data should be correct. */ + START_TEST (pdf_crypt_cipher_encrypt_002) { pdf_crypt_cipher_t cipher; - pdf_char_t *out; - pdf_char_t *in; - pdf_size_t out_size; - pdf_size_t in_size; - pdf_char_t key[16]; /* uninitialized data */ - - in_size = 0; - - pdf_crypt_init(); - - pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); - pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); - out_size = pdf_crypt_cipher_encrypt_size (cipher, in, in_size); - - out = pdf_alloc (out_size); - - fail_if (pdf_crypt_cipher_encrypt (cipher, out, out_size, in, in_size, &out_size) != PDF_OK); - - pdf_dealloc (out); - pdf_crypt_cipher_destroy (cipher); -} -END_TEST + + pdf_char_t out[80]; + + pdf_char_t key[16] = + { + 0x56, 0xe4, 0x7a, 0x38, + 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, + 0xba, 0x29, 0x03, 0x49 + }; + + pdf_char_t plain[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf + }; + + pdf_char_t ciphered[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e, + 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa, + 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6, + 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e, + 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf, + 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad, + 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d, + 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55, + }; + + pdf_crypt_init(); + + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); + pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); + + fail_if (pdf_crypt_cipher_encrypt (cipher, out, sizeof(out), plain, sizeof(plain), NULL) != PDF_OK); + fail_if (memcmp (out, ciphered, sizeof(out)) != 0); + + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + + + +/* + * Test: pdf_crypt_cipher_encrypt_003 + * Description: + * Encrypt an ciphered buffer incrementally (AEV2). + * Success condition: + * The ouput data should be correct. + */ + +START_TEST (pdf_crypt_cipher_encrypt_003) +{ + pdf_crypt_cipher_t cipher; + + pdf_char_t out[80]; + + pdf_char_t key[16] = + { + 0x56, 0xe4, 0x7a, 0x38, + 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, + 0xba, 0x29, 0x03, 0x49 + }; + + pdf_char_t plain[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf + }; + + pdf_char_t ciphered[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e, + 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa, + 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6, + 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e, + 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf, + 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad, + 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d, + 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55, + }; + + pdf_crypt_init(); + + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); + pdf_crypt_cipher_setkey (cipher, key, sizeof(key)); + fail_if (pdf_crypt_cipher_encrypt (cipher, out + 00, 16, plain + 00, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_encrypt (cipher, out + 16, 16, plain + 16, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_encrypt (cipher, out + 32, 16, plain + 32, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_encrypt (cipher, out + 48, 16, plain + 48, 16, NULL) != PDF_OK); + fail_if (pdf_crypt_cipher_encrypt (cipher, out + 64, 16, plain + 64, 16, NULL) != PDF_OK); + + fail_if (memcmp (out, ciphered, sizeof(out)) != 0); + + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + @@ -111,6 +216,7 @@ TCase *tc = tcase_create("pdf_crypt_cipher_encrypt"); tcase_add_test(tc, pdf_crypt_cipher_encrypt_001); tcase_add_test(tc, pdf_crypt_cipher_encrypt_002); + tcase_add_test(tc, pdf_crypt_cipher_encrypt_003); return tc; } === added file 'torture/unit/base/crypt/pdf-crypt-cipher-setkey.c' --- torture/unit/base/crypt/pdf-crypt-cipher-setkey.c 1970-01-01 00:00:00 +0000 +++ torture/unit/base/crypt/pdf-crypt-cipher-setkey.c 2008-12-23 18:16:49 +0000 @@ -0,0 +1,111 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-23 19:15:33 davazp" + * + * File: pdf-crypt-cipher-decrypt.c + * Date: Tue Dec 23 17:36:21 2008 + * + * GNU PDF Library - Unit tests for pdf_crypt_cipher_setkey + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include +#include +#include + + +/* + * Test: pdf_crypt_cipher_setkey_001 + * Description: + * Set a key of 16 bytes. (AESv2) + * Success condition: + * Returns PDF_OK + */ +START_TEST (pdf_crypt_cipher_setkey_001) +{ + pdf_crypt_cipher_t cipher; + pdf_crypt_init(); + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); + + fail_if (pdf_crypt_cipher_setkey (cipher, "0123456789abcdef", 16) != PDF_OK); + + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + + +/* + * Test: pdf_crypt_cipher_setkey_002 + * Description: + * Set a key of 3 bytes (AESv2) + * Success condition: + * Returns PDF_OK + */ +START_TEST (pdf_crypt_cipher_setkey_002) +{ + pdf_crypt_cipher_t cipher; + pdf_crypt_init(); + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_AESV2, &cipher); + + fail_if (pdf_crypt_cipher_setkey (cipher, "GNU", 3) == PDF_OK); + + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + + +/* + * Test: pdf_crypt_cipher_setkey_003 + * Description: + * Set a key of 6 bytes (V2) + * Success condition: + * Returns PDF_OK + */ +START_TEST (pdf_crypt_cipher_setkey_003) +{ + pdf_crypt_cipher_t cipher; + pdf_crypt_init(); + pdf_crypt_cipher_new (PDF_CRYPT_CIPHER_ALGO_V2, &cipher); + + fail_if (pdf_crypt_cipher_setkey (cipher, "GNUGNU", 6) != PDF_OK); + + pdf_crypt_cipher_destroy (cipher); +} +END_TEST + + + + +/* + * Test case creation function + */ +TCase * +test_pdf_crypt_cipher_setkey (void) +{ + TCase *tc = tcase_create("pdf_crypt_cipher_setkey"); + tcase_add_test(tc, pdf_crypt_cipher_setkey_001); + tcase_add_test(tc, pdf_crypt_cipher_setkey_002); + tcase_add_test(tc, pdf_crypt_cipher_setkey_003); + return tc; +} + + +/* End of pdf-crypt-cipher-setkey.c */ + === modified file 'torture/unit/base/crypt/pdf-crypt-md-destroy.c' --- torture/unit/base/crypt/pdf-crypt-md-destroy.c 2008-10-03 16:08:19 +0000 +++ torture/unit/base/crypt/pdf-crypt-md-destroy.c 2008-12-21 17:39:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "2008-09-09 04:18:49 david" +/* -*- mode: C -*- Time-stamp: "2008-12-15 18:17:41 davazp" * * File: pdf-crypt-md-destroy.c * Date: Wed Mar 12 12:43:00 2008 @@ -42,7 +42,7 @@ { pdf_crypt_md_t md; pdf_crypt_init(); - pdf_crypt_md_new (&md, PDF_CRYPT_MD_MD5); + pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md); fail_if (pdf_crypt_md_destroy (md)); } END_TEST === modified file 'torture/unit/base/crypt/pdf-crypt-md-new.c' --- torture/unit/base/crypt/pdf-crypt-md-new.c 2008-10-03 16:08:19 +0000 +++ torture/unit/base/crypt/pdf-crypt-md-new.c 2008-12-21 17:39:51 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "2008-09-09 03:13:18 david" +/* -*- mode: C -*- Time-stamp: "2008-12-15 18:14:03 davazp" * * File: pdf-crypt-md-new.c * Date: Wed Mar 12 12:43:00 2008 @@ -42,7 +42,7 @@ { pdf_crypt_md_t md; pdf_crypt_init(); - fail_if ( pdf_crypt_md_new (&md, PDF_CRYPT_MD_MD5) != PDF_OK); + fail_if ( pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md) != PDF_OK); pdf_crypt_md_destroy (md); } END_TEST === added file 'torture/unit/base/crypt/pdf-crypt-md-read.c' --- torture/unit/base/crypt/pdf-crypt-md-read.c 1970-01-01 00:00:00 +0000 +++ torture/unit/base/crypt/pdf-crypt-md-read.c 2008-12-23 18:16:49 +0000 @@ -0,0 +1,152 @@ +/* -*- mode: C -*- Time-stamp: "2008-12-23 17:42:38 davazp" + * + * File: pdf-crypt-md-read.c + * Date: Tue Dec 23 17:30:19 2008 + * + * GNU PDF Library - Unit tests for pdf_crypt_md_read + * + */ + +/* Copyright (C) 2008 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + + +/* + * Test: pdf_crypt_md_read_001 + * Description: + * Compute the md5 of an empty buffer. + * Success condition: + * Returns PDF_OK and output buffer matches. + */ +START_TEST (pdf_crypt_md_read_001) +{ + pdf_char_t *in; + pdf_char_t out[16]; + pdf_crypt_md_t md; + pdf_char_t real_out[] = { + 0xd4, 0x1d, 0x8c, 0xd9, + 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, + 0xec, 0xf8, 0x42, 0x7e + }; + + pdf_crypt_init(); + + pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md); + + pdf_crypt_md_write (md, in, 0); + + fail_if (pdf_crypt_md_read (md, out, sizeof(out)) != PDF_OK); + fail_if (memcmp (real_out, out, sizeof(out))); + + pdf_crypt_md_destroy (md); +} +END_TEST + + + +/* + * Test: pdf_crypt_md_read_002 + * Description: + * Compute the md5 checksum of a string + * Success condition: + * The output data should be correct. + */ +START_TEST (pdf_crypt_md_read_002) +{ + pdf_char_t in[1] = "a"; + pdf_char_t out[16]; + pdf_crypt_md_t md; + pdf_char_t real_out[] = { + 0x0C, 0xC1, 0x75, 0xB9, + 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, + 0x69, 0x77, 0x26, 0x61 + }; + + pdf_crypt_init(); + + pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md); + + pdf_crypt_md_write (md, in, sizeof(in)); + + fail_if (pdf_crypt_md_read (md, out, sizeof(out)) != PDF_OK); + fail_if (memcmp (real_out, out, sizeof(out))); + + pdf_crypt_md_destroy (md); +} +END_TEST + + + +/* + * Test: pdf_crypt_md_read_003 + * Description: + * Compute the md5 checksum of a string + * Success condition: + * The output data should be correct. + */ +START_TEST (pdf_crypt_md_read_003) +{ + pdf_char_t in[26] = "abcdefghijklmnopqrstuvwxyz"; + pdf_char_t out[16]; + pdf_crypt_md_t md; + pdf_char_t real_out[] = { + 0xC3, 0xFC, 0xD3, 0xD7, + 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, + 0xCA, 0x67, 0xE1, 0x3B + }; + + pdf_crypt_init(); + + pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md); + + pdf_crypt_md_write (md, in, sizeof(in)); + + fail_if (pdf_crypt_md_read (md, out, sizeof(out)) != PDF_OK); + fail_if (memcmp (real_out, out, sizeof(out))); + + pdf_crypt_md_destroy (md); +} +END_TEST + + + + +/* + * Test case creation function + */ +TCase * +test_pdf_crypt_md_read (void) +{ + TCase *tc = tcase_create("pdf_crypt_md_read"); + tcase_add_test(tc, pdf_crypt_md_read_001); + tcase_add_test(tc, pdf_crypt_md_read_002); + tcase_add_test(tc, pdf_crypt_md_read_003); + return tc; +} + + +/* End of pdf-crypt-md-read.c */ + === renamed file 'torture/unit/base/crypt/pdf-crypt-md-hash.c' => 'torture/unit/base/crypt/pdf-crypt-md-write.c' --- torture/unit/base/crypt/pdf-crypt-md-hash.c 2008-10-03 16:08:19 +0000 +++ torture/unit/base/crypt/pdf-crypt-md-write.c 2008-12-23 18:08:31 +0000 @@ -1,9 +1,9 @@ -/* -*- mode: C -*- Time-stamp: "2008-09-09 04:18:07 david" +/* -*- mode: C -*- Time-stamp: "2008-12-23 17:47:49 davazp" * * File: pdf-crypt-md-hash.c * Date: Wed Mar 12 12:43:00 2008 * - * GNU PDF Library - Unit tests for pdf_crypt_md_hash + * GNU PDF Library - Unit tests for pdf_crypt_md_write * */ @@ -32,48 +32,36 @@ /* - * Test: pdf_crypt_md_hash_001 + * Test: pdf_crypt_md_write_001 * Description: - * Compute the md5 of an empty buffer. + * Pass an empty message * Success condition: - * Returns PDF_OK and output buffer matches. + * Returns PDF_OK. */ -START_TEST (pdf_crypt_md_hash_001) +START_TEST (pdf_crypt_md_write_001) { - pdf_char_t *in; - pdf_char_t out[16]; + pdf_char_t * in; pdf_crypt_md_t md; - pdf_char_t real_out[] = { - 0xd4, 0x1d, 0x8c, 0xd9, - 0x8f, 0x00, 0xb2, 0x04, - 0xe9, 0x80, 0x09, 0x98, - 0xec, 0xf8, 0x42, 0x7e - }; - pdf_crypt_init(); - - pdf_crypt_md_new (&md, PDF_CRYPT_MD_MD5); - fail_if (pdf_crypt_md_hash (md, out, sizeof(out), in, 0) != PDF_OK); - fail_if (!memcmp (real_out, out, sizeof(out))); - + pdf_crypt_md_new (PDF_CRYPT_MD_MD5, &md); + fail_if (pdf_crypt_md_write (md, in, 0) != PDF_OK); pdf_crypt_md_destroy (md); } END_TEST - /* * Test case creation function */ TCase * -test_pdf_crypt_md_hash (void) +test_pdf_crypt_md_write (void) { - TCase *tc = tcase_create("pdf_crypt_md_hash"); - tcase_add_test(tc, pdf_crypt_md_hash_001); + TCase *tc = tcase_create("pdf_crypt_md_write"); + tcase_add_test(tc, pdf_crypt_md_write_001); return tc; } -/* End of pdf-crypt-md-hash.c */ +/* End of pdf-crypt-md-write.c */ === modified file 'torture/unit/base/crypt/tsuite-crypt.c' --- torture/unit/base/crypt/tsuite-crypt.c 2008-09-10 12:32:07 +0000 +++ torture/unit/base/crypt/tsuite-crypt.c 2008-12-23 18:08:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "08/09/10 14:30:20 jemarch" +/* -*- mode: C -*- Time-stamp: "2008-12-23 17:43:16 davazp" * * File: tsuite-alloc.c * Author: Jose E. Marchesi (address@hidden) @@ -28,6 +28,7 @@ extern TCase *test_pdf_crypt_init (void); extern TCase *test_pdf_crypt_cipher_new (void); +extern TCase *test_pdf_crypt_cipher_setkey (void); extern TCase *test_pdf_crypt_cipher_destroy (void); extern TCase *test_pdf_crypt_cipher_setkey (void); extern TCase *test_pdf_crypt_cipher_encrypt_size (void); @@ -35,7 +36,8 @@ extern TCase *test_pdf_crypt_cipher_encrypt (void); extern TCase *test_pdf_crypt_cipher_decrypt (void); extern TCase *test_pdf_crypt_md_new (void); -extern TCase *test_pdf_crypt_md_hash (void); +extern TCase *test_pdf_crypt_md_write (void); +extern TCase *test_pdf_crypt_md_read (void); extern TCase *test_pdf_crypt_md_destroy (void); @@ -49,14 +51,14 @@ suite_add_tcase (s, test_pdf_crypt_init ()); suite_add_tcase (s, test_pdf_crypt_cipher_new ()); + suite_add_tcase (s, test_pdf_crypt_cipher_setkey ()); suite_add_tcase (s, test_pdf_crypt_cipher_destroy ()); - suite_add_tcase (s, test_pdf_crypt_cipher_encrypt_size ()); - suite_add_tcase (s, test_pdf_crypt_cipher_decrypt_size ()); suite_add_tcase (s, test_pdf_crypt_cipher_encrypt ()); suite_add_tcase (s, test_pdf_crypt_cipher_decrypt ()); suite_add_tcase (s, test_pdf_crypt_md_new ()); - suite_add_tcase (s, test_pdf_crypt_md_hash ()); + suite_add_tcase (s, test_pdf_crypt_md_write ()); + suite_add_tcase (s, test_pdf_crypt_md_read ()); suite_add_tcase (s, test_pdf_crypt_md_destroy ()); return s; === modified file 'torture/unit/base/stm/pdf-stm-read.c' --- torture/unit/base/stm/pdf-stm-read.c 2008-10-05 15:08:05 +0000 +++ torture/unit/base/stm/pdf-stm-read.c 2008-12-25 15:49:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "2008-10-05 13:07:53 gerel" +/* -*- mode: C -*- Time-stamp: "2008-12-25 16:21:49 davazp" * * File: pdf-stm-read.c * Date: Sat Sep 20 15:20:17 2008 @@ -615,6 +615,120 @@ END_TEST + +/* + * Test: pdf_stm_read_011 + * Description: + * Create a memory-based writing stream and attach an V2 cipher filter + * decode to it. + * Success condition: + * The decoded data should be correct. + */ +START_TEST (pdf_stm_read_011) +{ + pdf_stm_t stm; + pdf_hash_t params; + + pdf_char_t out[14]; + pdf_size_t out_size = sizeof(out); + pdf_char_t in[] = + { + 0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B, + 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5 + }; + pdf_size_t in_size = sizeof(in); + pdf_char_t key[6] = "Secret"; /* not trailing '\0' */ + pdf_size_t keysize = sizeof(key); + pdf_char_t plaintext[] = "Attack at dawn"; + pdf_char_t read; + + pdf_crypt_init(); + + fail_if ( pdf_stm_mem_new (in, in_size, 0, PDF_STM_READ, &stm) != PDF_OK); + + pdf_hash_new (NULL, ¶ms); + pdf_hash_add (params, "Key", key, NULL); + pdf_hash_add (params, "KeySize", &keysize, NULL); + + fail_if ( pdf_stm_install_filter (stm, PDF_STM_FILTER_V2_DEC, params) != PDF_OK); + + read = pdf_stm_read (stm, out, out_size); + fail_if (read != out_size); + + fail_if (memcmp (out, plaintext, read) != 0); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + +/* + * Test: pdf_stm_read_012 + * Description: + * Create a memory-based reading stream and attach an AESV2 filter + * decoder to it. + * Success condition: + * The decoded data should be correct. + */ +START_TEST (pdf_stm_read_012) +{ + pdf_stm_t stm; + pdf_hash_t params; + pdf_char_t out[48]; + pdf_size_t out_size; + + pdf_char_t key[] = + { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; + pdf_size_t keysize = sizeof(key); + + pdf_char_t plain[] = + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* iv */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* content */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, + /* padding */ + /* 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f */ + }; + + pdf_char_t ciphered[] = + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* iv vector */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xbb, 0x03, 0x13, 0xee, 0x2f, 0x65, 0x43, 0xa9, /* content */ + 0x04, 0xf2, 0x8e, 0xff, 0x68, 0x59, 0x05, 0x35, + 0x81, 0x7e, 0x24, 0x33, 0x5f, 0x18, 0x72, 0x12, /* padding */ + 0x8c, 0xb8, 0x4c, 0x23, 0x59, 0xd0, 0xe0, 0x36, + }; + + pdf_crypt_init(); + + pdf_hash_new (NULL, ¶ms); + pdf_hash_add (params, "Key", key, NULL); + pdf_hash_add (params, "KeySize", &keysize, NULL); + + fail_if ( pdf_stm_mem_new (ciphered, sizeof(ciphered), 0, PDF_STM_READ, &stm) != PDF_OK); + fail_if ( pdf_stm_install_filter (stm, PDF_STM_FILTER_AESV2_DEC, params) != PDF_OK); + + out_size = pdf_stm_read (stm, out , sizeof(out)); + + fail_if (out_size != sizeof(plain)); + fail_if (memcmp (out, plain, out_size) != 0); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + /* * Test case creation function */ @@ -632,6 +746,8 @@ tcase_add_test(tc, pdf_stm_read_007); tcase_add_test(tc, pdf_stm_read_008); tcase_add_test(tc, pdf_stm_read_009); + tcase_add_test(tc, pdf_stm_read_011); + tcase_add_test(tc, pdf_stm_read_012); return tc; } === modified file 'torture/unit/base/stm/pdf-stm-write.c' --- torture/unit/base/stm/pdf-stm-write.c 2008-10-05 15:08:05 +0000 +++ torture/unit/base/stm/pdf-stm-write.c 2008-12-25 15:49:31 +0000 @@ -1,4 +1,4 @@ -/* -*- mode: C -*- Time-stamp: "2008-10-05 13:06:54 gerel" +/* -*- mode: C -*- Time-stamp: "2008-12-25 16:48:54 davazp" * * File: pdf-stm-write.c * Date: Sun Sep 21 16:37:27 2008 @@ -427,6 +427,273 @@ END_TEST + + + +/* + * Test: pdf_stm_write_008 + * Description: + * Create a memory-based writing stream and attach an V2 filter without parameters. + * Success condition: + * The installation of the filter should fail. + */ +START_TEST (pdf_stm_write_008) +{ + pdf_stm_t stm; + pdf_hash_t params; + pdf_char_t buffer[16]; + pdf_status_t ret; + + pdf_crypt_init(); + + ret = pdf_stm_mem_new (buffer, sizeof(buffer), 0, PDF_STM_WRITE, &stm); + fail_if (ret != PDF_OK); + + pdf_hash_new (NULL, ¶ms); + + ret = pdf_stm_install_filter (stm, PDF_STM_FILTER_V2_ENC, params); + fail_if (ret == PDF_OK); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + +/* + * Test: pdf_stm_write_009 + * Description: + * Create a memory-based writing stream and attach an V2 filter + * encoder to it. + * Success condition: + * The encoded data should be correct. + */ +START_TEST (pdf_stm_write_009) +{ + pdf_stm_t stm; + pdf_hash_t params; + + pdf_char_t out[14]; + pdf_size_t out_size = sizeof(out); + pdf_char_t in[14] = "Attack at dawn"; /* not trailing '\0' */ + pdf_size_t in_size = sizeof(in); + pdf_char_t key[6] = "Secret"; /* not trailing '\0' */ + pdf_size_t keysize = sizeof(key); + + pdf_char_t ciphered[] = { + 0x45, 0xA0, 0x1F, 0x64, 0x5F, 0xC3, 0x5B, + 0x38, 0x35, 0x52, 0x54, 0x4B, 0x9B, 0xF5 + }; + + pdf_char_t written; + + pdf_crypt_init(); + + fail_if ( pdf_stm_mem_new (out, out_size, 0, PDF_STM_WRITE, &stm) != PDF_OK); + + pdf_hash_new (NULL, ¶ms); + pdf_hash_add (params, "Key", key, NULL); + pdf_hash_add (params, "KeySize", &keysize, NULL); + + fail_if ( pdf_stm_install_filter (stm, PDF_STM_FILTER_V2_ENC, params) != PDF_OK); + + written = pdf_stm_write (stm, in, in_size); + fail_if (written != out_size); + + pdf_stm_flush (stm, PDF_TRUE); + + fail_if (memcmp (out, ciphered, written) != 0); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + +/* + * Test: pdf_stm_write_010 + * Description: + * Create a memory-based writing stream and attach an AESV2 filter + * encoder to it. + * Success condition: + * The encoded data should be correct. + */ +START_TEST (pdf_stm_write_010) +{ + pdf_stm_t stm; + pdf_hash_t params; + pdf_char_t out[96]; + pdf_char_t key[16] = + { + 0x56, 0xe4, 0x7a, 0x38, + 0xc5, 0x59, 0x89, 0x74, + 0xbc, 0x46, 0x90, 0x3d, + 0xba, 0x29, 0x03, 0x49 + }; + pdf_size_t keysize = sizeof(key); + pdf_char_t plain[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf + }; + + pdf_char_t ciphered[] = + { + 0x8c, 0xe8, 0x2e, 0xef, 0xbe, 0xa0, 0xda, 0x3c, /* iv vector */ + 0x44, 0x69, 0x9e, 0xd7, 0xdb, 0x51, 0xb7, 0xd9, + + 0xc3, 0x0e, 0x32, 0xff, 0xed, 0xc0, 0x77, 0x4e, + 0x6a, 0xff, 0x6a, 0xf0, 0x86, 0x9f, 0x71, 0xaa, + 0x0f, 0x3a, 0xf0, 0x7a, 0x9a, 0x31, 0xa9, 0xc6, + 0x84, 0xdb, 0x20, 0x7e, 0xb0, 0xef, 0x8e, 0x4e, + 0x35, 0x90, 0x7a, 0xa6, 0x32, 0xc3, 0xff, 0xdf, + 0x86, 0x8b, 0xb7, 0xb2, 0x9d, 0x3d, 0x46, 0xad, + 0x83, 0xce, 0x9f, 0x9a, 0x10, 0x2e, 0xe9, 0x9d, + 0x49, 0xa5, 0x3e, 0x87, 0xf4, 0xc3, 0xda, 0x55, + }; + + pdf_crypt_init(); + + pdf_hash_new (NULL, ¶ms); + pdf_hash_add (params, "Key", key, NULL); + pdf_hash_add (params, "KeySize", &keysize, NULL); + + fail_if ( pdf_stm_mem_new (out, sizeof(out), 0, PDF_STM_WRITE, &stm) != PDF_OK); + fail_if ( pdf_stm_install_filter (stm, PDF_STM_FILTER_AESV2_ENC, params) != PDF_OK); + + pdf_stm_write (stm, plain + 00 , 16); + pdf_stm_write (stm, plain + 16 , 16); + pdf_stm_write (stm, plain + 32 , 16); + pdf_stm_write (stm, plain + 48 , 16); + pdf_stm_write (stm, plain + 64 , 16); + + pdf_stm_flush (stm, PDF_TRUE); + + fail_if (memcmp (out, ciphered, sizeof(ciphered)) != 0); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + +/* + * Test: pdf_stm_write_011 + * Description: + * Create a memory-based writing stream and attach an MD5 + * encoder to it. + * Success condition: + * The output data should be correct. + */ +START_TEST (pdf_stm_write_011) +{ + pdf_stm_t stm; + pdf_hash_t params; + pdf_char_t in[26] = "abcdefghijklmnopqrstuvwxyz"; + pdf_char_t out[16]; + pdf_crypt_md_t md; + pdf_char_t real_out[] = { + 0xC3, 0xFC, 0xD3, 0xD7, + 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, + 0xCA, 0x67, 0xE1, 0x3B + }; + + pdf_crypt_init(); + + pdf_hash_new (NULL, ¶ms); + + fail_if ( pdf_stm_mem_new (out, sizeof(out), 0, PDF_STM_WRITE, &stm) != PDF_OK); + fail_if ( pdf_stm_install_filter (stm, PDF_STM_FILTER_MD5_ENC, params) != PDF_OK); + + pdf_stm_write (stm, in, sizeof(in)); + pdf_stm_flush (stm, PDF_TRUE); + + fail_if (memcmp (out, real_out, sizeof(out)) != 0); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + +/* + * Test: pdf_stm_write_012 + * Description: + * Create a memory-based writing stream and attach an AESV2 filter + * decoder to it. + * Success condition: + * The decoded data should be correct. + */ +START_TEST (pdf_stm_write_012) +{ + pdf_stm_t stm; + pdf_hash_t params; + pdf_char_t out[48]; + + pdf_char_t key[] = + { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; + pdf_size_t keysize = sizeof(key); + + pdf_char_t plain[] = + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* iv */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* content */ + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x0f, + /* padding */ + /* 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f */ + }; + + pdf_char_t ciphered[] = + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, /* iv vector */ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xbb, 0x03, 0x13, 0xee, 0x2f, 0x65, 0x43, 0xa9, /* content */ + 0x04, 0xf2, 0x8e, 0xff, 0x68, 0x59, 0x05, 0x35, + 0x81, 0x7e, 0x24, 0x33, 0x5f, 0x18, 0x72, 0x12, /* padding */ + 0x8c, 0xb8, 0x4c, 0x23, 0x59, 0xd0, 0xe0, 0x36, + }; + + pdf_crypt_init(); + + pdf_hash_new (NULL, ¶ms); + pdf_hash_add (params, "Key", key, NULL); + pdf_hash_add (params, "KeySize", &keysize, NULL); + + fail_if ( pdf_stm_mem_new (out, sizeof(out), 0, PDF_STM_WRITE, &stm) != PDF_OK); + fail_if ( pdf_stm_install_filter (stm, PDF_STM_FILTER_AESV2_ENC, params) != PDF_OK); + + pdf_stm_write (stm, plain , sizeof(plain)); + pdf_stm_flush (stm, PDF_TRUE); + + fail_if (memcmp (out, ciphered, sizeof(out)) != 0); + + pdf_hash_destroy (params); + pdf_stm_destroy (stm); +} +END_TEST + + + /* * Test case creation function */ @@ -442,7 +709,12 @@ tcase_add_test(tc, pdf_stm_write_005); tcase_add_test(tc, pdf_stm_write_006); tcase_add_test(tc, pdf_stm_write_007); - + tcase_add_test(tc, pdf_stm_write_008); + tcase_add_test(tc, pdf_stm_write_009); + tcase_add_test(tc, pdf_stm_write_010); + tcase_add_test(tc, pdf_stm_write_011); + tcase_add_test(tc, pdf_stm_write_012); + return tc; } # Begin bundle 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