Page MenuHome GnuPG

No OneTemporary

diff --git a/src/ChangeLog b/src/ChangeLog
index 7d56a299..e2f50c29 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,1227 +1,1238 @@
+2004-02-03 Werner Koch <wk@gnupg.org>
+
+ * secmem.c (_gcry_secmem_init): Do not print the "not locked into
+ core warning" if the NO_WARNING flag has been set.
+
+ * sexp.c (sexp_sscan): Allocate result in secure memory if BUFFER
+ is in secure memory. Switch to secure memory for the a secure %b
+ format item. Extra paranoid wipe on error.
+ (gcry_sexp_release): Added paranoid wiping for securely allocated
+ S-expressions.
+
2004-01-25 Moritz Schulte <mo@g10code.com>
* ath.h: Include <config.h>.
2004-01-12 Moritz Schulte <mo@g10code.com>
* gcrypt.h: Adjusted declarations of: gcry_ac_data_set,
gcry_ac_data_get_name, gcry_ac_data_get_index,
gcry_ac_key_pair_generate, gcry_ac_key_test,
gcry_ac_key_get_nbits, gcry_ac_key_get_grip.
* gcrypt.h (GCRY_AC_FLAG_DATA_NO_BLINDING): Removed symbol.
(GCRY_AC_FLAG_DEALLOC, GCRY_AC_FLAG_COPY)
(GCRY_AC_FLAG_NO_BLINDING): New symbols.
* global.c (gcry_strdup): Removed function.
* string.c: New file.
* Makefile.am (libgcrypt_real_la_SOURCES): Added: string.c.
* string.c (gcry_strdup): New function.
* gcrypt.h (gcry_strdup): Declare.
2003-12-19 Werner Koch <wk@gnupg.org>
* g10lib.h (wipememory, wipememory2): New; taken from gnupg.
2003-11-14 Werner Koch <wk@gnupg.org>
* global.c (gcry_strdup): Don't copy the string after a malloc
error.
2003-11-11 Werner Koch <wk@gnupg.org>
* sexp.c (sexp_sscan): Implemented "%b" format specifier.
2003-11-11 Moritz Schulte <mo@g10code.com>
* libgcrypt.m4: Do not set prefix when calling libgcrypt-config.
Thanks to Nikos Mavroyanopoulos.
2003-11-08 Moritz Schulte <mo@g10code.com>
* cipher.h (small_prime_numbers): Removed declaration.
(PUBKEY_FLAG_NO_BLINDING): Put braces around shift.
2003-11-04 Werner Koch <wk@gnupg.org>
* cipher.h (_gcry_sha1_has_buffer): New.
* gcrypt.h (gcry_create_nonce): New.
2003-10-31 Werner Koch <wk@gnupg.org>
* libgcrypt.vers (_gcry_generate_elg_prime): Removed this symbol;
gnutls does not need it anymore.
* secmem.c (mb_get_new): s/pool/block/ due to global pool.
* misc.c (gcry_set_log_handler): s/logf/f/ to avoid shadowing
warning against a builtin.
* ath-pth-compat.c: cast pth_connect to get rid of the const
prototype.
2003-10-27 Werner Koch <wk@gnupg.org>
* ath.h (ATH_MUTEX_INITIALIZER): Removed spurious semicolon.
2003-10-27 Moritz Schulte <mo@g10code.com>
* libgcrypt-config.in: Include libs/cflags of libgpg-error.
* sexp.c (sexp_sscan): Cleaned up, deallocate scanned sexp on
error.
* module.c (MODULE_ID_MIN): New symbol, use it.
2003-10-27 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_pk_testkey): Doc fix.
2003-09-29 Moritz Schulte <mo@g10code.com>
* libgcrypt-config.in: Fix --algorithms option.
2003-10-23 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_err_code): Use GPG_ERR_INLINE instead of
__inline__.
* secmem.c (lock_pool): Don't print the warning for certain
systems, handle ENOMEM.
2003-10-21 Werner Koch <wk@gnupg.org>
* secmem.c (_gcry_secmem_dump_stats): Fixed format sepcifier for a
size_t. Reported by Stephane Corthesy.
2003-10-10 Werner Koch <wk@gnupg.org>
* global.c (_gcry_malloc): Handle the no_secure_memory option.
* gcrypt.h (gcry_prime_group_generator): New.
(gcry_prime_release_factors): New.
2003-10-07 Werner Koch <wk@gnupg.org>
* sexp.c (sexp_sscan): Check that parenthesis are matching.
2003-09-28 Moritz Schulte <mo@g10code.com>
* g10lib.h: Declare: _gcry_malloc.
(GCRY_ALLOC_FLAG_SECURE): New symbol.
* global.c (_gcry_malloc): New function...
(gcry_malloc): ... use it.
(gcry_malloc_secure): Likewise.
* ath.c: Change License to LGPL.
* ath-pthread-compat.c: Likewise.
* ath-pthread.c: Likewise.
* ath-pth-compat.c: Likewise.
* ath-pth.c: Likewise.
* ath.h: Likewise.
* ath-compat.c: Likewise.
* secmem.c (_gcry_secmem_realloc): Do not forget to release secmem
lock. Thanks to low halo for triggering this bug.
2003-09-04 Werner Koch <wk@gnupg.org>
* gcrypt.h (_GCRY_ERR_SOURCE_DEFAULT): Removed cruft.
(gcry_prime_check_func_t): Renamed arg for clarity.
2003-09-02 Moritz Schulte <mo@g10code.com>
* gcrypt.h (GCRY_PRIME_FLAG_SPECIAL_FACTOR): New symbol.
2003-09-01 Moritz Schulte <mo@g10code.com>
* gcrypt.h (gcry_random_level_t): New type.
(gcry_prime_check_func_t): Likewise.
(GCRY_PRIME_FLAG_SECRET): New symbol.
(gcry_prime_generate, gcry_prime_check): Declare functions.
2003-08-28 Werner Koch <wk@gnupg.org>
* Makefile.am (libgcrypt_pth_la_LDFLAGS): Removed PTH_CFLAGS cruft.
2003-08-27 Moritz Schulte <mo@g10code.com>
* global.c (gcry_control): Remove call to ath_deinit.
* Makefile.am (libgcrypt_real_la_DEPENDENCIES): Fixed.
(libgcrypt_real_la_LIBADD): Fixed.
Removed unecessary variables.
* libgcrypt-config.in: Adjusted script for new thread handling.
* Makefile.am: New version, based on GPGMEs Makefile.am.
* ath.c, ath-compat.c, ath.h, ath-pth.c, ath-pth-compat.c,
ath-pthread.c, ath-pthread-compat.c: New files, merged from GPGME.
* ath.c, ath.h, ath-pthread.c, ath-pth.c: Removed files.
2003-08-08 Moritz Schulte <moritz@g10code.com>
* global.c (gcry_realloc): Remove FIXME about `clearing out
realloced memory', since _gcry_secmem_realloc takes care of
overwriting old memory.
2003-08-07 Werner Koch <wk@gnupg.org>
* module.c (_gcry_module_release): Don't act if module is NULL.
2003-07-30 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (enum gcry_ac_id): Added: GCRY_AC_ELG_E.
Reverted change: use gcry_md_flags enumeration list instead of
defines.
2003-07-29 Werner Koch <wk@gnupg.org>
* global.c (gcry_control): Add GCRYCTL_SET_RANDOM_SEED_FILE and
GCRYCTL_UPDATE_RANDOM_SEED_FILE.
* gcrypt.h: Ditto. Renamed index to idx, so avoid warning
related to the old index function.
2003-07-28 Moritz Schulte <moritz@g10code.com>
* global.c (gcry_err_code_from_errno, gcry_err_code_to_errno)
(gcry_err_make_from_errno, gcry_error_from_errno): New functions.
* gcrypt.h: Declared: gcry_err_code_from_errno,
gcry_err_code_to_errno, gcry_err_make_from_errno,
gcry_error_from_errno.
* Makefile.am (include_HEADERS): Added: gcrypt-module.h.
* gcrypt.h: Include <gcrypt-module.h>.
* gcrypt-module.h: New file.
2003-07-27 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_mpi_scan, gcry_mpi_print): API change.
(gcry_mpi_dump): New.
2003-07-21 Moritz Schulte <moritz@g10code.com>
* gcrypt.h: Declared: gcry_ac_key_data_get.
(gcry_pk_spec): Renamed member `sexp_names' into `aliases'.
2003-07-20 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (gcry_md_oid_spec_t): New type.
(gcry_md_spec): New member: oids.
2003-07-19 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (gcry_cipher_oid_spec_t): New type.
(gcry_cipher_spec): New member: oids;
2003-07-18 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_mpi_set_opaque): Add a warning comment.
2003-07-15 Moritz Schulte <moritz@g10code.com>
* secmem.c (compress_pool): Remove function, since unused blocks
are automatically concatenad.
* gcrypt.h: Bumped version number up to 1.1.42-cvs.
2003-07-14 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (gcry_cipher_spec): New member: aliases.
* Makefile.am (noinst_PROGRAMS, testapi_SOURCES, testapai_LDADD,
benchmark_SOURCES, benchmark_LDADD): Removed.
* benchmark.c, testapi.c: Removed files.
* mpi.h: Removed disabled typedef.
* g10lib.h: Likewise.
* benchmark.c, g10lib.h, gcrypt.h, global.c, module.c, sexp.c:
Used gcry_err* wrappers for libgpg-error symbols.
2003-07-12 Moritz Schulte <moritz@g10code.com>
* global.c: Likewise.
* gcrypt.h: New type: gcry_error_t, gcry_err_code_t and
gcry_err_source_t.
(gcry_err_make, gcry_error, gcry_err_code, gcry_err_source): New
functions.
* global.c (gcry_strerror): New function.
(gcry_strsource): New function.
* gcrypt.h: New symbol: GCRY_CIPHER_TWOFISH128.
2003-07-09 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (enum gcry_md_flags): Removed, used define instead,
since that is more common than an enumeration list when it comes
to flags that can be bitwise ORed.
2003-07-08 Moritz Schulte <moritz@g10code.com>
* global.c: Use new types for handlers.
* gcrypt.h: Declare: gcry_ac_data_copy.
2003-07-07 Moritz Schulte <moritz@g10code.com>
* sexp.c (gcry_sexp_build_array): Use dummy argument pointer.
Thanks to Simon Josefsson <jas@extunde.com>.
* gcrypt.h: Declare: gcry_cipher_list, gcry_pk_list, gcry_md_list.
2003-07-05 Moritz Schulte <moritz@g10code.com>
* gcrypt.h: Declare: gcry_cipher_register, gcry_cipher_unregister,
gcry_md_register, gcry_md_unregister, gcry_pk_register,
gcry_pk_unregister.
(gcry_cipher_spec): Removed member: algorithm.
(gcry_pk_spec): Likewise.
(gcry_md_spec): Likewise.
Adjusted declarations: gcry_cipher_register, gcry_pk_register,
gcry_md_register.
* module.c: Replaced all occurences of `id' with `mod_id', since
`id' is a keyword in obj-c.
* gcrypt.h (gcry_cipher_spec): Renamed member `id' to `algorithm'.
(gcry_pk_spec): Likewise.
(gcry_md_spec): Likewise.
* cipher.h: Removed types: gcry_pubkey_generate_t,
gcry_pubkey_check_secret_key_t, gcry_pubkey_encrypt_t,
gcry_pubkey_decrypt_t, gcry_pubkey_sign_t, gcry_pubkey_verify_t,
gcry_pubkey_get_nbits_t, gcry_pk_spec_t, gcry_digest_init_t,
gcry_digest_write_t, gcry_digest_final_t, gcry_digest_read_t,
gcry_digest_spec_t, gcry_cipher_setkey_t, gcry_cipher_encrypt_t,
gcry_cipher_decrypt_t, gcry_cipher_stencrypt_t,
gcry_cipher_stdecrypt_t, gcry_cipher_spec_t.
* gcrypt.h: New types: gcry_pk_generate_t,
gcry_pk_check_secret_key_t, gcry_pk_encrypt_t, gcry_pk_decrypt_t,
gcry_pk_sign_t, gcry_pk_verify_t, gcry_pk_get_nbits_t,
gcry_pk_spec_t, gcry_md_init_t, gcry_md_write_t, gcry_md_final_t,
gcry_md_read_t, gcry_md_spec_t, gcry_cipher_setkey_t,
gcry_cipher_encrypt_t, gcry_cipher_decrypt_t,
gcry_cipher_stencrypt_t, gcry_cipher_stdecrypt_t,
gcry_cipher_spec_t, gcry_module_t.
2003-07-04 Moritz Schulte <moritz@g10code.com>
* module.c (_gcry_module_list): New function.
2003-07-02 Moritz Schulte <moritz@g10code.com>
* module.c (_gcry_module_lookup): Fixed typo.
* gcrypt.h: Added all definitions and declarations necessary for
the new ac interface.
2003-06-30 Moritz Schulte <moritz@g10code.com>
* g10lib.h: Added declarations: _gcry_pk_module_lookup,
_gcry_pk_module_release.
2003-06-18 Werner Koch <wk@gnupg.org>
* benchmark.c (cipher_bench): Adjusted for new API of get_blklen
and get_keylen.
* gcrypt.h (gcry_cipher_get_algo_blklen)
(gcry_cipher_get_algo_keylen): Replaced macro by funcion.
2003-06-18 Moritz Schulte <moritz@g10code.com>
* cipher.h: Renamed types GcryDigestSpec, GcryCipherSpec and
GcryPubkeySpec into: gcry_digest_spec_t, gcry_cipher_spec_t and
gcry_pubkey_spec_t.
(gcry_pubkey_spec): Defined member `id' as unsigned.
(gcry_digest_spec): Likewise.
(gcry_cipher_spec): Likewise.
* module.c (_gcry_module_id_new): New function.
(_gcry_module_add): Generate a new ID via _gcry_module_id_new in
case `id' is zero.
* g10lib.h, module.c: Replace old type GcryModule with newer one:
gcry_module_t.
* module.c (_gcry_module_add): Added argument `id', use it.
* g10lib.h: Added declaration: _gcry_module_lookup_id.
(_gcry_module_add): Added argument `id'.
* module.c (_gcry_module_lookup_id): New function.
* g10lib.h (struct gcry_module): New member: id.
* gcrypt.h: New type: gcry_handler_progress_t,
gcry_handler_alloc_t, gcry_haandler_secure_check_t,
gcry_handler_realloc_t, gcry_handler_free_t,
gcry_handler_no_mem_t, gcry_handler_error_t, gcry_handler_log_t.
Use new types.
* cipher.h: Include <gcrypt.h>.
New types: gcry_pk_generate_t, gcry_pk_check_secret_key_t,
gcry_pk_encrypt_t, gcry_pk_decrypt_t, gcry_pk_sign_t,
gcry_pk_verify_t, gcry_pk_get_nbits_t, gcry_md_init_t,
gcry_md_write_t, gcry_md_final_t, gcry_md_read_t,
gcry_cipher_setkey_t, gcry_cipher_encrypt_t,
gcry_cipher_decrypt_t, gcry_cipher_stencrypt_t,
gcry_cipher_stdecrypt_t.
Use new types.
2003-06-17 Moritz Schulte <moritz@g10code.com>
* Makefile.am (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@.
2003-06-16 Moritz Schulte <moritz@g10code.com>
* g10lib.h: Replace last occurences of old type names with newer
names (i.e. replace MPI with gcry_mpi_t).
* mpi.h: Likewise.
* sexp.c: Likewise.
2003-06-15 Moritz Schulte <moritz@g10code.com>
* testapi.c (test_genkey): Use gpg_strerror instead of
gcry_strerror.
* global.c (gcry_control): Fixed typo.
* misc.c (_gcry_fatal_error): Use gpg_strerror instead of
gcry_strerror.
* types.h (STRLIST): Removed type since it is not used.
2003-06-11 Moritz Schulte <moritz@g10code.com>
* global.c (global_init): Call: _gcry_cipher_init, _gcry_md_init,
_gcry_pk_init.
* g10lib.h: Declare: _gcry_cipher_init, _gcry_md_init,
_gcry_pk_init.
* global.c (gcry_strerror): Remove compatibility code.
* Makefile.am: Remove support libgpg-error special handling.
(AM_CPPFLAGS): Add @GPG_ERROR_CFLAGS@
* gcrypt.h: Likewise.
2003-06-13 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_md_get_algo): Reverted to old API. This is a
convenience function anyway and error checking is not approriate.
(gcry_md_is_enabled): New.
(gcry_md_is_secure): Replaced macro by function and reverted to old
API.
2003-06-11 Werner Koch <wk@gnupg.org>
* gcrypt.h (GCRYERR): Define _GCRY_ERR_SOURCE_DEFAULT instead of
GPG_ERR_SOURCE_DEFAULT, so that libgpg-error still works despite
the use of the old gcrypt error codes.
(gcry_md_copy): Swapped arguments.
2003-06-09 Moritz Schulte <moritz@g10code.com>
* Makefile.am: Support for libgpg-error.
2003-06-08 Moritz Schulte <moritz@g10code.com>
* sexp.c (gcry_sexp_create): Expect sane error values from
gcry_sexp_canon_len instead of the `historical' values.
2003-06-07 Moritz Schulte <moritz@g10code.com>
* ath.c, ath.c, ath-pth.c, ath-pthread.c, benchmark.c, cipher.h,
g10lib.h, gcrypt.h, global.c, misc.c, missing-string.c, module.c,
mpi.h, secmem.c, secmem.h, sexp.c, stdmem.c, stdmem.h, testapi.c,
types.h: Edited all preprocessor instructions to remove whitespace
before the '#'. This is not required by C89, but there are some
compilers out there that don't like it. Replaced any occurence of
the now deprecated type names with the new ones.
* gcrypt.h: Re-organized checking for gcc features; New macro:
_GCRY_GCC_ATTR_DEPRECATED.
Include copy of libgpg-error's gpg-error.h in order to make it
easy to build libgcrypt without needing libgpg-error.h.
(GCRY_MPI, GcryMPI, GCRY_SEXP, GcrySexp, GCRY_CIPHER_HD,
GcryCipherHd, GCRY_MD_HD, GcryMDHd): Declared deprecated.
(gcry_mpi_t, gcry_sexp_t, gcry_cipher_hd_t, gcry_md_hd_t): New
types.
2003-06-04 Moritz Schulte <moritz@g10code.com>
* sexp.c (sexp_sscan): New argument: arg_list, adjusted all
callers.
(ARG_NEXT): New macro.
(sexp_sscan): Use ARG_NEXT for receiving format string arguments.
(gcry_sexp_build_array): New function.
2003-06-02 Moritz Schulte <moritz@g10code.com>
* gcrypt.h: Added some comments describing the gcry_sexp_*
functions.
Include <gpg-error.h> instead of <gpg/error.h>.
2003-06-01 Moritz Schulte <moritz@g10code.com>
* sexp.c (OLDPARSECODE): Removed macro...
(gcry_sexp_canon_len): ... and do not use it.
* gcrypt.h (gcry_errno): Removed declaration.
* g10lib.h (string_to_pubkey_algo, pubkey_algo_to_string,
pubkey_nbits): Removed declarations for non-existing functions.
2003-05-31 Moritz Schulte <moritz@g10code.com>
* cipher.h (is_RSA, is_ELGAMAL): Removed macros.
* g10lib.h (set_lasterr): Removed macro.
(_gcry_set_lasterr): Removed declaration.
* gcrypt.h: Changed declarations for: gcry_pk_algo_info,
gcry_md_open, gcry_md_copy, gcry_md_algo_info, gcry_md_info,
gcry_md_get_algo, gcry_random_add_bytes.
(gcry_md_is_secure): Adjust macro for new API.
2003-05-29 Moritz Schulte <moritz@g10code.com>
* gcrypt.h: Changed declarations for: gcry_cipher_open,
gcry_cipher_info, gcry_cipher_algo_info.
(gcry_cipher_get_algo_keylen): Adjuster for new
gcry_cipher_algo_info interface.
(gcry_cipher_get_algo_blklen): Likewise.
* global.c (gcry_errno): Removed function.
(gcry_strerror): Do not use gcry_errno.
(_gcry_set_lasterr): Removed function.
(last_ec): Removed variable.
2003-05-27 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (enum gcry_cipher_algos): Make Serpent IDs do not
conflict with OpenPGP. Reported by Timo Schulz.
* global.c (gcry_control): Fixed name of enum list.
2003-05-25 Moritz Schulte <moritz@g10code.com>
* cipher.h (gcry_cipher_spec): Adjust return type of `setkey' for
libgpg-error.
(gcry_pubkey_spec): Adjust return type of `generate',
`check_secret_key', `encrypt', `decrypt', `sign' and `verify' for
libgpg-error.
* sexp.c (gcry_sexp_canon_len): Adjusted for libgpg-error.
(gcry_sexp_create): Likewise.
(gcry_sexp_new): Likewise.
(sexp_sscan): Likewise.
(gcry_sexp_build): Likewise.
(gcry_sexp_sscan): Likewise.
* module.c (_gcry_module_add): Likewise.
* global.c (last_ec): Change type to gpg_error_t.
(gcry_control): Adjust for libgpg-error.
(gcry_errno): Likewise.
(gcry_strerror): Likewise.
(_gcry_set_lasterr): Likewise.
(gcry_xmalloc): Likewise.
(gcry_xrealloc): Likewise.
2003-05-22 Moritz Schulte <moritz@g10code.com>
* types.h: Merged code from GnuPG regarding U64_C.
* missing-string.c (strsep): Removed function.
* g10lib.h: Removed declarations: strsep, strlwr.
* secmem.c (secmem_lock): New variable.
(SECMEM_LOCK, SECMEM_UNLOCK): New macros.
(_gcry_secmem_set_flags): Use SECMEM_LOCK and SECMEM_UNLOCK.
(_gcry_secmem_get_flags): Likewise.
(_gcry_secmem_init): Likewie.
(_gcry_secmem_malloc): Likewise.
(_gcry_secmem_free): Likewise.
(_gcry_secmem_malloc): Renamed to ...
(_gcry_secmem_malloc_internal): ... this.
(_gcry_secmem_malloc): New function, use SECMEM_LOCK,
SECMEM_UNLOCK, call _gcry_secmem_malloc_internal.
(_gcry_secmem_free): Renamed to ...
(_gcry_secmem_free_internal): ... this.
(_gcry_secmem_free): New function, use SECMEM_LOCK, SECMEM_UNLOCK,
call _gcry_secmem_free_internal.
(_gcry_secmem_realloc): Use SECMEM_LOCK, SECMEM_UNLOCK, call
_gcry_secmem_malloc_internal and _gcry_secmem_free_internal.
(_gcry_private_is_secure): Use SECMEM_LOCK, SECMEM_UNLOCK.
(_gcry_secmem_dump_stats): Likewise.
(_gcry_secmem_malloc_internal): Removed unused variable:
compressed.
Include "ath.h".
2003-05-21 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (GCRY_CIPHER_SERPENT128, GCRY_CIPHER_SERPENT192,
GCRY_CIPHER_SERPENT256): New symbols.
2003-05-19 Moritz Schulte <moritz@g10code.com>
* gcrypt.h: Reversed changes from 2003-03-03 since they would have
been an unnecessary ABI break.
2003-05-13 Moritz Schulte <moritz@g10code.com>
* secmem.c (stats_update): New function.
(BLOCK_HEAD_SIZE): New symbol.
(MB_FLAG_ACTIVE): New symbol.
(ADDR_TO_BLOCK, BLOCK_VALID): New macros.
(mb_get_next): New function.
(mb_get_prev): New function.
(mb_merge): New function.
(mb_get_new): New function.
(unused_blocks): Removed variable.
(init_pool): Initialize new memory pool.
(_gcry_secmem_malloc): Use new heap management code.
(_gcry_secmem_free): Likewise.
(_gcry_secmem_realloc): Likewise.
Renamed type MEMBLOCK to memblock_t.
2003-04-27 Moritz Schulte <moritz@g10code.com>
* cipher.h (gcry_pubkey_spec): New member: sexp_names.
2003-04-23 Moritz Schulte <moritz@g10code.com>
* cipher.h (gcry_pubkey_spec): Removed members: npkey, nskey,
nenc, nsig.
(gcry_pubkey_spec): Added members: elements_pkey, elements_skey,
elements_enc, elements_sig, elements_grip.
2003-04-17 Moritz Schulte <moritz@g10code.com>
* g10lib.h (GcryModule): New typedef.
* gcrypt.h (gcry_cipher_register, gcry_cipher_unregister,
gcry_digest_register, gcry_digest_unregister,
gcry_pubkey_register, gcry_pubkey_unregister): Function
declarations removed - for now.
* gcrypt.h (GcryModule): Declaration removed.
* gcrypt.h (GcryPubkeySpec, GcryDigestSpec, GcryCipherSpec):
Types Moved...
* cipher.h: ... here.
2003-04-17 Moritz Schulte <moritz@g10code.com>
* cipher.h: Declare digest_spec_sha512 and digest_spec_384.
2003-04-16 Moritz Schulte <moritz@g10code.com>
* module.c (_gcry_module_use): New function.
* g10lib.h (_gcry_module_use): Declare function.
* libgcrypt-config.in: Support for --algorithms switch, which
prints the algorithms included in the built libgcrypt.
* global.c (gcry_set_progress_handler): Register progress
functions depending on the enabled algorithms.
2003-04-07 Moritz Schulte <moritz@g10code.com>
* Makefile.am (libgcrypt_la_SOURCES): Added module.c
* module.c: New file.
(_gcry_module_add): New function.
(_gcry_module_drop): New function.
(_gcry_module_lookup): New function.
(_gcry_module_release): New function.
* g10lib.h (GcryModule): New types.
(FLAG_MODULE_DISABLED): New symbol.
Added declarations for _gcry_module_add, _gcry_module_release and
_gcry_module_lookup.
* gcrypt.h: New types: GcryPubkeySpec, GcryDigestSpec,
GcryCipherSpec.
Added declarations for: gcry_cipher_register,
gcry_cipher_unregister, gcry_digest_register,
gcry_digest_unregister, gcry_pubkey_register and
gcry_pubkey_unregister.
* cipher.h: Removed symbols: CIPHER_ALGO_NONE, CIPHER_ALGO_IDEA,
CIPHER_ALGO_3DES, CIPHER_ALGO_CAST5, CIPHER_ALGO_BLOWFISH,
CIPHER_ALGO_SAFER_SK128, CIPHER_ALGO_DES_SK, CIPHER_ALGO_TWOFISH,
CIPHER_ALGO_TWOFISH_OLD, CIPHER_ALGO_DUMMY, PUBKEY_USAGE_SIG,
PUBKEY_USAGE_ENC, DIGEST_ALGO_MD5, DIGEST_ALGO_SHA1,
DIGEST_ALGO_RMD160, DIGEST_ALGO_TIGER, PUBKEY_ALGO_RSA,
PUBKEY_ALGO_RSA_E, PUBKEY_ALGO_RSA_S, PUBKEY_ALGO_DSA,
PUBKEY_ALGO_ELGAMAL, PUBKEY_ALGO_ELGAMAL_E.
2003-04-02 Moritz Schulte <moritz@g10code.com>
* benchmark.c (md_bench): Fix error message.
2003-03-31 Moritz Schulte <moritz@g10code.com>
* benchmark.c (cipher_bench): Added CTR mode.
2003-03-30 Simon Josefsson <jas@extundo.com>
* gcrypt.h (enum gcry_control_cmds): Add GCRY_SET_CTR.
(enum gcry_cipher_modes): Add GCRY_CIPHER_MODE_CTR.
(gcry_cipher_setctr): New macro to set counter.
2003-03-19 Moritz Schulte <moritz@g10code.com>
* cipher.h (PUBKEY_FLAG_NO_BLINDING): New symbol.
2003-03-22 Simon Josefsson <jas@extundo.com>
* gcrypt.h: Add GCRYCTL_SET_CBC_MAC and GCRY_CIPHER_CBC_MAC.
2003-03-19 Werner Koch <wk@gnupg.org>
* g10lib.h: Adjusted primegen.c prototypes.
2003-03-12 Werner Koch <wk@gnupg.org>
* sexp.c (sexp_sscan): Initialize NM. Thanks to Ian Peters for
valgrinding this.
2003-03-06 Moritz Schulte <mo@g10code.com>
* secmem.h (GCRY_SECMEM_FLAG_NO_WARNING,
GCRY_SECMEM_FLAG_SUSPEND_WARNING): New symbols.
* global.c (gcry_control): Use
GCRY_SECMEM_FLAG_{NO,SUSPEND}_WARNING, instead of hard-coded
values.
* secmem.c (_gcry_secmem_set_flags): Likewise.
* secmem.c (_gcry_secmem_get_flags): Likewise.
2003-03-03 Moritz Schulte <moritz@g10code.com>
* misc.c: Removed old FIXME, since there is already a function to
set the value of `verbosity_level'.
* gcrypt.h: Removed enumeration list: gcry_ctl_cmds.
New enumeration lists: gcry_global_control_cmds,
gcry_control_cmds, gcry_info_cmds, gcry_algo_info_cmds.
2003-03-02 Moritz Schulte <moritz@g10code.com>
* gcrypt.h (gcry_cipher_reset): New macro for resetting a handle.
2003-02-28 Moritz Schulte <moritz@g10code.com>
* secmem.c (DEFAULT_PAGESIZE): New symbol.
(init_pool): Use DEFAULT_PAGESIZE.
2003-02-23 Moritz Schulte <moritz@g10code.com>
* secmem.h: Fix typo in declaration of _gcry_secmem_term.
* sexp.c: Move macro definitions of `digitp', `octdigit', `alphap'
and `hexdigit' ...
* g10lib.h: ... here.
* misc.c (_gcry_burn_stack): New function (former name:
burn_stack).
* g10lib.h (burn_stack): Declare _gcry_burn_stack().
2003-01-24 Werner Koch <wk@gnupg.org>
* global.c (gcry_set_progress_handler): Register a random progress
handler.
2003-01-23 Werner Koch <wk@gnupg.org>
* gcrypt.h (GCRY_ENABLE_QUICK_RANDOM): New.
* global.c (gcry_control): Make use of it.
2003-01-21 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_random_add_bytes): Add QUALITY argument.
2003-01-21 Timo Schulz <twoaday@freakmail.de>
* gcrypt.h (gcry_random_add_bytes): New.
2003-01-20 Simon Josefsson <jas@extundo.com>
* gcrypt.h (gcry_md_algos): Add GCRY_MD_CRC32,
GCRY_MD_CRC32_RFC1510, GCRY_MD_CRC24_RFC2440.
2003-01-16 Werner Koch <wk@gnupg.org>
* gcrypt.h (gcry_md_write): Changed type of 2nd argument to void*.
(gcry_md_hash_buffer): Changed type of both buffers to void*.
(gcry_md_setkey): Changed type of 2nd argument to void*.
(gcry_md_get_asnoid): New.
2003-01-15 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_length): Fixed. This was seriously broken.
2003-01-14 Werner Koch <wk@gnupg.org>
* gcrypt.h (GCRYERR_INV_FLAG), global.c (gcry_strerror): New.
2003-01-02 Werner Koch <wk@gnupg.org>
* libgcrypt.vers: Temporary export _gcry_generate_elg_prime for
use by GNUTLS.
2002-12-21 Werner Koch <wk@gnupg.org>
* gcrypt.h: Make use of gcc's pure and malloc attributes
(gcry_md_putc): Use a helper variable to avoid multiple
evaluation of H.
* g10lib.h, stdmem.h, secmem.h: Use gcc attributes pure and malloc.
* stdmem.c (use_m_guard): Don't default to yes.
2002-12-19 Werner Koch <wk@gnupg.org>
* global.c (global_init): The meat was never run due to a faulty
check. Thanks to Nikos for pointing this out.
* global.c (gcry_control): Return 1 and not -1 for the
initialization tests.
* libgcrypt.vers: New.
* Makefile.am: Use this instead of the build symbol file.
* global.c (gcry_control) <initialization>: Call the random module
initializer to make sure that the pool lock flag has been
initialized.
2002-12-09 Werner Koch <wk@gnupg.org>
* global.c (gcry_calloc,gcry_calloc_secure): Check for overflow.
Noted by Florian Weimer.
2002-11-10 Simon Josefsson <jas@extundo.com>
* gcrypt.h (gcry_ctl_cmds): New GCRYCTL_SET_CBC_CTS control flag.
(gcry_cipher_flags): New GCRY_CIPHER_CBC_CTS gcry_cipher_open() flag.
(gcry_cipher_cts): New macro for toggling CTS.
2002-11-10 Werner Koch <wk@gnupg.org>
* gcrypt.h (GCRY_MD_MD4): New. We use a non OpenPGP value here.
2002-09-20 Werner Koch <wk@gnupg.org>
* ath.c: Include sys.time.h if sys/select.h does not exist.
(ath_select, ath_waitpid): Shortcut for Windows.
* ath.h: Include some Windows headers. By Timo.
2002-09-18 Werner Koch <wk@gnupg.org>
* ath.h: Prefix ath_deinit.
2002-09-17 Werner Koch <wk@gnupg.org>
* benchmark.c: New.
(mpi_bench, do_powm): Add a a simple test for RSA.
* global.c (global_init): New. Use it instead of the setting
any_init_done. Initialize the ATH system.
(gcry_check_version): Hook global_init in. This is the suggested
way to initialize the library.
(_gcry_no_internal_locking): Removed. We simply call a ath_deinit
and leave it to ATH to disbale the locking.
* ath.c, ath.h, ath-pth.c, ath-pthread.c: New. Taken from GPGME.
* mutex.h: Removed.
* Makefile.am (ath_components): New.
2002-09-16 Werner Koch <wk@gnupg.org>
* secmem.c (_gcry_secmem_dump_stats): Replaced fprintf by log_*.
2002-08-23 Werner Koch <wk@gnupg.org>
* missing-string.c: Removed unneeded strlwr.
* libgcrypt.m4: Made much more simple.
* libgcrypt-config.in: Made --prefix work for --libs.
2002-08-14 Werner Koch <wk@gnupg.org>
* gcrypt.h: Add GCRY_CIPGER_DES. Included string.h for size_t.
Suggested by Simon Josefsson.
2002-07-25 Werner Koch <wk@gnupg.org>
* cipher.h: Added prototypes for progress functions.
* global.c: Include cipher.h for those prototypes.
* stdmem.c (_gcry_private_realloc): Replaced void* by char * for
pointer arithmetic reasons. Noted by Stephan Austermuehle.
2002-06-24 Werner Koch <wk@gnupg.org>
* missing-string.c: Include ctype.h.
* gcrypt.h (gcry_mpi_invm, gcry_mpi_div, gcry_mpi_mod)
(gcry_mpi_swap): New.
2002-06-18 Werner Koch <wk@gnupg.org>
* gcrypt.h: Added a bunch of brief function descriptions.
2002-05-21 Werner Koch <wk@gnupg.org>
* misc.c (_gcry_log_printf): Don't initialize a va_list. Noted by
Jeff Johnson.
* global.c (gcry_set_progress_handler): New.
* gcrypt.h: Replaced the typedef for byte.
2002-05-16 Werner Koch <wk@gnupg.org>
* missing-string.c: New.
* gcrypt.h: Add new error codes GCRYERR_SEXP_ and typedefs
GcryMPI, GcrySexp, GcryCipherHd, GcryMDHd as aliases for the old
ones using an underscore.
* global.c (gcry_strerror): Add strings fro the new error codes.
* sexp.c (gcry_sexp_canon_len): Use a macro to convert from new to
old error codes.
(gcry_sexp_create,gcry_sexp_new): New.
2002-05-15 Werner Koch <wk@gnupg.org>
* mutex.h (DEFINE_LOCAL_MUTEX): Macro to define a mutex and
initialize it so that we can detect an unitialized mutex and don't
read from stdin.
2002-05-14 Werner Koch <wk@gnupg.org>
Changed license of all files to the LGPL.
2002-05-07 Werner Koch <wk@gnupg.org>
* global.c (gcry_control): Add commands
GCRYCTL_ANY_INITIALIZATION_P and GCRYCTL_INITIALIZATION_FINISHED_P
so that other libraries are able to check for required
initializations.
2002-05-02 Werner Koch <wk@gnupg.org>
* gcrypt.h (GCRYCTL_DISABLE_INTERNAL_LOCKING): New.
* global.c (gcry_control): Implement it.
(_gcry_no_internal_locking): New.
* mutex.h: Prefixed all fucntions with _gcry_. Bypass all
functions when desired.
* gcrypt.h (GCRYCTL_DISABLE_SECMEM): New.
* global.c (gcry_control,gcry_malloc_secure,gcry_is_secure):
Implement it here.
* secmem.c (_gcry_private_is_secure): Return false if the pool is
not initialized.
* gcrypt.h (GCRYCTL_INITIALIZATION_FINISHED): New.
* gcrypt.h (gcry_cipher_algos): Replaced RINDAEL by AES and change
the macros to expand from rijdael to aes.
* stdmem.c (_gcry_private_malloc): Return NULL for 0 byte allocation.
(_gcry_private_malloc_secure): Ditto.
* g10lib.h: Copied the JNLIB_GCC macros from ../jnlib/mischelp.h
and removed the inclusion of that file.
2002-04-15 Werner Koch <wk@gnupg.org>
* global.c (gcry_strdup): New.
2002-03-18 Werner Koch <wk@gnupg.org>
* mutex.h: New file with a portable thread mutex implementation
written by Marcus Brinkmann. Taken from GPGME.
2002-02-18 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_sscan): Don't initialize the dummy
variable. Suggested by Jordi Mallach.
2002-01-31 Werner Koch <wk@gnupg.org>
* sexp.c (suitable_encoding,convert_to_hex,convert_to_string)
(convert_to_token): New.
(gcry_sexp_sprint): Better formatting of advanced encoding, does
now insert LFs and escapes all unprintable characters.
(unquote_string): New.
(sexp_sscan): Implemented the missing conversion of quoted strings.
2002-01-26 Werner Koch <wk@gnupg.org>
* libgcrypt-config.in: Add copyright notice.
2002-01-11 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): Fixed last change.
2002-01-01 Timo Schulz <ts@winpt.org>
* stdmem.c (_gcry_private_realloc): If pointer is NULL now realloc
behaves like malloc.
2001-12-20 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): Describe the error codes and
return an error if this is not a S-Exp; i.e. it does not start
with an open parenthesis.
2001-12-18 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): Fixed the test on NULL buffer.
* Makefile.am (DISTCLEANFILES): Include libgcrypt.sym
* sexp.c: Removed the commented test code because we now have a
test in ../tests/
2001-12-17 Werner Koch <wk@gnupg.org>
* sexp.c (gcry_sexp_canon_len): New.
2001-12-11 Werner Koch <wk@gnupg.org>
* gcrypt.h: Fixed AES128 macro, add enum for OFB mode.
2001-12-05 Werner Koch <wk@gnupg.org>
* misc.c (_gcry_log_printf): New.
* sexp.c (dump_string,gcry_sexp_dump): Use logging functions
instead of stderr.
2001-11-16 Werner Koch <wk@gnupg.org>
* gcrypt.h: New constant GCRYCTL_IS_ALGO_ENABLED.
2001-10-02 Werner Koch <wk@gnupg.org>
* gcrypt.h: Removed a couple of trailing commas.
2001-08-28 Werner Koch <wk@gnupg.org>
* sexp.c (sexp_sscan): Add an argument to enable the
arg_ptr. Changed all callers. Suggested by Tom Holroyd.
2001-08-03 Werner Koch <wk@gnupg.org>
* global.c (gcry_strerror): Updated list of error codes.
2001-07-23 Werner Koch <wk@gnupg.org>
* gcrypt.h: Replaced the last ulong. Noted by Rami Lehti.
2001-05-31 Werner Koch <wk@gnupg.org>
* gcrypt.h, mpi.h: Made some mpi functions public.
* wrapper.c: Removed.
* global.c: Renamed all g10_ prefixed functions which had wrappers
to gcry_xxx. So we now use the exported memory functions inernally.
Renamed all g10_ prefixed functions to _gcry_ prefixed ones.
* g10lib.h (_GCRYPT_IN_LIBGCRYPT): Replace defintion by a test on it.
2001-05-28 Werner Koch <wk@gnupg.org>
* libgcrypt.m4: Check GCRYPT_VERSION macro and not LIBGCRYPT_VERSION.
* mpi.h: Removed mpi_fromstr prototype.
2001-01-11 Werner Koch <wk@gnupg.org>
* Makefile.am (libgcrypt_la_SOURCES): Add mpi.h
2000-12-19 Werner Koch <wk@gnupg.org>
* types.h: Moved from ../include to here.
Major change:
Removed all GnuPG stuff and renamed this piece of software
to gcrypt.
2000-11-14 Werner Koch <wk@gnupg.org>
* mpi.h: Moved to ../mpi.
* Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency
problems.
2000-10-11 Werner Koch <wk@gnupg.org>
* mpi.h: Changed the way mpi_limb_t is defined.
2000-10-10 Werner Koch <wk@gnupg.org>
* Makefile.am: Take version-info from configure.
2000-10-09 Werner Koch <wk@gnupg.org>
* gcrypt.h: New cipher mode, new algo Arcfour and new error code
GCRYERR_INV_CIPHER_MODE.
* global.c (gcry_strerror): New errorcode.
Wed Oct 4 13:16:18 CEST 2000 Werner Koch <wk@openit.de>
* gcrypt.h (gcry_md_setkey): Replaced macro by function prototype.
Mon Sep 18 16:35:45 CEST 2000 Werner Koch <wk@openit.de>
* gcrypt.h (GCRYCTL_GET_ALGO_USAGE): New.
* secmem.c (secmem_realloc): check for failed secmem_malloc. By
Matt Kraai.
Mon Jul 31 10:04:47 CEST 2000 Werner Koch <wk@openit.de>
* sexp.c: Removed the datalen fields from list tags.
(gcry_sexp_car_data,gcry_sexp_cdr_data,gcry_sexp_car_mpi,
gcry_sexp_cdr_mpi): Removed.
(gcry_sexp_nth,gcry_sexp_nth_data,gcry_sexp_nth_mpi): New.
Fri Jul 28 18:19:11 CEST 2000 Werner Koch <wk@openit.de>
* sexp.c (sexp_sscan): Fixed reallocation to secure memory.
(new_empty_list): Removed
(gcry_sexp_length): New.
(gcry_sexp_enum): Removed.
(normalize): New. Reworked the whole thing to use NULL for an empty list.
(make_space): New instead of the macro.
Tue Jul 25 17:44:15 CEST 2000 Werner Koch <wk@openit.de>
* sexp.c: Major rewrite.
(gcry_sexp_sscan): Reordered arguments. Moved functionality to ..
(sexp_sscan): .. this.
(gcry_sexp_build): New.
(gcry_sexp_new_name_mpi, gcry_sexp_new_name_data, gcry_sexp_new_data,
gcry_sexp_new_mpi): Removed.
Fri Jul 14 19:38:23 CEST 2000 Werner Koch <wk@>
* gcrypt.h (gcry_md_start_debug, gcry_md_stop_debug): New.
(gcry_ctl_cmds): New control values
* sexp.c (gcry_sexp_sscan): Add hex format parsing.
* secmem.c (lock_pool): Check for ENOSYS return my mlock() on old SCOs.
(pool_is_mmapped): Made volatile.
(lock_pool): No more warning for QNX. By Sam Roberts.
(lock_pool,secmem_init): Additional check for dropped privs.
2000-03-21 09:18:48 Werner Koch (wk@habibti.gnupg.de)
* gcrypt.h (gcry_md_setkey): New.
(GCRY_MD_FLAG_HMAC): New.
Mon Jan 31 16:37:34 CET 2000 Werner Koch <wk@gnupg.de>
* Makefile.am: Add g10lib.h
Thu Jan 27 18:00:44 CET 2000 Werner Koch <wk@gnupg.de>
* sexp.c (gcry_sexp_sscan): Allow NULL for erroff.
Mon Jan 24 22:24:38 CET 2000 Werner Koch <wk@gnupg.de>
* sexp.c (gcry_sexp_alist): New.
Mon Jan 24 13:04:28 CET 2000 Werner Koch <wk@gnupg.de>
* secmem.c: Moved from ../util to here.
* secmem.h: New.
* stdmem.c: New. Based on the old ../util/memory.c.
* stdmem.h: New.
Wed Dec 8 21:58:32 CET 1999 Werner Koch <wk@gnupg.de>
* gcrypt.m4: New.
* gcrypt-config: New.
* mpi.h (mpi_get_nbit_info): Removed
(mpi_set_nbit_info): Removed.
(struct gcry_mpi): Removed the nbits field.
* misc.c (g10_log_verbosity): New.
* global.c (g10_xstrdup): New.
* mpiapi.c: Removed.
* mpi.h: Moved from ../include to here. Removed some obsolete
prototypes and the iobuf.h header.
* cipher.h: Moved from ../include to here. Removed the mpi.h header.
* g10lib.h: Moved from ../include to here.
Fri Nov 19 17:15:20 CET 1999 Werner Koch <wk@gnupg.de>
* sexp.c (dump_string): New. Taken from gnupg/util/miscutil.c.
(do_dump_list): s/print_string/dump_string/.
* testapi.c: New.
* mpiapi.c (gcry_mpi_randomize): Use new random API.
Sat Nov 13 17:44:23 CET 1999 Werner Koch <wk@gnupg.de>
* gloabl.c (gcry_control): Add cases for dumping random
and secmem stats.
Tue Oct 26 14:10:21 CEST 1999 Werner Koch <wk@gnupg.de>
* pkapi.c: Removed.
* symapi.c: Removed.
* g10lib.h: Moved to ../include.
* mdapi.c: Removed.
Wed Jul 7 13:08:40 CEST 1999 Werner Koch <wk@isil.d.shuttle.de>
* sexp.c: New.
Tue Dec 8 13:15:16 CET 1998 Werner Koch <wk@isil.d.shuttle.de>
* gcrypt.h: New
* mpiapi.c: New
Copyright 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/src/secmem.c b/src/secmem.c
index c5772834..a7b5fcc1 100644
--- a/src/secmem.c
+++ b/src/secmem.c
@@ -1,654 +1,655 @@
/* secmem.c - memory allocation from a secure heap
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002,
+ * 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser general Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
#include <stddef.h>
#if defined(HAVE_MLOCK) || defined(HAVE_MMAP)
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef USE_CAPABILITIES
#include <sys/capability.h>
#endif
#endif
#include "ath.h"
#include "g10lib.h"
#include "secmem.h"
#if defined (MAP_ANON) && ! defined (MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
#define DEFAULT_POOL_SIZE 16384
#define DEFAULT_PAGE_SIZE 4096
typedef struct memblock
{
unsigned size; /* Size of the memory available to the
user. */
int flags; /* See below. */
PROPERLY_ALIGNED_TYPE aligned;
} memblock_t;
/* This flag specifies that the memory block is in use. */
#define MB_FLAG_ACTIVE 1 << 0
/* The pool of secure memory. */
static void *pool;
/* Size of POOL in bytes. */
static size_t pool_size;
/* True, if the memory pool is ready for use. May be checked in an
atexit function. */
static volatile int pool_okay;
/* True, if the memory pool is mmapped. */
static volatile int pool_is_mmapped;
/* FIXME? */
static int disable_secmem;
static int show_warning;
static int no_warning;
static int suspend_warning;
/* Stats. */
static unsigned int cur_alloced, cur_blocks;
/* Lock protecting accesses to the memory pool. */
static ath_mutex_t secmem_lock;
/* Convenient macros. */
#define SECMEM_LOCK ath_mutex_lock (&secmem_lock)
#define SECMEM_UNLOCK ath_mutex_unlock (&secmem_lock)
/* The size of the memblock structure; this does not include the
memory that is available to the user. */
#define BLOCK_HEAD_SIZE \
offsetof (memblock_t, aligned)
/* Convert an address into the according memory block structure. */
#define ADDR_TO_BLOCK(addr) \
(memblock_t *) ((char *) addr - BLOCK_HEAD_SIZE)
/* Check wether MB is a valid block. */
#define BLOCK_VALID(mb) \
(((char *) mb - (char *) pool) < pool_size)
/* Update the stats. */
static void
stats_update (size_t add, size_t sub)
{
if (add)
{
cur_alloced += add;
cur_blocks++;
}
if (sub)
{
cur_alloced -= sub;
cur_blocks--;
}
}
/* Return the block following MB or NULL, if MB is the last block. */
static memblock_t *
mb_get_next (memblock_t *mb)
{
memblock_t *mb_next;
mb_next = (memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE + mb->size);
if (! BLOCK_VALID (mb_next))
mb_next = NULL;
return mb_next;
}
/* Return the block preceeding MB or NULL, if MB is the first
block. */
static memblock_t *
mb_get_prev (memblock_t *mb)
{
memblock_t *mb_prev, *mb_next;
if (mb == pool)
mb_prev = NULL;
else
{
mb_prev = (memblock_t *) pool;
while (1)
{
mb_next = mb_get_next (mb_prev);
if (mb_next == mb)
break;
else
mb_prev = mb_next;
}
}
return mb_prev;
}
/* If the preceeding block of MB and/or the following block of MB
exist and are not active, merge them to form a bigger block. */
static void
mb_merge (memblock_t *mb)
{
memblock_t *mb_prev, *mb_next;
mb_prev = mb_get_prev (mb);
mb_next = mb_get_next (mb);
if (mb_prev && (! (mb_prev->flags & MB_FLAG_ACTIVE)))
{
mb_prev->size += BLOCK_HEAD_SIZE + mb->size;
mb = mb_prev;
}
if (mb_next && (! (mb_next->flags & MB_FLAG_ACTIVE)))
mb->size += BLOCK_HEAD_SIZE + mb_next->size;
}
/* Return a new block, which can hold SIZE bytes. */
static memblock_t *
mb_get_new (memblock_t *block, size_t size)
{
memblock_t *mb, *mb_split;
for (mb = block; BLOCK_VALID (mb); mb = mb_get_next (mb))
if (! (mb->flags & MB_FLAG_ACTIVE) && mb->size >= size)
{
/* Found a free block. */
mb->flags |= MB_FLAG_ACTIVE;
if (mb->size - size > BLOCK_HEAD_SIZE)
{
/* Split block. */
mb_split = (memblock_t *) (((char *) mb) + BLOCK_HEAD_SIZE + size);
mb_split->size = mb->size - size - BLOCK_HEAD_SIZE;
mb_split->flags = 0;
mb->size = size;
mb_merge (mb_split);
}
break;
}
if (! BLOCK_VALID (mb))
mb = NULL;
return mb;
}
/* Print a warning message. */
static void
print_warn (void)
{
if (!no_warning)
log_info (_("Warning: using insecure memory!\n"));
}
/* Lock the memory pages into core and drop privileges. */
static void
lock_pool (void *p, size_t n)
{
#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK)
int err;
cap_set_proc (cap_from_text ("cap_ipc_lock+ep"));
err = mlock (p, n);
if (err && errno)
err = errno;
cap_set_proc (cap_from_text ("cap_ipc_lock+p"));
if (err)
{
if (errno != EPERM
#ifdef EAGAIN /* OpenBSD returns this */
&& errno != EAGAIN
#endif
#ifdef ENOSYS /* Some SCOs return this (function not implemented) */
&& errno != ENOSYS
#endif
#ifdef ENOMEM /* Linux might return this. */
&& errno != ENOMEM
#endif
)
log_error ("can't lock memory: %s\n", strerror (err));
show_warning = 1;
}
#elif defined(HAVE_MLOCK)
uid_t uid;
int err;
uid = getuid ();
#ifdef HAVE_BROKEN_MLOCK
/* Under HP/UX mlock segfaults if called by non-root. Note, we have
noch checked whether mlock does really work under AIX where we
also detected a broken nlock. Note further, that using plock ()
is not a good idea under AIX. */
if (uid)
{
errno = EPERM;
err = errno;
}
else
{
err = mlock (p, n);
if (err && errno)
err = errno;
}
#else /* !HAVE_BROKEN_MLOCK */
err = mlock (p, n);
if (err && errno)
err = errno;
#endif /* !HAVE_BROKEN_MLOCK */
if (uid && ! geteuid ())
{
/* check that we really dropped the privs.
* Note: setuid(0) should always fail */
if (setuid (uid) || getuid () != geteuid () || !setuid (0))
log_fatal ("failed to reset uid: %s\n", strerror (errno));
}
if (err)
{
if (errno != EPERM
#ifdef EAGAIN /* OpenBSD returns this. */
&& errno != EAGAIN
#endif
#ifdef ENOSYS /* Some SCOs return this (function not implemented). */
&& errno != ENOSYS
#endif
#ifdef ENOMEM /* Linux might return this. */
&& errno != ENOMEM
#endif
)
log_error ("can't lock memory: %s\n", strerror (err));
show_warning = 1;
}
#elif defined ( __QNX__ )
/* QNX does not page at all, so the whole secure memory stuff does
* not make much sense. However it is still of use because it
* wipes out the memory on a free().
* Therefore it is sufficient to suppress the warning
*/
#elif defined (HAVE_DOSISH_SYSTEM) || defined (__CYGWIN__)
/* It does not make sense to print such a warning, given the fact that
* this whole Windows !@#$% and their user base are inherently insecure
*/
#elif defined (__riscos__)
/* no virtual memory on RISC OS, so no pages are swapped to disc,
* besides we don't have mmap, so we don't use it! ;-)
* But don't complain, as explained above.
*/
#else
log_info ("Please note that you don't have secure memory on this system\n");
#endif
}
/* Initialize POOL. */
static void
init_pool (size_t n)
{
size_t pgsize;
memblock_t *mb;
pool_size = n;
if (disable_secmem)
log_bug ("secure memory is disabled");
#ifdef HAVE_GETPAGESIZE
pgsize = getpagesize ();
#else
pgsize = DEFAULT_PAGE_SIZE;
#endif
#if HAVE_MMAP
pool_size = (pool_size + pgsize - 1) & ~(pgsize - 1);
#ifdef MAP_ANONYMOUS
pool = mmap (0, pool_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#else /* map /dev/zero instead */
{
int fd;
fd = open ("/dev/zero", O_RDWR);
if (fd == -1)
{
log_error ("can't open /dev/zero: %s\n", strerror (errno));
pool = (void *) -1;
}
else
{
pool = mmap (0, pool_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
}
}
#endif
if (pool == (void *) -1)
log_info ("can't mmap pool of %u bytes: %s - using malloc\n",
(unsigned) pool_size, strerror (errno));
else
{
pool_is_mmapped = 1;
pool_okay = 1;
}
#endif
if (!pool_okay)
{
pool = malloc (pool_size);
if (!pool)
log_fatal ("can't allocate memory pool of %u bytes\n",
(unsigned) pool_size);
else
pool_okay = 1;
}
/* Initialize first memory block. */
mb = (memblock_t *) pool;
mb->size = pool_size;
mb->flags = 0;
}
void
_gcry_secmem_set_flags (unsigned flags)
{
int was_susp;
SECMEM_LOCK;
was_susp = suspend_warning;
no_warning = flags & GCRY_SECMEM_FLAG_NO_WARNING;
suspend_warning = flags & GCRY_SECMEM_FLAG_SUSPEND_WARNING;
/* and now issue the warning if it is not longer suspended */
if (was_susp && !suspend_warning && show_warning)
{
show_warning = 0;
print_warn ();
}
SECMEM_UNLOCK;
}
unsigned
_gcry_secmem_get_flags (void)
{
unsigned flags;
SECMEM_LOCK;
flags = no_warning ? GCRY_SECMEM_FLAG_NO_WARNING : 0;
flags |= suspend_warning ? GCRY_SECMEM_FLAG_SUSPEND_WARNING : 0;
SECMEM_UNLOCK;
return flags;
}
/* Initialize the secure memory system. If running with the necessary
privileges, the secure memory pool will be locked into the core in
order to prevent page-outs of the data. Furthermore allocated
secure memory will be wiped out when released. */
void
_gcry_secmem_init (size_t n)
{
SECMEM_LOCK;
if (!n)
{
#ifdef USE_CAPABILITIES
/* drop all capabilities */
cap_set_proc (cap_from_text ("all-eip"));
#elif !defined(HAVE_DOSISH_SYSTEM)
uid_t uid;
disable_secmem = 1;
uid = getuid ();
if (uid != geteuid ())
{
if (setuid (uid) || getuid () != geteuid () || !setuid (0))
log_fatal ("failed to drop setuid\n");
}
#endif
}
else
{
if (n < DEFAULT_POOL_SIZE)
n = DEFAULT_POOL_SIZE;
if (! pool_okay)
{
init_pool (n);
if (! geteuid ())
lock_pool (pool, n);
- else
+ else if (!no_warning)
log_info ("Secure memory is not locked into core\n");
}
else
log_error ("Oops, secure memory pool already initialized\n");
}
SECMEM_UNLOCK;
}
static void *
_gcry_secmem_malloc_internal (size_t size)
{
memblock_t *mb;
if (!pool_okay)
{
log_info (_
("operation is not possible without initialized secure memory\n"));
log_info (_("(you may have used the wrong program for this task)\n"));
exit (2);
}
if (show_warning && !suspend_warning)
{
show_warning = 0;
print_warn ();
}
/* blocks are always a multiple of 32 */
size = ((size + 31) / 32) * 32;
mb = mb_get_new ((memblock_t *) pool, size);
if (mb)
stats_update (size, 0);
return mb ? &mb->aligned.c : NULL;
}
void *
_gcry_secmem_malloc (size_t size)
{
void *p;
SECMEM_LOCK;
p = _gcry_secmem_malloc_internal (size);
SECMEM_UNLOCK;
return p;
}
static void
_gcry_secmem_free_internal (void *a)
{
memblock_t *mb;
int size;
if (!a)
return;
mb = ADDR_TO_BLOCK (a);
size = mb->size;
/* This does not make much sense: probably this memory is held in the
* cache. We do it anyway: */
#define MB_WIPE_OUT(byte) \
memset ((memblock_t *) ((char *) mb + BLOCK_HEAD_SIZE), (byte), size);
MB_WIPE_OUT (0xff);
MB_WIPE_OUT (0xaa);
MB_WIPE_OUT (0x55);
MB_WIPE_OUT (0x00);
stats_update (0, size);
mb->flags &= ~MB_FLAG_ACTIVE;
/* Update stats. */
mb_merge (mb);
}
/* Wipe out and release memory. */
void
_gcry_secmem_free (void *a)
{
SECMEM_LOCK;
_gcry_secmem_free_internal (a);
SECMEM_UNLOCK;
}
/* Realloc memory. */
void *
_gcry_secmem_realloc (void *p, size_t newsize)
{
memblock_t *mb;
size_t size;
void *a;
SECMEM_LOCK;
mb = (memblock_t *) ((char *) p - ((size_t) &((memblock_t *) 0)->aligned.c));
size = mb->size;
if (newsize < size)
{
SECMEM_UNLOCK;
/* It is easier to not shrink the memory. */
a = p;
}
else
{
a = _gcry_secmem_malloc_internal (newsize);
if (a)
{
memcpy (a, p, size);
memset ((char *) a + size, 0, newsize - size);
_gcry_secmem_free_internal (p);
}
}
SECMEM_UNLOCK;
return a;
}
int
_gcry_private_is_secure (const void *p)
{
int ret = 0;
SECMEM_LOCK;
if (pool_okay && BLOCK_VALID (ADDR_TO_BLOCK (p)))
ret = 1;
SECMEM_UNLOCK;
return ret;
}
/****************
* Warning: This code might be called by an interrupt handler
* and frankly, there should really be such a handler,
* to make sure that the memory is wiped out.
* We hope that the OS wipes out mlocked memory after
* receiving a SIGKILL - it really should do so, otherwise
* there is no chance to get the secure memory cleaned.
*/
void
_gcry_secmem_term ()
{
if (!pool_okay)
return;
memset (pool, 0xff, pool_size);
memset (pool, 0xaa, pool_size);
memset (pool, 0x55, pool_size);
memset (pool, 0x00, pool_size);
#if HAVE_MMAP
if (pool_is_mmapped)
munmap (pool, pool_size);
#endif
pool = NULL;
pool_okay = 0;
pool_size = 0;
}
void
_gcry_secmem_dump_stats ()
{
#if 1
SECMEM_LOCK;
if (pool_okay)
log_info ("secmem usage: %u/%lu bytes in %u blocks\n",
cur_alloced, (unsigned long)pool_size, cur_blocks);
SECMEM_UNLOCK;
#else
memblock_t *mb;
int i;
SECMEM_LOCK;
for (i = 0, mb = (memblock_t *) pool;
BLOCK_VALID (mb);
mb = mb_get_next (mb), i++)
log_info ("SECMEM: [%s] block: %i; size: %i\n",
(mb->flags & MB_FLAG_ACTIVE) ? "used" : "free",
i,
mb->size);
SECMEM_UNLOCK;
#endif
}
diff --git a/src/sexp.c b/src/sexp.c
index e271414b..c19dc332 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -1,1741 +1,1804 @@
/* sexp.c - S-Expression handling
- * Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ * Copyright (C) 1999, 2000, 2001, 2002, 2003,
+ * 2004 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser general Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <assert.h>
#define GCRYPT_NO_MPI_MACROS 1
#include "g10lib.h"
#include "memory.h"
typedef struct gcry_sexp *NODE;
typedef unsigned short DATALEN;
struct gcry_sexp
{
byte d[1];
};
#define ST_STOP 0
#define ST_DATA 1 /* datalen follows */
#define ST_HINT 2 /* datalen follows */
#define ST_OPEN 3
#define ST_CLOSE 4
/* the atoi macros assume that the buffer has only valid digits */
#define atoi_1(p) (*(p) - '0' )
#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
*(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
#define TOKEN_SPECIALS "-./_:*+="
static gcry_error_t
sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length, int argflag,
va_list arg_ptr, void **arg_list);
#if 0
static void
dump_mpi( gcry_mpi_t a )
{
char buffer[1000];
size_t n = 1000;
if( !a )
fputs("[no MPI]", stderr );
else if( gcry_mpi_print( GCRYMPI_FMT_HEX, buffer, &n, a ) )
fputs("[MPI too large to print]", stderr );
else
fputs( buffer, stderr );
}
#endif
static void
dump_string (const byte *p, size_t n, int delim )
{
for (; n; n--, p++ )
{
if ((*p & 0x80) || iscntrl( *p ) || *p == delim )
{
if( *p == '\n' )
log_printf ("\\n");
else if( *p == '\r' )
log_printf ("\\r");
else if( *p == '\f' )
log_printf ("\\f");
else if( *p == '\v' )
log_printf ("\\v");
else if( *p == '\b' )
log_printf ("\\b");
else if( !*p )
log_printf ("\\0");
else
log_printf ("\\x%02x", *p );
}
else
log_printf ("%c", *p);
}
}
void
gcry_sexp_dump (const gcry_sexp_t a)
{
const byte *p;
int indent = 0;
int type;
if (!a)
{
log_printf ( "[nil]\n");
return;
}
p = a->d;
while ( (type = *p) != ST_STOP )
{
p++;
switch ( type )
{
case ST_OPEN:
log_printf ("%*s[open]\n", 2*indent, "");
indent++;
break;
case ST_CLOSE:
if( indent )
indent--;
log_printf ("%*s[close]\n", 2*indent, "");
break;
case ST_DATA: {
DATALEN n;
memcpy ( &n, p, sizeof n );
p += sizeof n;
log_printf ("%*s[data=\"", 2*indent, "" );
dump_string (p, n, '\"' );
log_printf ("\"]\n");
p += n;
}
break;
default:
log_printf ("%*s[unknown tag %d]\n", 2*indent, "", type);
break;
}
}
}
/****************
* Pass list through except when it is an empty list - in that case
* return NULL and release the passed list.
*/
static gcry_sexp_t
normalize ( gcry_sexp_t list )
{
char *p;
if ( !list )
return NULL;
p = list->d;
if ( *p == ST_STOP ) {
/* this is "" */
gcry_sexp_release ( list );
return NULL;
}
if( *p == ST_OPEN && p[1] == ST_CLOSE ) {
/* this is "()" */
gcry_sexp_release ( list );
return NULL;
}
return list;
}
/* Create a new S-expression object by reading LENGTH bytes from
BUFFER, assuming it is canonilized encoded or autodetected encoding
when AUTODETECT is set to 1. With FREEFNC not NULL, ownership of
the buffer is transferred to tyhe newle created object. FREEFNC
should be the freefnc used to release BUFFER; there is no guarantee
at which point this function is called; most likey you want to use
free() or gcry_free().
Passing LENGTH and AUTODETECT as 0 is allowed to indicate that
BUFFER points to a valid canonical encoded S-expression. A LENGTH
of 0 and AUTODETECT 1 indicates that buffer points to a
null-terminated string.
This function returns 0 and and the pointer to the new object in
RETSEXP or an error code in which case RETSEXP is set to NULL. */
gcry_error_t
gcry_sexp_create (gcry_sexp_t *retsexp, void *buffer, size_t length,
int autodetect, void (*freefnc)(void*) )
{
gcry_error_t errcode;
gcry_sexp_t se;
volatile va_list dummy_arg_ptr;
if (!retsexp)
return gcry_error (GPG_ERR_INV_ARG);
*retsexp = NULL;
if (autodetect < 0 || autodetect > 1 || !buffer)
return gcry_error (GPG_ERR_INV_ARG);
if (!length && !autodetect)
{ /* What a brave caller to assume that there is really a canonical
encoded S-expression in buffer */
length = gcry_sexp_canon_len (buffer, 0, NULL, &errcode);
if (!length)
return errcode;
}
else if (!length && autodetect)
{ /* buffer is a string */
length = strlen ((char *)buffer);
}
errcode = sexp_sscan (&se, NULL, buffer, length, 0, dummy_arg_ptr, NULL);
if (errcode)
return errcode;
*retsexp = se;
if (freefnc)
{
/* For now we release the buffer immediately. As soon as we
have changed the internal represenation of S-expression to
the canoncial format - which has the advantage of faster
parsing - we will use this function as a closure in our
GCRYSEXP object and use the BUFFER directly */
freefnc (buffer);
}
return gcry_error (GPG_ERR_NO_ERROR);
}
/* Same as gcry_sexp_create but don't transfer ownership */
gcry_error_t
gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length,
int autodetect)
{
return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL);
}
/****************
* Release resource of the given SEXP object.
*/
void
gcry_sexp_release( gcry_sexp_t sexp )
{
- gcry_free ( sexp );
+ if (sexp)
+ {
+ if (gcry_is_secure (sexp))
+ {
+ /* Extra paranoid wiping. */
+ const byte *p = sexp->d;
+ int type;
+
+ while ( (type = *p) != ST_STOP )
+ {
+ p++;
+ switch ( type )
+ {
+ case ST_OPEN:
+ break;
+ case ST_CLOSE:
+ break;
+ case ST_DATA:
+ {
+ DATALEN n;
+ memcpy ( &n, p, sizeof n );
+ p += sizeof n;
+ p += n;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ wipememory (sexp->d, p - sexp->d);
+ }
+ gcry_free ( sexp );
+ }
}
/****************
* Make a pair from lists a and b, don't use a or b later on.
* Special behaviour: If one is a single element list we put the
* element straight into the new pair.
*/
gcry_sexp_t
gcry_sexp_cons( const gcry_sexp_t a, const gcry_sexp_t b )
{
- /* NYI: Implementation should be quite easy with our new data representation */
- BUG ();
- return NULL;
+ /* NYI: Implementation should be quite easy with our new data
+ representation */
+ BUG ();
+ return NULL;
}
/****************
* Make a list from all items in the array the end of the array is marked
- * with a NULL. y a NULL
+ * with a NULL.
*/
gcry_sexp_t
gcry_sexp_alist( const gcry_sexp_t *array )
{
- /* NYI: Implementaion should be quite easy with our new data representation */
- BUG ();
- return NULL;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
}
/****************
* Make a list from all items, the end of list is indicated by a NULL
*/
gcry_sexp_t
gcry_sexp_vlist( const gcry_sexp_t a, ... )
{
- /* NYI: Implementaion should be quite easy with our new data representation */
- BUG ();
- return NULL;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
}
/****************
* Append n to the list a
* Returns: a new ist (which maybe a)
*/
gcry_sexp_t
gcry_sexp_append( const gcry_sexp_t a, const gcry_sexp_t n )
{
- /* NYI: Implementaion should be quite easy with our new data representation */
- BUG ();
- return NULL;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
}
gcry_sexp_t
gcry_sexp_prepend( const gcry_sexp_t a, const gcry_sexp_t n )
{
- /* NYI: Implementaion should be quite easy with our new data representation */
- BUG ();
- return NULL;
+ /* NYI: Implementation should be quite easy with our new data
+ representation. */
+ BUG ();
+ return NULL;
}
/****************
* Locate token in a list. The token must be the car of a sublist.
* Returns: A new list with this sublist or NULL if not found.
*/
gcry_sexp_t
gcry_sexp_find_token( const gcry_sexp_t list, const char *tok, size_t toklen )
{
const byte *p;
DATALEN n;
if ( !list )
return NULL;
if( !toklen )
toklen = strlen(tok);
p = list->d;
while ( *p != ST_STOP ) {
if ( *p == ST_OPEN && p[1] == ST_DATA ) {
const byte *head = p;
p += 2;
memcpy ( &n, p, sizeof n ); p += sizeof n;
if ( n == toklen && !memcmp( p, tok, toklen ) ) { /* found it */
gcry_sexp_t newlist;
byte *d;
int level = 1;
/* look for the end of the list */
for ( p += n; level; p++ ) {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--; /* compensate for later increment */
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
}
else if ( *p == ST_STOP ) {
BUG ();
}
} while ( level );
n = p - head;
newlist = gcry_xmalloc ( sizeof *newlist + n );
d = newlist->d;
memcpy ( d, head, n ); d += n;
*d++ = ST_STOP;
return normalize ( newlist );
}
p += n;
}
else if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n ); p += sizeof n;
p += n;
}
else
p++;
}
return NULL;
}
/****************
* Return the length of the given list
*/
int
gcry_sexp_length( const gcry_sexp_t list )
{
const byte *p;
DATALEN n;
int type;
int length = 0;
int level = 0;
if ( !list )
return 0;
p = list->d;
while ( (type=*p) != ST_STOP ) {
p++;
if ( type == ST_DATA ) {
memcpy ( &n, p, sizeof n );
p += sizeof n + n;
if ( level == 1 )
length++;
}
else if ( type == ST_OPEN ) {
if ( level == 1 )
length++;
level++;
}
else if ( type == ST_CLOSE ) {
level--;
}
}
return length;
}
/****************
* Extract the CAR of the given list
*/
gcry_sexp_t
gcry_sexp_nth( const gcry_sexp_t list, int number )
{
const byte *p;
DATALEN n;
gcry_sexp_t newlist;
byte *d;
int level = 0;
if ( !list || list->d[0] != ST_OPEN )
return NULL;
p = list->d;
while ( number > 0 ) {
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
number--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
number--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
}
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, p, sizeof n ); p += sizeof n;
newlist = gcry_xmalloc ( sizeof *newlist + n + 1 );
d = newlist->d;
memcpy ( d, p, n ); d += n;
*d++ = ST_STOP;
}
else if ( *p == ST_OPEN ) {
const byte *head = p;
level = 1;
do {
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
}
else if ( *p == ST_STOP ) {
BUG ();
}
} while ( level );
n = p + 1 - head;
newlist = gcry_xmalloc ( sizeof *newlist + n );
d = newlist->d;
memcpy ( d, head, n ); d += n;
*d++ = ST_STOP;
}
else
newlist = NULL;
return normalize (newlist);
}
gcry_sexp_t
gcry_sexp_car( const gcry_sexp_t list )
{
return gcry_sexp_nth ( list, 0 );
}
/****************
* Get data from the car. The returned value is valid as long as the list
* is not modified.
*/
const char *
gcry_sexp_nth_data( const gcry_sexp_t list, int number, size_t *datalen )
{
const byte *p;
DATALEN n;
int level = 0;
*datalen = 0;
if ( !list ) {
return NULL;
}
p = list->d;
if ( *p == ST_OPEN )
p++; /* yep, a list */
else if (number )
return NULL; /* not a list but an n > 0 element requested */
/* skip n elements */
while ( number > 0 ) {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
number--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
number--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
p++;
}
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
*datalen = n;
return p + sizeof n;
}
return NULL;
}
/****************
* Get a MPI from the car
*/
gcry_mpi_t
gcry_sexp_nth_mpi( gcry_sexp_t list, int number, int mpifmt )
{
const byte *p;
DATALEN n;
int level = 0;
if ( !list )
return NULL;
if ( !mpifmt )
mpifmt = GCRYMPI_FMT_STD;
p = list->d;
if ( *p == ST_OPEN )
p++; /* yep, a list */
else if (number )
return NULL; /* not a list but an n > 0 element requested */
/* skip n elements */
while ( number > 0 ) {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
number--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
number--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
p++;
}
if ( *p == ST_DATA ) {
gcry_mpi_t a;
size_t nbytes;
memcpy ( &n, ++p, sizeof n );
p += sizeof n;
nbytes = n;
if( !gcry_mpi_scan( &a, mpifmt, p, n, &nbytes ) )
return a;
}
return NULL;
}
/****************
* Get the CDR
*/
gcry_sexp_t
gcry_sexp_cdr( const gcry_sexp_t list )
{
const byte *p;
const byte *head;
DATALEN n;
gcry_sexp_t newlist;
byte *d;
int level = 0;
int skip = 1;
if ( !list || list->d[0] != ST_OPEN )
return NULL;
p = list->d;
while ( skip > 0 ) {
p++;
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
if ( !level )
skip--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
if ( !level )
skip--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
}
p++;
head = p;
level = 0;
do {
if ( *p == ST_DATA ) {
memcpy ( &n, ++p, sizeof n );
p += sizeof n + n;
p--;
}
else if ( *p == ST_OPEN ) {
level++;
}
else if ( *p == ST_CLOSE ) {
level--;
}
else if ( *p == ST_STOP ) {
return NULL;
}
p++;
} while ( level );
n = p - head;
newlist = gcry_xmalloc ( sizeof *newlist + n + 2 );
d = newlist->d;
*d++ = ST_OPEN;
memcpy ( d, head, n ); d += n;
*d++ = ST_CLOSE;
*d++ = ST_STOP;
return normalize (newlist);
}
gcry_sexp_t
gcry_sexp_cadr ( const gcry_sexp_t list )
{
gcry_sexp_t a, b;
a = gcry_sexp_cdr ( list );
b = gcry_sexp_car ( a );
gcry_sexp_release ( a );
return b;
}
static int
hextobyte( const byte *s )
{
int c=0;
if( *s >= '0' && *s <= '9' )
c = 16 * (*s - '0');
else if( *s >= 'A' && *s <= 'F' )
c = 16 * (10 + *s - 'A');
else if( *s >= 'a' && *s <= 'f' ) {
c = 16 * (10 + *s - 'a');
}
s++;
if( *s >= '0' && *s <= '9' )
c += *s - '0';
else if( *s >= 'A' && *s <= 'F' )
c += 10 + *s - 'A';
else if( *s >= 'a' && *s <= 'f' ) {
c += 10 + *s - 'a';
}
return c;
}
struct make_space_ctx {
gcry_sexp_t sexp;
size_t allocated;
byte *pos;
};
static void
make_space ( struct make_space_ctx *c, size_t n )
{
size_t used = c->pos - c->sexp->d;
if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) {
gcry_sexp_t newsexp;
byte *newhead;
c->allocated += 2*(n+sizeof(DATALEN)+1);
newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 );
newhead = newsexp->d;
c->pos = newhead + used;
c->sexp = newsexp;
}
}
/* Unquote STRING of LENGTH and store it into BUF. The surrounding
quotes are must already be removed from STRING. We assume that the
quoted string is syntacillay correct. */
static size_t
unquote_string (const unsigned char *string, size_t length, unsigned char *buf)
{
int esc = 0;
const unsigned char *s = string;
unsigned char *d = buf;
size_t n = length;
for (; n; n--, s++)
{
if (esc)
{
switch (*s)
{
case 'b': *d++ = '\b'; break;
case 't': *d++ = '\t'; break;
case 'v': *d++ = '\v'; break;
case 'n': *d++ = '\n'; break;
case 'f': *d++ = '\f'; break;
case 'r': *d++ = '\r'; break;
case '"': *d++ = '\"'; break;
case '\'': *d++ = '\''; break;
case '\\': *d++ = '\\'; break;
case '\r': /* ignore CR[,LF] */
if (n>1 && s[1] == '\n')
{
s++; n--;
}
esc = 0;
break;
case '\n': /* ignore LF[,CR] */
if (n>1 && s[1] == '\r')
{
s++; n--;
}
break;
case 'x': /* hex value */
if (n>2 && hexdigitp (s+1) && hexdigitp (s+2))
{
s++; n--;
*d++ = xtoi_2 (s);
s++; n--;
}
break;
default:
if (n>2 && octdigitp (s) && octdigitp (s+1) && octdigitp (s+2))
{
*d++ = (atoi_1 (s)*64) + (atoi_1 (s+1)*8) + atoi_1 (s+2);
s += 2;
n -= 2;
}
break;
}
esc = 0;
}
else if( *s == '\\' )
esc = 1;
else
*d++ = *s;
}
return d - buf;
}
/****************
* Scan the provided buffer and return the S expression in our internal
* format. Returns a newly allocated expression. If erroff is not NULL and
* a parsing error has occured, the offset into buffer will be returned.
* If ARGFLAG is true, the function supports some printf like
* expressions.
* These are:
* %m - MPI
* %s - string (no autoswitch to secure allocation)
* %d - integer stored as string (no autoswitch to secure allocation)
* %b - memory buffer; this takes _two_ arguments: an integer with the
* length of the buffer and a pointer to the buffer.
* all other format elements are currently not defined and return an error.
* this includes the "%%" sequence becauce the percent sign is not an
* allowed character.
* FIXME: We should find a way to store the secure-MPIs not in the string
* but as reference to somewhere - this can help us to save huge amounts
* of secure memory. The problem is, that if only one element is secure, all
- * other elements are automagicaly copied to secure meory too, so the most
+ * other elements are automagicaly copied to secure memory too, so the most
* common operation gcry_sexp_cdr_mpi() will always return a secure MPI
* regardless whether it is needed or not.
*/
static gcry_error_t
sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length, int argflag,
va_list arg_ptr, void **arg_list)
{
gcry_err_code_t err = GPG_ERR_NO_ERROR;
- static const char tokenchars[] = "\
-abcdefghijklmnopqrstuvwxyz\
-ABCDEFGHIJKLMNOPQRSTUVWXYZ\
-0123456789-./_:*+=";
+ static const char tokenchars[] =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789-./_:*+=";
const char *p;
size_t n;
const char *digptr = NULL;
const char *quoted = NULL;
const char *tokenp = NULL;
const char *hexfmt = NULL;
const char *base64 = NULL;
const char *disphint = NULL;
const char *percent = NULL;
int hexcount = 0;
int quoted_esc = 0;
int datalen = 0;
size_t dummy_erroff;
struct make_space_ctx c;
int arg_counter = 0;
int level = 0;
/* FIXME: invent better error codes (?). */
if (! erroff)
erroff = &dummy_erroff;
/* Depending on wether ARG_LIST is non-zero or not, this macro gives
us the next argument, either from the variable argument list as
specified by ARG_PTR or from the argument array ARG_LIST. */
#define ARG_NEXT(storage, type) \
do \
{ \
if (! arg_list) \
storage = va_arg (arg_ptr, type); \
else \
storage = *((type *) (arg_list[arg_counter++])); \
} \
while (0)
#define MAKE_SPACE(n) do { make_space ( &c, (n) ); } while (0)
#define STORE_LEN(p,n) do { \
DATALEN ashort = (n); \
memcpy ( (p), &ashort, sizeof(ashort) ); \
(p) += sizeof (ashort); \
} while (0)
/* We assume that the internal representation takes less memory
* than the provided one. However, we add space for one extra datalen
* so that the code which does the ST_CLOSE can use MAKE_SPACE */
c.allocated = length + sizeof(DATALEN);
- c.sexp = gcry_xmalloc (sizeof *c.sexp + c.allocated - 1);
+ if (buffer && length && gcry_is_secure (buffer))
+ c.sexp = gcry_xmalloc_secure (sizeof *c.sexp + c.allocated - 1);
+ else
+ c.sexp = gcry_xmalloc (sizeof *c.sexp + c.allocated - 1);
c.pos = c.sexp->d;
for (p = buffer, n = length; n; p++, n--)
{
if (tokenp && (! hexfmt))
{
if (strchr (tokenchars, *p))
continue;
else
{
datalen = p - tokenp;
MAKE_SPACE (datalen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, datalen);
memcpy (c.pos, tokenp, datalen);
c.pos += datalen;
tokenp = NULL;
}
}
if (quoted)
{
if (quoted_esc)
{
switch (*p)
{
case 'b': case 't': case 'v': case 'n': case 'f':
case 'r': case '"': case '\'': case '\\':
quoted_esc = 0;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
if (! ((n > 2)
&& (p[1] >= '0') && (p[1] <= '7')
&& (p[2] >= '0') && (p[2] <= '7')))
{
*erroff = p - buffer;
/* Invalid octal value. */
err = GPG_ERR_SEXP_BAD_QUOTATION;
//return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
}
p += 2;
n -= 2;
quoted_esc = 0;
break;
case 'x':
if (! ((n > 2) && isxdigit(p[1]) && isxdigit(p[2])))
{
*erroff = p - buffer;
/* Invalid hex value. */
err = GPG_ERR_SEXP_BAD_QUOTATION;
//return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
}
p += 2;
n -= 2;
quoted_esc = 0;
break;
case '\r':
/* ignore CR[,LF] */
if (n && (p[1] == '\n'))
{
p++;
n--;
}
quoted_esc = 0;
break;
case '\n':
/* ignore LF[,CR] */
if (n && (p[1] == '\r'))
{
p++;
n--;
}
quoted_esc = 0;
break;
default:
*erroff = p - buffer;
/* Invalid quoted string escape. */
err = GPG_ERR_SEXP_BAD_QUOTATION;
}
}
else if (*p == '\\')
quoted_esc = 1;
else if (*p == '\"')
{
- /* keep it easy - we know that the unquoted string will
- never be larger */
+ /* Keep it easy - we know that the unquoted string will
+ never be larger. */
char *save;
size_t len;
quoted++; /* Skip leading quote. */
MAKE_SPACE (p - quoted);
*c.pos++ = ST_DATA;
save = c.pos;
STORE_LEN (c.pos, 0); /* Will be fixed up later. */
len = unquote_string (quoted, p - quoted, c.pos);
c.pos += len;
STORE_LEN (save, len);
quoted = NULL;
}
}
else if (hexfmt)
{
if (isxdigit (*p))
hexcount++;
else if (*p == '#')
{
if ((hexcount & 1))
{
*erroff = p - buffer;
err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
}
datalen = hexcount / 2;
MAKE_SPACE (datalen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, datalen);
for (hexfmt++; hexfmt < p; hexfmt++)
{
if (isspace (*hexfmt))
continue;
*c.pos++ = hextobyte (hexfmt);
hexfmt++;
}
hexfmt = NULL;
}
else if (! isspace (*p))
{
*erroff = p - buffer;
err = GPG_ERR_SEXP_BAD_HEX_CHAR;
}
}
else if (base64)
{
if (*p == '|')
base64 = NULL;
}
else if (digptr)
{
if (isdigit (*p))
;
else if (*p == ':')
{
datalen = atoi (digptr); /* FIXME: check for overflow. */
digptr = NULL;
if (datalen > n - 1)
{
*erroff = p - buffer;
/* Buffer too short. */
err = GPG_ERR_SEXP_STRING_TOO_LONG;
}
/* Make a new list entry. */
MAKE_SPACE (datalen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, datalen);
memcpy (c.pos, p + 1, datalen);
c.pos += datalen;
n -= datalen;
p += datalen;
}
else if (*p == '\"')
{
digptr = NULL; /* We ignore the optional length. */
quoted = p;
quoted_esc = 0;
}
else if (*p == '#')
{
digptr = NULL; /* We ignore the optional length. */
hexfmt = p;
hexcount = 0;
}
else if (*p == '|')
{
digptr = NULL; /* We ignore the optional length. */
base64 = p;
}
else
{
*erroff = p - buffer;
err = GPG_ERR_SEXP_INV_LEN_SPEC;
}
}
else if (percent)
{
if (*p == 'm')
{
/* Insert an MPI. */
gcry_mpi_t m;
size_t nm = 0;
ARG_NEXT (m, gcry_mpi_t);
if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m))
BUG ();
MAKE_SPACE (nm);
if ((! gcry_is_secure (c.sexp->d))
&& gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
{
/* We have to switch to secure allocation. */
gcry_sexp_t newsexp;
byte *newhead;
newsexp = gcry_xmalloc_secure (sizeof *newsexp
+ c.allocated - 1);
newhead = newsexp->d;
memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
c.pos = newhead + (c.pos - c.sexp->d);
gcry_free (c.sexp);
c.sexp = newsexp;
}
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, nm);
if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m))
BUG ();
c.pos += nm;
}
else if (*p == 's')
{
/* Insert an string. */
const char *astr;
size_t alen;
ARG_NEXT (astr, const char *);
alen = strlen (astr);
MAKE_SPACE (alen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, alen);
memcpy (c.pos, astr, alen);
c.pos += alen;
}
else if (*p == 'b')
{
/* Insert a memory buffer. */
const char *astr;
int alen;
ARG_NEXT (alen, int);
ARG_NEXT (astr, const char *);
MAKE_SPACE (alen);
+ if (alen
+ && !gcry_is_secure (c.sexp->d)
+ && gcry_is_secure (astr))
+ {
+ /* We have to switch to secure allocation. */
+ gcry_sexp_t newsexp;
+ byte *newhead;
+
+ newsexp = gcry_xmalloc_secure (sizeof *newsexp
+ + c.allocated - 1);
+ newhead = newsexp->d;
+ memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
+ c.pos = newhead + (c.pos - c.sexp->d);
+ gcry_free (c.sexp);
+ c.sexp = newsexp;
+ }
+
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, alen);
memcpy (c.pos, astr, alen);
c.pos += alen;
}
else if (*p == 'd')
{
/* Insert an integer as string. */
int aint;
size_t alen;
char buf[20];
ARG_NEXT (aint, int);
sprintf (buf, "%d", aint);
alen = strlen (buf);
MAKE_SPACE (alen);
*c.pos++ = ST_DATA;
STORE_LEN (c.pos, alen);
memcpy (c.pos, buf, alen);
c.pos += alen;
}
else
{
*erroff = p - buffer;
/* Invalid format specifier. */
err = GPG_ERR_SEXP_INV_LEN_SPEC;
}
percent = NULL;
}
else if (*p == '(')
{
if (disphint)
{
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_UNMATCHED_DH;
}
MAKE_SPACE (0);
*c.pos++ = ST_OPEN;
level++;
}
else if (*p == ')')
{
/* Walk up. */
if (disphint)
{
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_UNMATCHED_DH;
}
MAKE_SPACE (0);
*c.pos++ = ST_CLOSE;
level--;
}
else if (*p == '\"')
{
quoted = p;
quoted_esc = 0;
}
else if (*p == '#')
{
hexfmt = p;
hexcount = 0;
}
else if (*p == '|')
base64 = p;
else if (*p == '[')
{
if (disphint)
{
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_NESTED_DH;
}
disphint = p;
}
else if (*p == ']')
{
if (! disphint)
{
*erroff = p - buffer;
/* Open display hint. */
err = GPG_ERR_SEXP_UNMATCHED_DH;
}
disphint = NULL;
}
else if (isdigit (*p))
{
if (*p == '0')
{
/* A length may not begin with zero. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_ZERO_PREFIX;
}
digptr = p;
}
else if (strchr (tokenchars, *p))
tokenp = p;
else if (isspace (*p))
;
else if (*p == '{')
{
/* fixme: handle rescanning: we can do this by saving our
current state and start over at p+1 -- Hmmm. At this
point here we are in a well defined state, so we don't
need to save it. Great. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
}
else if (strchr ("&\\", *p))
{
/* Reserved punctuation. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
}
else if (argflag && (*p == '%'))
percent = p;
else
{
/* Bad or unavailable. */
*erroff = p - buffer;
err = GPG_ERR_SEXP_BAD_CHARACTER;
}
}
MAKE_SPACE (0);
*c.pos++ = ST_STOP;
if (level)
err = GPG_ERR_SEXP_UNMATCHED_PAREN;
if (err)
{
/* Error -> deallocate. */
if (c.sexp)
- gcry_free (c.sexp);
+ {
+ /* Extra paranoid wipe on error. */
+ if (gcry_is_secure (c.sexp))
+ wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
+ gcry_free (c.sexp);
+ }
/* This might be expected by existing code... */
*retsexp = NULL;
}
else
*retsexp = normalize (c.sexp);
return gcry_error (err);
#undef MAKE_SPACE
#undef STORE_LEN
}
gcry_error_t
gcry_sexp_build (gcry_sexp_t *retsexp, size_t *erroff, const char *format, ...)
{
gcry_error_t rc;
va_list arg_ptr;
va_start (arg_ptr, format);
rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
arg_ptr, NULL);
va_end (arg_ptr);
return rc;
}
/* Like gcry_sexp_build, but uses an array instead of variable
function arguments. */
gcry_error_t
gcry_sexp_build_array (gcry_sexp_t *retsexp, size_t *erroff,
const char *format, void **arg_list)
{
/* We don't need the va_list because it is controlled by the
following flag, however we have to pass it but can't initialize
it as there is no portable way to do so. volatile is needed to
suppress the compiler warning */
volatile va_list dummy_arg_ptr;
gcry_error_t rc;
rc = sexp_sscan (retsexp, erroff, format, strlen(format), 1,
dummy_arg_ptr, arg_list);
return rc;
}
gcry_error_t
gcry_sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
const char *buffer, size_t length)
{
/* We don't need the va_list because it is controlled by the
following flag, however we have to pass it but can't initialize
it as there is no portable way to do so. volatile is needed to
suppress the compiler warning */
volatile va_list dummy_arg_ptr;
return sexp_sscan (retsexp, erroff, buffer, length, 0,
dummy_arg_ptr, NULL);
}
/* Figure out a suitable encoding for BUFFER of LENGTH.
Returns: 0 = Binary
1 = String possible
2 = Token possible
*/
static int
suitable_encoding (const unsigned char *buffer, size_t length)
{
const unsigned char *s;
int maybe_token = 1;
if (!length)
return 1;
for (s=buffer; length; s++, length--)
{
if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
&& !strchr ("\b\t\v\n\f\r\"\'\\", *s))
return 0; /*binary*/
if ( maybe_token
&& !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s))
maybe_token = 0;
}
s = buffer;
if ( maybe_token && !digitp (s) )
return 2;
return 1;
}
static int
convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
{
int i;
if (dest)
{
*dest++ = '#';
for (i=0; i < len; i++, dest += 2 )
sprintf (dest, "%02X", src[i]);
*dest++ = '#';
}
return len*2+2;
}
static int
convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
{
if (dest)
{
unsigned char *p = dest;
*p++ = '\"';
for (; len; len--, s++ )
{
switch (*s)
{
case '\b': *p++ = '\\'; *p++ = 'b'; break;
case '\t': *p++ = '\\'; *p++ = 't'; break;
case '\v': *p++ = '\\'; *p++ = 'v'; break;
case '\n': *p++ = '\\'; *p++ = 'n'; break;
case '\f': *p++ = '\\'; *p++ = 'f'; break;
case '\r': *p++ = '\\'; *p++ = 'r'; break;
case '\"': *p++ = '\\'; *p++ = '\"'; break;
case '\'': *p++ = '\\'; *p++ = '\''; break;
case '\\': *p++ = '\\'; *p++ = '\\'; break;
default:
if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
{
sprintf (p, "\\x%02x", *s);
p += 4;
}
else
*p++ = *s;
}
}
*p++ = '\"';
return p - dest;
}
else
{
int count = 2;
for (; len; len--, s++ )
{
switch (*s)
{
case '\b':
case '\t':
case '\v':
case '\n':
case '\f':
case '\r':
case '\"':
case '\'':
case '\\': count += 2; break;
default:
if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
count += 4;
else
count++;
}
}
return count;
}
}
static int
convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
{
if (dest)
memcpy (dest, src, len);
return len;
}
/****************
* Print SEXP to buffer using the MODE. Returns the length of the
* SEXP in buffer or 0 if the buffer is too short (We have at least an
* empty list consisting of 2 bytes). If a buffer of NULL is provided,
* the required length is returned.
*/
size_t
gcry_sexp_sprint( const gcry_sexp_t list, int mode,
char *buffer, size_t maxlength )
{
static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
const byte *s;
char *d;
DATALEN n;
char numbuf[20];
size_t len = 0;
int i, indent = 0;
s = list? list->d : empty;
d = buffer;
while ( *s != ST_STOP )
{
switch ( *s )
{
case ST_OPEN:
s++;
if ( mode != GCRYSEXP_FMT_CANON )
{
if (indent)
len++;
len += indent;
}
len++;
if ( buffer )
{
if ( len >= maxlength )
return 0;
if ( mode != GCRYSEXP_FMT_CANON )
{
if (indent)
*d++ = '\n';
for (i=0; i < indent; i++)
*d++ = ' ';
}
*d++ = '(';
}
indent++;
break;
case ST_CLOSE:
s++;
len++;
if ( buffer )
{
if ( len >= maxlength )
return 0;
*d++ = ')';
}
indent--;
if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
{
len++;
len += indent;
if (buffer)
{
if (len >= maxlength)
return 0;
*d++ = '\n';
for (i=0; i < indent; i++)
*d++ = ' ';
}
}
break;
case ST_DATA:
s++;
memcpy ( &n, s, sizeof n ); s += sizeof n;
if (mode == GCRYSEXP_FMT_ADVANCED)
{
int type;
size_t nn;
switch ( (type=suitable_encoding (s, n)))
{
case 1: nn = convert_to_string (s, n, NULL); break;
case 2: nn = convert_to_token (s, n, NULL); break;
default: nn = convert_to_hex (s, n, NULL); break;
}
len += nn;
if (buffer)
{
if (len >= maxlength)
return 0;
switch (type)
{
case 1: convert_to_string (s, n, d); break;
case 2: convert_to_token (s, n, d); break;
default: convert_to_hex (s, n, d); break;
}
d += nn;
}
if (s[n] != ST_CLOSE)
{
len++;
if (buffer)
{
if (len >= maxlength)
return 0;
*d++ = ' ';
}
}
}
else
{
sprintf (numbuf, "%u:", (unsigned int)n );
len += strlen (numbuf) + n;
if ( buffer )
{
if ( len >= maxlength )
return 0;
d = stpcpy ( d, numbuf );
memcpy ( d, s, n ); d += n;
}
}
s += n;
break;
default:
BUG ();
}
}
if ( mode != GCRYSEXP_FMT_CANON )
{
len++;
if (buffer)
{
if ( len >= maxlength )
return 0;
*d++ = '\n';
}
}
if (buffer)
{
if ( len >= maxlength )
return 0;
*d++ = 0; /* for convenience we make a C string */
}
else
len++; /* we need one byte more for this */
return len;
}
/* Scan a cannocial encoded buffer with implicit length values and
return the actual length this S-expression uses. For a valid S-Exp
it should never return 0. If LENGTH is not zero, the maximum
length to scan is given - this can be used for syntax checks of
data passed from outside. errorcode and erroff may both be passed as
NULL. */
size_t
gcry_sexp_canon_len (const unsigned char *buffer, size_t length,
size_t *erroff, gcry_error_t *errcode)
{
const unsigned char *p;
const char *disphint=NULL;
unsigned int datalen = 0;
size_t dummy_erroff;
gcry_error_t dummy_errcode;
size_t count = 0;
int level = 0;
if (!erroff)
erroff = &dummy_erroff;
if (!errcode)
errcode = &dummy_errcode;
*errcode = gcry_error (GPG_ERR_NO_ERROR);
*erroff = 0;
if (!buffer)
return 0;
if (*buffer != '(')
{
*errcode = gcry_error (GPG_ERR_SEXP_NOT_CANONICAL);
return 0;
}
for (p=buffer; ; p++, count++ )
{
if (length && count >= length)
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
return 0;
}
if (datalen)
{
if (*p == ':')
{
if (length && (count+datalen) >= length)
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_STRING_TOO_LONG);
return 0;
}
count += datalen;
p += datalen;
datalen = 0;
}
else if (digitp(p))
datalen = datalen*10 + atoi_1(p);
else
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_INV_LEN_SPEC);
return 0;
}
}
else if (*p == '(')
{
if (disphint)
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
return 0;
}
level++;
}
else if (*p == ')')
{ /* walk up */
if (!level)
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_PAREN);
return 0;
}
if (disphint)
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
return 0;
}
if (!--level)
return ++count; /* ready */
}
else if (*p == '[')
{
if (disphint)
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_NESTED_DH);
return 0;
}
disphint = p;
}
else if (*p == ']')
{
if( !disphint )
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_UNMATCHED_DH);
return 0;
}
disphint = NULL;
}
else if (digitp (p) )
{
if (*p == '0')
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_ZERO_PREFIX);
return 0;
}
datalen = atoi_1 (p);
}
else if (*p == '&' || *p == '\\')
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_UNEXPECTED_PUNC);
return 0;
}
else
{
*erroff = count;
*errcode = gcry_error (GPG_ERR_SEXP_BAD_CHARACTER);
return 0;
}
}
}
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 9bfa32f7..8d1656b5 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,293 +1,297 @@
+2004-02-03 Werner Koch <wk@gnupg.org>
+
+ * tsexp.c (basic): New pass to check secure memory switching.
+
2004-01-12 Moritz Schulte <mo@g10code.com>
* ac.c (check_one): Adjust to new ac API.
2003-11-22 Werner Koch <wk@gnupg.org>
* pubkey.c (check_keys_crypt): Fixed my last patch.
2003-11-11 Werner Koch <wk@gnupg.org>
* tsexp.c (basic): Add pass structure and a test for the %b
format.
2003-11-04 Werner Koch <wk@gnupg.org>
* Makefile.am (noinst_PROGRAMS): Use this so that test programs
get always build.
* keygen.c (check_nonce): New.
(main): Add a basic check for the nocen function.
2003-10-31 Werner Koch <wk@gnupg.org>
* basic.c (check_aes128_cbc_cts_cipher): Make it a prototype
* ac.c (check_run): Comment unused variable.
2003-10-10 Werner Koch <wk@gnupg.org>
* prime.c (check_primes): Generate a generator and avoid printing
unless in verbose mode.
2003-10-07 Werner Koch <wk@gnupg.org>
* tsexp.c (check_sscan): New.
2003-09-04 Werner Koch <wk@gnupg.org>
* pubkey.c (check_keys_crypt): Fix for compatibility mode.
2003-09-02 Moritz Schulte <mo@g10code.com>
* Makefile.am (TESTS): Added: prime.
* prime.c: New file.
2003-08-27 Moritz Schulte <mo@g10code.com>
* basic.c (check_ciphers): Added: Serpent.
Write braces around flags.
2003-08-04 Moritz Schulte <moritz@g10code.com>
* benchmark.c (do_powm): Adjust for new gcry_mpi_scan interface.
2003-07-23 Moritz Schulte <moritz@g10code.com>
* ac.c (key_copy): New function...
(check_one): ... use it.
2003-07-22 Moritz Schulte <moritz@g10code.com>
* basic.c (check_ciphers): Use gcry_cipher_map_name.
2003-07-18 Moritz Schulte <moritz@g10code.com>
* ac.c (check_run): Renamed to ...
(check_one): ... this, changed calling interface.
(check_run): New function.
* register.c: Adjust gcry_cipher_spec_t structure.
2003-07-14 Moritz Schulte <moritz@g10code.com>
* register.c: Adjust cipher specification structure.
* benchmark.c: New file.
* testapi.c: New file.
* Makefile.am (EXTRA_PROGRAMS): Set to: benchmark testapi.
(check_PROGRAMS): Set to: $(TESTS).
2003-07-12 Moritz Schulte <moritz@g10code.com>
* ac.c, basic.c, keygen.c, register.c, sexp.c, tsexp.c: Used
gcry_err* wrappers for libgpg symbols.
* basic.c (check_ciphers): Added: GCRY_CIPHER_TWOFISH128.
2003-07-08 Moritz Schulte <moritz@g10code.com>
* Makefile.am (LIBS): Remove: -lpthread.
* basic.c (check_one_cipher): Fix variable initialization. Thanks
to Simon Joseffson <jas@extundo.com>.
2003-07-07 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added: register.
2003-07-05 Moritz Schulte <moritz@g10code.com>
* register.c (check_run): Adjusted for new gcry_cipher_register API.
2003-07-02 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added: ac.
* ac.c: New file.
2003-06-18 Werner Koch <wk@gnupg.org>
* basic.c (check_cbc_mac_cipher): Adjusted for new API of get_blklen
and get_keylen.
(check_ctr_cipher): Ditto.
(check_one_cipher): Ditto.
(check_one_md): Adjusted for new API of gcry_md_copy.
2003-06-18 Moritz Schulte <moritz@g10code.com>
* register.c: Replace old type GcryModule with newer one:
gcry_module_t.
Adjusted for new API.
* Makefile.am (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@.
2003-06-15 Moritz Schulte <moritz@g10code.com>
* basic.c (get_keys_new): New function.
(do_check_one_pubkey): New function ...
(check_one_pubkey): ... use it.
(progress_handler): New function.
(main): Use gcry_set_progress_handler.
2003-06-14 Moritz Schulte <moritz@g10code.com>
* basic.c: Replaced calls to gcry_strerror with calls to
gpg_strerror.
(check_one_md): Adjust for new gcry_md_copy API.
* tsexp.c: Likewise.
* keygen.c: Likewise.
2003-06-12 Moritz Schulte <moritz@g10code.com>
* basic.c: Changed here and there, reorganized pubkey checks,
added DSA and ELG keys.
2003-06-09 Moritz Schulte <moritz@g10code.com>
* basic.c, keygen.c, pubkey.c, register.c, tsexp.c: Changed to use
new API.
2003-06-01 Moritz Schulte <moritz@g10code.com>
* tsexp.c (canon_len): Adjust for new gcry_sexp_canon_len API.
2003-05-26 Moritz Schulte <moritz@g10code.com>
* basic.c (verify_one_signature): Adjust for libgpg-error.
(check_pubkey_sign): Likewise.
(check_pubkey): Likewise.
* basic.c (check_pubkey_sign): Likewise.
* tsexp.c (canon_len): Likewise.
(back_and_forth_one): Likewise.
2003-04-27 Moritz Schulte <moritz@g10code.com>
* pubkey.c: Changed the sample private key to contain the
identifier `openpgp-rsa' instead of `rsa'.
* basic.c (check_digests): Enabled/fixed some tests for TIGER.
2003-04-17 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Removed `register' for now.
2003-04-17 Moritz Schulte <moritz@g10code.com>
* basic.c (check_digests): Include checks for SHA512 and SHA384.
2003-04-16 Moritz Schulte <moritz@g10code.com>
* basic.c (check_one_md): Also test md_copy.
2003-04-07 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added register.
* register.c: New file.
2003-03-30 Simon Josefsson <jas@extundo.com>
* basic.c (check_one_cipher): New. Test CTR.
(main): Call it.
(check_ciphers): Check CTR mode.
2003-03-26 Moritz Schulte <moritz@g10code.com>
* Makefile.am (TESTS): Added pubkey.
* pubkey.c: New file.
2003-03-22 Simon Josefsson <jas@extundo.com>
* basic.c (check_cbc_mac_cipher): New.
(main): Use it.
2003-03-19 Werner Koch <wk@gnupg.org>
* keygen.c (check_rsa_keys): Don't expect an exponent when asking
for e=0.
(check_generated_rsa_key): Just print exponent if EXPECTED_E is 0.
2003-03-02 Moritz Schulte <moritz@g10code.com>
* basic.c (check_one_cipher): Use gcry_cipher_reset() instead of
gcry_cipher_close(), gcry_cipher_open and gcry_cipher_setkey().
2003-01-23 Werner Koch <wk@gnupg.org>
* keygen.c: New.
2003-01-20 Simon Josefsson <jas@extundo.com>
* basic.c (check_digests): Add CRC.
(check_one_md): Print computed and expected values on error.
2003-01-20 Werner Koch <wk@gnupg.org>
* basic.c (check_one_md): Kludge to check a one million "a".
(check_digests): Add checks for SHA-256.
2003-01-20 Werner Koch <wk@gnupg.org>
* basic.c (check_pubkey): Check the keygrip for the sample key.
2003-01-15 Werner Koch <wk@gnupg.org>
* basic.c (verify_one_signature,check_pubkey_sign)
(check_pubkey): New.
(main): Check public key functions. Add a --debug option.
2002-11-23 Werner Koch <wk@gnupg.org>
* basic.c (check_digests): Add another test for MD4. By Simon
Josefsson.
2002-11-10 Simon Josefsson <jas@extundo.com>
* basic.c (check_aes128_cbc_cts_cipher): New function.
(check_one_cipher): Add flags parameter.
(check_ciphers): Support flags parameter.
(main): Check CTS.
2002-11-10 Werner Koch <wk@gnupg.org>
* basic.c (check_one_md): New. By Simon Josefsson.
(check_digests): New tests for MD4. By Simon.
2002-08-26 Werner Koch <wk@gnupg.org>
* basic.c (check_ciphers): Check simple DES.
2002-05-16 Werner Koch <wk@gnupg.org>
* tsexp.c (back_and_forth): Very minimal test of the new functions.
2002-05-14 Werner Koch <wk@gnupg.org>
Changed license of all files to the LGPL.
2002-05-02 Werner Koch <wk@gnupg.org>
* basic.c: Add option --verbose.
2002-01-11 Werner Koch <wk@gnupg.org>
* tsexp.c (canon_len): Fixed tests.
2001-12-18 Werner Koch <wk@gnupg.org>
* tsexp.c: New.
Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
This file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/tests/tsexp.c b/tests/tsexp.c
index 78aeb4e1..195b84ae 100644
--- a/tests/tsexp.c
+++ b/tests/tsexp.c
@@ -1,370 +1,395 @@
/* tsexp.c - S-expression regression tests
* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* Libgcrypt 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "../src/gcrypt.h"
#define PGMNAME "tsexp"
static int verbose;
static int error_count;
static void
info (const char *format, ...)
{
va_list arg_ptr;
if (verbose)
{
va_start( arg_ptr, format ) ;
vfprintf (stderr, format, arg_ptr );
va_end(arg_ptr);
}
}
static void
fail ( const char *format, ... )
{
va_list arg_ptr ;
fputs (PGMNAME ": ", stderr);
va_start( arg_ptr, format ) ;
vfprintf (stderr, format, arg_ptr );
va_end(arg_ptr);
error_count++;
}
/* fixme: we need better tests */
static void
basic (void)
{
int pass;
gcry_sexp_t sexp;
int idx;
+ char *secure_buffer;
+ size_t secure_buffer_len;
const char *string;
static struct {
const char *token;
const char *parm;
} values[] = {
{ "public-key", NULL },
{ "dsa", NULL },
{ "dsa", "p" },
{ "dsa", "y" },
{ "dsa", "q" },
{ "dsa", "g" },
{ NULL }
};
info ("doing some pretty pointless tests\n");
+ secure_buffer_len = 99;
+ secure_buffer = gcry_xmalloc_secure (secure_buffer_len);
+ memset (secure_buffer, 'G', secure_buffer_len);
+
for (pass=0;;pass++)
{
switch (pass)
{
case 0:
string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
"(q #61626364656667#) (g %m)))");
if ( gcry_sexp_build (&sexp, NULL, string,
gcry_mpi_set_ui (NULL, 42)) )
{
fail (" scanning `%s' failed\n", string);
return;
}
break;
case 1:
string = ("(public-key (dsa (p #41424344#) (y this_is_y) "
"(q %b) (g %m)))");
if ( gcry_sexp_build (&sexp, NULL, string,
15, "foo\0\x01\0x02789012345",
gcry_mpi_set_ui (NULL, 42)) )
{
fail (" scanning `%s' failed\n", string);
return;
}
break;
+
+ case 2:
+ string = ("(public-key (dsa (p #41424344#) (y silly_y_value) "
+ "(q %b) (g %m)))");
+
+ if ( gcry_sexp_build (&sexp, NULL, string,
+ secure_buffer_len, secure_buffer,
+ gcry_mpi_set_ui (NULL, 17)) )
+ {
+ fail (" scanning `%s' failed\n", string);
+ return;
+ }
+ if (!gcry_is_secure (sexp))
+ fail ("gcry_sexp_build did not switch to secure memory\n");
+ break;
default:
return; /* Ready. */
}
/* now find something */
for (idx=0; values[idx].token; idx++)
{
const char *token = values[idx].token;
const char *parm = values[idx].parm;
gcry_sexp_t s1, s2;
gcry_mpi_t a;
const char *p;
size_t n;
s1 = gcry_sexp_find_token (sexp, token, strlen(token) );
if (!s1)
{
fail ("didn't found `%s'\n", token);
continue;
}
p = gcry_sexp_nth_data (s1, 0, &n);
if (!p)
{
fail ("no car for `%s'\n", token);
continue;
}
info ("car=`%.*s'\n", (int)n, p);
s2 = gcry_sexp_cdr (s1);
if (!s2)
{
fail ("no cdr for `%s'\n", token);
continue;
}
p = gcry_sexp_nth_data (s2, 0, &n);
if (p)
{
fail ("data at car of `%s'\n", token);
continue;
}
if (parm)
{
s2 = gcry_sexp_find_token (s1, parm, strlen (parm));
if (!s2)
{
fail ("didn't found `%s'\n", parm);
continue;
}
p = gcry_sexp_nth_data (s2, 0, &n);
if (!p)
{
fail("no car for `%s'\n", parm );
continue;
}
info ("car=`%.*s'\n", (int)n, p);
p = gcry_sexp_nth_data (s2, 1, &n);
if (!p)
{
fail("no cdr for `%s'\n", parm );
continue;
}
info ("cdr=`%.*s'\n", (int)n, p);
a = gcry_sexp_nth_mpi (s2, 0, GCRYMPI_FMT_USG);
if (!a)
{
fail("failed to cdr the mpi for `%s'\n", parm);
continue;
}
}
}
gcry_sexp_release (sexp);
sexp = NULL;
}
+ gcry_free (secure_buffer);
}
static void
canon_len (void)
{
static struct {
size_t textlen; /* length of the buffer */
size_t expected;/* expected length or 0 on error and then ... */
size_t erroff; /* ... and at this offset */
gcry_error_t errcode; /* ... with this error code */
unsigned char *text;
} values[] = {
{ 14, 13, 0, GPG_ERR_NO_ERROR, "(9:abcdefghi) " },
{ 16, 15, 0, GPG_ERR_NO_ERROR, "(10:abcdefghix)" },
{ 14, 0,14, GPG_ERR_SEXP_STRING_TOO_LONG, "(10:abcdefghi)" },
{ 15, 0, 1, GPG_ERR_SEXP_ZERO_PREFIX, "(010:abcdefghi)" },
{ 2, 0, 0, GPG_ERR_SEXP_NOT_CANONICAL, "1:"},
{ 4, 0, 4, GPG_ERR_SEXP_STRING_TOO_LONG, "(1:)"},
{ 5, 5, 0, GPG_ERR_NO_ERROR, "(1:x)"},
{ 2, 2, 0, GPG_ERR_NO_ERROR, "()"},
{ 4, 2, 0, GPG_ERR_NO_ERROR, "()()"},
{ 4, 4, 0, GPG_ERR_NO_ERROR, "(())"},
{ 3, 0, 3, GPG_ERR_SEXP_STRING_TOO_LONG, "(()"},
{ 3, 0, 1, GPG_ERR_SEXP_BAD_CHARACTER, "( )"},
{ 9, 9, 0, GPG_ERR_NO_ERROR, "(3:abc())"},
{ 10, 0, 6, GPG_ERR_SEXP_BAD_CHARACTER, "(3:abc ())"},
/* fixme: we need much more cases */
{ 0 },
};
int idx;
gcry_error_t errcode;
size_t n, erroff;
info ("checking canoncial length test function\n");
for (idx=0; values[idx].text; idx++)
{
n = gcry_sexp_canon_len (values[idx].text, values[idx].textlen,
&erroff, &errcode);
if (n && n == values[idx].expected)
; /* success */
else if (!n && !values[idx].expected)
{ /* we expected an error - check that this is the right one */
if (values[idx].erroff != erroff)
fail ("canonical length test %d - wrong error offset %u\n",
idx, (unsigned int)erroff);
if (gcry_err_code (errcode) != values[idx].errcode)
fail ("canonical length test %d - wrong error code %d\n",
idx, errcode);
}
else
fail ("canonical length test %d failed - n=%u, off=%u, err=%d\n",
idx, (unsigned int)n, (unsigned int)erroff, errcode);
}
}
static void
back_and_forth_one (int testno, const char *buffer, size_t length)
{
gcry_error_t rc;
gcry_sexp_t se, se1;
size_t n, n1;
char *p1;
rc = gcry_sexp_new (&se, buffer, length, 1);
if (rc)
{
fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
return;
}
n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
if (!n1)
{
fail ("baf %d: get required length for canon failed\n", testno);
return;
}
p1 = gcry_xmalloc (n1);
n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */
{
fail ("baf %d: length mismatch for canon\n", testno);
return;
}
rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
if (rc)
{
fail ("baf %d: gcry_sexp_create failed: %s\n",
testno, gpg_strerror (rc));
return;
}
gcry_sexp_release (se1);
/* FIXME: we need a lot more tests */
gcry_sexp_release (se);
}
static void
back_and_forth (void)
{
static struct { char *buf; int len; } tests[] = {
{ "(7:g34:fgh1::2:())", 0 },
{ "(7:g34:fgh1::2:())", 18 },
{ NULL, 0 }
};
int idx;
for (idx=0; tests[idx].buf; idx++)
back_and_forth_one (idx, tests[idx].buf, tests[idx].len);
}
static void
check_sscan (void)
{
static struct {
const char *text;
gcry_error_t expected_err;
} values[] = {
/* Bug reported by Olivier L'Heureux 2003-10-07 */
{ "(7:sig-val(3:dsa"
"(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
"\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
"(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
"\xc5\xae\x23\xed\x32\x62\x30\x62\x3e)))",
GPG_ERR_NO_ERROR },
{ "(7:sig-val(3:dsa"
"(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
"\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
"(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
"\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))",
GPG_ERR_SEXP_UNMATCHED_PAREN },
{ "(7:sig-val(3:dsa"
"(1:r20:\x7e\xff\xd5\xba\xc9\xc9\xa4\x9b\xd4\x26\x8b\x64"
"\x06\x7a\xcf\x42\x7b\x6c\x51\xfb)"
"(1:s21:\x01\x8c\x6c\x6f\x37\x1a\x8d\xfd\x5a\xb3\x2a\x3d"
"\xc5\xae\x23\xed\x32\x62\x30\x62\x3e))))",
GPG_ERR_SEXP_UNMATCHED_PAREN },
{ NULL, 0 }
};
int idx;
gcry_error_t err;
gcry_sexp_t s;
info ("checking gcry_sexp_sscan\n");
for (idx=0; values[idx].text; idx++)
{
err = gcry_sexp_sscan (&s, NULL,
values[idx].text,
strlen (values[idx].text));
if (gpg_err_code (err) != values[idx].expected_err)
fail ("gcry_sexp_sscan test %d failed: %s\n", idx, gpg_strerror (err));
gcry_sexp_release (s);
}
}
int
main (int argc, char **argv)
{
if (argc > 1 && !strcmp (argv[1], "-v"))
verbose = 1;
+ gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
+ gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
+
basic ();
canon_len ();
back_and_forth ();
check_sscan ();
return error_count? 1:0;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Feb 1, 9:06 AM (1 d, 4 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
f1/de/767fc02efd4625b08983a14393b7

Event Timeline