diff --git a/deltachat-core.cbp b/deltachat-core.cbp index ad49f236..8bb5c742 100644 --- a/deltachat-core.cbp +++ b/deltachat-core.cbp @@ -54,7 +54,7 @@ - + @@ -372,58 +372,46 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - + diff --git a/libs/netpgp/netpgp-extra.h b/libs/netpgp/include/netpgp-extra.h similarity index 58% rename from libs/netpgp/netpgp-extra.h rename to libs/netpgp/include/netpgp-extra.h index 9f5bd73c..e981c89a 100644 --- a/libs/netpgp/netpgp-extra.h +++ b/libs/netpgp/include/netpgp-extra.h @@ -1,12 +1,13 @@ #ifndef __NETPGP_EXTRA_H__ #define __NETPGP_EXTRA_H__ +#include "netpgp/config-netpgp.h" #include -#include "packet-parse.h" -#include "errors-netpgp.h" -#include "netpgpdefs.h" -#include "crypto-netpgp.h" -#include "create-netpgp.h" +#include "netpgp/packet-parse.h" +#include "netpgp/errors.h" +#include "netpgp/defs.h" +#include "netpgp/crypto.h" +#include "netpgp/create.h" unsigned rsa_generate_keypair(pgp_key_t *keydata, const int numbits, const unsigned long e, const char *hashalg, const char *cipher); #endif // __NETPGP_EXTRA_H__ diff --git a/libs/netpgp/netpgp.h b/libs/netpgp/include/netpgp.h similarity index 97% rename from libs/netpgp/netpgp.h rename to libs/netpgp/include/netpgp.h index 0378697e..3a3c239e 100644 --- a/libs/netpgp/netpgp.h +++ b/libs/netpgp/include/netpgp.h @@ -57,9 +57,6 @@ typedef struct netpgp_t { int netpgp_init(netpgp_t *); int netpgp_end(netpgp_t *); -/* debugging, reflection and information */ -int netpgp_set_debug(const char *); -int netpgp_get_debug(const char *); const char *netpgp_get_info(const char *); int netpgp_list_packets(netpgp_t *, char *, int, char *); @@ -78,6 +75,8 @@ int netpgp_list_keys_json(netpgp_t *, char **, const int); int netpgp_find_key(netpgp_t *, char *); char *netpgp_get_key(netpgp_t *, const char *, const char *); char *netpgp_export_key(netpgp_t *, char *); +int netpgp_save_secring(netpgp_t *); +int netpgp_save_pubring(netpgp_t *); int netpgp_import_key(netpgp_t *, char *); int netpgp_generate_key(netpgp_t *, char *, int); diff --git a/libs/netpgp/config-netpgp.h b/libs/netpgp/include/netpgp/config-netpgp.h similarity index 100% rename from libs/netpgp/config-netpgp.h rename to libs/netpgp/include/netpgp/config-netpgp.h diff --git a/libs/netpgp/config-original-as-configured-for-ubuntu-16.04-64bit.h b/libs/netpgp/include/netpgp/config-original-as-configured-for-ubuntu-16.04-64bit.h similarity index 100% rename from libs/netpgp/config-original-as-configured-for-ubuntu-16.04-64bit.h rename to libs/netpgp/include/netpgp/config-original-as-configured-for-ubuntu-16.04-64bit.h diff --git a/libs/netpgp/include/netpgp/config-pep.h b/libs/netpgp/include/netpgp/config-pep.h new file mode 100644 index 00000000..f9cc1f72 --- /dev/null +++ b/libs/netpgp/include/netpgp/config-pep.h @@ -0,0 +1,160 @@ +// +// config.h +// netpgp + +#ifndef netpgp_config_h +#define netpgp_config_h + +/* Define to 1 if you have the header file. */ +#define HAVE_BZLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_COMMONCRYPTO_COMMONDIGEST_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DIRECT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DMALLOC_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if the system has the type 'long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MALLOC_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_AES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_BN_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CAMELLIA_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_CAST_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_DES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_DSA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_IDEA_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_MD5_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_RAND_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_SHA_H 1 + +/* Define to 1 if the system has the type `SHA256_CTX'. */ +#define HAVE_SHA256_CTX 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_CDEFS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the type 'unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ZLIB_H 1 + +/* Define to the sub-directory where libtool stores uninstalled libraries. */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "netpgp" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT " pEp NetPGP Team " + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "netpgp" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "netpgp beta0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "netpgp" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "beta0" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "beta0" + +#define OPENSSL_NO_IDEA 1 + +#endif diff --git a/libs/netpgp/create-netpgp.h b/libs/netpgp/include/netpgp/create.h similarity index 84% rename from libs/netpgp/create-netpgp.h rename to libs/netpgp/include/netpgp/create.h index 733422c1..3db88c23 100644 --- a/libs/netpgp/create-netpgp.h +++ b/libs/netpgp/include/netpgp/create.h @@ -52,13 +52,13 @@ #ifndef CREATE_H_ #define CREATE_H_ -#include "types-netpgp.h" -#include "packet-netpgp.h" -#include "crypto-netpgp.h" -#include "errors-netpgp.h" -#include "keyring-netpgp.h" -#include "writer-netpgp.h" -#include "memory-netpgp.h" +#include "types.h" +#include "packet.h" +#include "crypto.h" +#include "errors.h" +#include "keyring.h" +#include "writer.h" +#include "memory.h" /** * \ingroup Create @@ -78,28 +78,30 @@ void pgp_build_pubkey(pgp_memory_t *, const pgp_pubkey_t *, unsigned); unsigned pgp_calc_sesskey_checksum(pgp_pk_sesskey_t *, uint8_t *); unsigned pgp_write_struct_userid(pgp_output_t *, const uint8_t *); -unsigned pgp_write_ss_header(pgp_output_t *, unsigned, pgp_content_enum); +unsigned pgp_write_ss_header(pgp_output_t *, size_t, pgp_content_enum); +unsigned pgp_write_struct_seckey_ptag(const pgp_seckey_t *key, + const uint8_t *passphrase, + const size_t pplen, + pgp_output_t *output, + pgp_content_enum ptag); unsigned pgp_write_struct_seckey(const pgp_seckey_t *, const uint8_t *, const size_t, pgp_output_t *); +unsigned pgp_write_struct_pubkey(pgp_output_t *, const pgp_pubkey_t *); unsigned pgp_write_one_pass_sig(pgp_output_t *, const pgp_seckey_t *, const pgp_hash_alg_t, const pgp_sig_type_t); -unsigned pgp_write_litdata(pgp_output_t *, +unsigned pgp_write_litdata(pgp_output_t *, const uint8_t *, const int, const pgp_litdata_enum); -pgp_pk_sesskey_t *pgp_create_pk_sesskey(const pgp_key_t *, const char *); +pgp_pk_sesskey_t *pgp_create_pk_sesskey(pgp_key_t *, const char *, pgp_pk_sesskey_t *); unsigned pgp_write_pk_sesskey(pgp_output_t *, pgp_pk_sesskey_t *); -unsigned pgp_write_xfer_pubkey(pgp_output_t *, - const pgp_key_t *, const unsigned); -unsigned pgp_write_xfer_seckey(pgp_output_t *, - const pgp_key_t *, - const uint8_t *, - const size_t, - const unsigned); +unsigned pgp_write_xfer_key(pgp_output_t *output, + const pgp_key_t *key, + const unsigned armoured); void pgp_fast_create_userid(uint8_t **, uint8_t *); unsigned pgp_write_userid(const uint8_t *, pgp_output_t *); diff --git a/libs/netpgp/crypto-netpgp.h b/libs/netpgp/include/netpgp/crypto.h similarity index 88% rename from libs/netpgp/crypto-netpgp.h rename to libs/netpgp/include/netpgp/crypto.h index 8f0239bc..f1e874b3 100644 --- a/libs/netpgp/crypto-netpgp.h +++ b/libs/netpgp/include/netpgp/crypto.h @@ -53,9 +53,9 @@ #ifndef CRYPTO_H_ #define CRYPTO_H_ -#include "keyring-netpgp.h" -#include "packet-netpgp.h" -#include "memory-netpgp.h" +#include "keyring.h" +#include "packet.h" +#include "memory.h" #include "packet-parse.h" #include @@ -100,6 +100,17 @@ struct pgp_crypt_t { void *decrypt_key; }; +typedef struct pgp_validation_t { + unsigned validc; + pgp_sig_info_t *valid_sigs; + unsigned invalidc; + pgp_sig_info_t *invalid_sigs; + unsigned unknownc; + pgp_sig_info_t *unknown_sigs; + time_t birthtime; + time_t duration; +} pgp_validation_t; + void pgp_crypto_finish(void); void pgp_hash_md5(pgp_hash_t *); void pgp_hash_sha1(pgp_hash_t *); @@ -107,7 +118,7 @@ void pgp_hash_sha256(pgp_hash_t *); void pgp_hash_sha512(pgp_hash_t *); void pgp_hash_sha384(pgp_hash_t *); void pgp_hash_sha224(pgp_hash_t *); -void pgp_hash_any(pgp_hash_t *, pgp_hash_alg_t); +unsigned pgp_hash_any(pgp_hash_t *, pgp_hash_alg_t); pgp_hash_alg_t pgp_str_to_hash_alg(const char *); const char *pgp_text_from_hash(pgp_hash_t *); unsigned pgp_hash_size(pgp_hash_alg_t); @@ -190,8 +201,8 @@ unsigned pgp_decrypt_file(pgp_io_t *, pgp_memory_t * pgp_encrypt_buf(pgp_io_t *, const void *, const size_t, - const pgp_key_t *, - const unsigned, const char *); + const pgp_keyring_t *, + const unsigned, const char *, unsigned); pgp_memory_t * pgp_decrypt_buf(pgp_io_t *, const void *, @@ -204,18 +215,35 @@ pgp_decrypt_buf(pgp_io_t *, int, pgp_cbfunc_t *); +pgp_memory_t * +pgp_decrypt_and_validate_buf(pgp_io_t *io, + pgp_validation_t *result, + const void *input, + const size_t insize, + pgp_keyring_t *secring, + pgp_keyring_t *pubring, + const unsigned use_armour, + key_id_t **recipients_key_ids, + unsigned *recipients_count); + /* Keys */ pgp_key_t *pgp_rsa_new_selfsign_key(const int, const unsigned long, const uint8_t *, const char *, const char *); +unsigned pgp_rsa_generate_keypair(pgp_key_t *, + const int, + const unsigned long, + const char *, + const char *, + const uint8_t *, + const size_t); + int pgp_dsa_size(const pgp_dsa_pubkey_t *); -DSA_SIG *pgp_dsa_sign(uint8_t *, unsigned, +pgp_dsa_sig_t *pgp_dsa_sign(uint8_t *, unsigned, const pgp_dsa_seckey_t *, const pgp_dsa_pubkey_t *); -int openssl_read_pem_seckey(const char *, pgp_key_t *, const char *, int); - /** pgp_reader_t */ struct pgp_reader_t { pgp_reader_func_t *reader; /* reader func to get parse data */ @@ -228,6 +256,13 @@ struct pgp_reader_t { unsigned position; /* reader-specific offset */ pgp_reader_t *next; pgp_stream_t *parent;/* parent parse_info structure */ + + unsigned partial_read:1; + unsigned coalescing:1; + /* used for partial length coalescing */ + unsigned virtualc; + unsigned virtualoff; + uint8_t *virtualpkt; }; @@ -237,9 +272,10 @@ struct pgp_reader_t { struct pgp_cryptinfo_t { char *passphrase; pgp_keyring_t *secring; - const pgp_key_t *keydata; + pgp_key_t *keydata; pgp_cbfunc_t *getpassphrase; pgp_keyring_t *pubring; + DYNARRAY(key_id_t, recipients_key_ids); }; /** pgp_cbdata_t */ @@ -301,15 +337,10 @@ struct pgp_stream_t { pgp_cryptinfo_t cryptinfo; size_t hashc; pgp_hashtype_t *hashes; - unsigned reading_v3_secret:1; - unsigned reading_mpi_len:1; - unsigned exact_read:1; - unsigned partial_read:1; - unsigned coalescing:1; - /* used for partial length coalescing */ - unsigned virtualc; - unsigned virtualoff; - uint8_t *virtualpkt; + //unsigned reading_v3_secret:1; + //unsigned reading_mpi_len:1; + //unsigned exact_read:1; + }; #endif /* CRYPTO_H_ */ diff --git a/libs/netpgp/defs-netpgp.h b/libs/netpgp/include/netpgp/defs.h similarity index 98% rename from libs/netpgp/defs-netpgp.h rename to libs/netpgp/include/netpgp/defs.h index 2c62eb8d..760f1d30 100644 --- a/libs/netpgp/defs-netpgp.h +++ b/libs/netpgp/include/netpgp/defs.h @@ -1,4 +1,4 @@ -/* $NetBSD: defs.h,v 1.2 2009/12/06 17:43:05 agc Exp $ */ +/* $NetBSD$ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. diff --git a/libs/netpgp/errors-netpgp.h b/libs/netpgp/include/netpgp/errors.h similarity index 100% rename from libs/netpgp/errors-netpgp.h rename to libs/netpgp/include/netpgp/errors.h diff --git a/libs/netpgp/include/netpgp/keyring.h b/libs/netpgp/include/netpgp/keyring.h new file mode 100644 index 00000000..db6291b9 --- /dev/null +++ b/libs/netpgp/include/netpgp/keyring.h @@ -0,0 +1,206 @@ +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Alistair Crooks (agc@NetBSD.org) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) + * All rights reserved. + * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted + * their moral rights under the UK Copyright Design and Patents Act 1988 to + * be recorded as the authors of this copyright work. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \file + */ + +#ifndef KEYRING_H_ +#define KEYRING_H_ + +#include "packet.h" +#include "packet-parse.h" +#include "memory.h" + +enum { + MAX_ID_LENGTH = 128, + MAX_PASSPHRASE_LENGTH = 256 +}; + +typedef struct pgp_key_t pgp_key_t; + +/** \struct pgp_keyring_t + * A keyring + */ +typedef struct pgp_keyring_t { + DYNARRAY(pgp_key_t, key); + pgp_hash_alg_t hashtype; +} pgp_keyring_t; + +pgp_key_t *pgp_getkeybyid(pgp_io_t *, + const pgp_keyring_t *, + const uint8_t *, + unsigned *, + pgp_pubkey_t **, + pgp_seckey_t **, + unsigned checkrevoke, + unsigned checkexpiry); +unsigned pgp_deletekeybyid(pgp_io_t *, + pgp_keyring_t *, + const uint8_t *); +pgp_key_t *pgp_getkeybyfpr(pgp_io_t *, + const pgp_keyring_t *, + const uint8_t *fpr, + size_t length, + unsigned *from, + pgp_pubkey_t **, + unsigned checkrevoke, + unsigned checkexpiry); +unsigned pgp_deletekeybyfpr(pgp_io_t *, + pgp_keyring_t *, + const uint8_t *fpr, + size_t length); +const pgp_key_t *pgp_getkeybyname(pgp_io_t *, + const pgp_keyring_t *, + const char *); +const pgp_key_t *pgp_getnextkeybyname(pgp_io_t *, + const pgp_keyring_t *, + const char *, + unsigned *); +void pgp_key_free(pgp_key_t *); +void pgp_keydata_free(pgp_key_t *); +void pgp_keyring_free(pgp_keyring_t *); +void pgp_keyring_purge(pgp_keyring_t *); +void pgp_dump_keyring(const pgp_keyring_t *); +pgp_pubkey_t *pgp_key_get_pubkey(pgp_key_t *); +unsigned pgp_is_key_secret(pgp_key_t *); +pgp_seckey_t *pgp_get_seckey(pgp_key_t *); +pgp_seckey_t *pgp_get_writable_seckey(pgp_key_t *); +// pgp_seckey_t *pgp_decrypt_seckey(const pgp_key_t *, void *); + +unsigned +pgp_keyring_fileread(pgp_io_t *io, + pgp_keyring_t *pubring, + pgp_keyring_t *secring, + const unsigned armour, + const char *filename); + +unsigned +pgp_keyring_read_from_mem(pgp_io_t *io, + pgp_keyring_t *pubring, + pgp_keyring_t *secring, + const unsigned armour, + pgp_memory_t *mem); + +int pgp_keyring_list(pgp_io_t *, const pgp_keyring_t *, const int); + +void pgp_forget(void *, unsigned); + +// uint8_t *pgp_add_userid(pgp_key_t *, const uint8_t *); +unsigned pgp_update_userid( + pgp_key_t *key, + const uint8_t *userid, + const pgp_subpacket_t *sigpkt, + pgp_sig_info_t *siginfo); + +// pgp_subpacket_t *pgp_add_subpacket(pgp_key_t *, +// const pgp_subpacket_t *); +// pgp_subpacket_t *pgp_replace_subpacket(pgp_key_t *, +// const pgp_subpacket_t *, +// unsigned ); + +unsigned pgp_add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *userid, time_t duration); + +pgp_key_t *pgp_keydata_new(void); +void pgp_keydata_init(pgp_key_t *, const pgp_content_enum); + +char *pgp_export_key(pgp_io_t *, const pgp_key_t *, uint8_t *); + +int pgp_keyring_add(pgp_keyring_t *, const pgp_key_t *); +// int pgp_add_to_pubring(pgp_keyring_t *, const pgp_pubkey_t *, pgp_content_enum tag); +pgp_key_t *pgp_ensure_pubkey( + pgp_keyring_t *, + pgp_pubkey_t *, + uint8_t *); +pgp_key_t *pgp_ensure_seckey( + pgp_keyring_t *keyring, + pgp_seckey_t *seckey, + uint8_t *pubkeyid); +unsigned pgp_add_directsig( + pgp_key_t *key, + const pgp_subpacket_t *sigpkt, + pgp_sig_info_t *siginfo); +unsigned pgp_update_subkey( + pgp_key_t *key, + pgp_content_enum subkeytype, + pgp_keydata_key_t *subkey, + const pgp_subpacket_t *sigpkt, + pgp_sig_info_t *siginfo); +// int pgp_add_to_secring(pgp_keyring_t *, const pgp_seckey_t *); + +int pgp_append_keyring(pgp_keyring_t *, pgp_keyring_t *); + +pgp_subpacket_t * pgp_copy_packet(pgp_subpacket_t *, const pgp_subpacket_t *); +uint8_t * pgp_copy_userid(uint8_t **dst, const uint8_t *src); + +const int32_t pgp_key_get_uid0(pgp_key_t *keydata); +const uint8_t *pgp_key_get_primary_userid(pgp_key_t *key); + + +pgp_pubkey_t * pgp_key_get_sigkey(pgp_key_t *key); +pgp_seckey_t * pgp_key_get_certkey(pgp_key_t *key); +pgp_pubkey_t * pgp_key_get_enckey(pgp_key_t *key, const uint8_t **id); +pgp_seckey_t * pgp_key_get_deckey(pgp_key_t *key, const uint8_t **id); + +const int32_t +pgp_key_find_uid_cond( + const pgp_key_t *key, + unsigned(*uidcond) ( uint8_t *, void *), + void *uidcondarg, + unsigned(*sigcond) ( const pgp_sig_info_t *, void *), + void *sigcondarg, + time_t *youngest, + unsigned checkrevoke, + unsigned checkexpiry); + +const pgp_key_rating_t pgp_key_get_rating(pgp_key_t *key); + +unsigned +pgp_key_revoke(pgp_key_t *skey, pgp_key_t *pkey, uint8_t code, const char *reason); + +#endif /* KEYRING_H_ */ diff --git a/libs/netpgp/memory-netpgp.h b/libs/netpgp/include/netpgp/memory.h similarity index 99% rename from libs/netpgp/memory-netpgp.h rename to libs/netpgp/include/netpgp/memory.h index 9641b063..d8bd5763 100644 --- a/libs/netpgp/memory-netpgp.h +++ b/libs/netpgp/include/netpgp/memory.h @@ -54,7 +54,7 @@ #include -#include "packet-netpgp.h" +#include "packet.h" /** pgp_memory_t */ diff --git a/libs/netpgp/netpgpdefs.h b/libs/netpgp/include/netpgp/netpgpdefs.h similarity index 97% rename from libs/netpgp/netpgpdefs.h rename to libs/netpgp/include/netpgp/netpgpdefs.h index d2c3ee27..37b2bf7f 100644 --- a/libs/netpgp/netpgpdefs.h +++ b/libs/netpgp/include/netpgp/netpgpdefs.h @@ -65,8 +65,4 @@ void *pgp_new(size_t); } \ } while(/* CONSTCOND */0) -#ifndef MIN -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#endif - #endif /* !NETPGPDEFS_H_ */ diff --git a/libs/netpgp/netpgpdigest.h b/libs/netpgp/include/netpgp/netpgpdigest.h similarity index 97% rename from libs/netpgp/netpgpdigest.h rename to libs/netpgp/include/netpgp/netpgpdigest.h index 3b15a25b..be776c45 100644 --- a/libs/netpgp/netpgpdigest.h +++ b/libs/netpgp/include/netpgp/netpgpdigest.h @@ -50,6 +50,7 @@ /* SHA1 Hash Size */ #define PGP_SHA1_HASH_SIZE SHA_DIGEST_LENGTH #define PGP_SHA256_HASH_SIZE SHA256_DIGEST_LENGTH +#define PGP_SHA512_HASH_SIZE SHA512_DIGEST_LENGTH #define PGP_CHECKHASH_SIZE PGP_SHA1_HASH_SIZE #endif /* NETPGPDIGEST_H_ */ diff --git a/libs/netpgp/netpgpsdk.h b/libs/netpgp/include/netpgp/netpgpsdk.h similarity index 81% rename from libs/netpgp/netpgpsdk.h rename to libs/netpgp/include/netpgp/netpgpsdk.h index 12ba9684..4747b260 100644 --- a/libs/netpgp/netpgpsdk.h +++ b/libs/netpgp/include/netpgp/netpgpsdk.h @@ -29,34 +29,17 @@ #ifndef NETPGPSDK_H_ #define NETPGPSDK_H_ -#include "keyring-netpgp.h" -#include "crypto-netpgp.h" -#include "signature-netpgp.h" +#include "keyring.h" +#include "crypto.h" +#include "signature.h" #include "packet-show.h" #ifndef __printflike #define __printflike(n, m) __attribute__((format(printf,n,m))) #endif -typedef struct pgp_validation_t { - unsigned validc; - pgp_sig_info_t *valid_sigs; - unsigned invalidc; - pgp_sig_info_t *invalid_sigs; - unsigned unknownc; - pgp_sig_info_t *unknown_sigs; - time_t birthtime; - time_t duration; -} pgp_validation_t; - void pgp_validate_result_free(pgp_validation_t *); -unsigned -pgp_validate_key_sigs(pgp_validation_t *, - const pgp_key_t *, - const pgp_keyring_t *, - pgp_cb_ret_t cb(const pgp_packet_t *, pgp_cbdata_t *)); - unsigned pgp_validate_all_sigs(pgp_validation_t *, const pgp_keyring_t *, @@ -74,5 +57,4 @@ void netpgp_log(const char *, ...) __printflike(1, 2); int netpgp_strcasecmp(const char *, const char *); char *netpgp_strdup(const char *); - #endif diff --git a/libs/netpgp/include/netpgp/openssl11stub.h b/libs/netpgp/include/netpgp/openssl11stub.h new file mode 100644 index 00000000..5d759ff8 --- /dev/null +++ b/libs/netpgp/include/netpgp/openssl11stub.h @@ -0,0 +1,133 @@ + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((r->n == NULL && n == NULL) + || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) { + BN_free(r->n); + r->n = n; + } + if (e != NULL) { + BN_free(r->e); + r->e = e; + } + if (d != NULL) { + BN_free(r->d); + r->d = d; + } + + return 1; +} + +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +{ + /* If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->p == NULL && p == NULL) + || (r->q == NULL && q == NULL)) + return 0; + + if (p != NULL) { + BN_free(r->p); + r->p = p; + } + if (q != NULL) { + BN_free(r->q); + r->q = q; + } + + return 1; +} + +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *q = r->q; +} + +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p, q and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((d->p == NULL && p == NULL) + || (d->q == NULL && q == NULL) + || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) { + BN_free(d->p); + d->p = p; + } + if (q != NULL) { + BN_free(d->q); + d->q = q; + } + if (g != NULL) { + BN_free(d->g); + d->g = g; + } + + return 1; +} + +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in d is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) { + BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) { + BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} + diff --git a/libs/netpgp/packet-parse.h b/libs/netpgp/include/netpgp/packet-parse.h similarity index 98% rename from libs/netpgp/packet-parse.h rename to libs/netpgp/include/netpgp/packet-parse.h index ee4381b5..0406ff03 100644 --- a/libs/netpgp/packet-parse.h +++ b/libs/netpgp/include/netpgp/packet-parse.h @@ -54,8 +54,8 @@ #ifndef PACKET_PARSE_H_ #define PACKET_PARSE_H_ -#include "types-netpgp.h" -#include "packet-netpgp.h" +#include "types.h" +#include "packet.h" /** pgp_region_t */ typedef struct pgp_region_t { @@ -166,4 +166,7 @@ int pgp_decompress(pgp_region_t *, pgp_stream_t *, unsigned pgp_writez(pgp_output_t *, const uint8_t *, const unsigned); +void +copy_sig_info(pgp_sig_info_t *dst, const pgp_sig_info_t *src); + #endif /* PACKET_PARSE_H_ */ diff --git a/libs/netpgp/packet-show.h b/libs/netpgp/include/netpgp/packet-show.h similarity index 93% rename from libs/netpgp/packet-show.h rename to libs/netpgp/include/netpgp/packet-show.h index d567f56b..02172707 100644 --- a/libs/netpgp/packet-show.h +++ b/libs/netpgp/include/netpgp/packet-show.h @@ -53,7 +53,7 @@ #ifndef PACKET_SHOW_H_ #define PACKET_SHOW_H_ -#include "packet-netpgp.h" +#include "packet.h" /** pgp_list_t */ @@ -86,10 +86,8 @@ const char *pgp_show_ss_type(pgp_content_enum); const char *pgp_show_sig_type(pgp_sig_type_t); const char *pgp_show_pka(pgp_pubkey_alg_t); -pgp_text_t *pgp_showall_ss_zpref(const pgp_data_t *); const char *pgp_show_ss_zpref(uint8_t); -pgp_text_t *pgp_showall_ss_hashpref(const pgp_data_t *); const char *pgp_show_hash_alg(uint8_t); const char *pgp_show_symm_alg(uint8_t); @@ -100,10 +98,8 @@ const char *pgp_show_ss_rr_code(pgp_ss_rr_code_t); pgp_text_t *pgp_showall_ss_features(pgp_data_t); -pgp_text_t *pgp_showall_ss_key_flags(const pgp_data_t *); const char *pgp_show_ss_key_flag(uint8_t, pgp_bit_map_t *); -pgp_text_t *pgp_show_keyserv_prefs(const pgp_data_t *); const char *pgp_show_keyserv_pref(uint8_t, pgp_bit_map_t *); pgp_text_t *pgp_showall_notation(pgp_ss_notation_t); diff --git a/libs/netpgp/packet-netpgp.h b/libs/netpgp/include/netpgp/packet.h similarity index 93% rename from libs/netpgp/packet-netpgp.h rename to libs/netpgp/include/netpgp/packet.h index 1f38fbe9..d8d01719 100644 --- a/libs/netpgp/packet-netpgp.h +++ b/libs/netpgp/include/netpgp/packet.h @@ -54,16 +54,16 @@ #ifndef PACKET_H_ #define PACKET_H_ -#include "config-netpgp.h" - #include #ifdef HAVE_OPENSSL_BN_H #include #endif -#include "types-netpgp.h" -#include "errors-netpgp.h" +#include + +#include "types.h" +#include "errors.h" /* structure to keep track of printing state variables */ typedef struct pgp_printstate_t { @@ -620,6 +620,8 @@ typedef struct pgp_sig_info_t { pgp_sig_type_t type; /* signature type value */ time_t birthtime; /* creation time of the signature */ time_t duration; /* number of seconds it's valid for */ + time_t key_expiry; /* number of seconds key is valid for */ + uint8_t key_flags; uint8_t signer_id[PGP_KEY_ID_SIZE]; /* Eight-octet key ID * of signer */ pgp_pubkey_alg_t key_alg; /* public key algorithm number */ @@ -635,8 +637,21 @@ typedef struct pgp_sig_info_t { unsigned birthtime_set:1; unsigned signer_id_set:1; unsigned duration_set:1; + unsigned key_expiry_set:1; + unsigned key_flags_set:1; + unsigned primary_userid:1; } pgp_sig_info_t; +typedef enum { + PGP_KEYFLAG_CERT_KEYS = 0x01, + PGP_KEYFLAG_SIGN_DATA = 0x02, + PGP_KEYFLAG_ENC_COMM = 0x04, + PGP_KEYFLAG_ENC_STORAGE = 0x08, + PGP_KEYFLAG_SPLIT = 0x10, + PGP_KEYFLAG_AUTH = 0x20, + PGP_KEYFLAG_GROUP = 0x80 +} pgp_key_flags_t; + /** Struct used when parsing a signature */ typedef struct pgp_sig_t { pgp_sig_info_t info; /* The signature information */ @@ -789,9 +804,10 @@ typedef union { } pgp_pk_sesskey_params_t; /** pgp_pk_sesskey_t */ +typedef uint8_t key_id_t[PGP_KEY_ID_SIZE]; typedef struct { unsigned version; - uint8_t key_id[PGP_KEY_ID_SIZE]; + key_id_t key_id; pgp_pubkey_alg_t alg; pgp_pk_sesskey_params_t params; pgp_symm_alg_t symm_alg; @@ -886,6 +902,7 @@ int pgp_fingerprint(pgp_fingerprint_t *, const pgp_pubkey_t *, pgp_hash_alg_t); void pgp_finish(void); void pgp_pubkey_free(pgp_pubkey_t *); +int pgp_pubkey_dup(pgp_pubkey_t *,pgp_pubkey_t *); void pgp_userid_free(uint8_t **); void pgp_data_free(pgp_data_t *); void pgp_sig_free(pgp_sig_t *); @@ -896,10 +913,9 @@ void pgp_ss_sig_target_free(pgp_ss_sig_target_t *); void pgp_subpacket_free(pgp_subpacket_t *); void pgp_parser_content_free(pgp_packet_t *); void pgp_seckey_free(pgp_seckey_t *); +int pgp_seckey_dup(pgp_seckey_t *,pgp_seckey_t *); void pgp_pk_sesskey_free(pgp_pk_sesskey_t *); -int pgp_print_packet(pgp_printstate_t *, const pgp_packet_t *); - #define DYNARRAY(type, arr) \ unsigned arr##c; unsigned arr##vsize; type *arr##s @@ -921,6 +937,21 @@ int pgp_print_packet(pgp_printstate_t *, const pgp_packet_t *); } \ } while(/*CONSTCOND*/0) +#define FREE_ARRAY(str, arr) do { \ + if (str->arr##s) { \ + free(str->arr##s); \ + str->arr##s = NULL; \ + str->arr##vsize = 0; \ + str->arr##c = 0; \ + } \ +} while(/*CONSTCOND*/0) + +#define INIT_ARRAY(str, arr) do { \ + str->arr##s = NULL; \ + str->arr##vsize = 0; \ + str->arr##c = 0; \ +} while(/*CONSTCOND*/0) + /** pgp_keydata_key_t */ typedef union { @@ -928,47 +959,59 @@ typedef union { pgp_seckey_t seckey; } pgp_keydata_key_t; - -/* sigpacket_t */ -typedef struct { - uint8_t **userid; - pgp_subpacket_t *packet; -} sigpacket_t; - -/* user revocation info */ -typedef struct pgp_revoke_t { - uint32_t uid; /* index in uid array */ - uint8_t code; /* revocation code */ - char *reason; /* c'mon, spill the beans */ -} pgp_revoke_t; - -/** signature subpackets */ -typedef struct pgp_subsig_t { +/** userid signature subpackets */ +typedef struct pgp_uidsig_t { uint32_t uid; /* index in userid array in key */ - pgp_sig_t sig; /* trust signature */ + pgp_sig_info_t siginfo; uint8_t trustlevel; /* level of trust */ uint8_t trustamount; /* amount of trust */ -} pgp_subsig_t; + pgp_subpacket_t packet; +} pgp_uidsig_t; + +/** subkey signature subpackets */ +typedef struct pgp_subkeysig_t { + uint32_t subkey; /* index of subkey in array */ + pgp_sig_info_t siginfo; + pgp_subpacket_t packet; +} pgp_subkeysig_t; + +typedef struct pgp_subkey_t { + pgp_keydata_key_t key; /* pubkey/seckey data */ + uint8_t id[PGP_KEY_ID_SIZE]; +} pgp_subkey_t; + +typedef struct pgp_directsig_t { + pgp_sig_info_t siginfo; + pgp_subpacket_t packet; +} pgp_directsig_t; /* describes a user's key */ struct pgp_key_t { - DYNARRAY(uint8_t *, uid); /* array of user ids */ - DYNARRAY(pgp_subpacket_t, packet); /* array of raw subpackets */ - DYNARRAY(pgp_subsig_t, subsig); /* array of signature subkeys */ - DYNARRAY(pgp_revoke_t, revoke); /* array of signature revocations */ pgp_content_enum type; /* type of key */ pgp_keydata_key_t key; /* pubkey/seckey data */ - pgp_pubkey_t sigkey; /* signature key */ - uint8_t sigid[PGP_KEY_ID_SIZE]; - pgp_fingerprint_t sigfingerprint; /* pgp signature fingerprint */ - pgp_pubkey_t enckey; /* encryption key */ - uint8_t encid[PGP_KEY_ID_SIZE]; - pgp_fingerprint_t encfingerprint; /* pgp encryption id fingerprint */ - uint32_t uid0; /* primary uid index in uids array */ - uint8_t revoked; /* key has been revoked */ - pgp_revoke_t revocation; /* revocation reason */ + + DYNARRAY(pgp_directsig_t, directsig); /* direct signatures */ + + DYNARRAY(uint8_t *, uid); /* array of user ids */ + DYNARRAY(pgp_uidsig_t, uidsig); /* array of signature for user ids */ + + /* TODO user attributes */ + + DYNARRAY(pgp_subkey_t, subkey); /* array of subkeys */ + DYNARRAY(pgp_subkeysig_t, subkeysig); /* array of sigs for subkeys */ + + uint8_t pubkeyid[PGP_KEY_ID_SIZE]; + pgp_fingerprint_t pubkeyfpr; /* pgp signature fingerprint */ }; -#define MDC_PKT_TAG 0xd3 +typedef enum { + PGP_VALID, + PGP_WEAK, + PGP_TOOSHORT, + PGP_INVALID, + PGP_EXPIRED, + PGP_REVOKED +} pgp_key_rating_t; +#define MDC_PKT_TAG 0xd3 #endif /* PACKET_H_ */ diff --git a/libs/netpgp/readerwriter-netpgp.h b/libs/netpgp/include/netpgp/readerwriter.h similarity index 97% rename from libs/netpgp/readerwriter-netpgp.h rename to libs/netpgp/include/netpgp/readerwriter.h index 303cf23a..51029f5f 100644 --- a/libs/netpgp/readerwriter-netpgp.h +++ b/libs/netpgp/include/netpgp/readerwriter.h @@ -50,9 +50,9 @@ #ifndef READERWRITER_H_ #define READERWRITER_H_ -#include "create-netpgp.h" +#include "create.h" -#include "memory-netpgp.h" +#include "memory.h" /* if this is defined, we'll use mmap in preference to file ops */ #define USE_MMAP_FOR_FILES 1 @@ -75,7 +75,7 @@ unsigned pgp_write_se_ip_pktset(pgp_output_t *, const uint8_t *, const unsigned, pgp_crypt_t *); void pgp_push_enc_crypt(pgp_output_t *, pgp_crypt_t *); -int pgp_push_enc_se_ip(pgp_output_t *, const pgp_key_t *, const char *); +int pgp_push_enc_se_ip(pgp_output_t *, const pgp_keyring_t *, const char *, unsigned); /* Secret Key checksum */ void pgp_push_checksum_writer(pgp_output_t *, pgp_seckey_t *); diff --git a/libs/netpgp/signature-netpgp.h b/libs/netpgp/include/netpgp/signature.h similarity index 80% rename from libs/netpgp/signature-netpgp.h rename to libs/netpgp/include/netpgp/signature.h index 895f472c..0606623d 100644 --- a/libs/netpgp/signature-netpgp.h +++ b/libs/netpgp/include/netpgp/signature.h @@ -57,9 +57,9 @@ #include -#include "packet-netpgp.h" -#include "create-netpgp.h" -#include "memory-netpgp.h" +#include "packet.h" +#include "create.h" +#include "memory.h" typedef struct pgp_create_sig_t pgp_create_sig_t; @@ -69,22 +69,18 @@ void pgp_create_sig_delete(pgp_create_sig_t *); unsigned pgp_check_useridcert_sig(const pgp_pubkey_t *, const uint8_t *, const pgp_sig_t *, - const pgp_pubkey_t *, - const uint8_t *); + const pgp_pubkey_t *); unsigned pgp_check_userattrcert_sig(const pgp_pubkey_t *, const pgp_data_t *, const pgp_sig_t *, - const pgp_pubkey_t *, - const uint8_t *); + const pgp_pubkey_t *); unsigned pgp_check_subkey_sig(const pgp_pubkey_t *, const pgp_pubkey_t *, const pgp_sig_t *, - const pgp_pubkey_t *, - const uint8_t *); + const pgp_pubkey_t *); unsigned pgp_check_direct_sig(const pgp_pubkey_t *, const pgp_sig_t *, - const pgp_pubkey_t *, - const uint8_t *); + const pgp_pubkey_t *); unsigned pgp_check_hash_sig(pgp_hash_t *, const pgp_sig_t *, const pgp_pubkey_t *); @@ -102,19 +98,31 @@ pgp_hash_t *pgp_sig_get_hash(pgp_create_sig_t *); unsigned pgp_end_hashed_subpkts(pgp_create_sig_t *); unsigned pgp_write_sig(pgp_output_t *, pgp_create_sig_t *, const pgp_pubkey_t *, const pgp_seckey_t *); -unsigned pgp_add_time(pgp_create_sig_t *, int64_t, const char *); unsigned pgp_add_issuer_keyid(pgp_create_sig_t *, const uint8_t *); void pgp_add_primary_userid(pgp_create_sig_t *, unsigned); +unsigned +pgp_add_creation_time(pgp_create_sig_t *sig, time_t when); +unsigned +pgp_add_sig_expiration_time(pgp_create_sig_t *sig, time_t duration); +unsigned +pgp_add_key_expiration_time(pgp_create_sig_t *sig, time_t duration); +unsigned +pgp_add_key_flags(pgp_create_sig_t *sig, uint8_t flags); +unsigned +pgp_add_key_prefs(pgp_create_sig_t *sig); +unsigned +pgp_add_key_features(pgp_create_sig_t *sig); + /* Standard Interface */ unsigned pgp_sign_file(pgp_io_t *, const char *, const char *, const pgp_seckey_t *, const char *, - const int64_t, - const uint64_t, + const time_t, + const time_t, const unsigned, const unsigned, const unsigned); @@ -122,10 +130,10 @@ unsigned pgp_sign_file(pgp_io_t *, int pgp_sign_detached(pgp_io_t *, const char *, char *, - pgp_seckey_t *, + const pgp_seckey_t *, const char *, - const int64_t, - const uint64_t, + const time_t, + const time_t, const unsigned, const unsigned); @@ -157,15 +165,33 @@ pgp_memory_t *pgp_sign_buf(pgp_io_t *, const void *, const size_t, const pgp_seckey_t *, - const int64_t, - const uint64_t, + const time_t, + const time_t, const char *, const unsigned, const unsigned); -unsigned pgp_keyring_read_from_mem(pgp_io_t *, - pgp_keyring_t *, - const unsigned, - pgp_memory_t *); +/** \ingroup Core_Create + * needed for signature creation + */ +struct pgp_create_sig_t { + pgp_hash_t hash; + pgp_sig_t sig; + pgp_memory_t *mem; + pgp_output_t *output; /* how to do the writing */ + unsigned hashoff; /* hashed count offset */ + unsigned hashlen; + unsigned unhashoff; +}; + +void +pgp_sig_start_key_rev(pgp_create_sig_t *sig, + const pgp_pubkey_t *key, + pgp_sig_type_t type); + +unsigned +pgp_add_revocation_reason( + pgp_create_sig_t *sig, + uint8_t code, const char *reason); #endif /* SIGNATURE_H_ */ diff --git a/libs/netpgp/types-netpgp.h b/libs/netpgp/include/netpgp/types.h similarity index 99% rename from libs/netpgp/types-netpgp.h rename to libs/netpgp/include/netpgp/types.h index c4ee1d1c..cc03f7b0 100644 --- a/libs/netpgp/types-netpgp.h +++ b/libs/netpgp/include/netpgp/types.h @@ -49,8 +49,6 @@ #ifndef TYPES_H_ #define TYPES_H_ -#include "config-netpgp.h" - #ifdef HAVE_INTTYPES_H #include #endif diff --git a/libs/netpgp/validate-netpgp.h b/libs/netpgp/include/netpgp/validate.h similarity index 71% rename from libs/netpgp/validate-netpgp.h rename to libs/netpgp/include/netpgp/validate.h index e28ec30c..44455a33 100644 --- a/libs/netpgp/validate-netpgp.h +++ b/libs/netpgp/include/netpgp/validate.h @@ -49,29 +49,36 @@ #ifndef VALIDATE_H_ #define VALIDATE_H_ 1 -typedef struct { - const pgp_key_t *key; - unsigned packet; - unsigned offset; -} validate_reader_t; - /** Struct used with the validate_key_cb callback */ -typedef struct { - pgp_pubkey_t pubkey; - pgp_pubkey_t subkey; - pgp_seckey_t seckey; +typedef struct validate_key_cb_t{ + pgp_content_enum type; /* type of key */ + pgp_keydata_key_t key; /* pubkey/seckey data */ + pgp_keydata_key_t subkey; + uint8_t pubkeyid[PGP_KEY_ID_SIZE]; enum { - ATTRIBUTE = 1, - ID + LS_UNKNOWN = 0, + LS_ATTRIBUTE, + LS_ID, + LS_SUBKEY, + LS_PRIMARY, } last_seen; + uint8_t *userid; pgp_data_t userattr; uint8_t hash[PGP_MAX_HASH_SIZE]; const pgp_keyring_t *keyring; - validate_reader_t *reader; pgp_validation_t *result; pgp_cb_ret_t(*getpassphrase) (const pgp_packet_t *, pgp_cbdata_t *); + + unsigned not_commited; /* tells on_valid it is first commit of that key */ + pgp_sig_info_t valid_sig_info; /* store last valid sig info */ + unsigned sig_is_valid; /* condition to call on_valid at packet end */ + pgp_cb_ret_t(*on_valid) ( /* callback for action on valid sig */ + struct validate_key_cb_t *, /* this struct */ + const pgp_subpacket_t *); /* sig packet */ + void *on_valid_args; /* pointer to argument for on_valid callback */ + } validate_key_cb_t; /** Struct use with the validate_data_cb callback */ @@ -87,13 +94,10 @@ typedef struct { uint8_t hash[PGP_MAX_HASH_SIZE]; pgp_memory_t *mem; const pgp_keyring_t *keyring; - validate_reader_t *reader;/* reader-specific arg */ pgp_validation_t *result; char *detachname; } validate_data_cb_t; -void pgp_keydata_reader_set(pgp_stream_t *, const pgp_key_t *); - pgp_cb_ret_t pgp_validate_key_cb(const pgp_packet_t *, pgp_cbdata_t *); unsigned check_binary_sig(const uint8_t *, @@ -115,6 +119,30 @@ unsigned pgp_validate_mem(pgp_io_t *, const int, const pgp_keyring_t *); -pgp_cb_ret_t validate_data_cb(const pgp_packet_t *, pgp_cbdata_t *); +unsigned pgp_validate_mem_detached(pgp_io_t *, + pgp_validation_t *, + pgp_memory_t *, + pgp_memory_t **, + const int, + const pgp_keyring_t *, + pgp_memory_t *); +pgp_cb_ret_t validate_data_cb(const pgp_packet_t *, pgp_cbdata_t *); +void pgp_free_sig_info(pgp_sig_info_t *); + +unsigned +pgp_filter_keys_fileread(pgp_io_t *io, + pgp_keyring_t *destpubring, + pgp_keyring_t *destsecring, + pgp_keyring_t *certring, + const unsigned armour, + const char *filename); + +unsigned +pgp_filter_keys_from_mem(pgp_io_t *io, + pgp_keyring_t *destpubring, + pgp_keyring_t *destsecring, + pgp_keyring_t *certring, + const unsigned armour, + pgp_memory_t *mem); #endif /* !VALIDATE_H_ */ diff --git a/libs/netpgp/version-netpgp.h b/libs/netpgp/include/netpgp/version.h similarity index 96% rename from libs/netpgp/version-netpgp.h rename to libs/netpgp/include/netpgp/version.h index 984a9e95..6ecec0cf 100644 --- a/libs/netpgp/version-netpgp.h +++ b/libs/netpgp/include/netpgp/version.h @@ -58,9 +58,9 @@ #endif /* development versions have .99 suffix */ -#define NETPGP_BASE_VERSION "3.99.17" +#define NETPGP_BASE_VERSION "3.99.99" -#define NETPGP_VERSION_CAT(a, b) "NetPGP portable " a "/[" b "]" +#define NETPGP_VERSION_CAT(a, b) "NetPGP for pEp " a "/[" b "]" #define NETPGP_VERSION_STRING \ NETPGP_VERSION_CAT(NETPGP_BASE_VERSION, NETPGP_AUTOCONF_VERSION) diff --git a/libs/netpgp/writer-netpgp.h b/libs/netpgp/include/netpgp/writer.h similarity index 93% rename from libs/netpgp/writer-netpgp.h rename to libs/netpgp/include/netpgp/writer.h index 1d903620..632eeeb6 100644 --- a/libs/netpgp/writer-netpgp.h +++ b/libs/netpgp/include/netpgp/writer.h @@ -53,11 +53,11 @@ #ifndef WRITER_H_ #define WRITER_H_ -#include "types-netpgp.h" -#include "packet-netpgp.h" -#include "crypto-netpgp.h" -#include "errors-netpgp.h" -#include "keyring-netpgp.h" +#include "types.h" +#include "packet.h" +#include "crypto.h" +#include "errors.h" +#include "keyring.h" /** * \ingroup Writer @@ -69,7 +69,7 @@ typedef unsigned pgp_writer_func_t(const uint8_t *, unsigned, pgp_error_t **, pgp_writer_t *); -typedef unsigned +typedef unsigned pgp_writer_finaliser_t(pgp_error_t **, pgp_writer_t *); typedef void pgp_writer_destroyer_t(pgp_writer_t *); @@ -114,6 +114,10 @@ unsigned pgp_write_mpi(pgp_output_t *, const BIGNUM *); void pgp_writer_info_delete(pgp_writer_t *); unsigned pgp_writer_info_finalise(pgp_error_t **, pgp_writer_t *); -void pgp_push_stream_enc_se_ip(pgp_output_t *, const pgp_key_t *, const char *); +void pgp_push_stream_enc_se_ip(pgp_output_t *, pgp_key_t *, const char *); + +void pgp_push_sum16_writer(pgp_output_t *output); + +uint16_t pgp_pop_sum16_writer(pgp_output_t *output); #endif /* WRITER_H_ */ diff --git a/libs/netpgp/keyring-netpgp.h b/libs/netpgp/keyring-netpgp.h deleted file mode 100644 index 70dc45f4..00000000 --- a/libs/netpgp/keyring-netpgp.h +++ /dev/null @@ -1,152 +0,0 @@ -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Alistair Crooks (agc@NetBSD.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ - -#ifndef KEYRING_H_ -#define KEYRING_H_ - -#include "packet-netpgp.h" -#include "packet-parse.h" -#include "mj.h" - -enum { - MAX_ID_LENGTH = 128, - MAX_PASSPHRASE_LENGTH = 256 -}; - -typedef struct pgp_key_t pgp_key_t; - -/** \struct pgp_keyring_t - * A keyring - */ -typedef struct pgp_keyring_t { - DYNARRAY(pgp_key_t, key); - pgp_hash_alg_t hashtype; -} pgp_keyring_t; - -const pgp_key_t *pgp_getkeybyid(pgp_io_t *, - const pgp_keyring_t *, - const uint8_t *, - unsigned *, - pgp_pubkey_t **); -const pgp_key_t *pgp_getkeybyname(pgp_io_t *, - const pgp_keyring_t *, - const char *); -const pgp_key_t *pgp_getnextkeybyname(pgp_io_t *, - const pgp_keyring_t *, - const char *, - unsigned *); -void pgp_keydata_free(pgp_key_t *); -void pgp_keyring_free(pgp_keyring_t *); -void pgp_dump_keyring(const pgp_keyring_t *); -const pgp_pubkey_t *pgp_get_pubkey(const pgp_key_t *); -unsigned pgp_is_key_secret(const pgp_key_t *); -const pgp_seckey_t *pgp_get_seckey(const pgp_key_t *); -pgp_seckey_t *pgp_get_writable_seckey(pgp_key_t *); -pgp_seckey_t *pgp_decrypt_seckey(const pgp_key_t *, void *); - -unsigned pgp_keyring_fileread(pgp_keyring_t *, const unsigned, - const char *); - -int pgp_keyring_list(pgp_io_t *, const pgp_keyring_t *, const int); -int pgp_keyring_json(pgp_io_t *, const pgp_keyring_t *, mj_t *, const int); - -void pgp_set_seckey(pgp_contents_t *, const pgp_key_t *); -void pgp_forget(void *, unsigned); - -const uint8_t *pgp_get_key_id(const pgp_key_t *); -unsigned pgp_get_userid_count(const pgp_key_t *); -const uint8_t *pgp_get_userid(const pgp_key_t *, unsigned); -unsigned pgp_is_key_supported(const pgp_key_t *); - -uint8_t *pgp_add_userid(pgp_key_t *, const uint8_t *); -pgp_subpacket_t *pgp_add_subpacket(pgp_key_t *, - const pgp_subpacket_t *); - -unsigned pgp_add_selfsigned_userid(pgp_key_t *, const uint8_t *); - -pgp_key_t *pgp_keydata_new(void); -void pgp_keydata_init(pgp_key_t *, const pgp_content_enum); - -int pgp_parse_and_accumulate(pgp_keyring_t *, pgp_stream_t *); - -int pgp_sprint_keydata(pgp_io_t *, const pgp_keyring_t *, - const pgp_key_t *, char **, const char *, - const pgp_pubkey_t *, const int); -int pgp_sprint_mj(pgp_io_t *, const pgp_keyring_t *, - const pgp_key_t *, mj_t *, const char *, - const pgp_pubkey_t *, const int); -int pgp_hkp_sprint_keydata(pgp_io_t *, const pgp_keyring_t *, - const pgp_key_t *, char **, - const pgp_pubkey_t *, const int); -void pgp_print_keydata(pgp_io_t *, const pgp_keyring_t *, const pgp_key_t *, - const char *, const pgp_pubkey_t *, const int); -void pgp_print_sig(pgp_io_t *, const pgp_key_t *, const char *, - const pgp_pubkey_t *); -void pgp_print_pubkey(const pgp_pubkey_t *); -int pgp_sprint_pubkey(const pgp_key_t *, char *, size_t); - -int pgp_list_packets(pgp_io_t *, - char *, - unsigned, - pgp_keyring_t *, - pgp_keyring_t *, - void *, - pgp_cbfunc_t *); - -char *pgp_export_key(pgp_io_t *, const pgp_key_t *, uint8_t *); - -int pgp_add_to_pubring(pgp_keyring_t *, const pgp_pubkey_t *, pgp_content_enum tag); -int pgp_add_to_secring(pgp_keyring_t *, const pgp_seckey_t *); - -int pgp_append_keyring(pgp_keyring_t *, pgp_keyring_t *); - -#endif /* KEYRING_H_ */ diff --git a/libs/netpgp/keyring.c b/libs/netpgp/keyring.c deleted file mode 100644 index 2d4e26bd..00000000 --- a/libs/netpgp/keyring.c +++ /dev/null @@ -1,1151 +0,0 @@ -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Alistair Crooks (agc@NetBSD.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** \file - */ -#include "config-netpgp.h" - -#ifdef HAVE_SYS_CDEFS_H -#include -#endif - -#if defined(__NetBSD__) -__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: keyring.c,v 1.50 2011/06/25 00:37:44 agc Exp $"); -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif - -#include -#include -#include - -#ifdef HAVE_TERMIOS_H -#include -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "types-netpgp.h" -#include "keyring-netpgp.h" -#include "packet-parse.h" -#include "signature-netpgp.h" -#include "netpgpsdk.h" -#include "readerwriter-netpgp.h" -#include "netpgpdefs.h" -#include "packet-netpgp.h" -#include "crypto-netpgp.h" -#include "validate-netpgp.h" -#include "netpgpdefs.h" -#include "netpgpdigest.h" - - - -/** - \ingroup HighLevel_Keyring - - \brief Creates a new pgp_key_t struct - - \return A new pgp_key_t struct, initialised to zero. - - \note The returned pgp_key_t struct must be freed after use with pgp_keydata_free. -*/ - -pgp_key_t * -pgp_keydata_new(void) -{ - return calloc(1, sizeof(pgp_key_t)); -} - - -/** - \ingroup HighLevel_Keyring - - \brief Frees keydata and its memory - - \param keydata Key to be freed. - - \note This frees the keydata itself, as well as any other memory alloc-ed by it. -*/ -void -pgp_keydata_free(pgp_key_t *keydata) -{ - unsigned n; - - for (n = 0; n < keydata->uidc; ++n) { - pgp_userid_free(&keydata->uids[n]); - } - free(keydata->uids); - keydata->uids = NULL; - keydata->uidc = 0; - - for (n = 0; n < keydata->packetc; ++n) { - pgp_subpacket_free(&keydata->packets[n]); - } - free(keydata->packets); - keydata->packets = NULL; - keydata->packetc = 0; - - if (keydata->type == PGP_PTAG_CT_PUBLIC_KEY) { - pgp_pubkey_free(&keydata->key.pubkey); - } else { - pgp_seckey_free(&keydata->key.seckey); - } - - free(keydata); -} - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the public key in the given keydata. - \param keydata - - \return Pointer to public key - - \note This is not a copy, do not free it after use. -*/ - -const pgp_pubkey_t * -pgp_get_pubkey(const pgp_key_t *keydata) -{ - return (keydata->type == PGP_PTAG_CT_PUBLIC_KEY) ? - &keydata->key.pubkey : - &keydata->key.seckey.pubkey; -} - -/** -\ingroup HighLevel_KeyGeneral - -\brief Check whether this is a secret key or not. -*/ - -unsigned -pgp_is_key_secret(const pgp_key_t *data) -{ - return data->type != PGP_PTAG_CT_PUBLIC_KEY; -} - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the secret key in the given keydata. - - \note This is not a copy, do not free it after use. - - \note This returns a const. If you need to be able to write to this - pointer, use pgp_get_writable_seckey -*/ - -const pgp_seckey_t * -pgp_get_seckey(const pgp_key_t *data) -{ - return (data->type == PGP_PTAG_CT_SECRET_KEY) ? - &data->key.seckey : NULL; -} - -/** - \ingroup HighLevel_KeyGeneral - - \brief Returns the secret key in the given keydata. - - \note This is not a copy, do not free it after use. - - \note If you do not need to be able to modify this key, there is an - equivalent read-only function pgp_get_seckey. -*/ - -pgp_seckey_t * -pgp_get_writable_seckey(pgp_key_t *data) -{ - return (data->type == PGP_PTAG_CT_SECRET_KEY) ? - &data->key.seckey : NULL; -} - -/* utility function to zero out memory */ -void -pgp_forget(void *vp, unsigned size) -{ - (void) memset(vp, 0x0, size); -} - -typedef struct { - FILE *passfp; - const pgp_key_t *key; - char *passphrase; - pgp_seckey_t *seckey; -} decrypt_t; - -static pgp_cb_ret_t -decrypt_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) -{ - const pgp_contents_t *content = &pkt->u; - decrypt_t *decrypt; - char pass[MAX_PASSPHRASE_LENGTH]; - - decrypt = pgp_callback_arg(cbinfo); - switch (pkt->tag) { - case PGP_PARSER_PTAG: - case PGP_PTAG_CT_USER_ID: - case PGP_PTAG_CT_SIGNATURE: - case PGP_PTAG_CT_SIGNATURE_HEADER: - case PGP_PTAG_CT_SIGNATURE_FOOTER: - case PGP_PTAG_CT_TRUST: - break; - - case PGP_GET_PASSPHRASE: - (void) pgp_getpassphrase(decrypt->passfp, pass, sizeof(pass)); - *content->skey_passphrase.passphrase = netpgp_strdup(pass); - pgp_forget(pass, (unsigned)sizeof(pass)); - return PGP_KEEP_MEMORY; - - case PGP_PARSER_ERRCODE: - switch (content->errcode.errcode) { - case PGP_E_P_MPI_FORMAT_ERROR: - /* Generally this means a bad passphrase */ - fprintf(stderr, "Bad passphrase!\n"); - return PGP_RELEASE_MEMORY; - - case PGP_E_P_PACKET_CONSUMED: - /* And this is because of an error we've accepted */ - return PGP_RELEASE_MEMORY; - default: - break; - } - (void) fprintf(stderr, "parse error: %s\n", - pgp_errcode(content->errcode.errcode)); - return PGP_FINISHED; - - case PGP_PARSER_ERROR: - fprintf(stderr, "parse error: %s\n", content->error); - return PGP_FINISHED; - - case PGP_PTAG_CT_SECRET_KEY: - if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) { - (void) fprintf(stderr, "decrypt_cb: bad alloc\n"); - return PGP_FINISHED; - } - decrypt->seckey->checkhash = calloc(1, PGP_CHECKHASH_SIZE); - *decrypt->seckey = content->seckey; - return PGP_KEEP_MEMORY; - - case PGP_PARSER_PACKET_END: - /* nothing to do */ - break; - - default: - fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag, - pkt->tag); - return PGP_FINISHED; - } - - return PGP_RELEASE_MEMORY; -} - -/** -\ingroup Core_Keys -\brief Decrypts secret key from given keydata with given passphrase -\param key Key from which to get secret key -\param passphrase Passphrase to use to decrypt secret key -\return secret key -*/ -pgp_seckey_t * -pgp_decrypt_seckey(const pgp_key_t *key, void *passfp) -{ - pgp_stream_t *stream; - const int printerrors = 1; - decrypt_t decrypt; - - (void) memset(&decrypt, 0x0, sizeof(decrypt)); - decrypt.key = key; - decrypt.passfp = passfp; - stream = pgp_new(sizeof(*stream)); - pgp_keydata_reader_set(stream, key); - pgp_set_callback(stream, decrypt_cb, &decrypt); - stream->readinfo.accumulate = 1; - pgp_parse(stream, !printerrors); - return decrypt.seckey; -} - -/** -\ingroup Core_Keys -\brief Set secret key in content -\param content Content to be set -\param key Keydata to get secret key from -*/ -void -pgp_set_seckey(pgp_contents_t *cont, const pgp_key_t *key) -{ - *cont->get_seckey.seckey = &key->key.seckey; -} - -/** -\ingroup Core_Keys -\brief Get Key ID from keydata -\param key Keydata to get Key ID from -\return Pointer to Key ID inside keydata -*/ -const uint8_t * -pgp_get_key_id(const pgp_key_t *key) -{ - return key->sigid; -} - -/** -\ingroup Core_Keys -\brief How many User IDs in this key? -\param key Keydata to check -\return Num of user ids -*/ -unsigned -pgp_get_userid_count(const pgp_key_t *key) -{ - return key->uidc; -} - -/** -\ingroup Core_Keys -\brief Get indexed user id from key -\param key Key to get user id from -\param index Which key to get -\return Pointer to requested user id -*/ -const uint8_t * -pgp_get_userid(const pgp_key_t *key, unsigned subscript) -{ - return key->uids[subscript]; -} - -/** - \ingroup HighLevel_Supported - \brief Checks whether key's algorithm and type are supported by OpenPGP::SDK - \param keydata Key to be checked - \return 1 if key algorithm and type are supported by OpenPGP::SDK; 0 if not -*/ - -unsigned -pgp_is_key_supported(const pgp_key_t *key) -{ - if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { - switch(key->key.pubkey.alg) { - case PGP_PKA_RSA: - case PGP_PKA_DSA: - case PGP_PKA_ELGAMAL: - return 1; - default: - break; - } - } - return 0; -} - -/* \todo check where userid pointers are copied */ -/** -\ingroup Core_Keys -\brief Copy user id, including contents -\param dst Destination User ID -\param src Source User ID -\note If dst already has a userid, it will be freed. -*/ -static uint8_t * -copy_userid(uint8_t **dst, const uint8_t *src) -{ - size_t len; - - len = strlen((const char *) src); - if (*dst) { - free(*dst); - } - if ((*dst = calloc(1, len + 1)) == NULL) { - (void) fprintf(stderr, "copy_userid: bad alloc\n"); - } else { - (void) memcpy(*dst, src, len); - } - return *dst; -} - -/* \todo check where pkt pointers are copied */ -/** -\ingroup Core_Keys -\brief Copy packet, including contents -\param dst Destination packet -\param src Source packet -\note If dst already has a packet, it will be freed. -*/ -static pgp_subpacket_t * -copy_packet(pgp_subpacket_t *dst, const pgp_subpacket_t *src) -{ - if (dst->raw) { - free(dst->raw); - } - if ((dst->raw = calloc(1, src->length)) == NULL) { - (void) fprintf(stderr, "copy_packet: bad alloc\n"); - } else { - dst->length = src->length; - (void) memcpy(dst->raw, src->raw, src->length); - } - return dst; -} - -/** -\ingroup Core_Keys -\brief Add User ID to key -\param key Key to which to add User ID -\param userid User ID to add -\return Pointer to new User ID -*/ -uint8_t * -pgp_add_userid(pgp_key_t *key, const uint8_t *userid) -{ - uint8_t **uidp; - - EXPAND_ARRAY(key, uid); - /* initialise new entry in array */ - uidp = &key->uids[key->uidc++]; - *uidp = NULL; - /* now copy it */ - return copy_userid(uidp, userid); -} - -void print_packet_hex(const pgp_subpacket_t *pkt); - -/** -\ingroup Core_Keys -\brief Add packet to key -\param keydata Key to which to add packet -\param packet Packet to add -\return Pointer to new packet -*/ -pgp_subpacket_t * -pgp_add_subpacket(pgp_key_t *keydata, const pgp_subpacket_t *packet) -{ - pgp_subpacket_t *subpktp; - - EXPAND_ARRAY(keydata, packet); - /* initialise new entry in array */ - subpktp = &keydata->packets[keydata->packetc++]; - subpktp->length = 0; - subpktp->raw = NULL; - /* now copy it */ - return copy_packet(subpktp, packet); -} - -/** -\ingroup Core_Keys -\brief Add selfsigned User ID to key -\param keydata Key to which to add user ID -\param userid Self-signed User ID to add -\return 1 if OK; else 0 -*/ -unsigned -pgp_add_selfsigned_userid(pgp_key_t *key, const uint8_t *userid) -{ - pgp_create_sig_t *sig; - pgp_subpacket_t sigpacket; - pgp_memory_t *mem_userid = NULL; - pgp_output_t *useridoutput = NULL; - pgp_memory_t *mem_sig = NULL; - pgp_output_t *sigoutput = NULL; - - /* - * create signature packet for this userid - */ - - /* create userid pkt */ - pgp_setup_memory_write(&useridoutput, &mem_userid, 128); - pgp_write_struct_userid(useridoutput, userid); - - /* create sig for this pkt */ - sig = pgp_create_sig_new(); - pgp_sig_start_key_sig(sig, &key->key.seckey.pubkey, userid, PGP_CERT_POSITIVE); - pgp_add_time(sig, (int64_t)time(NULL), "birth"); - pgp_add_issuer_keyid(sig, key->sigid); - pgp_add_primary_userid(sig, 1); - pgp_end_hashed_subpkts(sig); - - pgp_setup_memory_write(&sigoutput, &mem_sig, 128); - pgp_write_sig(sigoutput, sig, &key->key.seckey.pubkey, &key->key.seckey); - - /* add this packet to key */ - sigpacket.length = pgp_mem_len(mem_sig); - sigpacket.raw = pgp_mem_data(mem_sig); - - /* add userid to key */ - (void) pgp_add_userid(key, userid); - (void) pgp_add_subpacket(key, &sigpacket); - - /* cleanup */ - pgp_create_sig_delete(sig); - pgp_output_delete(useridoutput); - pgp_output_delete(sigoutput); - pgp_memory_free(mem_userid); - pgp_memory_free(mem_sig); - - return 1; -} - -/** -\ingroup Core_Keys -\brief Initialise pgp_key_t -\param keydata Keydata to initialise -\param type PGP_PTAG_CT_PUBLIC_KEY or PGP_PTAG_CT_SECRET_KEY -*/ -void -pgp_keydata_init(pgp_key_t *keydata, const pgp_content_enum type) -{ - if (keydata->type != PGP_PTAG_CT_RESERVED) { - (void) fprintf(stderr, - "pgp_keydata_init: wrong keydata type\n"); - } else if (type != PGP_PTAG_CT_PUBLIC_KEY && - type != PGP_PTAG_CT_SECRET_KEY) { - (void) fprintf(stderr, "pgp_keydata_init: wrong type\n"); - } else { - keydata->type = type; - } -} - -/* used to point to data during keyring read */ -typedef struct keyringcb_t { - pgp_keyring_t *keyring; /* the keyring we're reading */ -} keyringcb_t; - - -static pgp_cb_ret_t -cb_keyring_read(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) -{ - pgp_keyring_t *keyring; - pgp_revoke_t *revocation; - pgp_key_t *key; - keyringcb_t *cb; - - cb = pgp_callback_arg(cbinfo); - keyring = cb->keyring; - switch (pkt->tag) { - case PGP_PARSER_PTAG: - case PGP_PTAG_CT_ENCRYPTED_SECRET_KEY: - /* we get these because we didn't prompt */ - break; - case PGP_PTAG_CT_SIGNATURE_HEADER: - key = &keyring->keys[keyring->keyc - 1]; - EXPAND_ARRAY(key, subsig); - key->subsigs[key->subsigc].uid = key->uidc - 1; - (void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig, - sizeof(pkt->u.sig)); - key->subsigc += 1; - break; - case PGP_PTAG_CT_SIGNATURE: - key = &keyring->keys[keyring->keyc - 1]; - EXPAND_ARRAY(key, subsig); - key->subsigs[key->subsigc].uid = key->uidc - 1; - (void) memcpy(&key->subsigs[key->subsigc].sig, &pkt->u.sig, - sizeof(pkt->u.sig)); - key->subsigc += 1; - break; - case PGP_PTAG_CT_TRUST: - key = &keyring->keys[keyring->keyc - 1]; - key->subsigs[key->subsigc - 1].trustlevel = pkt->u.ss_trust.level; - key->subsigs[key->subsigc - 1].trustamount = pkt->u.ss_trust.amount; - break; - case PGP_PTAG_SS_KEY_EXPIRY: - EXPAND_ARRAY(keyring, key); - if (keyring->keyc > 0) { - keyring->keys[keyring->keyc - 1].key.pubkey.duration = pkt->u.ss_time; - } - break; - case PGP_PTAG_SS_ISSUER_KEY_ID: - key = &keyring->keys[keyring->keyc - 1]; - (void) memcpy(&key->subsigs[key->subsigc - 1].sig.info.signer_id, - pkt->u.ss_issuer, - sizeof(pkt->u.ss_issuer)); - key->subsigs[key->subsigc - 1].sig.info.signer_id_set = 1; - break; - case PGP_PTAG_SS_CREATION_TIME: - key = &keyring->keys[keyring->keyc - 1]; - key->subsigs[key->subsigc - 1].sig.info.birthtime = pkt->u.ss_time; - key->subsigs[key->subsigc - 1].sig.info.birthtime_set = 1; - break; - case PGP_PTAG_SS_EXPIRATION_TIME: - key = &keyring->keys[keyring->keyc - 1]; - key->subsigs[key->subsigc - 1].sig.info.duration = pkt->u.ss_time; - key->subsigs[key->subsigc - 1].sig.info.duration_set = 1; - break; - case PGP_PTAG_SS_PRIMARY_USER_ID: - key = &keyring->keys[keyring->keyc - 1]; - key->uid0 = key->uidc - 1; - break; - case PGP_PTAG_SS_REVOCATION_REASON: - key = &keyring->keys[keyring->keyc - 1]; - if (key->uidc == 0) { - /* revoke whole key */ - key->revoked = 1; - revocation = &key->revocation; - } else { - /* revoke the user id */ - EXPAND_ARRAY(key, revoke); - revocation = &key->revokes[key->revokec]; - key->revokes[key->revokec].uid = key->uidc - 1; - key->revokec += 1; - } - revocation->code = pkt->u.ss_revocation.code; - revocation->reason = netpgp_strdup(pgp_show_ss_rr_code(pkt->u.ss_revocation.code)); - break; - case PGP_PTAG_CT_SIGNATURE_FOOTER: - case PGP_PARSER_ERRCODE: - break; - - default: - break; - } - - return PGP_RELEASE_MEMORY; -} - -/** - \ingroup HighLevel_KeyringRead - - \brief Reads a keyring from a file - - \param keyring Pointer to an existing pgp_keyring_t struct - \param armour 1 if file is armoured; else 0 - \param filename Filename of keyring to be read - - \return pgp 1 if OK; 0 on error - - \note Keyring struct must already exist. - - \note Can be used with either a public or secret keyring. - - \note You must call pgp_keyring_free() after usage to free alloc-ed memory. - - \note If you call this twice on the same keyring struct, without calling - pgp_keyring_free() between these calls, you will introduce a memory leak. - - \sa pgp_keyring_read_from_mem() - \sa pgp_keyring_free() - -*/ - -unsigned -pgp_keyring_fileread(pgp_keyring_t *keyring, - const unsigned armour, - const char *filename) -{ - pgp_stream_t *stream; - keyringcb_t cb; - unsigned res = 1; - int fd; - - (void) memset(&cb, 0x0, sizeof(cb)); - cb.keyring = keyring; - stream = pgp_new(sizeof(*stream)); - - /* add this for the moment, */ - /* - * \todo need to fix the problems with reading signature subpackets - * later - */ - - /* pgp_parse_options(parse,PGP_PTAG_SS_ALL,PGP_PARSE_RAW); */ - pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); - -#ifdef O_BINARY - fd = open(filename, O_RDONLY | O_BINARY); -#else - fd = open(filename, O_RDONLY); -#endif - if (fd < 0) { - pgp_stream_delete(stream); - perror(filename); - return 0; - } -#ifdef USE_MMAP_FOR_FILES - pgp_reader_set_mmap(stream, fd); -#else - pgp_reader_set_fd(stream, fd); -#endif - - pgp_set_callback(stream, cb_keyring_read, &cb); - - if (armour) { - pgp_reader_push_dearmour(stream); - } - res = pgp_parse_and_accumulate(keyring, stream); - pgp_print_errors(pgp_stream_get_errors(stream)); - - if (armour) { - pgp_reader_pop_dearmour(stream); - } - - (void)close(fd); - - pgp_stream_delete(stream); - - return res; -} - -/** - \ingroup HighLevel_KeyringRead - - \brief Reads a keyring from memory - - \param keyring Pointer to existing pgp_keyring_t struct - \param armour 1 if file is armoured; else 0 - \param mem Pointer to a pgp_memory_t struct containing keyring to be read - - \return pgp 1 if OK; 0 on error - - \note Keyring struct must already exist. - - \note Can be used with either a public or secret keyring. - - \note You must call pgp_keyring_free() after usage to free alloc-ed memory. - - \note If you call this twice on the same keyring struct, without calling - pgp_keyring_free() between these calls, you will introduce a memory leak. - - \sa pgp_keyring_fileread - \sa pgp_keyring_free -*/ -unsigned -pgp_keyring_read_from_mem(pgp_io_t *io, - pgp_keyring_t *keyring, - const unsigned armour, - pgp_memory_t *mem) -{ - pgp_stream_t *stream; - const unsigned noaccum = 0; - keyringcb_t cb; - unsigned res; - - (void) memset(&cb, 0x0, sizeof(cb)); - cb.keyring = keyring; - stream = pgp_new(sizeof(*stream)); - pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); - pgp_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read, - noaccum); - if (armour) { - pgp_reader_push_dearmour(stream); - } - res = (unsigned)pgp_parse_and_accumulate(keyring, stream); - pgp_print_errors(pgp_stream_get_errors(stream)); - if (armour) { - pgp_reader_pop_dearmour(stream); - } - /* don't call teardown_memory_read because memory was passed in */ - pgp_stream_delete(stream); - return res; -} - -/** - \ingroup HighLevel_KeyringRead - - \brief Frees keyring's contents (but not keyring itself) - - \param keyring Keyring whose data is to be freed - - \note This does not free keyring itself, just the memory alloc-ed in it. - */ -void -pgp_keyring_free(pgp_keyring_t *keyring) -{ - (void)free(keyring->keys); - keyring->keys = NULL; - keyring->keyc = keyring->keyvsize = 0; -} - -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key in keyring from its Key ID - - \param keyring Keyring to be searched - \param keyid ID of required key - - \return Pointer to key, if found; NULL, if not found - - \note This returns a pointer to the key inside the given keyring, - not a copy. Do not free it after use. - -*/ -const pgp_key_t * -pgp_getkeybyid(pgp_io_t *io, const pgp_keyring_t *keyring, - const uint8_t *keyid, unsigned *from, pgp_pubkey_t **pubkey) -{ - uint8_t nullid[PGP_KEY_ID_SIZE]; - - (void) memset(nullid, 0x0, sizeof(nullid)); - for ( ; keyring && *from < keyring->keyc; *from += 1) { - if (pgp_get_debug_level(__FILE__)) { - hexdump(io->errs, "keyring keyid", keyring->keys[*from].sigid, PGP_KEY_ID_SIZE); - hexdump(io->errs, "keyid", keyid, PGP_KEY_ID_SIZE); - } - if (memcmp(keyring->keys[*from].sigid, keyid, PGP_KEY_ID_SIZE) == 0 || - memcmp(&keyring->keys[*from].sigid[PGP_KEY_ID_SIZE / 2], - keyid, PGP_KEY_ID_SIZE / 2) == 0) { - if (pubkey) { - *pubkey = &keyring->keys[*from].key.pubkey; - } - return &keyring->keys[*from]; - } - if (memcmp(&keyring->keys[*from].encid, nullid, sizeof(nullid)) == 0) { - continue; - } - if (memcmp(&keyring->keys[*from].encid, keyid, PGP_KEY_ID_SIZE) == 0 || - memcmp(&keyring->keys[*from].encid[PGP_KEY_ID_SIZE / 2], keyid, PGP_KEY_ID_SIZE / 2) == 0) { - if (pubkey) { - *pubkey = &keyring->keys[*from].enckey; - } - return &keyring->keys[*from]; - } - } - return NULL; -} - -/* convert a string keyid into a binary keyid */ -static void -str2keyid(const char *userid, uint8_t *keyid, size_t len) -{ - static const char *uppers = "0123456789ABCDEF"; - static const char *lowers = "0123456789abcdef"; - const char *hi; - const char *lo; - uint8_t hichar; - uint8_t lochar; - size_t j; - int i; - - for (i = 0, j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) { - if ((hi = strchr(uppers, userid[i])) == NULL) { - if ((hi = strchr(lowers, userid[i])) == NULL) { - break; - } - hichar = (uint8_t)(hi - lowers); - } else { - hichar = (uint8_t)(hi - uppers); - } - if ((lo = strchr(uppers, userid[i + 1])) == NULL) { - if ((lo = strchr(lowers, userid[i + 1])) == NULL) { - break; - } - lochar = (uint8_t)(lo - lowers); - } else { - lochar = (uint8_t)(lo - uppers); - } - keyid[j] = (hichar << 4) | (lochar); - } - keyid[j] = 0x0; -} - -/* return the next key which matches, starting searching at *from */ -static const pgp_key_t * -getkeybyname(pgp_io_t *io, - const pgp_keyring_t *keyring, - const char *name, - unsigned *from) -{ - const pgp_key_t *kp; - uint8_t **uidp; - unsigned i = 0; - pgp_key_t *keyp; - unsigned savedstart; - regex_t r; - uint8_t keyid[PGP_KEY_ID_SIZE + 1]; - size_t len; - - if (!keyring || !name || !from) { - return NULL; - } - len = strlen(name); - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(io->outs, "[%u] name '%s', len %zu\n", - *from, name, len); - } - /* first try name as a keyid */ - (void) memset(keyid, 0x0, sizeof(keyid)); - str2keyid(name, keyid, sizeof(keyid)); - if (pgp_get_debug_level(__FILE__)) { - hexdump(io->outs, "keyid", keyid, 4); - } - savedstart = *from; - if ((kp = pgp_getkeybyid(io, keyring, keyid, from, NULL)) != NULL) { - return kp; - } - *from = savedstart; - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(io->outs, "regex match '%s' from %u\n", - name, *from); - } - /* match on full name or email address as a NOSUB, ICASE regexp */ - (void) regcomp(&r, name, REG_EXTENDED | REG_ICASE); - for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) { - uidp = keyp->uids; - for (i = 0 ; i < keyp->uidc; i++, uidp++) { - if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) { - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(io->outs, - "MATCHED keyid \"%s\" len %" PRIsize "u\n", - (char *) *uidp, len); - } - regfree(&r); - return keyp; - } - } - } - regfree(&r); - return NULL; -} - -/** - \ingroup HighLevel_KeyringFind - - \brief Finds key from its User ID - - \param keyring Keyring to be searched - \param userid User ID of required key - - \return Pointer to Key, if found; NULL, if not found - - \note This returns a pointer to the key inside the keyring, not a - copy. Do not free it. - -*/ -const pgp_key_t * -pgp_getkeybyname(pgp_io_t *io, - const pgp_keyring_t *keyring, - const char *name) -{ - unsigned from; - - from = 0; - return getkeybyname(io, keyring, name, &from); -} - -const pgp_key_t * -pgp_getnextkeybyname(pgp_io_t *io, - const pgp_keyring_t *keyring, - const char *name, - unsigned *n) -{ - return getkeybyname(io, keyring, name, n); -} - -/** - \ingroup HighLevel_KeyringList - - \brief Prints all keys in keyring to stdout. - - \param keyring Keyring to use - - \return none -*/ -int -pgp_keyring_list(pgp_io_t *io, const pgp_keyring_t *keyring, const int psigs) -{ - pgp_key_t *key; - unsigned n; - - (void) fprintf(io->res, "%u key%s\n", keyring->keyc, - (keyring->keyc == 1) ? "" : "s"); - for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { - if (pgp_is_key_secret(key)) { - pgp_print_keydata(io, keyring, key, "sec", - &key->key.seckey.pubkey, 0); - } else { - pgp_print_keydata(io, keyring, key, "signature ", &key->key.pubkey, psigs); - } - (void) fputc('\n', io->res); - } - return 1; -} - -int -pgp_keyring_json(pgp_io_t *io, const pgp_keyring_t *keyring, mj_t *obj, const int psigs) -{ - pgp_key_t *key; - unsigned n; - - (void) memset(obj, 0x0, sizeof(*obj)); - mj_create(obj, "array"); - obj->size = keyring->keyvsize; - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(io->errs, "pgp_keyring_json: vsize %u\n", obj->size); - } - if ((obj->value.v = calloc(sizeof(*obj->value.v), obj->size)) == NULL) { - (void) fprintf(io->errs, "calloc failure\n"); - return 0; - } - for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { - if (pgp_is_key_secret(key)) { - pgp_sprint_mj(io, keyring, key, &obj->value.v[obj->c], - "sec", &key->key.seckey.pubkey, psigs); - } else { - pgp_sprint_mj(io, keyring, key, &obj->value.v[obj->c], - "signature ", &key->key.pubkey, psigs); - } - if (obj->value.v[obj->c].type != 0) { - obj->c += 1; - } - } - if (pgp_get_debug_level(__FILE__)) { - char *s; - - mj_asprint(&s, obj, MJ_JSON_ENCODE); - (void) fprintf(stderr, "pgp_keyring_json: '%s'\n", s); - free(s); - } - return 1; -} - - -/* this interface isn't right - hook into callback for getting passphrase */ -char * -pgp_export_key(pgp_io_t *io, const pgp_key_t *keydata, uint8_t *passphrase) -{ - pgp_output_t *output; - pgp_memory_t *mem; - char *cp; - - __PGP_USED(io); - pgp_setup_memory_write(&output, &mem, 128); - if (keydata->type == PGP_PTAG_CT_PUBLIC_KEY) { - pgp_write_xfer_pubkey(output, keydata, 1); - } else { - pgp_write_xfer_seckey(output, keydata, passphrase, - strlen((char *)passphrase), 1); - } - cp = netpgp_strdup(pgp_mem_data(mem)); - pgp_teardown_memory_write(output, mem); - return cp; -} - -/* add a key to a public keyring */ -int -pgp_add_to_pubring(pgp_keyring_t *keyring, const pgp_pubkey_t *pubkey, pgp_content_enum tag) -{ - pgp_key_t *key; - time_t duration; - - if (pgp_get_debug_level(__FILE__)) { - fprintf(stderr, "pgp_add_to_pubring (type %u)\n", tag); - } - switch(tag) { - case PGP_PTAG_CT_PUBLIC_KEY: - EXPAND_ARRAY(keyring, key); - key = &keyring->keys[keyring->keyc++]; - duration = key->key.pubkey.duration; - (void) memset(key, 0x0, sizeof(*key)); - key->type = tag; - pgp_keyid(key->sigid, PGP_KEY_ID_SIZE, pubkey, keyring->hashtype); - pgp_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype); - key->key.pubkey = *pubkey; - key->key.pubkey.duration = duration; - return 1; - case PGP_PTAG_CT_PUBLIC_SUBKEY: - /* subkey is not the first */ - key = &keyring->keys[keyring->keyc - 1]; - pgp_keyid(key->encid, PGP_KEY_ID_SIZE, pubkey, keyring->hashtype); - duration = key->key.pubkey.duration; - (void) memcpy(&key->enckey, pubkey, sizeof(key->enckey)); - key->enckey.duration = duration; - return 1; - default: - return 0; - } -} - -/* add a key to a secret keyring */ -int -pgp_add_to_secring(pgp_keyring_t *keyring, const pgp_seckey_t *seckey) -{ - const pgp_pubkey_t *pubkey; - pgp_key_t *key; - - if (pgp_get_debug_level(__FILE__)) { - fprintf(stderr, "pgp_add_to_secring\n"); - } - if (keyring->keyc > 0) { - key = &keyring->keys[keyring->keyc - 1]; - if (pgp_get_debug_level(__FILE__) && - key->key.pubkey.alg == PGP_PKA_DSA && - seckey->pubkey.alg == PGP_PKA_ELGAMAL) { - fprintf(stderr, "pgp_add_to_secring: found elgamal seckey\n"); - } - } - EXPAND_ARRAY(keyring, key); - key = &keyring->keys[keyring->keyc++]; - (void) memset(key, 0x0, sizeof(*key)); - pubkey = &seckey->pubkey; - pgp_keyid(key->sigid, PGP_KEY_ID_SIZE, pubkey, keyring->hashtype); - pgp_fingerprint(&key->sigfingerprint, pubkey, keyring->hashtype); - key->type = PGP_PTAG_CT_SECRET_KEY; - key->key.seckey = *seckey; - if (pgp_get_debug_level(__FILE__)) { - fprintf(stderr, "pgp_add_to_secring: keyc %u\n", keyring->keyc); - } - return 1; -} - -/* append one keyring to another */ -int -pgp_append_keyring(pgp_keyring_t *keyring, pgp_keyring_t *newring) -{ - unsigned i; - - for (i = 0 ; i < newring->keyc ; i++) { - EXPAND_ARRAY(keyring, key); - (void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i], - sizeof(newring->keys[i])); - keyring->keyc += 1; - } - return 1; -} diff --git a/libs/netpgp/mj.c b/libs/netpgp/mj.c deleted file mode 100644 index 3396303b..00000000 --- a/libs/netpgp/mj.c +++ /dev/null @@ -1,653 +0,0 @@ -/*- - * Copyright (c) 2010 Alistair Crooks - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "mj.h" -#include "defs-netpgp.h" - -/* save 'n' chars of 's' in malloc'd memory */ -static char * -strnsave(const char *s, int n, unsigned encoded) -{ - char *newc; - char *cp; - int i; - - if (n < 0) { - n = (int)strlen(s); - } - NEWARRAY(char, cp, n + n + 1, "strnsave", return NULL); - if (encoded) { - newc = cp; - for (i = 0 ; i < n ; i++) { - if ((uint8_t)*s == 0xac) { - *newc++ = (char)0xac; - *newc++ = '1'; - s += 1; - } else if (*s == '"') { - *newc++ = (char)0xac; - *newc++ = '2'; - s += 1; - } else if (*s == 0x0) { - *newc++ = (char)0xac; - *newc++ = '0'; - s += 1; - } else { - *newc++ = *s++; - } - } - *newc = 0x0; - } else { - (void) memcpy(cp, s, (unsigned)n); - cp[n] = 0x0; - } - return cp; -} - -/* look in an object for the item */ -static int -findentry(mj_t *atom, const char *name, const unsigned from, const unsigned incr) -{ - unsigned i; - - for (i = from ; i < atom->c ; i += incr) { - if (strcmp(name, atom->value.v[i].value.s) == 0) { - return i; - } - } - return -1; -} - -/* create a real number */ -static void -create_number(mj_t *atom, double d) -{ - char number[128]; - - atom->type = MJ_NUMBER; - atom->c = snprintf(number, sizeof(number), "%g", d); - atom->value.s = strnsave(number, (int)atom->c, MJ_HUMAN); -} - -/* create an integer */ -static void -create_integer(mj_t *atom, int64_t i) -{ - char number[128]; - - atom->type = MJ_NUMBER; - atom->c = snprintf(number, sizeof(number), "%" PRIi64, i); - atom->value.s = strnsave(number, (int)atom->c, MJ_HUMAN); -} - -/* create a string */ -static void -create_string(mj_t *atom, const char *s, ssize_t len) -{ - atom->type = MJ_STRING; - atom->value.s = strnsave(s, (int)len, MJ_JSON_ENCODE); - atom->c = (unsigned)strlen(atom->value.s); -} - -#define MJ_OPEN_BRACKET (MJ_OBJECT + 1) /* 8 */ -#define MJ_CLOSE_BRACKET (MJ_OPEN_BRACKET + 1) /* 9 */ -#define MJ_OPEN_BRACE (MJ_CLOSE_BRACKET + 1) /* 10 */ -#define MJ_CLOSE_BRACE (MJ_OPEN_BRACE + 1) /* 11 */ -#define MJ_COLON (MJ_CLOSE_BRACE + 1) /* 12 */ -#define MJ_COMMA (MJ_COLON + 1) /* 13 */ - -/* return the token type, and start and finish locations in string */ -static int -gettok(const char *s, int *from, int *to, int *tok) -{ - static regex_t tokregex; - regmatch_t matches[15]; - static int compiled; - - if (!compiled) { - compiled = 1; - (void) regcomp(&tokregex, - "[ \t\r\n]*(([+-]?[0-9]{1,21}(\\.[0-9]*)?([eE][-+][0-9]+)?)|" - "(\"([^\"]|\\\\.)*\")|(null)|(false)|(true)|([][{}:,]))", - REG_EXTENDED); - } - if (regexec(&tokregex, &s[*from = *to], 15, matches, 0) != 0) { - return *tok = -1; - } - *to = *from + (int)(matches[1].rm_eo); - *tok = (matches[2].rm_so >= 0) ? MJ_NUMBER : - (matches[5].rm_so >= 0) ? MJ_STRING : - (matches[7].rm_so >= 0) ? MJ_NULL : - (matches[8].rm_so >= 0) ? MJ_FALSE : - (matches[9].rm_so >= 0) ? MJ_TRUE : - (matches[10].rm_so < 0) ? -1 : - (s[*from + (int)(matches[10].rm_so)] == '[') ? MJ_OPEN_BRACKET : - (s[*from + (int)(matches[10].rm_so)] == ']') ? MJ_CLOSE_BRACKET : - (s[*from + (int)(matches[10].rm_so)] == '{') ? MJ_OPEN_BRACE : - (s[*from + (int)(matches[10].rm_so)] == '}') ? MJ_CLOSE_BRACE : - (s[*from + (int)(matches[10].rm_so)] == ':') ? MJ_COLON : - MJ_COMMA; - *from += (int)(matches[1].rm_so); - return *tok; -} - -/* minor function used to indent a JSON field */ -static void -indent(FILE *fp, unsigned depth, const char *trailer) -{ - unsigned i; - - for (i = 0 ; i < depth ; i++) { - (void) fprintf(fp, " "); - } - if (trailer) { - (void) fprintf(fp, "%s", trailer); - } -} - -/***************************************************************************/ - -/* return the number of entries in the array */ -int -mj_arraycount(mj_t *atom) -{ - return atom->c; -} - -/* create a new JSON node */ -int -mj_create(mj_t *atom, const char *type, ...) -{ - va_list args; - ssize_t len; - char *s; - - if (strcmp(type, "false") == 0) { - atom->type = MJ_FALSE; - atom->c = 0; - } else if (strcmp(type, "true") == 0) { - atom->type = MJ_TRUE; - atom->c = 1; - } else if (strcmp(type, "null") == 0) { - atom->type = MJ_NULL; - } else if (strcmp(type, "number") == 0) { - va_start(args, type); - create_number(atom, (double)va_arg(args, double)); - va_end(args); - } else if (strcmp(type, "integer") == 0) { - va_start(args, type); - create_integer(atom, (int64_t)va_arg(args, int64_t)); - va_end(args); - } else if (strcmp(type, "string") == 0) { - va_start(args, type); - s = (char *)va_arg(args, char *); - len = (size_t)va_arg(args, size_t); - va_end(args); - create_string(atom, s, len); - } else if (strcmp(type, "array") == 0) { - atom->type = MJ_ARRAY; - } else if (strcmp(type, "object") == 0) { - atom->type = MJ_OBJECT; - } else { - (void) fprintf(stderr, "weird type '%s'\n", type); - return 0; - } - return 1; -} - -/* put a JSON tree into a text string */ -int -mj_snprint(char *buf, size_t size, mj_t *atom, int encoded) -{ - unsigned i; - char *s; - char *bp; - int cc; - - switch(atom->type) { - case MJ_NULL: - return snprintf(buf, size, "null"); - case MJ_FALSE: - return snprintf(buf, size, "false"); - case MJ_TRUE: - return snprintf(buf, size, "true"); - case MJ_NUMBER: - return snprintf(buf, size, "%s", atom->value.s); - case MJ_STRING: - if (encoded) { - return snprintf(buf, size, "\"%s\"", atom->value.s); - } - for (bp = buf, *bp++ = '"', s = atom->value.s ; - (size_t)(bp - buf) < size && (unsigned)(s - atom->value.s) < atom->c ; ) { - if ((uint8_t)*s == 0xac) { - switch(s[1]) { - case '0': - *bp++ = 0x0; - s += 2; - break; - case '1': - *bp++ = (char)0xac; - s += 2; - break; - case '2': - *bp++ = '"'; - s += 2; - break; - default: - (void) fprintf(stderr, "unrecognised character '%02x'\n", (uint8_t)s[1]); - s += 1; - break; - } - } else { - *bp++ = *s++; - } - } - *bp++ = '"'; - *bp = 0x0; - return (int)(bp - buf) - 1; - case MJ_ARRAY: - cc = snprintf(buf, size, "[ "); - for (i = 0 ; i < atom->c ; i++) { - cc += mj_snprint(&buf[cc], size - cc, &atom->value.v[i], encoded); - if (i < atom->c - 1) { - cc += snprintf(&buf[cc], size - cc, ", "); - } - } - return cc + snprintf(&buf[cc], size - cc, "]\n"); - case MJ_OBJECT: - cc = snprintf(buf, size, "{ "); - for (i = 0 ; i < atom->c ; i += 2) { - cc += mj_snprint(&buf[cc], size - cc, &atom->value.v[i], encoded); - cc += snprintf(&buf[cc], size - cc, ":"); - cc += mj_snprint(&buf[cc], size - cc, &atom->value.v[i + 1], encoded); - if (i + 1 < atom->c - 1) { - cc += snprintf(&buf[cc], size - cc, ", "); - } - } - return cc + snprintf(&buf[cc], size - cc, "}\n"); - default: - (void) fprintf(stderr, "mj_snprint: weird type %d\n", atom->type); - return 0; - } -} - -/* allocate and print the atom */ -int -mj_asprint(char **buf, mj_t *atom, int encoded) -{ - int size; - - size = mj_string_size(atom); - if ((*buf = calloc(1, (unsigned)(size + 1))) == NULL) { - return -1; - } - return mj_snprint(*buf, (unsigned)(size + 1), atom, encoded) + 1; -} - -/* read into a JSON tree from a string */ -int -mj_parse(mj_t *atom, const char *s, int *from, int *to, int *tok) -{ - int i; - - switch(atom->type = *tok = gettok(s, from, to, tok)) { - case MJ_NUMBER: - atom->value.s = strnsave(&s[*from], *to - *from, MJ_JSON_ENCODE); - atom->c = atom->size = (unsigned)strlen(atom->value.s); - return gettok(s, from, to, tok); - case MJ_STRING: - atom->value.s = strnsave(&s[*from + 1], *to - *from - 2, MJ_HUMAN); - atom->c = atom->size = (unsigned)strlen(atom->value.s); - return gettok(s, from, to, tok); - case MJ_NULL: - case MJ_FALSE: - case MJ_TRUE: - atom->c = (unsigned)*to; - return gettok(s, from, to, tok); - case MJ_OPEN_BRACKET: - mj_create(atom, "array"); - ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0); - while (mj_parse(&atom->value.v[atom->c++], s, from, to, tok) >= 0 && *tok != MJ_CLOSE_BRACKET) { - if (*tok != MJ_COMMA) { - (void) fprintf(stderr, "1. expected comma (got %d) at '%s'\n", *tok, &s[*from]); - break; - } - ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0); - } - return gettok(s, from, to, tok); - case MJ_OPEN_BRACE: - mj_create(atom, "object"); - ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0); - for (i = 0 ; mj_parse(&atom->value.v[atom->c++], s, from, to, tok) >= 0 && *tok != MJ_CLOSE_BRACE ; i++) { - if (((i % 2) == 0 && *tok != MJ_COLON) || ((i % 2) == 1 && *tok != MJ_COMMA)) { - (void) fprintf(stderr, "2. expected comma (got %d) at '%s'\n", *tok, &s[*from]); - break; - } - ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_parse()", return 0); - } - return gettok(s, from, to, tok); - default: - return *tok; - } -} - -/* return the index of the item which corresponds to the name in the array */ -int -mj_object_find(mj_t *atom, const char *name, const unsigned from, const unsigned incr) -{ - return findentry(atom, name, from, incr); -} - -/* find an atom in a composite mj JSON node */ -mj_t * -mj_get_atom(mj_t *atom, ...) -{ - unsigned i; - va_list args; - char *name; - int n; - - switch(atom->type) { - case MJ_ARRAY: - va_start(args, atom); - i = va_arg(args, int); - va_end(args); - return (i < atom->c) ? &atom->value.v[i] : NULL; - case MJ_OBJECT: - va_start(args, atom); - name = va_arg(args, char *); - va_end(args); - return ((n = findentry(atom, name, 0, 2)) >= 0) ? &atom->value.v[n + 1] : NULL; - default: - return NULL; - } -} - -/* perform a deep copy on an mj JSON atom */ -int -mj_deepcopy(mj_t *dst, mj_t *src) -{ - unsigned i; - - switch(src->type) { - case MJ_FALSE: - case MJ_TRUE: - case MJ_NULL: - (void) memcpy(dst, src, sizeof(*dst)); - return 1; - case MJ_STRING: - case MJ_NUMBER: - (void) memcpy(dst, src, sizeof(*dst)); - dst->value.s = strnsave(src->value.s, -1, MJ_HUMAN); - dst->c = dst->size = (unsigned)strlen(dst->value.s); - return 1; - case MJ_ARRAY: - case MJ_OBJECT: - (void) memcpy(dst, src, sizeof(*dst)); - NEWARRAY(mj_t, dst->value.v, dst->size, "mj_deepcopy()", return 0); - for (i = 0 ; i < src->c ; i++) { - if (!mj_deepcopy(&dst->value.v[i], &src->value.v[i])) { - return 0; - } - } - return 1; - default: - (void) fprintf(stderr, "weird type '%d'\n", src->type); - return 0; - } -} - -/* do a deep delete on the object */ -void -mj_delete(mj_t *atom) -{ - unsigned i; - - switch(atom->type) { - case MJ_STRING: - case MJ_NUMBER: - free(atom->value.s); - break; - case MJ_ARRAY: - case MJ_OBJECT: - for (i = 0 ; i < atom->c ; i++) { - mj_delete(&atom->value.v[i]); - } - /* XXX - agc - causing problems? free(atom->value.v); */ - break; - default: - break; - } -} - -/* return the string size needed for the textual output of the JSON node */ -int -mj_string_size(mj_t *atom) -{ - unsigned i; - int cc; - - switch(atom->type) { - case MJ_NULL: - case MJ_TRUE: - return 4; - case MJ_FALSE: - return 5; - case MJ_NUMBER: - return atom->c; - case MJ_STRING: - return atom->c + 2; - case MJ_ARRAY: - for (cc = 2, i = 0 ; i < atom->c ; i++) { - cc += mj_string_size(&atom->value.v[i]); - if (i < atom->c - 1) { - cc += 2; - } - } - return cc + 1 + 1; - case MJ_OBJECT: - for (cc = 2, i = 0 ; i < atom->c ; i += 2) { - cc += mj_string_size(&atom->value.v[i]) + 1 + mj_string_size(&atom->value.v[i + 1]); - if (i + 1 < atom->c - 1) { - cc += 2; - } - } - return cc + 1 + 1; - default: - (void) fprintf(stderr, "mj_string_size: weird type %d\n", atom->type); - return 0; - } -} - -/* create a new atom, and append it to the array or object */ -int -mj_append(mj_t *atom, const char *type, ...) -{ - va_list args; - ssize_t len; - char *s; - - if (atom->type != MJ_ARRAY && atom->type != MJ_OBJECT) { - return 0; - } - ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_append()", return 0); - va_start(args, type); - if (strcmp(type, "string") == 0) { - s = (char *)va_arg(args, char *); - len = (ssize_t)va_arg(args, ssize_t); - create_string(&atom->value.v[atom->c++], s, len); - } else if (strcmp(type, "integer") == 0) { - create_integer(&atom->value.v[atom->c++], (int64_t)va_arg(args, int64_t)); - } else if (strcmp(type, "object") == 0 || strcmp(type, "array") == 0) { - mj_deepcopy(&atom->value.v[atom->c++], (mj_t *)va_arg(args, mj_t *)); - } else { - (void) fprintf(stderr, "mj_append: weird type '%s'\n", type); - } - va_end(args); - return 1; -} - -/* append a field to an object */ -int -mj_append_field(mj_t *atom, const char *name, const char *type, ...) -{ - va_list args; - ssize_t len; - char *s; - - if (atom->type != MJ_OBJECT) { - return 0; - } - mj_append(atom, "string", name, -1); - ALLOC(mj_t, atom->value.v, atom->size, atom->c, 10, 10, "mj_append_field()", return 0); - va_start(args, type); - if (strcmp(type, "string") == 0) { - s = (char *)va_arg(args, char *); - len = (ssize_t)va_arg(args, ssize_t); - create_string(&atom->value.v[atom->c++], s, len); - } else if (strcmp(type, "integer") == 0) { - create_integer(&atom->value.v[atom->c++], (int64_t)va_arg(args, int64_t)); - } else if (strcmp(type, "object") == 0 || strcmp(type, "array") == 0) { - mj_deepcopy(&atom->value.v[atom->c++], (mj_t *)va_arg(args, mj_t *)); - } else { - (void) fprintf(stderr, "mj_append_field: weird type '%s'\n", type); - } - va_end(args); - return 1; -} - -/* make sure a JSON object is politically correct */ -int -mj_lint(mj_t *obj) -{ - unsigned i; - int ret; - - switch(obj->type) { - case MJ_NULL: - case MJ_FALSE: - case MJ_TRUE: - if (obj->value.s != NULL) { - (void) fprintf(stderr, "null/false/true: non zero string\n"); - return 0; - } - return 1; - case MJ_NUMBER: - case MJ_STRING: - if (obj->c > obj->size) { - (void) fprintf(stderr, "string/number lint c (%u) > size (%u)\n", obj->c, obj->size); - return 0; - } - return 1; - case MJ_ARRAY: - case MJ_OBJECT: - if (obj->c > obj->size) { - (void) fprintf(stderr, "array/object lint c (%u) > size (%u)\n", obj->c, obj->size); - return 0; - } - for (ret = 1, i = 0 ; i < obj->c ; i++) { - if (!mj_lint(&obj->value.v[i])) { - (void) fprintf(stderr, "array/object lint found at %d of %p\n", i, obj); - ret = 0; - } - } - return ret; - default: - (void) fprintf(stderr, "problem type %d in %p\n", obj->type, obj); - return 0; - } -} - -/* pretty-print a JSON struct - can be called recursively */ -int -mj_pretty(mj_t *mj, void *vp, unsigned depth, const char *trailer) -{ - unsigned i; - FILE *fp; - char *s; - - fp = (FILE *)vp; - switch(mj->type) { - case MJ_NUMBER: - case MJ_TRUE: - case MJ_FALSE: - case MJ_NULL: - indent(fp, depth, mj->value.s); - break; - case MJ_STRING: - indent(fp, depth, NULL); - mj_asprint(&s, mj, MJ_HUMAN); - (void) fprintf(fp, "\"%s\"", s); - free(s); - break; - case MJ_ARRAY: - indent(fp, depth, "[\n"); - for (i = 0 ; i < mj->c ; i++) { - mj_pretty(&mj->value.v[i], fp, depth + 1, (i < mj->c - 1) ? ",\n" : "\n"); - } - indent(fp, depth, "]"); - break; - case MJ_OBJECT: - indent(fp, depth, "{\n"); - for (i = 0 ; i < mj->c ; i += 2) { - mj_pretty(&mj->value.v[i], fp, depth + 1, " : "); - mj_pretty(&mj->value.v[i + 1], fp, 0, (i < mj->c - 2) ? ",\n" : "\n"); - } - indent(fp, depth, "}"); - break; - } - indent(fp, 0, trailer); - return 1; -} - -/* show the contents of the simple atom as a string representation */ -const char * -mj_string_rep(mj_t *atom) -{ - if (atom == NULL) { - return 0; - } - switch(atom->type) { - case MJ_STRING: - case MJ_NUMBER: - return atom->value.s; - case MJ_NULL: - return "null"; - case MJ_FALSE: - return "false"; - case MJ_TRUE: - return "true"; - default: - return NULL; - } -} diff --git a/libs/netpgp/mj.h b/libs/netpgp/mj.h deleted file mode 100644 index b22913bd..00000000 --- a/libs/netpgp/mj.h +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * Copyright (c) 2010,2011 Alistair Crooks - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef MJ_H_ -#define MJ_H_ 20110607 - -enum { - MJ_NULL = 1, - MJ_FALSE = 2, - MJ_TRUE = 3, - MJ_NUMBER = 4, - MJ_STRING = 5, - MJ_ARRAY = 6, - MJ_OBJECT = 7, - - MJ_LAST = MJ_OBJECT, - - MJ_HUMAN = 0, /* human readable, not encoded */ - MJ_JSON_ENCODE = 1 /* encoded JSON */ -}; - -/* a minimalist JSON node */ -typedef struct mj_t { - unsigned type; /* type of JSON node */ - unsigned c; /* # of chars */ - unsigned size; /* size of array */ - union { - struct mj_t *v; /* sub-objects */ - char *s; /* string value */ - } value; -} mj_t; - -/* creation and deletion */ -int mj_create(mj_t */*atom*/, const char */*type*/, .../*value*/); -int mj_parse(mj_t */*atom*/, const char */*s*/, int */*from*/, - int */*to*/, int */*token*/); -int mj_append(mj_t */*atom*/, const char */*type*/, .../*value*/); -int mj_append_field(mj_t */*atom*/, const char */*name*/, const char */*type*/, - .../*value*/); -int mj_deepcopy(mj_t */*dst*/, mj_t */*src*/); -void mj_delete(mj_t */*atom*/); - -/* JSON object access */ -int mj_arraycount(mj_t */*atom*/); -int mj_object_find(mj_t */*atom*/, const char */*name*/, - const unsigned /*from*/, const unsigned /*incr*/); -mj_t *mj_get_atom(mj_t */*atom*/, ...); -int mj_lint(mj_t */*atom*/); - -/* textual output */ -int mj_snprint(char */*buf*/, size_t /*size*/, mj_t */*atom*/, int /*encoded*/); -int mj_asprint(char **/*bufp*/, mj_t */*atom*/, int /*encoded*/); -int mj_string_size(mj_t */*atom*/); -int mj_pretty(mj_t */*atom*/, void */*fp*/, unsigned /*depth*/, - const char */*trailer*/); -const char *mj_string_rep(mj_t */*atom*/); - -#endif diff --git a/libs/netpgp/netpgp.c b/libs/netpgp/netpgp.c deleted file mode 100644 index 706dc6b8..00000000 --- a/libs/netpgp/netpgp.c +++ /dev/null @@ -1,1978 +0,0 @@ -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Alistair Crooks (agc@NetBSD.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "config-netpgp.h" - -#ifdef HAVE_SYS_CDEFS_H -#include -#endif - -#if defined(__NetBSD__) -__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: netpgp.c,v 1.96 2012/02/22 06:58:54 agc Exp $"); -#endif - -#include -#include -#include -#include - -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include - -#ifdef HAVE_LIMITS_H -#include -#endif - -#include - -#include "packet-netpgp.h" -#include "packet-parse.h" -#include "keyring-netpgp.h" -#include "errors-netpgp.h" -#include "packet-show.h" -#include "create-netpgp.h" -#include "netpgpsdk.h" -#include "memory-netpgp.h" -#include "validate-netpgp.h" -#include "readerwriter-netpgp.h" -#include "netpgpdefs.h" -#include "crypto-netpgp.h" -//#include "ssh2pgp.h" -#include "defs-netpgp.h" - -#if defined(ANDROID) || defined(__ANDROID__) -char * getpass (const char *prompt) -{ - return strdup("foo"); -} -#endif - -/* read any gpg config file */ -#if 0 ////// -static int -conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length) -{ - regmatch_t matchv[10]; - regex_t keyre; - char buf[BUFSIZ]; - FILE *fp; - - __PGP_USED(netpgp); - (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); - if ((fp = fopen(buf, "r")) == NULL) { - return 0; - } - (void) memset(&keyre, 0x0, sizeof(keyre)); - (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", - REG_EXTENDED); - while (fgets(buf, (int)sizeof(buf), fp) != NULL) { - if (regexec(&keyre, buf, 10, matchv, 0) == 0) { - (void) memcpy(userid, &buf[(int)matchv[1].rm_so], - MIN((unsigned)(matchv[1].rm_eo - - matchv[1].rm_so), length)); - if (netpgp->passfp == NULL) { - (void) fprintf(stderr, - "netpgp: default key set to \"%.*s\"\n", - (int)(matchv[1].rm_eo - matchv[1].rm_so), - &buf[(int)matchv[1].rm_so]); - } - } - } - (void) fclose(fp); - regfree(&keyre); - return 1; -} -#endif ////// - -/* small function to pretty print an 8-character raw userid */ -static char * -userid_to_id(const uint8_t *userid, char *id) -{ - static const char *hexes = "0123456789abcdef"; - int i; - - for (i = 0; i < 8 ; i++) { - id[i * 2] = hexes[(unsigned)(userid[i] & 0xf0) >> 4]; - id[(i * 2) + 1] = hexes[userid[i] & 0xf]; - } - id[8 * 2] = 0x0; - return id; -} - -/* print out the successful signature information */ -static void -resultp(pgp_io_t *io, - const char *f, - pgp_validation_t *res, - pgp_keyring_t *ring) -{ - const pgp_key_t *key; - pgp_pubkey_t *sigkey; - unsigned from; - unsigned i; - time_t t; - char id[MAX_ID_LENGTH + 1]; - - for (i = 0; i < res->validc; i++) { - (void) fprintf(io->res, - "Good signature for %s made %s", - (f) ? f : "", - ctime(&res->valid_sigs[i].birthtime)); - if (res->duration > 0) { - t = res->birthtime + res->duration; - (void) fprintf(io->res, "Valid until %s", ctime(&t)); - } - (void) fprintf(io->res, - "using %s key %s\n", - pgp_show_pka(res->valid_sigs[i].key_alg), - userid_to_id(res->valid_sigs[i].signer_id, id)); - from = 0; - key = pgp_getkeybyid(io, ring, - (const uint8_t *) res->valid_sigs[i].signer_id, - &from, &sigkey); - if (sigkey == &key->enckey) { - (void) fprintf(io->res, - "WARNING: signature for %s made with encryption key\n", - (f) ? f : ""); - } - pgp_print_keydata(io, ring, key, "signature ", &key->key.pubkey, 0); - } -} - -/* check there's enough space in the arrays */ -static int -size_arrays(netpgp_t *netpgp, unsigned needed) -{ - char **temp; - - if (netpgp->size == 0) { - /* only get here first time around */ - netpgp->size = needed; - if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { - (void) fprintf(stderr, "size_arrays: bad alloc\n"); - return 0; - } - if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { - free(netpgp->name); - (void) fprintf(stderr, "size_arrays: bad alloc\n"); - return 0; - } - } else if (netpgp->c == netpgp->size) { - /* only uses 'needed' when filled array */ - netpgp->size += needed; - temp = realloc(netpgp->name, sizeof(char *) * needed); - if (temp == NULL) { - (void) fprintf(stderr, "size_arrays: bad alloc\n"); - return 0; - } - netpgp->name = temp; - temp = realloc(netpgp->value, sizeof(char *) * needed); - if (temp == NULL) { - (void) fprintf(stderr, "size_arrays: bad alloc\n"); - return 0; - } - netpgp->value = temp; - } - return 1; -} - -/* find the name in the array */ -static int -findvar(netpgp_t *netpgp, const char *name) -{ - unsigned i; - - for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { - } - return (i == netpgp->c) ? -1 : (int)i; -} - -/* read a keyring and return it */ -#if 0 ////// -static void * -readkeyring(netpgp_t *netpgp, const char *name) -{ - pgp_keyring_t *keyring; - const unsigned noarmor = 0; - char f[MAXPATHLEN]; - char *filename; - char *homedir; - - homedir = netpgp_getvar(netpgp, "homedir"); - if ((filename = netpgp_getvar(netpgp, name)) == NULL) { - (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); - filename = f; - } - if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { - (void) fprintf(stderr, "readkeyring: bad alloc\n"); - return NULL; - } - if (!pgp_keyring_fileread(keyring, noarmor, filename)) { - free(keyring); - (void) fprintf(stderr, "Can't read %s %s\n", name, filename); - return NULL; - } - netpgp_setvar(netpgp, name, filename); - return keyring; -} -#endif ////// - -/* read keys from ssh key files */ -#if 0 ////// -static int -readsshkeys(netpgp_t *netpgp, char *homedir, const char *needseckey) -{ - pgp_keyring_t *pubring; - pgp_keyring_t *secring; - struct stat st; - unsigned hashtype; - char *hash; - char f[MAXPATHLEN]; - char *filename; - - if ((filename = netpgp_getvar(netpgp, "sshkeyfile")) == NULL) { - /* set reasonable default for RSA key */ - (void) snprintf(f, sizeof(f), "%s/id_rsa.pub", homedir); - filename = f; - } else if (strcmp(&filename[strlen(filename) - 4], ".pub") != 0) { - /* got ssh keys, check for pub file name */ - (void) snprintf(f, sizeof(f), "%s.pub", filename); - filename = f; - } - /* check the pub file exists */ - if (stat(filename, &st) != 0) { - (void) fprintf(stderr, "readsshkeys: bad pubkey filename '%s'\n", filename); - return 0; - } - if ((pubring = calloc(1, sizeof(*pubring))) == NULL) { - (void) fprintf(stderr, "readsshkeys: bad alloc\n"); - return 0; - } - /* openssh2 keys use md5 by default */ - hashtype = PGP_HASH_MD5; - if ((hash = netpgp_getvar(netpgp, "hash")) != NULL) { - /* openssh 2 hasn't really caught up to anything else yet */ - if (netpgp_strcasecmp(hash, "md5") == 0) { - hashtype = PGP_HASH_MD5; - } else if (netpgp_strcasecmp(hash, "sha1") == 0) { - hashtype = PGP_HASH_SHA1; - } else if (netpgp_strcasecmp(hash, "sha256") == 0) { - hashtype = PGP_HASH_SHA256; - } - } - if (!pgp_ssh2_readkeys(netpgp->io, pubring, NULL, filename, NULL, hashtype)) { - free(pubring); - (void) fprintf(stderr, "readsshkeys: can't read %s\n", - filename); - return 0; - } - if (netpgp->pubring == NULL) { - netpgp->pubring = pubring; - } else { - pgp_append_keyring(netpgp->pubring, pubring); - } - if (needseckey) { - netpgp_setvar(netpgp, "sshpubfile", filename); - /* try to take the ".pub" off the end */ - if (filename == f) { - f[strlen(f) - 4] = 0x0; - } else { - (void) snprintf(f, sizeof(f), "%.*s", - (int)strlen(filename) - 4, filename); - filename = f; - } - if ((secring = calloc(1, sizeof(*secring))) == NULL) { - free(pubring); - (void) fprintf(stderr, "readsshkeys: bad alloc\n"); - return 0; - } - if (!pgp_ssh2_readkeys(netpgp->io, pubring, secring, NULL, filename, hashtype)) { - free(pubring); - free(secring); - (void) fprintf(stderr, "readsshkeys: can't read sec %s\n", filename); - return 0; - } - netpgp->secring = secring; - netpgp_setvar(netpgp, "sshsecfile", filename); - } - return 1; -} -#endif ////// - -/* get the uid of the first key in the keyring */ -#if 0 ////// -static int -get_first_ring(pgp_keyring_t *ring, char *id, size_t len, int last) -{ - uint8_t *src; - int i; - int n; - - if (ring == NULL) { - return 0; - } - (void) memset(id, 0x0, len); - src = ring->keys[(last) ? ring->keyc - 1 : 0].sigid; - for (i = 0, n = 0 ; i < PGP_KEY_ID_SIZE ; i += 2) { - n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); - } - id[n] = 0x0; - return 1; -} -#endif ////// - -/* find the time - in a specific %Y-%m-%d format - using a regexp */ -static int -grabdate(char *s, int64_t *t) -{ - static regex_t r; - static int compiled; - regmatch_t matches[10]; - struct tm tm; - - if (!compiled) { - compiled = 1; - (void) regcomp(&r, "([0-9][0-9][0-9][0-9])[-/]([0-9][0-9])[-/]([0-9][0-9])", REG_EXTENDED); - } - if (regexec(&r, s, 10, matches, 0) == 0) { - (void) memset(&tm, 0x0, sizeof(tm)); - tm.tm_year = (int)strtol(&s[(int)matches[1].rm_so], NULL, 10); - tm.tm_mon = (int)strtol(&s[(int)matches[2].rm_so], NULL, 10) - 1; - tm.tm_mday = (int)strtol(&s[(int)matches[3].rm_so], NULL, 10); - *t = mktime(&tm); - return 1; - } - return 0; -} - -/* get expiration in seconds */ -static uint64_t -get_duration(char *s) -{ - uint64_t now; - int64_t t; - char *mult; - - if (s == NULL) { - return 0; - } - now = (uint64_t)strtoull(s, NULL, 10); - if ((mult = strchr("hdwmy", s[strlen(s) - 1])) != NULL) { - switch(*mult) { - case 'h': - return now * 60 * 60; - case 'd': - return now * 60 * 60 * 24; - case 'w': - return now * 60 * 60 * 24 * 7; - case 'm': - return now * 60 * 60 * 24 * 31; - case 'y': - return now * 60 * 60 * 24 * 365; - } - } - if (grabdate(s, &t)) { - return t; - } - return (uint64_t)strtoll(s, NULL, 10); -} - -/* get birthtime in seconds */ -static int64_t -get_birthtime(char *s) -{ - int64_t t; - - if (s == NULL) { - return time(NULL); - } - if (grabdate(s, &t)) { - return t; - } - return (uint64_t)strtoll(s, NULL, 10); -} - -/* resolve the userid */ -static const pgp_key_t * -resolve_userid(netpgp_t *netpgp, const pgp_keyring_t *keyring, const char *userid) -{ - const pgp_key_t *key; - pgp_io_t *io; - - if (userid == NULL) { - userid = netpgp_getvar(netpgp, "userid"); - if (userid == NULL) - return NULL; - } else if (userid[0] == '0' && userid[1] == 'x') { - userid += 2; - } - io = netpgp->io; - if ((key = pgp_getkeybyname(io, keyring, userid)) == NULL) { - (void) fprintf(io->errs, "Can't find key '%s'\n", userid); - } - return key; -} - -/* append a key to a keyring */ -#if 0 ////// -static int -appendkey(pgp_io_t *io, pgp_key_t *key, char *ringfile) -{ - pgp_output_t *create; - const unsigned noarmor = 0; - int fd; - - if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { - fd = pgp_setup_file_write(&create, ringfile, 0); - } - if (fd < 0) { - (void) fprintf(io->errs, "can't open pubring '%s'\n", ringfile); - return 0; - } - if (!pgp_write_xfer_pubkey(create, key, noarmor)) { - (void) fprintf(io->errs, "Cannot write pubkey\n"); - return 0; - } - pgp_teardown_file_write(create, fd); - return 1; -} -#endif ////// - -/* return 1 if the file contains ascii-armoured text */ -static unsigned -isarmoured(pgp_io_t *io, const char *f, const void *memory, const char *text) -{ - regmatch_t matches[10]; - unsigned armoured; - regex_t r; - FILE *fp; - char buf[BUFSIZ]; - - armoured = 0; - (void) regcomp(&r, text, REG_EXTENDED); - if (f) { - if ((fp = fopen(f, "r")) == NULL) { - (void) fprintf(io->errs, "isarmoured: can't open '%s'\n", f); - regfree(&r); - return 0; - } - if (fgets(buf, (int)sizeof(buf), fp) != NULL) { - if (regexec(&r, buf, 10, matches, 0) == 0) { - armoured = 1; - } - } - (void) fclose(fp); - } else { - if (regexec(&r, memory, 10, matches, 0) == 0) { - armoured = 1; - } - } - regfree(&r); - return armoured; -} - -/* vararg print function */ -static void -p(FILE *fp, const char *s, ...) -{ - va_list args; - - va_start(args, s); - while (s != NULL) { - (void) fprintf(fp, "%s", s); - s = va_arg(args, char *); - } - va_end(args); -} - -/* print a JSON object to the FILE stream */ -static void -pobj(FILE *fp, mj_t *obj, int depth) -{ - unsigned i; - char *s; - - if (obj == NULL) { - (void) fprintf(stderr, "No object found\n"); - return; - } - for (i = 0 ; i < (unsigned)depth ; i++) { - p(fp, " ", NULL); - } - switch(obj->type) { - case MJ_NULL: - case MJ_FALSE: - case MJ_TRUE: - p(fp, (obj->type == MJ_NULL) ? "null" : (obj->type == MJ_FALSE) ? "false" : "true", NULL); - break; - case MJ_NUMBER: - p(fp, obj->value.s, NULL); - break; - case MJ_STRING: - if ((i = mj_asprint(&s, obj, MJ_HUMAN)) > 2) { - (void) fprintf(fp, "%.*s", (int)i - 2, &s[1]); - free(s); - } - break; - case MJ_ARRAY: - for (i = 0 ; i < obj->c ; i++) { - pobj(fp, &obj->value.v[i], depth + 1); - if (i < obj->c - 1) { - (void) fprintf(fp, ", "); - } - } - (void) fprintf(fp, "\n"); - break; - case MJ_OBJECT: - for (i = 0 ; i < obj->c ; i += 2) { - pobj(fp, &obj->value.v[i], depth + 1); - p(fp, ": ", NULL); - pobj(fp, &obj->value.v[i + 1], 0); - if (i < obj->c - 1) { - p(fp, ", ", NULL); - } - } - p(fp, "\n", NULL); - break; - default: - break; - } -} - -/* return the time as a string */ -static char * -ptimestr(char *dest, size_t size, time_t t) -{ - struct tm *tm; - - tm = gmtime(&t); - (void) snprintf(dest, size, "%04d-%02d-%02d", - tm->tm_year + 1900, - tm->tm_mon + 1, - tm->tm_mday); - return dest; -} - -/* format a JSON object */ -static void -format_json_key(FILE *fp, mj_t *obj, const int psigs) -{ - int64_t birthtime; - int64_t duration; - time_t now; - char tbuf[32]; - char *s; - mj_t *sub; - int i; - - if (pgp_get_debug_level(__FILE__)) { - mj_asprint(&s, obj, MJ_HUMAN); - (void) fprintf(stderr, "formatobj: json is '%s'\n", s); - free(s); - } - if (obj->c == 2 && obj->value.v[1].type == MJ_STRING && - strcmp(obj->value.v[1].value.s, "[REVOKED]") == 0) { - /* whole key has been rovoked - just return */ - return; - } - pobj(fp, &obj->value.v[mj_object_find(obj, "header", 0, 2) + 1], 0); - p(fp, " ", NULL); - pobj(fp, &obj->value.v[mj_object_find(obj, "key bits", 0, 2) + 1], 0); - p(fp, "/", NULL); - pobj(fp, &obj->value.v[mj_object_find(obj, "pka", 0, 2) + 1], 0); - p(fp, " ", NULL); - pobj(fp, &obj->value.v[mj_object_find(obj, "key id", 0, 2) + 1], 0); - birthtime = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "birthtime", 0, 2) + 1].value.s, NULL, 10); - p(fp, " ", ptimestr(tbuf, sizeof(tbuf), birthtime), NULL); - duration = (int64_t)strtoll(obj->value.v[mj_object_find(obj, "duration", 0, 2) + 1].value.s, NULL, 10); - if (duration > 0) { - now = time(NULL); - p(fp, " ", (birthtime + duration < now) ? "[EXPIRED " : "[EXPIRES ", - ptimestr(tbuf, sizeof(tbuf), birthtime + duration), "]", NULL); - } - p(fp, "\n", "Key fingerprint: ", NULL); - pobj(fp, &obj->value.v[mj_object_find(obj, "fingerprint", 0, 2) + 1], 0); - p(fp, "\n", NULL); - /* go to field after \"duration\" */ - for (i = mj_object_find(obj, "duration", 0, 2) + 2; i < mj_arraycount(obj) ; i += 2) { - if (strcmp(obj->value.v[i].value.s, "uid") == 0) { - sub = &obj->value.v[i + 1]; - p(fp, "uid", NULL); - pobj(fp, &sub->value.v[0], (psigs) ? 4 : 14); /* human name */ - pobj(fp, &sub->value.v[1], 1); /* any revocation */ - p(fp, "\n", NULL); - } else if (strcmp(obj->value.v[i].value.s, "encryption") == 0) { - sub = &obj->value.v[i + 1]; - p(fp, "encryption", NULL); - pobj(fp, &sub->value.v[0], 1); /* size */ - p(fp, "/", NULL); - pobj(fp, &sub->value.v[1], 0); /* alg */ - p(fp, " ", NULL); - pobj(fp, &sub->value.v[2], 0); /* id */ - p(fp, " ", ptimestr(tbuf, sizeof(tbuf), - (time_t)strtoll(sub->value.v[3].value.s, NULL, 10)), - "\n", NULL); - } else if (strcmp(obj->value.v[i].value.s, "sig") == 0) { - sub = &obj->value.v[i + 1]; - p(fp, "sig", NULL); - pobj(fp, &sub->value.v[0], 8); /* size */ - p(fp, " ", ptimestr(tbuf, sizeof(tbuf), - (time_t)strtoll(sub->value.v[1].value.s, NULL, 10)), - " ", NULL); /* time */ - pobj(fp, &sub->value.v[2], 0); /* human name */ - p(fp, "\n", NULL); - } else { - fprintf(stderr, "weird '%s'\n", obj->value.v[i].value.s); - pobj(fp, &obj->value.v[i], 0); /* human name */ - } - } - p(fp, "\n", NULL); -} - -/* save a pgp pubkey to a temp file */ -static int -savepubkey(char *res, char *f, size_t size) -{ - size_t len; - int cc; - int wc; - int fd; - - (void) snprintf(f, size, "/tmp/pgp2ssh.XXXXXXX"); - if ((fd = mkstemp(f)) < 0) { - (void) fprintf(stderr, "can't create temp file '%s'\n", f); - return 0; - } - len = strlen(res); - for (cc = 0 ; (wc = (int)write(fd, &res[cc], len - (size_t)cc)) > 0 ; cc += wc) { - } - (void) close(fd); - return 1; -} - -/* format a uint32_t */ -static int -formatu32(uint8_t *buffer, uint32_t value) -{ - buffer[0] = (uint8_t)(value >> 24) & 0xff; - buffer[1] = (uint8_t)(value >> 16) & 0xff; - buffer[2] = (uint8_t)(value >> 8) & 0xff; - buffer[3] = (uint8_t)value & 0xff; - return sizeof(uint32_t); -} - -/* format a string as (len, string) */ -static int -formatstring(char *buffer, const uint8_t *s, size_t len) -{ - int cc; - - cc = formatu32((uint8_t *)buffer, (uint32_t)len); - (void) memcpy(&buffer[cc], s, len); - return cc + (int)len; -} - -/* format a bignum, checking for "interesting" high bit values */ -static int -formatbignum(char *buffer, BIGNUM *bn) -{ - size_t len; - uint8_t *cp; - int cc; - - len = (size_t) BN_num_bytes(bn); - if ((cp = calloc(1, len + 1)) == NULL) { - (void) fprintf(stderr, "calloc failure in formatbignum\n"); - return 0; - } - (void) BN_bn2bin(bn, cp + 1); - cp[0] = 0x0; - cc = (cp[1] & 0x80) ? formatstring(buffer, cp, len + 1) : formatstring(buffer, &cp[1], len); - free(cp); - return cc; -} - -#define MAX_PASSPHRASE_ATTEMPTS 3 -#define INFINITE_ATTEMPTS -1 - -/* get the passphrase from the user */ -#if 0 ////// -static int -find_passphrase(FILE *passfp, const char *id, char *passphrase, size_t size, int attempts) -{ - char prompt[BUFSIZ]; - char buf[128]; - char *cp; - int cc; - int i; - - if (passfp) { - if (fgets(passphrase, (int)size, passfp) == NULL) { - return 0; - } - return (int)strlen(passphrase); - } - for (i = 0 ; i < attempts ; i++) { - (void) snprintf(prompt, sizeof(prompt), "Enter passphrase for %.16s: ", id); - if ((cp = getpass(prompt)) == NULL) { - break; - } - cc = snprintf(buf, sizeof(buf), "%s", cp); - (void) snprintf(prompt, sizeof(prompt), "Repeat passphrase for %.16s: ", id); - if ((cp = getpass(prompt)) == NULL) { - break; - } - cc = snprintf(passphrase, size, "%s", cp); - if (strcmp(buf, passphrase) == 0) { - (void) memset(buf, 0x0, sizeof(buf)); - return cc; - } - } - (void) memset(buf, 0x0, sizeof(buf)); - (void) memset(passphrase, 0x0, size); - return 0; -} -#endif ////// - -/***************************************************************************/ -/* exported functions start here */ -/***************************************************************************/ - -/* initialise a netpgp_t structure */ -#if 0 ////// -int -netpgp_init(netpgp_t *netpgp) -{ - pgp_io_t *io; - time_t t; - char id[MAX_ID_LENGTH]; - char *homedir; - char *userid; - char *stream; - char *passfd; - char *results; - int coredumps; - int last; - -#ifdef HAVE_SYS_RESOURCE_H - struct rlimit limit; - - coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; - if (!coredumps) { - (void) memset(&limit, 0x0, sizeof(limit)); - if (setrlimit(RLIMIT_CORE, &limit) != 0) { - (void) fprintf(stderr, - "netpgp: warning - can't turn off core dumps\n"); - coredumps = 1; - } - } -#else - coredumps = 1; -#endif - if ((io = calloc(1, sizeof(*io))) == NULL) { - (void) fprintf(stderr, "netpgp_init: bad alloc\n"); - return 0; - } - io->outs = stdout; - if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && - strcmp(stream, "") == 0) { - io->outs = stderr; - } - io->errs = stderr; - if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && - strcmp(stream, "") == 0) { - io->errs = stdout; - } - if ((results = netpgp_getvar(netpgp, "res")) == NULL) { - io->res = io->errs; - } else if (strcmp(results, "") == 0) { - io->res = stdout; - } else if (strcmp(results, "") == 0) { - io->res = stderr; - } else { - if ((io->res = fopen(results, "w")) == NULL) { - (void) fprintf(io->errs, "Can't open results %s for writing\n", - results); - free(io); - return 0; - } - } - netpgp->io = io; - /* get passphrase from an fd */ - if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && - (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { - (void) fprintf(io->errs, "Can't open fd %s for reading\n", - passfd); - return 0; - } - /* warn if core dumps are enabled */ - if (coredumps) { - (void) fprintf(io->errs, - "netpgp: warning: core dumps enabled\n"); - } - /* get home directory - where keyrings are in a subdir */ - if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { - (void) fprintf(io->errs, "netpgp: bad homedir\n"); - return 0; - } - if (netpgp_getvar(netpgp, "ssh keys") == NULL) { - /* read from ordinary pgp keyrings */ - netpgp->pubring = readkeyring(netpgp, "pubring"); - if (netpgp->pubring == NULL) { - (void) fprintf(io->errs, "Can't read pub keyring\n"); - return 0; - } - /* if a userid has been given, we'll use it */ - if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { - /* also search in config file for default id */ - (void) memset(id, 0x0, sizeof(id)); - (void) conffile(netpgp, homedir, id, sizeof(id)); - if (id[0] != 0x0) { - netpgp_setvar(netpgp, "userid", userid = id); - } - } - /* only read secret keys if we need to */ - if (netpgp_getvar(netpgp, "need seckey")) { - /* read the secret ring */ - netpgp->secring = readkeyring(netpgp, "secring"); - if (netpgp->secring == NULL) { - (void) fprintf(io->errs, "Can't read sec keyring\n"); - return 0; - } - /* now, if we don't have a valid user, use the first in secring */ - if (!userid && netpgp_getvar(netpgp, "need userid") != NULL) { - /* signing - need userid and sec key */ - (void) memset(id, 0x0, sizeof(id)); - if (get_first_ring(netpgp->secring, id, sizeof(id), 0)) { - netpgp_setvar(netpgp, "userid", userid = id); - } - } - } else if (netpgp_getvar(netpgp, "need userid") != NULL) { - /* encrypting - get first in pubring */ - if (!userid && get_first_ring(netpgp->pubring, id, sizeof(id), 0)) { - (void) netpgp_setvar(netpgp, "userid", userid = id); - } - } - if (!userid && netpgp_getvar(netpgp, "need userid")) { - /* if we don't have a user id, and we need one, fail */ - (void) fprintf(io->errs, "Cannot find user id\n"); - return 0; - } - } else { - /* read from ssh keys */ - last = (netpgp->pubring != NULL); - if (!readsshkeys(netpgp, homedir, netpgp_getvar(netpgp, "need seckey"))) { - (void) fprintf(io->errs, "Can't read ssh keys\n"); - return 0; - } - if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { - get_first_ring(netpgp->pubring, id, sizeof(id), last); - netpgp_setvar(netpgp, "userid", userid = id); - } - if (userid == NULL) { - if (netpgp_getvar(netpgp, "need userid") != NULL) { - (void) fprintf(io->errs, - "Cannot find user id\n"); - return 0; - } - } else { - (void) netpgp_setvar(netpgp, "userid", userid); - } - } - t = time(NULL); - netpgp_setvar(netpgp, "initialised", ctime(&t)); - return 1; -} -#endif ////// - -/* finish off with the netpgp_t struct */ -int -netpgp_end(netpgp_t *netpgp) -{ - unsigned i; - - for (i = 0 ; i < netpgp->c ; i++) { - if (netpgp->name[i] != NULL) { - free(netpgp->name[i]); - } - if (netpgp->value[i] != NULL) { - free(netpgp->value[i]); - } - } - if (netpgp->name != NULL) { - free(netpgp->name); - } - if (netpgp->value != NULL) { - free(netpgp->value); - } - if (netpgp->pubring != NULL) { - pgp_keyring_free(netpgp->pubring); - } - if (netpgp->secring != NULL) { - pgp_keyring_free(netpgp->secring); - } - free(netpgp->io); - return 1; -} - -/* list the keys in a keyring */ -int -netpgp_list_keys(netpgp_t *netpgp, const int psigs) -{ - if (netpgp->pubring == NULL) { - (void) fprintf(stderr, "No keyring\n"); - return 0; - } - return pgp_keyring_list(netpgp->io, netpgp->pubring, psigs); -} - -/* list the keys in a keyring, returning a JSON encoded string */ -int -netpgp_list_keys_json(netpgp_t *netpgp, char **json, const int psigs) -{ - mj_t obj; - int ret; - - if (netpgp->pubring == NULL) { - (void) fprintf(stderr, "No keyring\n"); - return 0; - } - (void) memset(&obj, 0x0, sizeof(obj)); - if (!pgp_keyring_json(netpgp->io, netpgp->pubring, &obj, psigs)) { - (void) fprintf(stderr, "No keys in keyring\n"); - return 0; - } - ret = mj_asprint(json, &obj, MJ_JSON_ENCODE); - mj_delete(&obj); - return ret; -} - -DEFINE_ARRAY(strings_t, char *); - -#ifndef HKP_VERSION -#define HKP_VERSION 1 -#endif - -/* find and list some keys in a keyring */ -int -netpgp_match_keys(netpgp_t *netpgp, char *name, const char *fmt, void *vp, const int psigs) -{ - const pgp_key_t *key; - unsigned k; - strings_t pubs; - FILE *fp = (FILE *)vp; - - if (name[0] == '0' && name[1] == 'x') { - name += 2; - } - (void) memset(&pubs, 0x0, sizeof(pubs)); - k = 0; - do { - key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, - name, &k); - if (key != NULL) { - ALLOC(char *, pubs.v, pubs.size, pubs.c, 10, 10, - "netpgp_match_keys", return 0); - if (strcmp(fmt, "mr") == 0) { - pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, - key, &pubs.v[pubs.c], - &key->key.pubkey, psigs); - } else { - pgp_sprint_keydata(netpgp->io, netpgp->pubring, - key, &pubs.v[pubs.c], - "signature ", - &key->key.pubkey, psigs); - } - if (pubs.v[pubs.c] != NULL) { - pubs.c += 1; - } - k += 1; - } - } while (key != NULL); - if (strcmp(fmt, "mr") == 0) { - (void) fprintf(fp, "info:%d:%d\n", HKP_VERSION, pubs.c); - } else { - (void) fprintf(fp, "%d key%s found\n", pubs.c, - (pubs.c == 1) ? "" : "s"); - } - for (k = 0 ; k < pubs.c ; k++) { - (void) fprintf(fp, "%s%s", pubs.v[k], (k < pubs.c - 1) ? "\n" : ""); - free(pubs.v[k]); - } - free(pubs.v); - return pubs.c; -} - -/* find and list some keys in a keyring - return JSON string */ -int -netpgp_match_keys_json(netpgp_t *netpgp, char **json, char *name, const char *fmt, const int psigs) -{ - const pgp_key_t *key; - unsigned k; - mj_t id_array; - char *newkey; - int ret; - - if (name[0] == '0' && name[1] == 'x') { - name += 2; - } - (void) memset(&id_array, 0x0, sizeof(id_array)); - k = 0; - *json = NULL; - mj_create(&id_array, "array"); - do { - key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, - name, &k); - if (key != NULL) { - if (strcmp(fmt, "mr") == 0) { - pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, - key, &newkey, - &key->key.pubkey, 0); - if (newkey) { - printf("%s\n", newkey); - free(newkey); - } - } else { - ALLOC(mj_t, id_array.value.v, id_array.size, - id_array.c, 10, 10, "netpgp_match_keys_json", return 0); - pgp_sprint_mj(netpgp->io, netpgp->pubring, - key, &id_array.value.v[id_array.c++], - "signature ", - &key->key.pubkey, psigs); - } - k += 1; - } - } while (key != NULL); - ret = mj_asprint(json, &id_array, MJ_JSON_ENCODE); - mj_delete(&id_array); - return ret; -} - -/* find and list some public keys in a keyring */ -int -netpgp_match_pubkeys(netpgp_t *netpgp, char *name, void *vp) -{ - const pgp_key_t *key; - unsigned k; - ssize_t cc; - char out[1024 * 64]; - FILE *fp = (FILE *)vp; - - k = 0; - do { - key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, - name, &k); - if (key != NULL) { - cc = pgp_sprint_pubkey(key, out, sizeof(out)); - (void) fprintf(fp, "%.*s", (int)cc, out); - k += 1; - } - } while (key != NULL); - return k; -} - -/* find a key in a keyring */ -int -netpgp_find_key(netpgp_t *netpgp, char *id) -{ - pgp_io_t *io; - - io = netpgp->io; - if (id == NULL) { - (void) fprintf(io->errs, "NULL id to search for\n"); - return 0; - } - return pgp_getkeybyname(netpgp->io, netpgp->pubring, id) != NULL; -} - -/* get a key in a keyring */ -char * -netpgp_get_key(netpgp_t *netpgp, const char *name, const char *fmt) -{ - const pgp_key_t *key; - char *newkey; - - if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { - return NULL; - } - if (strcmp(fmt, "mr") == 0) { - return (pgp_hkp_sprint_keydata(netpgp->io, netpgp->pubring, - key, &newkey, - &key->key.pubkey, - netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; - } - return (pgp_sprint_keydata(netpgp->io, netpgp->pubring, - key, &newkey, "signature", - &key->key.pubkey, - netpgp_getvar(netpgp, "subkey sigs") != NULL) > 0) ? newkey : NULL; -} - -/* export a given key */ -char * -netpgp_export_key(netpgp_t *netpgp, char *name) -{ - const pgp_key_t *key; - pgp_io_t *io; - - io = netpgp->io; - if ((key = resolve_userid(netpgp, netpgp->pubring, name)) == NULL) { - return NULL; - } - return pgp_export_key(io, key, NULL); -} - -#define IMPORT_ARMOR_HEAD "-----BEGIN PGP PUBLIC KEY BLOCK-----" - -/* import a key into our keyring */ -int -netpgp_import_key(netpgp_t *netpgp, char *f) -{ - pgp_io_t *io; - unsigned realarmor; - int done; - - io = netpgp->io; - realarmor = isarmoured(io, f, NULL, IMPORT_ARMOR_HEAD); - done = pgp_keyring_fileread(netpgp->pubring, realarmor, f); - if (!done) { - (void) fprintf(io->errs, "Cannot import key from file %s\n", f); - return 0; - } - return pgp_keyring_list(io, netpgp->pubring, 0); -} - -#define ID_OFFSET 38 - -/* generate a new key */ -#if 0 ////// -int -netpgp_generate_key(netpgp_t *netpgp, char *id, int numbits) -{ - pgp_output_t *create; - const unsigned noarmor = 0; - pgp_key_t *key; - pgp_io_t *io; - uint8_t *uid; - char passphrase[128]; - char newid[1024]; - char filename[MAXPATHLEN]; - char dir[MAXPATHLEN]; - char *cp; - char *ringfile; - char *numtries; - int attempts; - int passc; - int fd; - int cc; - - uid = NULL; - io = netpgp->io; - /* generate a new key */ - if (id) { - (void) snprintf(newid, sizeof(newid), "%s", id); - } else { - (void) snprintf(newid, sizeof(newid), - "RSA %d-bit key <%s@localhost>", numbits, getenv("LOGNAME")); - } - uid = (uint8_t *)newid; - key = pgp_rsa_new_selfsign_key(numbits, 65537UL, uid, - netpgp_getvar(netpgp, "hash"), - netpgp_getvar(netpgp, "cipher")); - if (key == NULL) { - (void) fprintf(io->errs, "Cannot generate key\n"); - return 0; - } - cp = NULL; - pgp_sprint_keydata(netpgp->io, NULL, key, &cp, "signature ", &key->key.seckey.pubkey, 0); - (void) fprintf(stdout, "%s", cp); - /* write public key */ - cc = snprintf(dir, sizeof(dir), "%s/%.16s", netpgp_getvar(netpgp, "homedir"), &cp[ID_OFFSET]); - netpgp_setvar(netpgp, "generated userid", &dir[cc - 16]); - if (mkdir(dir, 0700) < 0) { - (void) fprintf(io->errs, "can't mkdir '%s'\n", dir); - return 0; - } - (void) fprintf(io->errs, "netpgp: generated keys in directory %s\n", dir); - (void) snprintf(ringfile = filename, sizeof(filename), "%s/pubring.gpg", dir); - if (!appendkey(io, key, ringfile)) { - (void) fprintf(io->errs, "Cannot write pubkey to '%s'\n", ringfile); - return 0; - } - if (netpgp->pubring != NULL) { - pgp_keyring_free(netpgp->pubring); - } - /* write secret key */ - (void) snprintf(ringfile = filename, sizeof(filename), "%s/secring.gpg", dir); - if ((fd = pgp_setup_file_append(&create, ringfile)) < 0) { - fd = pgp_setup_file_write(&create, ringfile, 0); - } - if (fd < 0) { - (void) fprintf(io->errs, "can't append secring '%s'\n", ringfile); - return 0; - } - /* get the passphrase */ - if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || - (attempts = atoi(numtries)) <= 0) { - attempts = MAX_PASSPHRASE_ATTEMPTS; - } else if (strcmp(numtries, "unlimited") == 0) { - attempts = INFINITE_ATTEMPTS; - } - passc = find_passphrase(netpgp->passfp, &cp[ID_OFFSET], passphrase, sizeof(passphrase), attempts); - if (!pgp_write_xfer_seckey(create, key, (uint8_t *)passphrase, (const unsigned)passc, noarmor)) { - (void) fprintf(io->errs, "Cannot write seckey\n"); - return 0; - } - pgp_teardown_file_write(create, fd); - if (netpgp->secring != NULL) { - pgp_keyring_free(netpgp->secring); - } - pgp_keydata_free(key); - free(cp); - return 1; -} -#endif ////// - -/* encrypt a file */ -int -netpgp_encrypt_file(netpgp_t *netpgp, - const char *userid, - const char *f, - char *out, - int armored) -{ - const pgp_key_t *key; - const unsigned overwrite = 1; - const char *suffix; - pgp_io_t *io; - char outname[MAXPATHLEN]; - - io = netpgp->io; - if (f == NULL) { - (void) fprintf(io->errs, - "netpgp_encrypt_file: no filename specified\n"); - return 0; - } - suffix = (armored) ? ".asc" : ".gpg"; - /* get key with which to sign */ - if ((key = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { - return 0; - } - if (out == NULL) { - (void) snprintf(outname, sizeof(outname), "%s%s", f, suffix); - out = outname; - } - return (int)pgp_encrypt_file(io, f, out, key, (unsigned)armored, - overwrite, netpgp_getvar(netpgp, "cipher")); -} - -#define ARMOR_HEAD "-----BEGIN PGP MESSAGE-----" - -/* decrypt a file */ -int -netpgp_decrypt_file(netpgp_t *netpgp, const char *f, char *out, int armored) -{ - const unsigned overwrite = 1; - pgp_io_t *io; - unsigned realarmor; - unsigned sshkeys; - char *numtries; - int attempts; - - __PGP_USED(armored); - io = netpgp->io; - if (f == NULL) { - (void) fprintf(io->errs, - "netpgp_decrypt_file: no filename specified\n"); - return 0; - } - realarmor = isarmoured(io, f, NULL, ARMOR_HEAD); - sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); - if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || - (attempts = atoi(numtries)) <= 0) { - attempts = MAX_PASSPHRASE_ATTEMPTS; - } else if (strcmp(numtries, "unlimited") == 0) { - attempts = INFINITE_ATTEMPTS; - } - return pgp_decrypt_file(netpgp->io, f, out, netpgp->secring, - netpgp->pubring, - realarmor, overwrite, sshkeys, - netpgp->passfp, attempts, get_passphrase_cb); -} - -/* sign a file */ -int -netpgp_sign_file(netpgp_t *netpgp, - const char *userid, - const char *f, - char *out, - int armored, - int cleartext, - int detached) -{ - const pgp_key_t *keypair; - const pgp_key_t *pubkey; - const unsigned overwrite = 1; - pgp_seckey_t *seckey; - const char *hashalg; - pgp_io_t *io; - char *numtries; - int attempts; - int ret; - int i; - - io = netpgp->io; - if (f == NULL) { - (void) fprintf(io->errs, - "netpgp_sign_file: no filename specified\n"); - return 0; - } - /* get key with which to sign */ - if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { - return 0; - } - ret = 1; - if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || - (attempts = atoi(numtries)) <= 0) { - attempts = MAX_PASSPHRASE_ATTEMPTS; - } else if (strcmp(numtries, "unlimited") == 0) { - attempts = INFINITE_ATTEMPTS; - } - for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { - if (netpgp->passfp == NULL) { - /* print out the user id */ - pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); - if (pubkey == NULL) { - (void) fprintf(io->errs, - "netpgp: warning - using pubkey from secring\n"); - pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", - &keypair->key.seckey.pubkey, 0); - } else { - pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", - &pubkey->key.pubkey, 0); - } - } - if (netpgp_getvar(netpgp, "ssh keys") == NULL) { - /* now decrypt key */ - seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); - if (seckey == NULL) { - (void) fprintf(io->errs, "Bad passphrase\n"); - } - } else { - pgp_keyring_t *secring; - - secring = netpgp->secring; - seckey = &secring->keys[0].key.seckey; - } - } - if (seckey == NULL) { - (void) fprintf(io->errs, "Bad passphrase\n"); - return 0; - } - /* sign file */ - hashalg = netpgp_getvar(netpgp, "hash"); - if (seckey->pubkey.alg == PGP_PKA_DSA) { - hashalg = "sha1"; - } - if (detached) { - ret = pgp_sign_detached(io, f, out, seckey, hashalg, - get_birthtime(netpgp_getvar(netpgp, "birthtime")), - get_duration(netpgp_getvar(netpgp, "duration")), - (unsigned)armored, - overwrite); - } else { - ret = pgp_sign_file(io, f, out, seckey, hashalg, - get_birthtime(netpgp_getvar(netpgp, "birthtime")), - get_duration(netpgp_getvar(netpgp, "duration")), - (unsigned)armored, (unsigned)cleartext, - overwrite); - } - pgp_forget(seckey, (unsigned)sizeof(*seckey)); - return ret; -} - -#define ARMOR_SIG_HEAD "-----BEGIN PGP (SIGNATURE|SIGNED MESSAGE)-----" - -/* verify a file */ -int -netpgp_verify_file(netpgp_t *netpgp, const char *in, const char *out, int armored) -{ - pgp_validation_t result; - pgp_io_t *io; - unsigned realarmor; - - __PGP_USED(armored); - (void) memset(&result, 0x0, sizeof(result)); - io = netpgp->io; - if (in == NULL) { - (void) fprintf(io->errs, - "netpgp_verify_file: no filename specified\n"); - return 0; - } - realarmor = isarmoured(io, in, NULL, ARMOR_SIG_HEAD); - if (pgp_validate_file(io, &result, in, out, (const int)realarmor, netpgp->pubring)) { - resultp(io, in, &result, netpgp->pubring); - return 1; - } - if (result.validc + result.invalidc + result.unknownc == 0) { - (void) fprintf(io->errs, - "\"%s\": No signatures found - is this a signed file?\n", - in); - } else if (result.invalidc == 0 && result.unknownc == 0) { - (void) fprintf(io->errs, - "\"%s\": file verification failure: invalid signature time\n", in); - } else { - (void) fprintf(io->errs, -"\"%s\": verification failure: %u invalid signatures, %u unknown signatures\n", - in, result.invalidc, result.unknownc); - } - return 0; -} - -/* sign some memory */ -int -netpgp_sign_memory(netpgp_t *netpgp, - const char *userid, - char *mem, - size_t size, - char *out, - size_t outsize, - const unsigned armored, - const unsigned cleartext) -{ - const pgp_key_t *keypair; - const pgp_key_t *pubkey; - pgp_seckey_t *seckey; - pgp_memory_t *signedmem; - const char *hashalg; - pgp_io_t *io; - char *numtries; - int attempts; - int ret; - int i; - - io = netpgp->io; - if (mem == NULL) { - (void) fprintf(io->errs, - "netpgp_sign_memory: no memory to sign\n"); - return 0; - } - if ((keypair = resolve_userid(netpgp, netpgp->secring, userid)) == NULL) { - return 0; - } - ret = 1; - if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || - (attempts = atoi(numtries)) <= 0) { - attempts = MAX_PASSPHRASE_ATTEMPTS; - } else if (strcmp(numtries, "unlimited") == 0) { - attempts = INFINITE_ATTEMPTS; - } - for (i = 0, seckey = NULL ; !seckey && (i < attempts || attempts == INFINITE_ATTEMPTS) ; i++) { - if (netpgp->passfp == NULL) { - /* print out the user id */ - pubkey = pgp_getkeybyname(io, netpgp->pubring, userid); - if (pubkey == NULL) { - (void) fprintf(io->errs, - "netpgp: warning - using pubkey from secring\n"); - pgp_print_keydata(io, netpgp->pubring, keypair, "signature ", - &keypair->key.seckey.pubkey, 0); - } else { - pgp_print_keydata(io, netpgp->pubring, pubkey, "signature ", - &pubkey->key.pubkey, 0); - } - } - /* now decrypt key */ - seckey = pgp_decrypt_seckey(keypair, netpgp->passfp); - if (seckey == NULL) { - (void) fprintf(io->errs, "Bad passphrase\n"); - } - } - if (seckey == NULL) { - (void) fprintf(io->errs, "Bad passphrase\n"); - return 0; - } - /* sign file */ - (void) memset(out, 0x0, outsize); - hashalg = netpgp_getvar(netpgp, "hash"); - if (seckey->pubkey.alg == PGP_PKA_DSA) { - hashalg = "sha1"; - } - signedmem = pgp_sign_buf(io, mem, size, seckey, - get_birthtime(netpgp_getvar(netpgp, "birthtime")), - get_duration(netpgp_getvar(netpgp, "duration")), - hashalg, armored, cleartext); - if (signedmem) { - size_t m; - - m = MIN(pgp_mem_len(signedmem), outsize); - (void) memcpy(out, pgp_mem_data(signedmem), m); - pgp_memory_free(signedmem); - ret = (int)m; - } else { - ret = 0; - } - pgp_forget(seckey, (unsigned)sizeof(*seckey)); - return ret; -} - -/* verify memory */ -int -netpgp_verify_memory(netpgp_t *netpgp, const void *in, const size_t size, - void *out, size_t outsize, const int armored) -{ - pgp_validation_t result; - pgp_memory_t *signedmem; - pgp_memory_t *cat; - pgp_io_t *io; - size_t m; - int ret; - - (void) memset(&result, 0x0, sizeof(result)); - io = netpgp->io; - if (in == NULL) { - (void) fprintf(io->errs, - "netpgp_verify_memory: no memory to verify\n"); - return 0; - } - signedmem = pgp_memory_new(); - pgp_memory_add(signedmem, in, size); - if (out) { - cat = pgp_memory_new(); - } - ret = pgp_validate_mem(io, &result, signedmem, - (out) ? &cat : NULL, - armored, netpgp->pubring); - /* signedmem is freed from pgp_validate_mem */ - if (ret) { - resultp(io, "", &result, netpgp->pubring); - if (out) { - m = MIN(pgp_mem_len(cat), outsize); - (void) memcpy(out, pgp_mem_data(cat), m); - pgp_memory_free(cat); - } else { - m = 1; - } - return (int)m; - } - if (result.validc + result.invalidc + result.unknownc == 0) { - (void) fprintf(io->errs, - "No signatures found - is this memory signed?\n"); - } else if (result.invalidc == 0 && result.unknownc == 0) { - (void) fprintf(io->errs, - "memory verification failure: invalid signature time\n"); - } else { - (void) fprintf(io->errs, -"memory verification failure: %u invalid signatures, %u unknown signatures\n", - result.invalidc, result.unknownc); - } - return 0; -} - -/* encrypt some memory */ -int -netpgp_encrypt_memory(netpgp_t *netpgp, - const char *userid, - void *in, - const size_t insize, - char *out, - size_t outsize, - int armored) -{ - const pgp_key_t *keypair; - pgp_memory_t *enc; - pgp_io_t *io; - size_t m; - - io = netpgp->io; - if (in == NULL) { - (void) fprintf(io->errs, - "netpgp_encrypt_buf: no memory to encrypt\n"); - return 0; - } - if ((keypair = resolve_userid(netpgp, netpgp->pubring, userid)) == NULL) { - return 0; - } - if (in == out) { - (void) fprintf(io->errs, - "netpgp_encrypt_buf: input and output bufs need to be different\n"); - return 0; - } - if (outsize < insize) { - (void) fprintf(io->errs, - "netpgp_encrypt_buf: input size is larger than output size\n"); - return 0; - } - enc = pgp_encrypt_buf(io, in, insize, keypair, (unsigned)armored, - netpgp_getvar(netpgp, "cipher")); - m = MIN(pgp_mem_len(enc), outsize); - (void) memcpy(out, pgp_mem_data(enc), m); - pgp_memory_free(enc); - return (int)m; -} - -/* decrypt a chunk of memory */ -int -netpgp_decrypt_memory(netpgp_t *netpgp, const void *input, const size_t insize, - char *out, size_t outsize, const int armored) -{ - pgp_memory_t *mem; - pgp_io_t *io; - unsigned realarmour; - unsigned sshkeys; - size_t m; - char *numtries; - int attempts; - - __PGP_USED(armored); - io = netpgp->io; - if (input == NULL) { - (void) fprintf(io->errs, - "netpgp_decrypt_memory: no memory\n"); - return 0; - } - realarmour = isarmoured(io, NULL, input, ARMOR_HEAD); - sshkeys = (unsigned)(netpgp_getvar(netpgp, "ssh keys") != NULL); - if ((numtries = netpgp_getvar(netpgp, "numtries")) == NULL || - (attempts = atoi(numtries)) <= 0) { - attempts = MAX_PASSPHRASE_ATTEMPTS; - } else if (strcmp(numtries, "unlimited") == 0) { - attempts = INFINITE_ATTEMPTS; - } - mem = pgp_decrypt_buf(netpgp->io, input, insize, netpgp->secring, - netpgp->pubring, - realarmour, sshkeys, - netpgp->passfp, - attempts, - get_passphrase_cb); - if (mem == NULL) { - return -1; - } - m = MIN(pgp_mem_len(mem), outsize); - (void) memcpy(out, pgp_mem_data(mem), m); - pgp_memory_free(mem); - return (int)m; -} - -/* wrappers for the ops_debug_level functions we added to openpgpsdk */ - -/* set the debugging level per filename */ -int -netpgp_set_debug(const char *f) -{ - return pgp_set_debug_level(f); -} - -/* get the debugging level per filename */ -int -netpgp_get_debug(const char *f) -{ - return pgp_get_debug_level(f); -} - -/* return the version for the library */ -const char * -netpgp_get_info(const char *type) -{ - return pgp_get_info(type); -} - -/* list all the packets in a file */ -int -netpgp_list_packets(netpgp_t *netpgp, char *f, int armor, char *pubringname) -{ - pgp_keyring_t *keyring; - const unsigned noarmor = 0; - struct stat st; - pgp_io_t *io; - char ringname[MAXPATHLEN]; - char *homedir; - int ret; - - io = netpgp->io; - if (f == NULL) { - (void) fprintf(io->errs, "No file containing packets\n"); - return 0; - } - if (stat(f, &st) < 0) { - (void) fprintf(io->errs, "No such file '%s'\n", f); - return 0; - } - homedir = netpgp_getvar(netpgp, "homedir"); - if (pubringname == NULL) { - (void) snprintf(ringname, sizeof(ringname), - "%s/pubring.gpg", homedir); - pubringname = ringname; - } - if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { - (void) fprintf(io->errs, "netpgp_list_packets: bad alloc\n"); - return 0; - } - if (!pgp_keyring_fileread(keyring, noarmor, pubringname)) { - free(keyring); - (void) fprintf(io->errs, "Cannot read pub keyring %s\n", - pubringname); - return 0; - } - netpgp->pubring = keyring; - netpgp_setvar(netpgp, "pubring", pubringname); - ret = pgp_list_packets(io, f, (unsigned)armor, - netpgp->secring, - netpgp->pubring, - netpgp->passfp, - get_passphrase_cb); - free(keyring); - return ret; -} - -/* set a variable */ -int -netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) -{ - char *newval; - int i; - - /* protect against the case where 'value' is netpgp->value[i] */ - newval = netpgp_strdup(value); - if ((i = findvar(netpgp, name)) < 0) { - /* add the element to the array */ - if (size_arrays(netpgp, netpgp->size + 15)) { - netpgp->name[i = netpgp->c++] = netpgp_strdup(name); - } - } else { - /* replace the element in the array */ - if (netpgp->value[i]) { - free(netpgp->value[i]); - netpgp->value[i] = NULL; - } - } - /* sanity checks for range of values */ - if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { - if (pgp_str_to_hash_alg(newval) == PGP_HASH_UNKNOWN) { - free(newval); - return 0; - } - } - netpgp->value[i] = newval; - return 1; -} - -/* unset a variable */ -int -netpgp_unsetvar(netpgp_t *netpgp, const char *name) -{ - int i; - - if ((i = findvar(netpgp, name)) >= 0) { - if (netpgp->value[i]) { - free(netpgp->value[i]); - netpgp->value[i] = NULL; - } - netpgp->value[i] = NULL; - return 1; - } - return 0; -} - -/* get a variable's value (NULL if not set) */ -char * -netpgp_getvar(netpgp_t *netpgp, const char *name) -{ - int i; - - return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; -} - -/* increment a value */ -int -netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) -{ - char *cp; - char num[16]; - int val; - - val = 0; - if ((cp = netpgp_getvar(netpgp, name)) != NULL) { - val = atoi(cp); - } - (void) snprintf(num, sizeof(num), "%d", val + delta); - netpgp_setvar(netpgp, name, num); - return 1; -} - -/* set the home directory value to "home/subdir" */ -int -netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) -{ - struct stat st; - char d[MAXPATHLEN]; - - if (home == NULL) { - if (!quiet) { - (void) fprintf(stderr, "NULL HOME directory\n"); - } - return 0; - } - (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); - if (stat(d, &st) == 0) { - if ((st.st_mode & S_IFMT) == S_IFDIR) { - netpgp_setvar(netpgp, "homedir", d); - return 1; - } - (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", - d); - return 0; - } - if (!quiet) { - (void) fprintf(stderr, - "netpgp: warning homedir \"%s\" not found\n", d); - } - netpgp_setvar(netpgp, "homedir", d); - return 1; -} - -/* validate all sigs in the pub keyring */ -int -netpgp_validate_sigs(netpgp_t *netpgp) -{ - pgp_validation_t result; - - return (int)pgp_validate_all_sigs(&result, netpgp->pubring, NULL); -} - -/* print the json out on 'fp' */ -int -netpgp_format_json(void *vp, const char *json, const int psigs) -{ - mj_t ids; - FILE *fp; - int from; - int idc; - int tok; - int to; - int i; - - if ((fp = (FILE *)vp) == NULL || json == NULL) { - return 0; - } - /* ids is an array of strings, each containing 1 entry */ - (void) memset(&ids, 0x0, sizeof(ids)); - from = to = tok = 0; - /* convert from string into an mj structure */ - (void) mj_parse(&ids, json, &from, &to, &tok); - if ((idc = mj_arraycount(&ids)) == 1 && strchr(json, '{') == NULL) { - idc = 0; - } - (void) fprintf(fp, "%d key%s found\n", idc, (idc == 1) ? "" : "s"); - for (i = 0 ; i < idc ; i++) { - format_json_key(fp, &ids.value.v[i], psigs); - } - /* clean up */ - mj_delete(&ids); - return idc; -} - -/* find a key in keyring, and write it in ssh format */ -int -netpgp_write_sshkey(netpgp_t *netpgp, char *s, const char *userid, char *out, size_t size) -{ - const pgp_key_t *key; - pgp_keyring_t *keyring; - pgp_io_t *io; - unsigned k; - size_t cc; - char f[MAXPATHLEN]; - - keyring = NULL; - io = NULL; - cc = 0; - if ((io = calloc(1, sizeof(pgp_io_t))) == NULL) { - (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 1\n"); - goto done; - } - io->outs = stdout; - io->errs = stderr; - io->res = stderr; - netpgp->io = io; - /* write new to temp file */ - savepubkey(s, f, sizeof(f)); - if ((keyring = calloc(1, sizeof(*keyring))) == NULL) { - (void) fprintf(stderr, "netpgp_save_sshpub: bad alloc 2\n"); - goto done; - } - if (!pgp_keyring_fileread(netpgp->pubring = keyring, 1, f)) { - (void) fprintf(stderr, "can't import key\n"); - goto done; - } - /* get rsa key */ - k = 0; - key = pgp_getnextkeybyname(netpgp->io, netpgp->pubring, userid, &k); - if (key == NULL) { - (void) fprintf(stderr, "no key found for '%s'\n", userid); - goto done; - } - if (key->key.pubkey.alg != PGP_PKA_RSA) { - /* we're not interested in supporting DSA either :-) */ - (void) fprintf(stderr, "key not RSA '%s'\n", userid); - goto done; - } - /* XXX - check trust sigs */ - /* XXX - check expiry */ - /* XXX - check start */ - /* XXX - check not weak key */ - /* get rsa e and n */ - (void) memset(out, 0x0, size); - cc = formatstring((char *)out, (const uint8_t *)"ssh-rsa", 7); - cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.e); - cc += formatbignum((char *)&out[cc], key->key.pubkey.key.rsa.n); -done: - if (io) { - free(io); - } - if (keyring) { - free(keyring); - } - return (int)cc; -} diff --git a/libs/netpgp/packet-print.c b/libs/netpgp/packet-print.c deleted file mode 100644 index adb7e47d..00000000 --- a/libs/netpgp/packet-print.c +++ /dev/null @@ -1,1456 +0,0 @@ -/*- - * Copyright (c) 2009 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Alistair Crooks (agc@NetBSD.org) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) - * All rights reserved. - * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted - * their moral rights under the UK Copyright Design and Patents Act 1988 to - * be recorded as the authors of this copyright work. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * ! \file \brief Standard API print functions - */ -#include "config-netpgp.h" - -#ifdef HAVE_SYS_CDEFS_H -#include -#endif - -#if defined(__NetBSD__) -__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: packet-print.c,v 1.42 2012/02/22 06:29:40 agc Exp $"); -#endif - -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "crypto-netpgp.h" -#include "keyring-netpgp.h" -#include "packet-show.h" -#include "signature-netpgp.h" -#include "readerwriter-netpgp.h" -#include "netpgpdefs.h" -#include "netpgpsdk.h" -#include "packet-netpgp.h" -#include "netpgpdigest.h" -#include "mj.h" - -/* static functions */ - -static void -print_indent(int indent) -{ - int i; - - for (i = 0; i < indent; i++) { - printf(" "); - } -} - -static void -print_name(int indent, const char *name) -{ - print_indent(indent); - if (name) { - printf("%s: ", name); - } -} - -static void -print_hexdump(int indent, const char *name, const uint8_t *data, unsigned len) -{ - print_name(indent, name); - hexdump(stdout, NULL, data, len); -} - -static void -hexdump_data(int indent, const char *name, const uint8_t *data, unsigned len) -{ - print_name(indent, name); - hexdump(stdout, NULL, data, len); -} - -static void -print_uint(int indent, const char *name, unsigned val) -{ - print_name(indent, name); - printf("%u\n", val); -} - -static void -showtime(const char *name, time_t t) -{ - printf("%s=%" PRItime "d (%.24s)", name, (long long) t, ctime(&t)); -} - -static void -print_time(int indent, const char *name, time_t t) -{ - print_indent(indent); - printf("%s: ", name); - showtime("time", t); - printf("\n"); -} - -static void -print_string_and_value(int indent, const char *name, const char *str, uint8_t value) -{ - print_name(indent, name); - printf("%s (0x%x)\n", str, value); -} - -static void -print_tagname(int indent, const char *str) -{ - print_indent(indent); - printf("%s packet\n", str); -} - -static void -print_data(int indent, const char *name, const pgp_data_t *data) -{ - print_hexdump(indent, name, data->contents, (unsigned)data->len); -} - -static void -print_bn(int indent, const char *name, const BIGNUM *bn) -{ - print_indent(indent); - printf("%s=", name); - if (bn) { - BN_print_fp(stdout, bn); - putchar('\n'); - } else { - puts("(unset)"); - } -} - -static void -print_packet_hex(const pgp_subpacket_t *pkt) -{ - hexdump(stdout, "packet contents:", pkt->raw, pkt->length); -} - -static void -print_escaped(const uint8_t *data, size_t length) -{ - while (length-- > 0) { - if ((*data >= 0x20 && *data < 0x7f && *data != '%') || - *data == '\n') { - putchar(*data); - } else { - printf("%%%02x", *data); - } - ++data; - } -} - -static void -print_string(int indent, const char *name, const char *str) -{ - print_name(indent, name); - print_escaped((const uint8_t *) str, strlen(str)); - putchar('\n'); -} - -static void -print_utf8_string(int indent, const char *name, const uint8_t *str) -{ - /* \todo Do this better for non-English character sets */ - print_string(indent, name, (const char *) str); -} - -static void -print_duration(int indent, const char *name, time_t t) -{ - int mins, hours, days, years; - - print_indent(indent); - printf("%s: ", name); - printf("duration %" PRItime "d seconds", (long long) t); - - mins = (int)(t / 60); - hours = mins / 60; - days = hours / 24; - years = days / 365; - - printf(" (approx. "); - if (years) { - printf("%d %s", years, years == 1 ? "year" : "years"); - } else if (days) { - printf("%d %s", days, days == 1 ? "day" : "days"); - } else if (hours) { - printf("%d %s", hours, hours == 1 ? "hour" : "hours"); - } - printf(")\n"); -} - -static void -print_boolean(int indent, const char *name, uint8_t boolval) -{ - print_name(indent, name); - printf("%s\n", (boolval) ? "Yes" : "No"); -} - -static void -print_text_breakdown(int indent, pgp_text_t *text) -{ - const char *prefix = ".. "; - unsigned i; - - /* these were recognised */ - for (i = 0; i < text->known.used; i++) { - print_indent(indent); - printf("%s", prefix); - printf("%s\n", text->known.strings[i]); - } - /* - * these were not recognised. the strings will contain the hex value - * of the unrecognised value in string format - see - * process_octet_str() - */ - if (text->unknown.used) { - printf("\n"); - print_indent(indent); - printf("Not Recognised: "); - } - for (i = 0; i < text->unknown.used; i++) { - print_indent(indent); - printf("%s", prefix); - printf("%s\n", text->unknown.strings[i]); - } -} - -static void -print_headers(const pgp_headers_t *h) -{ - unsigned i; - - for (i = 0; i < h->headerc; ++i) { - printf("%s=%s\n", h->headers[i].key, h->headers[i].value); - } -} - -static void -print_block(int indent, const char *name, const uint8_t *str, size_t length) -{ - int o = (int)length; - - print_indent(indent); - printf(">>>>> %s >>>>>\n", name); - - print_indent(indent); - for (; length > 0; --length) { - if (*str >= 0x20 && *str < 0x7f && *str != '%') { - putchar(*str); - } else if (*str == '\n') { - putchar(*str); - print_indent(indent); - } else { - printf("%%%02x", *str); - } - ++str; - } - if (o && str[-1] != '\n') { - putchar('\n'); - print_indent(indent); - fputs("[no newline]", stdout); - } else { - print_indent(indent); - } - printf("<<<<< %s <<<<<\n", name); -} - -/* return the number of bits in the public key */ -static int -numkeybits(const pgp_pubkey_t *pubkey) -{ - switch(pubkey->alg) { - case PGP_PKA_RSA: - case PGP_PKA_RSA_ENCRYPT_ONLY: - case PGP_PKA_RSA_SIGN_ONLY: - return BN_num_bytes(pubkey->key.rsa.n) * 8; - case PGP_PKA_DSA: - switch(BN_num_bytes(pubkey->key.dsa.q)) { - case 20: - return 1024; - case 28: - return 2048; - case 32: - return 3072; - default: - return 0; - } - case PGP_PKA_ELGAMAL: - return BN_num_bytes(pubkey->key.elgamal.y) * 8; - default: - return -1; - } -} - -/* return the hexdump as a string */ -static char * -strhexdump(char *dest, const uint8_t *src, size_t length, const char *sep) -{ - unsigned i; - int n; - - for (n = 0, i = 0 ; i < length ; i += 2) { - n += snprintf(&dest[n], 3, "%02x", *src++); - n += snprintf(&dest[n], 10, "%02x%s", *src++, sep); - } - return dest; -} - -/* return the time as a string */ -static char * -ptimestr(char *dest, size_t size, time_t t) -{ - struct tm *tm; - - tm = gmtime(&t); - (void) snprintf(dest, size, "%04d-%02d-%02d", - tm->tm_year + 1900, - tm->tm_mon + 1, - tm->tm_mday); - return dest; -} - -/* print the sub key binding signature info */ -static int -psubkeybinding(char *buf, size_t size, const pgp_key_t *key, const char *expired) -{ - char keyid[512]; - char t[32]; - - return snprintf(buf, size, "encryption %d/%s %s %s %s\n", - numkeybits(&key->enckey), - pgp_show_pka(key->enckey.alg), - strhexdump(keyid, key->encid, PGP_KEY_ID_SIZE, ""), - ptimestr(t, sizeof(t), key->enckey.birthtime), - expired); -} - -static int -isrevoked(const pgp_key_t *key, unsigned uid) -{ - unsigned r; - - for (r = 0 ; r < key->revokec ; r++) { - if (key->revokes[r].uid == uid) { - return r; - } - } - return -1; -} - -#ifndef KB -#define KB(x) ((x) * 1024) -#endif - -/* print into a string (malloc'ed) the pubkeydata */ -int -pgp_sprint_keydata(pgp_io_t *io, const pgp_keyring_t *keyring, - const pgp_key_t *key, char **buf, const char *header, - const pgp_pubkey_t *pubkey, const int psigs) -{ - const pgp_key_t *trustkey; - unsigned from; - unsigned i; - unsigned j; - time_t now; - char uidbuf[KB(128)]; - char keyid[PGP_KEY_ID_SIZE * 3]; - char fp[(PGP_FINGERPRINT_SIZE * 3) + 1]; - char expired[128]; - char t[32]; - int cc; - int n; - int r; - - if (key == NULL || key->revoked) { - return -1; - } - now = time(NULL); - if (pubkey->duration > 0) { - cc = snprintf(expired, sizeof(expired), - (pubkey->birthtime + pubkey->duration < now) ? - "[EXPIRED " : "[EXPIRES "); - ptimestr(&expired[cc], sizeof(expired) - cc, - pubkey->birthtime + pubkey->duration); - cc += 10; - cc += snprintf(&expired[cc], sizeof(expired) - cc, "]"); - } else { - expired[0] = 0x0; - } - for (i = 0, n = 0; i < key->uidc; i++) { - if ((r = isrevoked(key, i)) >= 0 && - key->revokes[r].code == PGP_REVOCATION_COMPROMISED) { - continue; - } - n += snprintf(&uidbuf[n], sizeof(uidbuf) - n, "uid%s%s%s\n", - (psigs) ? " " : " ", - key->uids[i], - (isrevoked(key, i) >= 0) ? " [REVOKED]" : ""); - for (j = 0 ; j < key->subsigc ; j++) { - if (psigs) { - if (key->subsigs[j].uid != i) { - continue; - } - } else { - if (!(key->subsigs[j].sig.info.version == 4 && - key->subsigs[j].sig.info.type == PGP_SIG_SUBKEY && - i == key->uidc - 1)) { - continue; - } - } - from = 0; - trustkey = pgp_getkeybyid(io, keyring, key->subsigs[j].sig.info.signer_id, &from, NULL); - if (key->subsigs[j].sig.info.version == 4 && - key->subsigs[j].sig.info.type == PGP_SIG_SUBKEY) { - psubkeybinding(&uidbuf[n], sizeof(uidbuf) - n, key, expired); - } else { - n += snprintf(&uidbuf[n], sizeof(uidbuf) - n, - "sig %s %s %s\n", - strhexdump(keyid, key->subsigs[j].sig.info.signer_id, PGP_KEY_ID_SIZE, ""), - ptimestr(t, sizeof(t), key->subsigs[j].sig.info.birthtime), - (trustkey) ? (char *)trustkey->uids[trustkey->uid0] : "[unknown]"); - } - } - } - return pgp_asprintf(buf, "%s %d/%s %s %s %s\nKey fingerprint: %s\n%s", - header, - numkeybits(pubkey), - pgp_show_pka(pubkey->alg), - strhexdump(keyid, key->sigid, PGP_KEY_ID_SIZE, ""), - ptimestr(t, sizeof(t), pubkey->birthtime), - expired, - strhexdump(fp, key->sigfingerprint.fingerprint, key->sigfingerprint.length, " "), - uidbuf); -} - -/* return the key info as a JSON encoded string */ -int -pgp_sprint_mj(pgp_io_t *io, const pgp_keyring_t *keyring, - const pgp_key_t *key, mj_t *keyjson, const char *header, - const pgp_pubkey_t *pubkey, const int psigs) -{ - const pgp_key_t *trustkey; - unsigned from; - unsigned i; - unsigned j; - mj_t sub_obj; - char keyid[PGP_KEY_ID_SIZE * 3]; - char fp[(PGP_FINGERPRINT_SIZE * 3) + 1]; - int r; - - if (key == NULL || key->revoked) { - return -1; - } - (void) memset(keyjson, 0x0, sizeof(*keyjson)); - mj_create(keyjson, "object"); - mj_append_field(keyjson, "header", "string", header, -1); - mj_append_field(keyjson, "key bits", "integer", (int64_t) numkeybits(pubkey)); - mj_append_field(keyjson, "pka", "string", pgp_show_pka(pubkey->alg), -1); - mj_append_field(keyjson, "key id", "string", strhexdump(keyid, key->sigid, PGP_KEY_ID_SIZE, ""), -1); - mj_append_field(keyjson, "fingerprint", "string", - strhexdump(fp, key->sigfingerprint.fingerprint, key->sigfingerprint.length, " "), -1); - mj_append_field(keyjson, "birthtime", "integer", pubkey->birthtime); - mj_append_field(keyjson, "duration", "integer", pubkey->duration); - for (i = 0; i < key->uidc; i++) { - if ((r = isrevoked(key, i)) >= 0 && - key->revokes[r].code == PGP_REVOCATION_COMPROMISED) { - continue; - } - (void) memset(&sub_obj, 0x0, sizeof(sub_obj)); - mj_create(&sub_obj, "array"); - mj_append(&sub_obj, "string", key->uids[i], -1); - mj_append(&sub_obj, "string", (r >= 0) ? "[REVOKED]" : "", -1); - mj_append_field(keyjson, "uid", "array", &sub_obj); - mj_delete(&sub_obj); - for (j = 0 ; j < key->subsigc ; j++) { - if (psigs) { - if (key->subsigs[j].uid != i) { - continue; - } - } else { - if (!(key->subsigs[j].sig.info.version == 4 && - key->subsigs[j].sig.info.type == PGP_SIG_SUBKEY && - i == key->uidc - 1)) { - continue; - } - } - (void) memset(&sub_obj, 0x0, sizeof(sub_obj)); - mj_create(&sub_obj, "array"); - if (key->subsigs[j].sig.info.version == 4 && - key->subsigs[j].sig.info.type == PGP_SIG_SUBKEY) { - mj_append(&sub_obj, "integer", (int64_t)numkeybits(&key->enckey)); - mj_append(&sub_obj, "string", - (const char *)pgp_show_pka(key->enckey.alg), -1); - mj_append(&sub_obj, "string", - strhexdump(keyid, key->encid, PGP_KEY_ID_SIZE, ""), -1); - mj_append(&sub_obj, "integer", (int64_t)key->enckey.birthtime); - mj_append_field(keyjson, "encryption", "array", &sub_obj); - mj_delete(&sub_obj); - } else { - mj_append(&sub_obj, "string", - strhexdump(keyid, key->subsigs[j].sig.info.signer_id, PGP_KEY_ID_SIZE, ""), -1); - mj_append(&sub_obj, "integer", - (int64_t)(key->subsigs[j].sig.info.birthtime)); - from = 0; - trustkey = pgp_getkeybyid(io, keyring, key->subsigs[j].sig.info.signer_id, &from, NULL); - mj_append(&sub_obj, "string", - (trustkey) ? (char *)trustkey->uids[trustkey->uid0] : "[unknown]", -1); - mj_append_field(keyjson, "sig", "array", &sub_obj); - mj_delete(&sub_obj); - } - } - } - if (pgp_get_debug_level(__FILE__)) { - char *buf; - - mj_asprint(&buf, keyjson, 1); - (void) fprintf(stderr, "pgp_sprint_mj: '%s'\n", buf); - free(buf); - } - return 1; -} - -int -pgp_hkp_sprint_keydata(pgp_io_t *io, const pgp_keyring_t *keyring, - const pgp_key_t *key, char **buf, - const pgp_pubkey_t *pubkey, const int psigs) -{ - const pgp_key_t *trustkey; - unsigned from; - unsigned i; - unsigned j; - char keyid[PGP_KEY_ID_SIZE * 3]; - char uidbuf[KB(128)]; - char fp[(PGP_FINGERPRINT_SIZE * 3) + 1]; - int n; - - if (key->revoked) { - return -1; - } - for (i = 0, n = 0; i < key->uidc; i++) { - n += snprintf(&uidbuf[n], sizeof(uidbuf) - n, - "uid:%lld:%lld:%s\n", - (long long)pubkey->birthtime, - (long long)pubkey->duration, - key->uids[i]); - for (j = 0 ; j < key->subsigc ; j++) { - if (psigs) { - if (key->subsigs[j].uid != i) { - continue; - } - } else { - if (!(key->subsigs[j].sig.info.version == 4 && - key->subsigs[j].sig.info.type == PGP_SIG_SUBKEY && - i == key->uidc - 1)) { - continue; - } - } - from = 0; - trustkey = pgp_getkeybyid(io, keyring, key->subsigs[j].sig.info.signer_id, &from, NULL); - if (key->subsigs[j].sig.info.version == 4 && - key->subsigs[j].sig.info.type == PGP_SIG_SUBKEY) { - n += snprintf(&uidbuf[n], sizeof(uidbuf) - n, "sub:%d:%d:%s:%lld:%lld\n", - numkeybits(pubkey), - key->subsigs[j].sig.info.key_alg, - strhexdump(keyid, key->subsigs[j].sig.info.signer_id, PGP_KEY_ID_SIZE, ""), - (long long)(key->subsigs[j].sig.info.birthtime), - (long long)pubkey->duration); - } else { - n += snprintf(&uidbuf[n], sizeof(uidbuf) - n, - "sig:%s:%lld:%s\n", - strhexdump(keyid, key->subsigs[j].sig.info.signer_id, PGP_KEY_ID_SIZE, ""), - (long long)key->subsigs[j].sig.info.birthtime, - (trustkey) ? (char *)trustkey->uids[trustkey->uid0] : ""); - } - } - } - return pgp_asprintf(buf, "pub:%s:%d:%d:%lld:%lld\n%s", - strhexdump(fp, key->sigfingerprint.fingerprint, PGP_FINGERPRINT_SIZE, ""), - pubkey->alg, - numkeybits(pubkey), - (long long)pubkey->birthtime, - (long long)pubkey->duration, - uidbuf); -} - -/* print the key data for a pub or sec key */ -void -pgp_print_keydata(pgp_io_t *io, const pgp_keyring_t *keyring, - const pgp_key_t *key, const char *header, - const pgp_pubkey_t *pubkey, const int psigs) -{ - char *cp; - - if (pgp_sprint_keydata(io, keyring, key, &cp, header, pubkey, psigs) >= 0) { - (void) fprintf(io->res, "%s", cp); - free(cp); - } -} - -/** -\ingroup Core_Print -\param pubkey -*/ -void -pgp_print_pubkey(const pgp_pubkey_t *pubkey) -{ - printf("------- PUBLIC KEY ------\n"); - print_uint(0, "Version", (unsigned)pubkey->version); - print_time(0, "Creation Time", pubkey->birthtime); - if (pubkey->version == PGP_V3) { - print_uint(0, "Days Valid", pubkey->days_valid); - } - print_string_and_value(0, "Algorithm", pgp_show_pka(pubkey->alg), - pubkey->alg); - switch (pubkey->alg) { - case PGP_PKA_DSA: - print_bn(0, "p", pubkey->key.dsa.p); - print_bn(0, "q", pubkey->key.dsa.q); - print_bn(0, "g", pubkey->key.dsa.g); - print_bn(0, "y", pubkey->key.dsa.y); - break; - - case PGP_PKA_RSA: - case PGP_PKA_RSA_ENCRYPT_ONLY: - case PGP_PKA_RSA_SIGN_ONLY: - print_bn(0, "n", pubkey->key.rsa.n); - print_bn(0, "e", pubkey->key.rsa.e); - break; - - case PGP_PKA_ELGAMAL: - case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn(0, "p", pubkey->key.elgamal.p); - print_bn(0, "g", pubkey->key.elgamal.g); - print_bn(0, "y", pubkey->key.elgamal.y); - break; - - default: - (void) fprintf(stderr, - "pgp_print_pubkey: Unusual algorithm\n"); - } - - printf("------- end of PUBLIC KEY ------\n"); -} - -int -pgp_sprint_pubkey(const pgp_key_t *key, char *out, size_t outsize) -{ - char fp[(PGP_FINGERPRINT_SIZE * 3) + 1]; - int cc; - - cc = snprintf(out, outsize, "key=%s\nname=%s\ncreation=%lld\nexpiry=%lld\nversion=%d\nalg=%d\n", - strhexdump(fp, key->sigfingerprint.fingerprint, PGP_FINGERPRINT_SIZE, ""), - key->uids[key->uid0], - (long long)key->key.pubkey.birthtime, - (long long)key->key.pubkey.days_valid, - key->key.pubkey.version, - key->key.pubkey.alg); - switch (key->key.pubkey.alg) { - case PGP_PKA_DSA: - cc += snprintf(&out[cc], outsize - cc, - "p=%s\nq=%s\ng=%s\ny=%s\n", - BN_bn2hex(key->key.pubkey.key.dsa.p), - BN_bn2hex(key->key.pubkey.key.dsa.q), - BN_bn2hex(key->key.pubkey.key.dsa.g), - BN_bn2hex(key->key.pubkey.key.dsa.y)); - break; - case PGP_PKA_RSA: - case PGP_PKA_RSA_ENCRYPT_ONLY: - case PGP_PKA_RSA_SIGN_ONLY: - cc += snprintf(&out[cc], outsize - cc, - "n=%s\ne=%s\n", - BN_bn2hex(key->key.pubkey.key.rsa.n), - BN_bn2hex(key->key.pubkey.key.rsa.e)); - break; - case PGP_PKA_ELGAMAL: - case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - cc += snprintf(&out[cc], outsize - cc, - "p=%s\ng=%s\ny=%s\n", - BN_bn2hex(key->key.pubkey.key.elgamal.p), - BN_bn2hex(key->key.pubkey.key.elgamal.g), - BN_bn2hex(key->key.pubkey.key.elgamal.y)); - break; - default: - (void) fprintf(stderr, - "pgp_print_pubkey: Unusual algorithm\n"); - } - return cc; -} - -/** -\ingroup Core_Print -\param type -\param seckey -*/ -static void -print_seckey_verbose(const pgp_content_enum type, - const pgp_seckey_t *seckey) -{ - printf("------- SECRET KEY or ENCRYPTED SECRET KEY ------\n"); - print_tagname(0, (type == PGP_PTAG_CT_SECRET_KEY) ? - "SECRET_KEY" : - "ENCRYPTED_SECRET_KEY"); - /* pgp_print_pubkey(key); */ - printf("S2K Usage: %d\n", seckey->s2k_usage); - if (seckey->s2k_usage != PGP_S2KU_NONE) { - printf("S2K Specifier: %d\n", seckey->s2k_specifier); - printf("Symmetric algorithm: %d (%s)\n", seckey->alg, - pgp_show_symm_alg(seckey->alg)); - printf("Hash algorithm: %d (%s)\n", seckey->hash_alg, - pgp_show_hash_alg((uint8_t)seckey->hash_alg)); - if (seckey->s2k_specifier != PGP_S2KS_SIMPLE) { - print_hexdump(0, "Salt", seckey->salt, - (unsigned)sizeof(seckey->salt)); - } - if (seckey->s2k_specifier == PGP_S2KS_ITERATED_AND_SALTED) { - printf("Octet count: %u\n", seckey->octetc); - } - print_hexdump(0, "IV", seckey->iv, pgp_block_size(seckey->alg)); - } - /* no more set if encrypted */ - if (type == PGP_PTAG_CT_ENCRYPTED_SECRET_KEY) { - return; - } - switch (seckey->pubkey.alg) { - case PGP_PKA_RSA: - print_bn(0, "d", seckey->key.rsa.d); - print_bn(0, "p", seckey->key.rsa.p); - print_bn(0, "q", seckey->key.rsa.q); - print_bn(0, "u", seckey->key.rsa.u); - break; - - case PGP_PKA_DSA: - print_bn(0, "x", seckey->key.dsa.x); - break; - - default: - (void) fprintf(stderr, - "print_seckey_verbose: unusual algorithm\n"); - } - if (seckey->s2k_usage == PGP_S2KU_ENCRYPTED_AND_HASHED) { - print_hexdump(0, "Checkhash", seckey->checkhash, - PGP_CHECKHASH_SIZE); - } else { - printf("Checksum: %04x\n", seckey->checksum); - } - printf("------- end of SECRET KEY or ENCRYPTED SECRET KEY ------\n"); -} - - -/** -\ingroup Core_Print -\param tag -\param key -*/ -static void -print_pk_sesskey(pgp_content_enum tag, - const pgp_pk_sesskey_t * key) -{ - print_tagname(0, (tag == PGP_PTAG_CT_PK_SESSION_KEY) ? - "PUBLIC KEY SESSION KEY" : - "ENCRYPTED PUBLIC KEY SESSION KEY"); - printf("Version: %d\n", key->version); - print_hexdump(0, "Key ID", key->key_id, (unsigned)sizeof(key->key_id)); - printf("Algorithm: %d (%s)\n", key->alg, - pgp_show_pka(key->alg)); - switch (key->alg) { - case PGP_PKA_RSA: - print_bn(0, "encrypted_m", key->params.rsa.encrypted_m); - break; - - case PGP_PKA_ELGAMAL: - print_bn(0, "g_to_k", key->params.elgamal.g_to_k); - print_bn(0, "encrypted_m", key->params.elgamal.encrypted_m); - break; - - default: - (void) fprintf(stderr, - "print_pk_sesskey: unusual algorithm\n"); - } - if (tag == PGP_PTAG_CT_PK_SESSION_KEY) { - printf("Symmetric algorithm: %d (%s)\n", key->symm_alg, - pgp_show_symm_alg(key->symm_alg)); - print_hexdump(0, "Key", key->key, pgp_key_size(key->symm_alg)); - printf("Checksum: %04x\n", key->checksum); - } -} - -static void -start_subpacket(int *indent, int type) -{ - *indent += 1; - print_indent(*indent); - printf("-- %s (type 0x%02x)\n", - pgp_show_ss_type((pgp_content_enum)type), - type - PGP_PTAG_SIG_SUBPKT_BASE); -} - -static void -end_subpacket(int *indent) -{ - *indent -= 1; -} - -/** -\ingroup Core_Print -\param contents -*/ -int -pgp_print_packet(pgp_printstate_t *print, const pgp_packet_t *pkt) -{ - const pgp_contents_t *content = &pkt->u; - pgp_text_t *text; - const char *str; - - if (print->unarmoured && pkt->tag != PGP_PTAG_CT_UNARMOURED_TEXT) { - print->unarmoured = 0; - puts("UNARMOURED TEXT ends"); - } - if (pkt->tag == PGP_PARSER_PTAG) { - printf("=> PGP_PARSER_PTAG: %s\n", - pgp_show_packet_tag((pgp_content_enum)content->ptag.type)); - } else { - printf("=> %s\n", pgp_show_packet_tag(pkt->tag)); - } - - switch (pkt->tag) { - case PGP_PARSER_ERROR: - printf("parse error: %s\n", content->error); - break; - - case PGP_PARSER_ERRCODE: - printf("parse error: %s\n", - pgp_errcode(content->errcode.errcode)); - break; - - case PGP_PARSER_PACKET_END: - print_packet_hex(&content->packet); - break; - - case PGP_PARSER_PTAG: - if (content->ptag.type == PGP_PTAG_CT_PUBLIC_KEY) { - print->indent = 0; - printf("\n*** NEXT KEY ***\n"); - } - printf("\n"); - print_indent(print->indent); - printf("==== ptag new_format=%u type=%u length_type=%d" - " length=0x%x (%u) position=0x%x (%u)\n", - content->ptag.new_format, - content->ptag.type, content->ptag.length_type, - content->ptag.length, content->ptag.length, - content->ptag.position, content->ptag.position); - print_tagname(print->indent, pgp_show_packet_tag((pgp_content_enum)content->ptag.type)); - break; - - case PGP_PTAG_CT_SE_DATA_HEADER: - print_tagname(print->indent, "SYMMETRIC ENCRYPTED DATA"); - break; - - case PGP_PTAG_CT_SE_IP_DATA_HEADER: - print_tagname(print->indent, - "SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA HEADER"); - printf("Version: %d\n", content->se_ip_data_header); - break; - - case PGP_PTAG_CT_SE_IP_DATA_BODY: - print_tagname(print->indent, - "SYMMETRIC ENCRYPTED INTEGRITY PROTECTED DATA BODY"); - hexdump(stdout, "data", content->se_data_body.data, - content->se_data_body.length); - break; - - case PGP_PTAG_CT_PUBLIC_KEY: - case PGP_PTAG_CT_PUBLIC_SUBKEY: - print_tagname(print->indent, (pkt->tag == PGP_PTAG_CT_PUBLIC_KEY) ? - "PUBLIC KEY" : - "PUBLIC SUBKEY"); - pgp_print_pubkey(&content->pubkey); - break; - - case PGP_PTAG_CT_TRUST: - print_tagname(print->indent, "TRUST"); - print_data(print->indent, "Trust", &content->trust); - break; - - case PGP_PTAG_CT_USER_ID: - print_tagname(print->indent, "USER ID"); - print_utf8_string(print->indent, "userid", content->userid); - break; - - case PGP_PTAG_CT_SIGNATURE: - print_tagname(print->indent, "SIGNATURE"); - print_indent(print->indent); - print_uint(print->indent, "Signature Version", - (unsigned)content->sig.info.version); - if (content->sig.info.birthtime_set) { - print_time(print->indent, "Signature Creation Time", - content->sig.info.birthtime); - } - if (content->sig.info.duration_set) { - print_uint(print->indent, "Signature Duration", - (unsigned)content->sig.info.duration); - } - - print_string_and_value(print->indent, "Signature Type", - pgp_show_sig_type(content->sig.info.type), - content->sig.info.type); - - if (content->sig.info.signer_id_set) { - hexdump_data(print->indent, "Signer ID", - content->sig.info.signer_id, - (unsigned)sizeof(content->sig.info.signer_id)); - } - - print_string_and_value(print->indent, "Public Key Algorithm", - pgp_show_pka(content->sig.info.key_alg), - content->sig.info.key_alg); - print_string_and_value(print->indent, "Hash Algorithm", - pgp_show_hash_alg((uint8_t) - content->sig.info.hash_alg), - (uint8_t)content->sig.info.hash_alg); - print_uint(print->indent, "Hashed data len", - (unsigned)content->sig.info.v4_hashlen); - print_indent(print->indent); - hexdump_data(print->indent, "hash2", &content->sig.hash2[0], 2); - switch (content->sig.info.key_alg) { - case PGP_PKA_RSA: - case PGP_PKA_RSA_SIGN_ONLY: - print_bn(print->indent, "sig", content->sig.info.sig.rsa.sig); - break; - - case PGP_PKA_DSA: - print_bn(print->indent, "r", content->sig.info.sig.dsa.r); - print_bn(print->indent, "s", content->sig.info.sig.dsa.s); - break; - - case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn(print->indent, "r", content->sig.info.sig.elgamal.r); - print_bn(print->indent, "s", content->sig.info.sig.elgamal.s); - break; - - default: - (void) fprintf(stderr, - "pgp_print_packet: Unusual algorithm\n"); - return 0; - } - - if (content->sig.hash) - printf("data hash is set\n"); - - break; - - case PGP_PTAG_CT_COMPRESSED: - print_tagname(print->indent, "COMPRESSED"); - print_uint(print->indent, "Compressed Data Type", - (unsigned)content->compressed); - break; - - case PGP_PTAG_CT_1_PASS_SIG: - print_tagname(print->indent, "ONE PASS SIGNATURE"); - - print_uint(print->indent, "Version", (unsigned)content->one_pass_sig.version); - print_string_and_value(print->indent, "Signature Type", - pgp_show_sig_type(content->one_pass_sig.sig_type), - content->one_pass_sig.sig_type); - print_string_and_value(print->indent, "Hash Algorithm", - pgp_show_hash_alg((uint8_t)content->one_pass_sig.hash_alg), - (uint8_t)content->one_pass_sig.hash_alg); - print_string_and_value(print->indent, "Public Key Algorithm", - pgp_show_pka(content->one_pass_sig.key_alg), - content->one_pass_sig.key_alg); - hexdump_data(print->indent, "Signer ID", - content->one_pass_sig.keyid, - (unsigned)sizeof(content->one_pass_sig.keyid)); - print_uint(print->indent, "Nested", content->one_pass_sig.nested); - break; - - case PGP_PTAG_CT_USER_ATTR: - print_tagname(print->indent, "USER ATTRIBUTE"); - print_hexdump(print->indent, "User Attribute", - content->userattr.contents, - (unsigned)content->userattr.len); - break; - - case PGP_PTAG_RAW_SS: - if (pkt->critical) { - (void) fprintf(stderr, "contents are critical\n"); - return 0; - } - start_subpacket(&print->indent, pkt->tag); - print_uint(print->indent, "Raw Signature Subpacket: tag", - (unsigned)(content->ss_raw.tag - - (unsigned)PGP_PTAG_SIG_SUBPKT_BASE)); - print_hexdump(print->indent, "Raw Data", - content->ss_raw.raw, - (unsigned)content->ss_raw.length); - break; - - case PGP_PTAG_SS_CREATION_TIME: - start_subpacket(&print->indent, pkt->tag); - print_time(print->indent, "Signature Creation Time", content->ss_time); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_EXPIRATION_TIME: - start_subpacket(&print->indent, pkt->tag); - print_duration(print->indent, "Signature Expiration Time", - content->ss_time); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_KEY_EXPIRY: - start_subpacket(&print->indent, pkt->tag); - print_duration(print->indent, "Key Expiration Time", content->ss_time); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_TRUST: - start_subpacket(&print->indent, pkt->tag); - print_string(print->indent, "Trust Signature", ""); - print_uint(print->indent, "Level", (unsigned)content->ss_trust.level); - print_uint(print->indent, "Amount", (unsigned)content->ss_trust.amount); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_REVOCABLE: - start_subpacket(&print->indent, pkt->tag); - print_boolean(print->indent, "Revocable", content->ss_revocable); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_REVOCATION_KEY: - start_subpacket(&print->indent, pkt->tag); - /* not yet tested */ - printf(" revocation key: class=0x%x", - content->ss_revocation_key.class); - if (content->ss_revocation_key.class & 0x40) { - printf(" (sensitive)"); - } - printf(", algid=0x%x", content->ss_revocation_key.algid); - hexdump(stdout, "fingerprint", content->ss_revocation_key.fingerprint, - PGP_FINGERPRINT_SIZE); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_ISSUER_KEY_ID: - start_subpacket(&print->indent, pkt->tag); - print_hexdump(print->indent, "Issuer Key Id", - content->ss_issuer, (unsigned)sizeof(content->ss_issuer)); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_PREFERRED_SKA: - start_subpacket(&print->indent, pkt->tag); - print_data(print->indent, "Preferred Symmetric Algorithms", - &content->ss_skapref); - text = pgp_showall_ss_skapref(&content->ss_skapref); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_PRIMARY_USER_ID: - start_subpacket(&print->indent, pkt->tag); - print_boolean(print->indent, "Primary User ID", - content->ss_primary_userid); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_PREFERRED_HASH: - start_subpacket(&print->indent, pkt->tag); - print_data(print->indent, "Preferred Hash Algorithms", - &content->ss_hashpref); - text = pgp_showall_ss_hashpref(&content->ss_hashpref); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_PREF_COMPRESS: - start_subpacket(&print->indent, pkt->tag); - print_data(print->indent, "Preferred Compression Algorithms", - &content->ss_zpref); - text = pgp_showall_ss_zpref(&content->ss_zpref); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_KEY_FLAGS: - start_subpacket(&print->indent, pkt->tag); - print_data(print->indent, "Key Flags", &content->ss_key_flags); - - text = pgp_showall_ss_key_flags(&content->ss_key_flags); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_KEYSERV_PREFS: - start_subpacket(&print->indent, pkt->tag); - print_data(print->indent, "Key Server Preferences", - &content->ss_key_server_prefs); - text = pgp_show_keyserv_prefs(&content->ss_key_server_prefs); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_FEATURES: - start_subpacket(&print->indent, pkt->tag); - print_data(print->indent, "Features", &content->ss_features); - text = pgp_showall_ss_features(content->ss_features); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_NOTATION_DATA: - start_subpacket(&print->indent, pkt->tag); - print_indent(print->indent); - printf("Notation Data:\n"); - - print->indent++; - print_data(print->indent, "Flags", &content->ss_notation.flags); - text = pgp_showall_notation(content->ss_notation); - print_text_breakdown(print->indent, text); - pgp_text_free(text); - - print_data(print->indent, "Name", &content->ss_notation.name); - - print_data(print->indent, "Value", &content->ss_notation.value); - - print->indent--; - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_REGEXP: - start_subpacket(&print->indent, pkt->tag); - print_hexdump(print->indent, "Regular Expression", - (uint8_t *) content->ss_regexp, - (unsigned)strlen(content->ss_regexp)); - print_string(print->indent, NULL, content->ss_regexp); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_POLICY_URI: - start_subpacket(&print->indent, pkt->tag); - print_string(print->indent, "Policy URL", content->ss_policy); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_SIGNERS_USER_ID: - start_subpacket(&print->indent, pkt->tag); - print_utf8_string(print->indent, "Signer's User ID", content->ss_signer); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_PREF_KEYSERV: - start_subpacket(&print->indent, pkt->tag); - print_string(print->indent, "Preferred Key Server", content->ss_keyserv); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_EMBEDDED_SIGNATURE: - start_subpacket(&print->indent, pkt->tag); - end_subpacket(&print->indent);/* \todo print out contents? */ - break; - - case PGP_PTAG_SS_USERDEFINED00: - case PGP_PTAG_SS_USERDEFINED01: - case PGP_PTAG_SS_USERDEFINED02: - case PGP_PTAG_SS_USERDEFINED03: - case PGP_PTAG_SS_USERDEFINED04: - case PGP_PTAG_SS_USERDEFINED05: - case PGP_PTAG_SS_USERDEFINED06: - case PGP_PTAG_SS_USERDEFINED07: - case PGP_PTAG_SS_USERDEFINED08: - case PGP_PTAG_SS_USERDEFINED09: - case PGP_PTAG_SS_USERDEFINED10: - start_subpacket(&print->indent, pkt->tag); - print_hexdump(print->indent, "Internal or user-defined", - content->ss_userdef.contents, - (unsigned)content->ss_userdef.len); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_RESERVED: - start_subpacket(&print->indent, pkt->tag); - print_hexdump(print->indent, "Reserved", - content->ss_userdef.contents, - (unsigned)content->ss_userdef.len); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_SS_REVOCATION_REASON: - start_subpacket(&print->indent, pkt->tag); - print_hexdump(print->indent, "Revocation Reason", - &content->ss_revocation.code, - 1); - str = pgp_show_ss_rr_code(content->ss_revocation.code); - print_string(print->indent, NULL, str); - end_subpacket(&print->indent); - break; - - case PGP_PTAG_CT_LITDATA_HEADER: - print_tagname(print->indent, "LITERAL DATA HEADER"); - printf(" literal data header format=%c filename='%s'\n", - content->litdata_header.format, - content->litdata_header.filename); - showtime(" modification time", - content->litdata_header.mtime); - printf("\n"); - break; - - case PGP_PTAG_CT_LITDATA_BODY: - print_tagname(print->indent, "LITERAL DATA BODY"); - printf(" literal data body length=%u\n", - content->litdata_body.length); - printf(" data="); - print_escaped(content->litdata_body.data, - content->litdata_body.length); - printf("\n"); - break; - - case PGP_PTAG_CT_SIGNATURE_HEADER: - print_tagname(print->indent, "SIGNATURE"); - print_indent(print->indent); - print_uint(print->indent, "Signature Version", - (unsigned)content->sig.info.version); - if (content->sig.info.birthtime_set) { - print_time(print->indent, "Signature Creation Time", - content->sig.info.birthtime); - } - if (content->sig.info.duration_set) { - print_uint(print->indent, "Signature Duration", - (unsigned)content->sig.info.duration); - } - print_string_and_value(print->indent, "Signature Type", - pgp_show_sig_type(content->sig.info.type), - content->sig.info.type); - if (content->sig.info.signer_id_set) { - hexdump_data(print->indent, "Signer ID", - content->sig.info.signer_id, - (unsigned)sizeof(content->sig.info.signer_id)); - } - print_string_and_value(print->indent, "Public Key Algorithm", - pgp_show_pka(content->sig.info.key_alg), - content->sig.info.key_alg); - print_string_and_value(print->indent, "Hash Algorithm", - pgp_show_hash_alg((uint8_t)content->sig.info.hash_alg), - (uint8_t)content->sig.info.hash_alg); - print_uint(print->indent, "Hashed data len", - (unsigned)content->sig.info.v4_hashlen); - - break; - - case PGP_PTAG_CT_SIGNATURE_FOOTER: - print_indent(print->indent); - hexdump_data(print->indent, "hash2", &content->sig.hash2[0], 2); - - switch (content->sig.info.key_alg) { - case PGP_PKA_RSA: - print_bn(print->indent, "sig", content->sig.info.sig.rsa.sig); - break; - - case PGP_PKA_DSA: - print_bn(print->indent, "r", content->sig.info.sig.dsa.r); - print_bn(print->indent, "s", content->sig.info.sig.dsa.s); - break; - - case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - print_bn(print->indent, "r", content->sig.info.sig.elgamal.r); - print_bn(print->indent, "s", content->sig.info.sig.elgamal.s); - break; - - case PGP_PKA_PRIVATE00: - case PGP_PKA_PRIVATE01: - case PGP_PKA_PRIVATE02: - case PGP_PKA_PRIVATE03: - case PGP_PKA_PRIVATE04: - case PGP_PKA_PRIVATE05: - case PGP_PKA_PRIVATE06: - case PGP_PKA_PRIVATE07: - case PGP_PKA_PRIVATE08: - case PGP_PKA_PRIVATE09: - case PGP_PKA_PRIVATE10: - print_data(print->indent, "Private/Experimental", - &content->sig.info.sig.unknown); - break; - - default: - (void) fprintf(stderr, - "pgp_print_packet: Unusual key algorithm\n"); - return 0; - } - break; - - case PGP_GET_PASSPHRASE: - print_tagname(print->indent, "PGP_GET_PASSPHRASE"); - break; - - case PGP_PTAG_CT_SECRET_KEY: - print_tagname(print->indent, "PGP_PTAG_CT_SECRET_KEY"); - print_seckey_verbose(pkt->tag, &content->seckey); - break; - - case PGP_PTAG_CT_ENCRYPTED_SECRET_KEY: - print_tagname(print->indent, "PGP_PTAG_CT_ENCRYPTED_SECRET_KEY"); - print_seckey_verbose(pkt->tag, &content->seckey); - break; - - case PGP_PTAG_CT_ARMOUR_HEADER: - print_tagname(print->indent, "ARMOUR HEADER"); - print_string(print->indent, "type", content->armour_header.type); - break; - - case PGP_PTAG_CT_SIGNED_CLEARTEXT_HEADER: - print_tagname(print->indent, "SIGNED CLEARTEXT HEADER"); - print_headers(&content->cleartext_head); - break; - - case PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY: - print_tagname(print->indent, "SIGNED CLEARTEXT BODY"); - print_block(print->indent, "signed cleartext", content->cleartext_body.data, - content->cleartext_body.length); - break; - - case PGP_PTAG_CT_SIGNED_CLEARTEXT_TRAILER: - print_tagname(print->indent, "SIGNED CLEARTEXT TRAILER"); - printf("hash algorithm: %d\n", - content->cleartext_trailer->alg); - printf("\n"); - break; - - case PGP_PTAG_CT_UNARMOURED_TEXT: - if (!print->unarmoured) { - print_tagname(print->indent, "UNARMOURED TEXT"); - print->unarmoured = 1; - } - putchar('['); - print_escaped(content->unarmoured_text.data, - content->unarmoured_text.length); - putchar(']'); - break; - - case PGP_PTAG_CT_ARMOUR_TRAILER: - print_tagname(print->indent, "ARMOUR TRAILER"); - print_string(print->indent, "type", content->armour_header.type); - break; - - case PGP_PTAG_CT_PK_SESSION_KEY: - case PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: - print_pk_sesskey(pkt->tag, &content->pk_sesskey); - break; - - case PGP_GET_SECKEY: - print_pk_sesskey(PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, - content->get_seckey.pk_sesskey); - break; - - default: - print_tagname(print->indent, "UNKNOWN PACKET TYPE"); - fprintf(stderr, "pgp_print_packet: unknown tag=%d (0x%x)\n", - pkt->tag, pkt->tag); - return 0; - } - return 1; -} - -static pgp_cb_ret_t -cb_list_packets(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) -{ - pgp_print_packet(&cbinfo->printstate, pkt); - return PGP_RELEASE_MEMORY; -} - -/** -\ingroup Core_Print -\param filename -\param armour -\param keyring -\param cb_get_passphrase -*/ -int -pgp_list_packets(pgp_io_t *io, - char *filename, - unsigned armour, - pgp_keyring_t *secring, - pgp_keyring_t *pubring, - void *passfp, - pgp_cbfunc_t *cb_get_passphrase) -{ - pgp_stream_t *stream = NULL; - const unsigned accumulate = 1; - const int printerrors = 1; - int fd; - - fd = pgp_setup_file_read(io, &stream, filename, NULL, cb_list_packets, - accumulate); - pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); - stream->cryptinfo.secring = secring; - stream->cryptinfo.pubring = pubring; - stream->cbinfo.passfp = passfp; - stream->cryptinfo.getpassphrase = cb_get_passphrase; - if (armour) { - pgp_reader_push_dearmour(stream); - } - pgp_parse(stream, printerrors); - pgp_teardown_file_read(stream, fd); - return 1; -} diff --git a/libs/netpgp/compress.c b/libs/netpgp/src/compress.c similarity index 97% rename from libs/netpgp/compress.c rename to libs/netpgp/src/compress.c index 1460e0dc..3186a019 100644 --- a/libs/netpgp/compress.c +++ b/libs/netpgp/src/compress.c @@ -49,7 +49,7 @@ /** \file */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -57,7 +57,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: compress.c,v 1.23 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #ifdef HAVE_ZLIB_H @@ -70,12 +70,12 @@ __RCSID("$NetBSD: compress.c,v 1.23 2012/03/05 02:20:18 christos Exp $"); #include -#include "packet-parse.h" -#include "errors-netpgp.h" -#include "netpgpdefs.h" -#include "crypto-netpgp.h" -#include "memory-netpgp.h" -#include "writer-netpgp.h" +#include "netpgp/packet-parse.h" +#include "netpgp/errors.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/crypto.h" +#include "netpgp/memory.h" +#include "netpgp/writer.h" #define DECOMPRESS_BUFFER 1024 @@ -108,7 +108,7 @@ typedef struct { } compress_t; /* - * \todo remove code duplication between this and + * \todo re move code duplication between this and * bzip2_compressed_data_reader */ static int @@ -188,8 +188,9 @@ zlib_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length, return 0; } len = (size_t)(z->zstream.next_out - &z->out[z->offset]); - if (len > length) { - len = length; + size_t left_in_cdest = length - cc; + if (len > left_in_cdest) { + len = left_in_cdest; } (void) memcpy(&cdest[cc], &z->out[z->offset], len); z->offset += len; diff --git a/libs/netpgp/create.c b/libs/netpgp/src/create.c similarity index 71% rename from libs/netpgp/create.c rename to libs/netpgp/src/create.c index 41487da5..2c80856e 100644 --- a/libs/netpgp/create.c +++ b/libs/netpgp/src/create.c @@ -49,7 +49,7 @@ /** \file */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -57,7 +57,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: create.c,v 1.38 2010/11/15 08:03:39 agc Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -78,15 +78,15 @@ __RCSID("$NetBSD: create.c,v 1.38 2010/11/15 08:03:39 agc Exp $"); #include #endif -#include "create-netpgp.h" -#include "keyring-netpgp.h" -#include "packet-netpgp.h" -#include "signature-netpgp.h" -#include "writer-netpgp.h" -#include "readerwriter-netpgp.h" -#include "memory-netpgp.h" -#include "netpgpdefs.h" -#include "netpgpdigest.h" +#include "netpgp/create.h" +#include "netpgp/keyring.h" +#include "netpgp/packet.h" +#include "netpgp/signature.h" +#include "netpgp/writer.h" +#include "netpgp/readerwriter.h" +#include "netpgp/memory.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/netpgpdigest.h" /** * \ingroup Core_Create @@ -98,10 +98,10 @@ __RCSID("$NetBSD: create.c,v 1.38 2010/11/15 08:03:39 agc Exp $"); unsigned pgp_write_ss_header(pgp_output_t *output, - unsigned length, + size_t length, pgp_content_enum type) { - return pgp_write_length(output, length) && + return pgp_write_length(output, (unsigned int)length) && pgp_write_scalar(output, (unsigned)(type - (unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1); } @@ -176,6 +176,11 @@ pubkey_length(const pgp_pubkey_t *key) case PGP_PKA_RSA: return mpi_length(key->key.rsa.n) + mpi_length(key->key.rsa.e); + case PGP_PKA_ELGAMAL: + return mpi_length(key->key.elgamal.p) + + mpi_length(key->key.elgamal.g) + + mpi_length(key->key.elgamal.y); + default: (void) fprintf(stderr, "pubkey_length: unknown key algorithm\n"); @@ -188,7 +193,6 @@ seckey_length(const pgp_seckey_t *key) { int len; - len = 0; switch (key->pubkey.alg) { case PGP_PKA_DSA: return (unsigned)(mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey)); @@ -197,6 +201,11 @@ seckey_length(const pgp_seckey_t *key) mpi_length(key->key.rsa.q) + mpi_length(key->key.rsa.u); return (unsigned)(len + pubkey_length(&key->pubkey)); + + case PGP_PKA_ELGAMAL: + return (unsigned)( + mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey)); + default: (void) fprintf(stderr, "seckey_length: unknown key algorithm\n"); @@ -273,7 +282,7 @@ write_pubkey_body(const pgp_pubkey_t *key, pgp_output_t *output) * Note that we support v3 keys here because they're needed for * verification. */ -unsigned +static unsigned write_seckey_body(const pgp_seckey_t *key, const uint8_t *passphrase, const size_t pplen, @@ -285,160 +294,166 @@ write_seckey_body(const pgp_seckey_t *key, pgp_hash_t hash; unsigned done = 0; unsigned i = 0; - uint8_t *hashed; uint8_t sesskey[CAST_KEY_LENGTH]; if (!write_pubkey_body(&key->pubkey, output)) { return 0; } - if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) { - (void) fprintf(stderr, "write_seckey_body: s2k usage\n"); - return 0; - } - if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) { - return 0; - } + if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) { + return 0; + } + if (key->s2k_usage != PGP_S2KU_NONE) { + if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) { + (void) fprintf(stderr, "write_seckey_body: s2k usage\n"); + return 0; + } - if (key->alg != PGP_SA_CAST5) { - (void) fprintf(stderr, "write_seckey_body: algorithm\n"); - return 0; - } - if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) { - return 0; - } + if (key->alg != PGP_SA_CAST5) { + (void) fprintf(stderr, "write_seckey_body: algorithm\n"); + return 0; + } + if (!pgp_write_scalar(output, (unsigned)key->alg, 1)) { + return 0; + } - if (key->s2k_specifier != PGP_S2KS_SIMPLE && - key->s2k_specifier != PGP_S2KS_SALTED) { - /* = 1 \todo could also be iterated-and-salted */ - (void) fprintf(stderr, "write_seckey_body: s2k spec\n"); - return 0; - } - if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) { - return 0; - } - if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) { - return 0; - } + if (key->s2k_specifier != PGP_S2KS_SIMPLE && + key->s2k_specifier != PGP_S2KS_SALTED) { + /* = 1 \todo could also be iterated-and-salted */ + (void) fprintf(stderr, "write_seckey_body: s2k spec\n"); + return 0; + } + if (!pgp_write_scalar(output, (unsigned)key->s2k_specifier, 1)) { + return 0; + } + if (!pgp_write_scalar(output, (unsigned)key->hash_alg, 1)) { + return 0; + } - switch (key->s2k_specifier) { - case PGP_S2KS_SIMPLE: - /* nothing more to do */ - break; + switch (key->s2k_specifier) { + case PGP_S2KS_SIMPLE: + /* nothing more to do */ + break; - case PGP_S2KS_SALTED: - /* 8-octet salt value */ - pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE); - if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) { - return 0; - } - break; + case PGP_S2KS_SALTED: + /* 8-octet salt value */ + pgp_random(__UNCONST(&key->salt[0]), PGP_SALT_SIZE); + if (!pgp_write(output, key->salt, PGP_SALT_SIZE)) { + return 0; + } + break; - /* - * \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt - * value // 1-octet count break; - */ + /* + * \todo case PGP_S2KS_ITERATED_AND_SALTED: // 8-octet salt + * value // 1-octet count break; + */ - default: - (void) fprintf(stderr, - "invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - return 0; - } + default: + (void) fprintf(stderr, + "invalid/unsupported s2k specifier %d\n", + key->s2k_specifier); + return 0; + } - if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) { - return 0; - } + if (!pgp_write(output, &key->iv[0], pgp_block_size(key->alg))) { + return 0; + } - /* - * create the session key for encrypting the algorithm-specific - * fields - */ + /* + * create the session key for encrypting the algorithm-specific + * fields + */ - switch (key->s2k_specifier) { - case PGP_S2KS_SIMPLE: - case PGP_S2KS_SALTED: - /* RFC4880: section 3.7.1.1 and 3.7.1.2 */ + switch (key->s2k_specifier) { + case PGP_S2KS_SIMPLE: + case PGP_S2KS_SALTED: + /* RFC4880: section 3.7.1.1 and 3.7.1.2 */ - for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) { - unsigned hashsize; - unsigned j; - unsigned needed; - unsigned size; - uint8_t zero = 0; + for (done = 0, i = 0; done < CAST_KEY_LENGTH; i++) { + unsigned hashsize; + unsigned j; + unsigned needed; + unsigned size; + uint8_t zero = 0; + uint8_t *hashed; - /* Hard-coded SHA1 for session key */ - pgp_hash_any(&hash, PGP_HASH_SHA1); - hashsize = pgp_hash_size(key->hash_alg); - needed = CAST_KEY_LENGTH - done; - size = MIN(needed, hashsize); - if ((hashed = calloc(1, hashsize)) == NULL) { - (void) fprintf(stderr, "write_seckey_body: bad alloc\n"); - return 0; - } - if (!hash.init(&hash)) { - (void) fprintf(stderr, "write_seckey_body: bad alloc\n"); - return 0; - } + /* Hard-coded SHA1 for session key */ + pgp_hash_any(&hash, PGP_HASH_SHA1); + hashsize = pgp_hash_size(key->hash_alg); + needed = CAST_KEY_LENGTH - done; + size = MIN(needed, hashsize); + if ((hashed = calloc(1, hashsize)) == NULL) { + (void) fprintf(stderr, "write_seckey_body: bad alloc\n"); + return 0; + } + if (!hash.init(&hash)) { + (void) fprintf(stderr, "write_seckey_body: bad alloc\n"); + free(hashed); + return 0; + } - /* preload if iterating */ - for (j = 0; j < i; j++) { - /* - * Coverity shows a DEADCODE error on this - * line. This is expected since the hardcoded - * use of SHA1 and CAST5 means that it will - * not used. This will change however when - * other algorithms are supported. - */ - hash.add(&hash, &zero, 1); - } + /* preload if iterating */ + for (j = 0; j < i; j++) { + /* + * Coverity shows a DEADCODE error on this + * line. This is expected since the hardcoded + * use of SHA1 and CAST5 means that it will + * not used. This will change however when + * other algorithms are supported. + */ + hash.add(&hash, &zero, 1); + } - if (key->s2k_specifier == PGP_S2KS_SALTED) { - hash.add(&hash, key->salt, PGP_SALT_SIZE); - } - hash.add(&hash, passphrase, (unsigned)pplen); - hash.finish(&hash, hashed); + if (key->s2k_specifier == PGP_S2KS_SALTED) { + hash.add(&hash, key->salt, PGP_SALT_SIZE); + } + hash.add(&hash, passphrase, (unsigned)pplen); + hash.finish(&hash, hashed); - /* - * if more in hash than is needed by session key, use - * the leftmost octets - */ - (void) memcpy(&sesskey[i * hashsize], - hashed, (unsigned)size); - done += (unsigned)size; - if (done > CAST_KEY_LENGTH) { - (void) fprintf(stderr, - "write_seckey_body: short add\n"); - return 0; - } - } + /* + * if more in hash than is needed by session key, use + * the leftmost octets + */ + (void) memcpy(&sesskey[i * hashsize], + hashed, (unsigned)size); + done += (unsigned)size; + free(hashed); + if (done > CAST_KEY_LENGTH) { + (void) fprintf(stderr, + "write_seckey_body: short add\n"); + return 0; + } + } - break; + break; - /* - * \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt - * value * 1-octet count break; - */ + /* + * \todo case PGP_S2KS_ITERATED_AND_SALTED: * 8-octet salt + * value * 1-octet count break; + */ - default: - (void) fprintf(stderr, - "invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - return 0; - } + default: + (void) fprintf(stderr, + "invalid/unsupported s2k specifier %d\n", + key->s2k_specifier); + return 0; + } - /* use this session key to encrypt */ + /* use this session key to encrypt */ - pgp_crypt_any(&crypted, key->alg); - crypted.set_iv(&crypted, key->iv); - crypted.set_crypt_key(&crypted, sesskey); - pgp_encrypt_init(&crypted); + pgp_crypt_any(&crypted, key->alg); + crypted.set_iv(&crypted, key->iv); + crypted.set_crypt_key(&crypted, sesskey); + pgp_encrypt_init(&crypted); - if (pgp_get_debug_level(__FILE__)) { - hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg)); - hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH); - (void) fprintf(stderr, "\nturning encryption on...\n"); - } - pgp_push_enc_crypt(output, &crypted); + if (pgp_get_debug_level(__FILE__)) { + hexdump(stderr, "writing: iv=", key->iv, pgp_block_size(key->alg)); + hexdump(stderr, "key= ", sesskey, CAST_KEY_LENGTH); + (void) fprintf(stderr, "\nturning encryption on...\n"); + } + pgp_push_enc_crypt(output, &crypted); + }else{ + pgp_push_sum16_writer(output); + } switch (key->pubkey.alg) { case PGP_PKA_RSA: @@ -463,11 +478,19 @@ write_seckey_body(const pgp_seckey_t *key, return 0; } - if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) { - return 0; - } - pgp_writer_pop(output); + if (key->s2k_usage != PGP_S2KU_NONE) { + + if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) { + return 0; + } + pgp_writer_pop(output); + }else{ + uint16_t checksum = pgp_pop_sum16_writer(output); + if (!pgp_write_scalar(output, checksum, 2)) { + return 0; + } + } return 1; } @@ -480,13 +503,20 @@ write_seckey_body(const pgp_seckey_t *key, * \return 1 if OK, otherwise 0 */ unsigned -write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key) +pgp_write_struct_pubkey_ptag( + pgp_output_t *output, + const pgp_pubkey_t *key, + pgp_content_enum ptag) { - return pgp_write_ptag(output, PGP_PTAG_CT_PUBLIC_KEY) && + return pgp_write_ptag(output, ptag) && pgp_write_length(output, 1 + 4 + 1 + pubkey_length(key)) && write_pubkey_body(key, output); } - +unsigned +pgp_write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key) +{ + return pgp_write_struct_pubkey_ptag(output, key, PGP_PTAG_CT_PUBLIC_KEY); +} /** \ingroup HighLevel_KeyWrite @@ -500,46 +530,110 @@ write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key) */ unsigned -pgp_write_xfer_pubkey(pgp_output_t *output, - const pgp_key_t *key, - const unsigned armoured) +pgp_write_xfer_key(pgp_output_t *output, + const pgp_key_t *key, + const unsigned armoured) { - unsigned i, j; + unsigned directsigidx = 0; + pgp_directsig_t *directsigp; + unsigned uididx = 0; + unsigned uidsigidx = 0; + uint8_t **uidp; + pgp_uidsig_t *uidsigp; + pgp_subkey_t *subkeyp; + unsigned subkeyidx = 0; + unsigned subkeysigidx = 0; + pgp_subkeysig_t *subkeysigp; - if (armoured) { - pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK); - } - /* public key */ - if (!write_struct_pubkey(output, &key->key.pubkey)) { - return 0; - } + if (armoured) { + pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK); + } - /* TODO: revocation signatures go here */ + /* primary key */ + if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { + if (!pgp_write_struct_pubkey(output, &key->key.pubkey)) { + return 0; + } + }else{ + if (!pgp_write_struct_seckey(&key->key.seckey, (const uint8_t *)"", 0, output)) { + return 0; + } + } - /* user ids and corresponding signatures */ - for (i = 0; i < key->uidc; i++) { - if (!pgp_write_struct_userid(output, key->uids[i])) { - return 0; - } - for (j = 0; j < key->packetc; j++) { - if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) { - return 0; - } - } - } + directsigp = key->directsigs; + for (directsigidx = 0 ; directsigidx < key->directsigc; + directsigidx++, directsigp++) + { + if (!pgp_write(output, directsigp->packet.raw, + (unsigned)directsigp->packet.length)) { + return 0; + } + } - /* TODO: user attributes and corresponding signatures */ + /* Loop over key's user ids*/ + uidp = key->uids; + for (uididx = 0 ; uididx < key->uidc; uididx++, uidp++) + { + if (!pgp_write_struct_userid(output, *uidp)) { + return 0; + } + /* Loop over key's user ids sigs */ + uidsigp = key->uidsigs; + for (uidsigidx = 0 ; uidsigidx < key->uidsigc; uidsigidx++, uidsigp++) + { + /* matching selected user id */ + if(uidsigp->uid == uididx) + { + if (!pgp_write(output, uidsigp->packet.raw, + (unsigned)uidsigp->packet.length)) { + return 0; + } + } + } + } - /* - * subkey packets and corresponding signatures and optional - * revocation - */ + /* TODO attibutes */ - if (armoured) { - pgp_writer_info_finalise(&output->errors, &output->writer); - pgp_writer_pop(output); - } - return 1; + /* Loop over key's subkeys */ + subkeyp = key->subkeys; + for (subkeyidx = 0 ; subkeyidx < key->subkeyc; subkeyidx++, subkeyp++) + { + if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { + if (!pgp_write_struct_pubkey_ptag( + output, &subkeyp->key.pubkey, + PGP_PTAG_CT_PUBLIC_SUBKEY)) { + return 0; + } + }else{ + if (!pgp_write_struct_seckey_ptag( + /* TODO support passphrase again */ + &subkeyp->key.seckey, (const uint8_t *)"", 0, output, + PGP_PTAG_CT_SECRET_SUBKEY)) { + return 0; + } + } + + /* Loop over key's subkeys sigs */ + subkeysigp = key->subkeysigs; + for (subkeysigidx = 0 ; subkeysigidx < key->subkeysigc; + subkeysigidx++, subkeysigp++) + { + /* matching selected subkey */ + if(subkeysigp->subkey == subkeyidx) + { + if (!pgp_write(output, subkeysigp->packet.raw, + (unsigned)subkeysigp->packet.length)) { + return 0; + } + } + } + } + + if (armoured) { + pgp_writer_info_finalise(&output->errors, &output->writer); + pgp_writer_pop(output); + } + return 1; } /** @@ -554,52 +648,14 @@ pgp_write_xfer_pubkey(pgp_output_t *output, \param output Output stream */ - +/* TODO have encrypted key export again unsigned pgp_write_xfer_seckey(pgp_output_t *output, const pgp_key_t *key, const uint8_t *passphrase, const size_t pplen, unsigned armoured) -{ - unsigned i, j; - - if (armoured) { - pgp_writer_push_armoured(output, PGP_PGP_PRIVATE_KEY_BLOCK); - } - /* public key */ - if (!pgp_write_struct_seckey(&key->key.seckey, passphrase, - pplen, output)) { - return 0; - } - - /* TODO: revocation signatures go here */ - - /* user ids and corresponding signatures */ - for (i = 0; i < key->uidc; i++) { - if (!pgp_write_struct_userid(output, key->uids[i])) { - return 0; - } - for (j = 0; j < key->packetc; j++) { - if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) { - return 0; - } - } - } - - /* TODO: user attributes and corresponding signatures */ - - /* - * subkey packets and corresponding signatures and optional - * revocation - */ - - if (armoured) { - pgp_writer_info_finalise(&output->errors, &output->writer); - pgp_writer_pop(output); - } - return 1; -} +*/ /** * \ingroup Core_WritePackets @@ -620,7 +676,7 @@ pgp_write_rsa_pubkey(time_t t, const BIGNUM *n, pgp_pubkey_t key; pgp_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e)); - return write_struct_pubkey(output, &key); + return pgp_write_struct_pubkey(output, &key); } /** @@ -693,10 +749,11 @@ pgp_fast_create_rsa_seckey(pgp_seckey_t *key, time_t t, * \return 1 if OK; else 0 */ unsigned -pgp_write_struct_seckey(const pgp_seckey_t *key, +pgp_write_struct_seckey_ptag(const pgp_seckey_t *key, const uint8_t *passphrase, const size_t pplen, - pgp_output_t *output) + pgp_output_t *output, + pgp_content_enum ptag) { int length = 0; @@ -709,7 +766,7 @@ pgp_write_struct_seckey(const pgp_seckey_t *key, /* Ref: RFC4880 Section 5.5.3 */ /* pubkey, excluding MPIs */ - length += 1 + 4 + 1 + 1; + length += 1 + 4 + 1; /* s2k usage */ length += 1; @@ -776,12 +833,21 @@ pgp_write_struct_seckey(const pgp_seckey_t *key, /* secret key and public key MPIs */ length += (unsigned)seckey_length(key); - return pgp_write_ptag(output, PGP_PTAG_CT_SECRET_KEY) && + return pgp_write_ptag(output, ptag) && /* pgp_write_length(output,1+4+1+1+seckey_length(key)+2) && */ pgp_write_length(output, (unsigned)length) && write_seckey_body(key, passphrase, pplen, output); } +unsigned +pgp_write_struct_seckey(const pgp_seckey_t *key, + const uint8_t *passphrase, + const size_t pplen, + pgp_output_t *output) +{ + return pgp_write_struct_seckey_ptag( + key, passphrase, pplen, output, PGP_PTAG_CT_SECRET_KEY); +} /** * \ingroup Core_Create * @@ -932,7 +998,7 @@ encode_m_buf(const uint8_t *M, size_t mLen, const pgp_pubkey_t * pubkey, \note Currently hard-coded to use RSA */ pgp_pk_sesskey_t * -pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername) +pgp_create_pk_sesskey(pgp_key_t *key, const char *ciphername, pgp_pk_sesskey_t *initial_sesskey) { /* * Creates a random session key and encrypts it for the given key @@ -941,7 +1007,7 @@ pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername) * can be any, we're hardcoding RSA for now */ - const pgp_pubkey_t *pubkey; + pgp_pubkey_t *pubkey; pgp_pk_sesskey_t *sesskey; pgp_symm_alg_t cipher; const uint8_t *id; @@ -950,13 +1016,8 @@ pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername) uint8_t *encoded_m_buf; size_t sz_encoded_m_buf; - if (memcmp(key->encid, "\0\0\0\0\0\0\0\0", 8) == 0) { - pubkey = pgp_get_pubkey(key); - id = key->sigid; - } else { - pubkey = &key->enckey; - id = key->encid; - } + pubkey = pgp_key_get_enckey(key, &id); + /* allocate unencoded_m_buf here */ (void) memset(&cipherinfo, 0x0, sizeof(cipherinfo)); pgp_crypt_any(&cipherinfo, @@ -1022,7 +1083,14 @@ pgp_create_pk_sesskey(const pgp_key_t *key, const char *ciphername) sesskey->alg = pubkey->alg; sesskey->symm_alg = cipher; - pgp_random(sesskey->key, cipherinfo.keysize); + if(initial_sesskey){ + if(initial_sesskey->symm_alg != cipher){ + return NULL; + } + memcpy(sesskey->key, initial_sesskey->key, cipherinfo.keysize); + }else{ + pgp_random(sesskey->key, cipherinfo.keysize); + } if (pgp_get_debug_level(__FILE__)) { hexdump(stderr, "sesskey created", sesskey->key, diff --git a/libs/netpgp/crypto.c b/libs/netpgp/src/crypto.c similarity index 77% rename from libs/netpgp/crypto.c rename to libs/netpgp/src/crypto.c index 2fdc4651..7e5319d4 100644 --- a/libs/netpgp/crypto.c +++ b/libs/netpgp/src/crypto.c @@ -46,7 +46,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -54,7 +54,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: crypto.c,v 1.36 2014/02/17 07:39:19 agc Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -66,12 +66,14 @@ __RCSID("$NetBSD: crypto.c,v 1.36 2014/02/17 07:39:19 agc Exp $"); #include -#include "types-netpgp.h" -#include "crypto-netpgp.h" -#include "readerwriter-netpgp.h" -#include "memory-netpgp.h" -#include "netpgpdefs.h" -#include "signature-netpgp.h" +#include "netpgp/types.h" +#include "netpgp/crypto.h" +#include "netpgp/readerwriter.h" +#include "netpgp/memory.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/signature.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/validate.h" /** \ingroup Core_MPI @@ -273,7 +275,7 @@ write_parsed_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) if (pgp_get_debug_level(__FILE__)) { printf("write_parsed_cb: "); - pgp_print_packet(&cbinfo->printstate, pkt); + //pgp_print_packet(&cbinfo->printstate, pkt); } if (pkt->tag != PGP_PTAG_CT_UNARMOURED_TEXT && cbinfo->printstate.skipping) { puts("...end of skip"); @@ -304,7 +306,10 @@ write_parsed_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) return pgp_get_seckey_cb(pkt, cbinfo); case PGP_GET_PASSPHRASE: - return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); + if (cbinfo->cryptinfo.getpassphrase) { + return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); + } + break; case PGP_PTAG_CT_LITDATA_BODY: return pgp_litdata_cb(pkt, cbinfo); @@ -356,6 +361,7 @@ pgp_encrypt_file(pgp_io_t *io, { pgp_output_t *output; pgp_memory_t *inmem; + pgp_keyring_t *rcpts; int fd_out; __PGP_USED(io); @@ -374,11 +380,23 @@ pgp_encrypt_file(pgp_io_t *io, pgp_writer_push_armor_msg(output); } + if ((rcpts = calloc(1, sizeof(*rcpts))) == NULL) { + (void) fprintf(io->errs, + "netpgp_encrypt_buf: out of memory to create recipients list\n"); + return 0; + } + pgp_keyring_add(rcpts, key); + if(rcpts->keys == NULL){ + (void) fprintf(io->errs, + "netpgp_encrypt_buf: out of memory to add recipient\n"); + return 0; + } /* Push the encrypted writer */ - if (!pgp_push_enc_se_ip(output, key, cipher)) { + if (!pgp_push_enc_se_ip(output, rcpts, cipher, 0)) { pgp_memory_free(inmem); return 0; } + pgp_keyring_free(rcpts); /* This does the writing */ pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem)); @@ -395,9 +413,10 @@ pgp_memory_t * pgp_encrypt_buf(pgp_io_t *io, const void *input, const size_t insize, - const pgp_key_t *pubkey, + const pgp_keyring_t *pubkeys, const unsigned use_armour, - const char *cipher) + const char *cipher, + unsigned raw) { pgp_output_t *output; pgp_memory_t *outmem; @@ -417,7 +436,7 @@ pgp_encrypt_buf(pgp_io_t *io, } /* Push the encrypted writer */ - pgp_push_enc_se_ip(output, pubkey, cipher); + pgp_push_enc_se_ip(output, pubkeys, cipher, raw); /* This does the writing */ pgp_write(output, input, (unsigned)insize); @@ -610,3 +629,132 @@ pgp_decrypt_buf(pgp_io_t *io, /* if we didn't get the passphrase, return NULL */ return (parse->cbinfo.gotpass) ? outmem : NULL; } + +/* Special callback for decrypt and validate */ +static pgp_cb_ret_t +pgp_decrypt_and_validate_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) +{ + pgp_cb_ret_t ret_write_cb = PGP_RELEASE_MEMORY; + pgp_cb_ret_t ret_validate_cb = PGP_RELEASE_MEMORY; + + ret_write_cb = write_parsed_cb(pkt, cbinfo); + + /* Filter pkt sent to validate callback */ + switch (pkt->tag) { + case PGP_PTAG_CT_LITDATA_BODY: + case PGP_PTAG_CT_SIGNED_CLEARTEXT_BODY: + case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */ + case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ + ret_validate_cb = validate_data_cb(pkt, cbinfo); + break; + default: + break; + } + + /* Only validate_data_cb takes some arguments. + * Otherwise, stacked callbacks would have been necessary + */ + return (ret_write_cb == PGP_KEEP_MEMORY || + ret_validate_cb == PGP_KEEP_MEMORY) ? + PGP_KEEP_MEMORY : PGP_RELEASE_MEMORY; +} + +/* decrypt and validate an area of memory */ +pgp_memory_t * +pgp_decrypt_and_validate_buf(pgp_io_t *io, + pgp_validation_t *result, + const void *input, + const size_t insize, + pgp_keyring_t *secring, + pgp_keyring_t *pubring, + const unsigned use_armour, + key_id_t **recipients_key_ids, + unsigned *recipients_count) +{ + // historical code bloat... + const unsigned sshkeys = 0; + void *passfp = NULL; + int numtries = -1; + pgp_cbfunc_t *getpassfunc = NULL; + + validate_data_cb_t validation; + pgp_stream_t *stream = NULL; + pgp_memory_t *outmem; + pgp_memory_t *inmem; + const int printerrors = 1; + + if (input == NULL) { + (void) fprintf(io->errs, + "pgp_encrypt_buf: null memory\n"); + return 0; + } + + inmem = pgp_memory_new(); + pgp_memory_add(inmem, input, insize); + + /* set up to read from memory */ + pgp_setup_memory_read(io, &stream, inmem, + &validation, + pgp_decrypt_and_validate_cb, + 1); + + /* Set verification reader and handling options */ + (void) memset(&validation, 0x0, sizeof(validation)); + validation.result = result; + validation.keyring = pubring; + validation.mem = pgp_memory_new(); + pgp_memory_init(validation.mem, 128); + + /* setup for writing decrypted contents */ + pgp_setup_memory_write(&stream->cbinfo.output, &outmem, insize); + + /* setup keyring and passphrase callback */ + stream->cbinfo.cryptinfo.secring = secring; + stream->cbinfo.cryptinfo.pubring = pubring; + stream->cbinfo.passfp = passfp; + stream->cbinfo.cryptinfo.getpassphrase = getpassfunc; + stream->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; + stream->cbinfo.numtries = numtries; + + /* Set up armour */ + if (use_armour) { + pgp_reader_push_dearmour(stream); + } + + /* Do it */ + pgp_parse(stream, printerrors); + + /* Unsetup */ + if (use_armour) { + pgp_reader_pop_dearmour(stream); + } + + *recipients_count = stream->cbinfo.cryptinfo.recipients_key_idsc; + if (*recipients_count == 0) { + *recipients_key_ids = NULL; + } else { + *recipients_key_ids = calloc(sizeof(key_id_t),*recipients_count); + if( *recipients_key_ids != NULL) + { + memcpy(*recipients_key_ids, + stream->cbinfo.cryptinfo.recipients_key_idss, + sizeof(key_id_t) * *recipients_count); + } + } + + if( *recipients_key_ids == NULL) + { + pgp_memory_free(outmem); + *recipients_count = 0; + outmem = NULL; + } + + /* tidy up */ + pgp_writer_close(stream->cbinfo.output); + pgp_output_delete(stream->cbinfo.output); + + pgp_teardown_memory_read(stream, inmem); + pgp_memory_free(validation.mem); + + return outmem; +} diff --git a/libs/netpgp/src/keyring.c b/libs/netpgp/src/keyring.c new file mode 100644 index 00000000..35a53e8a --- /dev/null +++ b/libs/netpgp/src/keyring.c @@ -0,0 +1,1644 @@ +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Alistair Crooks (agc@NetBSD.org) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) + * All rights reserved. + * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted + * their moral rights under the UK Copyright Design and Patents Act 1988 to + * be recorded as the authors of this copyright work. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. + * + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \file + */ +#include "netpgp/config-netpgp.h" + +#ifdef HAVE_SYS_CDEFS_H +#include +#endif + +#if defined(__NetBSD__) +__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); +__RCSID("$NetBSD$"); +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include +#include + +#ifdef HAVE_TERMIOS_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "netpgp/types.h" +#include "netpgp/keyring.h" +#include "netpgp/packet-parse.h" +#include "netpgp/signature.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/readerwriter.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/packet.h" +#include "netpgp/crypto.h" +#include "netpgp/validate.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/netpgpdigest.h" + + + +/** + \ingroup HighLevel_Keyring + + \brief Creates a new pgp_key_t struct + + \return A new pgp_key_t struct, initialised to zero. + + \note The returned pgp_key_t struct must be freed after use with pgp_keydata_free. +*/ + +pgp_key_t * +pgp_keydata_new(void) +{ + return calloc(1, sizeof(pgp_key_t)); +} + + +/** + \ingroup HighLevel_Keyring + + \brief Frees key's allocated memory + + \param keydata Key to be freed. + + \note This does not free the keydata itself, but any other memory alloc-ed by it. +*/ +void +pgp_key_free(pgp_key_t *key) +{ + unsigned n; + + if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { + pgp_pubkey_free(&key->key.pubkey); + } else { + pgp_seckey_free(&key->key.seckey); + } + + for (n = 0; n < key->directsigc; ++n) { + pgp_free_sig_info(&key->directsigs[n].siginfo); + pgp_subpacket_free(&key->directsigs[n].packet); + } + FREE_ARRAY(key, directsig); + + for (n = 0; n < key->uidc; ++n) { + pgp_userid_free(&key->uids[n]); + } + FREE_ARRAY(key, uid); + + for (n = 0; n < key->uidsigc; ++n) { + pgp_free_sig_info(&key->uidsigs[n].siginfo); + pgp_subpacket_free(&key->uidsigs[n].packet); + } + FREE_ARRAY(key, uidsig); + + for (n = 0; n < key->subkeyc; ++n) { + if (key->type == PGP_PTAG_CT_PUBLIC_KEY) { + pgp_pubkey_free(&key->subkeys[n].key.pubkey); + } else { + pgp_seckey_free(&key->subkeys[n].key.seckey); + } + } + FREE_ARRAY(key, subkey); + + for (n = 0; n < key->subkeysigc; ++n) { + pgp_free_sig_info(&key->subkeysigs[n].siginfo); + pgp_subpacket_free(&key->subkeysigs[n].packet); + } + FREE_ARRAY(key, subkeysig); +} + +/** + \ingroup HighLevel_Keyring + + \brief Frees keydata and its memory + + \param keydata Key to be freed. + + \note This frees the keydata itself, as well as any other memory alloc-ed by it. +*/ +void +pgp_keydata_free(pgp_key_t *keydata) +{ + pgp_key_free(keydata); + free(keydata); +} + +static unsigned siginfo_in_time(pgp_sig_info_t *siginfo){ + time_t now; + now = time(NULL); + /* in sig validity time frame */ + return now >= siginfo->birthtime && ( + siginfo->key_expiry == 0 || + now < siginfo->birthtime + + siginfo->key_expiry); +} + +const int32_t +pgp_key_find_uid_cond( + const pgp_key_t *key, + unsigned(*uidcond) ( uint8_t *, void *), + void *uidcondarg, + unsigned(*sigcond) ( const pgp_sig_info_t *, void *), + void *sigcondarg, + time_t *youngest, + unsigned checkrevoke, + unsigned checkexpiry) +{ + unsigned uididx = 0; + unsigned uidsigidx = 0; + int32_t res = -1; /* Not found */ + int32_t lastgood; + uint8_t **uidp; + pgp_uidsig_t *uidsigp; + time_t yngst = 0; + + /* If not maximum age given, take default */ + if(!youngest) + youngest = &yngst; + + /* Loop over key's user ids*/ + uidp = key->uids; + for (uididx = 0 ; uididx < key->uidc; uididx++, uidp++) + { + if(uidcond && !uidcond(*uidp, uidcondarg)) continue; + + lastgood = res; + /* Loop over key's user ids sigs */ + uidsigp = key->uidsigs; + for (uidsigidx = 0 ; uidsigidx < key->uidsigc; uidsigidx++, uidsigp++) + { + /* matching selected user id */ + if(uidsigp->uid == uididx) + { + /* if uid is revoked */ + /* revoke on secret keys has no effect*/ + if(uidsigp->siginfo.type == PGP_SIG_REV_CERT) + { + /* ignore revocation if secret */ + if(!checkrevoke) + continue; + + /* revert to last good candidate */ + res = lastgood; + break; /* jump to next uid */ + } + + /* in sig validity time frame */ + if(!checkexpiry || siginfo_in_time(&uidsigp->siginfo)) + { + /* sig cond is ok ? */ + if(!sigcond || sigcond(&uidsigp->siginfo, sigcondarg)) + { + /* youngest signature is deciding */ + if(uidsigp->siginfo.birthtime > *youngest) + { + *youngest = uidsigp->siginfo.birthtime; + res = uididx; + } + } + } + } + } + } + return res; +} + +/* + * Returns : + * -2 not found + * -1 match is priamary key + * >=0 index of matching valid subkey + * */ +const int32_t +pgp_key_find_key_conds( + pgp_key_t *key, + unsigned(*keycond) ( const pgp_pubkey_t *, const uint8_t *, void*), + void *keycondarg, + unsigned(*sigcond) ( const pgp_sig_info_t *, void*), + void *sigcondarg, + unsigned checkrevoke, + unsigned checkexpiry) +{ + unsigned subkeyidx = 0; + unsigned subkeysigidx = 0; + unsigned directsigidx = 0; + int32_t res = -2; /* Not found */ + int32_t lastgood; + pgp_subkey_t *subkeyp; + pgp_subkeysig_t *subkeysigp; + pgp_directsig_t *directsigp; + time_t youngest; + + youngest = 0; + + /* check pubkey first */ + if(!keycond || keycond(pgp_key_get_pubkey(key), + key->pubkeyid, keycondarg)){ + + int32_t uidres; + + /* Loop over key's direct sigs */ + directsigp = key->directsigs; + + for (directsigidx = 0 ; directsigidx < key->directsigc; + directsigidx++, directsigp++) + { + /* if direct is revoked */ + if(directsigp->siginfo.type == PGP_SIG_REV_KEY) + { + /* ignore revocation if secret */ + if(!checkrevoke) + continue; + + return -2; /* Key is globally revoked, no result */ + } + + /* in sig validity time frame */ + if(!checkexpiry || siginfo_in_time(&directsigp->siginfo)) + { + /* condition on sig is ok */ + if(!sigcond || sigcond(&directsigp->siginfo, sigcondarg)) + { + /* youngest signature is deciding */ + if(directsigp->siginfo.birthtime > youngest) + { + youngest = directsigp->siginfo.birthtime; + res = -1; /* Primary key is a candidate */ + } + } + } + } + + uidres = pgp_key_find_uid_cond( + key, NULL, NULL, sigcond, sigcondarg, &youngest, + checkrevoke, checkexpiry); + + /* if matching uid sig, then primary is matching key */ + if(uidres != -1){ + res = -1; + } + } + + /* Loop over key's subkeys */ + subkeyp = key->subkeys; + for (subkeyidx = 0 ; subkeyidx < key->subkeyc; subkeyidx++, subkeyp++) + { + lastgood = res; + + subkeysigp = key->subkeysigs; + + /* Skip this subkey if key condition not met */ + if(keycond && !keycond(&subkeyp->key.pubkey, subkeyp->id, keycondarg)) + continue; + + /* Loop over key's subkeys sigs */ + for (subkeysigidx = 0 ; subkeysigidx < key->subkeysigc; + subkeysigidx++, subkeysigp++) + { + /* matching selected subkey */ + if(subkeysigp->subkey == subkeyidx) + { + /* if subkey is revoked */ + if(subkeysigp->siginfo.type == PGP_SIG_REV_SUBKEY) + { + /* ignore revocation if secret */ + if(!checkrevoke) + continue; + + /* revert to last good candidate */ + res = lastgood; + break; /* jump to next subkey */ + } + + /* in sig validity time frame */ + if(!checkexpiry || siginfo_in_time(&subkeysigp->siginfo)) + { + /* subkey sig condition is ok */ + if(!sigcond || sigcond(&subkeysigp->siginfo, sigcondarg)) + { + /* youngest signature is deciding */ + if(subkeysigp->siginfo.birthtime > youngest) + { + youngest = subkeysigp->siginfo.birthtime; + res = subkeyidx; + } + } + } + } + } + } + return res; +} + +/** + \ingroup HighLevel_KeyGeneral + + \brief Returns the public key in the given keydata. + \param keydata + + \return Pointer to public key + + \note This is not a copy, do not free it after use. +*/ + +pgp_pubkey_t * +pgp_key_get_pubkey(pgp_key_t *keydata) +{ + return (keydata->type == PGP_PTAG_CT_PUBLIC_KEY) ? + &keydata->key.pubkey : + &keydata->key.seckey.pubkey; +} + +pgp_pubkey_t * +pgp_key_get_subpubkey(pgp_key_t *key, int32_t subkeyidx) +{ + return (key->type == PGP_PTAG_CT_PUBLIC_KEY) ? + &key->subkeys[subkeyidx].key.pubkey : + &key->subkeys[subkeyidx].key.seckey.pubkey; +} + +pgp_seckey_t * +pgp_key_get_subseckey(pgp_key_t *key, int32_t subkeyidx) +{ + return (key->type == PGP_PTAG_CT_SECRET_KEY) ? + &key->subkeys[subkeyidx].key.seckey : + NULL; +} +static pgp_pubkey_t * +key_get_pubkey_from_subidx( + pgp_key_t *key, + const uint8_t **id, + int32_t subkeyidx) +{ + if(subkeyidx == -2){ + return NULL; + } + + if(subkeyidx != -1) + { + if(id) + *id = key->subkeys[subkeyidx].id; + + return pgp_key_get_subpubkey(key, subkeyidx); + + } + + if(id) + *id = key->pubkeyid; + + return pgp_key_get_pubkey(key); +} + +static pgp_seckey_t * +key_get_seckey_from_subidx( + pgp_key_t *key, + const uint8_t **id, + int32_t subkeyidx) +{ + if(subkeyidx == -2){ + return NULL; + } + + if(subkeyidx != -1) + { + if(id) + *id = key->subkeys[subkeyidx].id; + + return pgp_key_get_subseckey(key, subkeyidx); + + } + + if(id) + *id = key->pubkeyid; + + return pgp_get_seckey(key); +} + +static unsigned is_signing_role(const pgp_sig_info_t *siginfo, void *arg) +{ + return siginfo->key_flags & PGP_KEYFLAG_SIGN_DATA; +} + +/* Get a pub key to check signature */ +pgp_pubkey_t * +pgp_key_get_sigkey(pgp_key_t *key) +{ + int32_t subkeyidx = + pgp_key_find_key_conds(key, NULL, NULL, &is_signing_role, NULL, 0, 0); + return key_get_pubkey_from_subidx(key, NULL, subkeyidx); +} + +/* Get a sec key to write a signature */ +pgp_seckey_t * +pgp_key_get_certkey(pgp_key_t *key) +{ + int32_t subkeyidx = + pgp_key_find_key_conds(key, NULL, NULL, &is_signing_role, NULL, 1, 0); + return key_get_seckey_from_subidx(key, NULL, subkeyidx); +} + +static unsigned is_encryption_role(const pgp_sig_info_t *siginfo, void *arg) +{ + return siginfo->key_flags & PGP_KEYFLAG_ENC_COMM; +} + +pgp_pubkey_t * +pgp_key_get_enckey(pgp_key_t *key, const uint8_t **id) +{ + int32_t subkeyidx = + pgp_key_find_key_conds(key, NULL, NULL, &is_encryption_role, NULL, 1, 0); + + return key_get_pubkey_from_subidx(key, id, subkeyidx); +} + +pgp_seckey_t * +pgp_key_get_deckey(pgp_key_t *key, const uint8_t **id) +{ + int32_t subkeyidx = + pgp_key_find_key_conds(key, NULL, NULL, &is_encryption_role, NULL, 0, 0); + + return key_get_seckey_from_subidx(key, id, subkeyidx); +} + +static unsigned primary_uid_sigcond(const pgp_sig_info_t *siginfo, void *arg) +{ + return siginfo->primary_userid; +} + +const int32_t pgp_key_get_uid0(pgp_key_t *key) +{ + int32_t res = + pgp_key_find_uid_cond(key, NULL, NULL, &primary_uid_sigcond, NULL, NULL, 1, 0); + + /* arbitrarily use youngest uid if no primary is found */ + return res == -1 ? + pgp_key_find_uid_cond(key, NULL, NULL, NULL, NULL, NULL, 1, 0): + res; +} + +const uint8_t *pgp_key_get_primary_userid(pgp_key_t *key) +{ + const int32_t uid0 = pgp_key_get_uid0(key); + if( uid0 >= 0 && key->uids && key->uidc > uid0) + { + return key->uids[uid0]; + } + return NULL; +} + +unsigned key_bit_len(const pgp_pubkey_t *key) +{ + switch (key->alg) { + case PGP_PKA_DSA: + return BN_num_bits(key->key.dsa.p); + + case PGP_PKA_RSA: + return BN_num_bits(key->key.rsa.n); + + case PGP_PKA_ELGAMAL: + return BN_num_bits(key->key.elgamal.p); + + default: + return 0; + } +} + +unsigned key_is_weak( + const pgp_pubkey_t *key, + const uint8_t *keyid, + void *arg) +{ + unsigned kbl; + pgp_key_rating_t *res; + + res = (pgp_key_rating_t*)arg; + kbl = key_bit_len(key); + + if(kbl == 0) + { + *res = PGP_INVALID; + } + else if(kbl < 1024) + { + *res = PGP_TOOSHORT; + } + else if(kbl == 1024 && key->alg == PGP_PKA_RSA) + { + *res = PGP_WEAK; + } + + return 0; +} + +const pgp_key_rating_t pgp_key_get_rating(pgp_key_t *key) +{ + /* keys exist in rings only if valid */ + pgp_key_rating_t res = PGP_VALID; + + pgp_key_find_key_conds(key, &key_is_weak, (void*)&res, NULL, NULL, 0, 0); + + if(res == PGP_VALID) + { + if(pgp_key_find_key_conds( + key, NULL, NULL, NULL, NULL, 1, 0) == -2) + { + return PGP_REVOKED; + } + if(pgp_key_find_key_conds( + key, NULL, NULL, NULL, NULL, 0, 1) == -2) + { + return PGP_EXPIRED; + } + } + + return res; +} +/** +\ingroup HighLevel_KeyGeneral + +\brief Check whether this is a secret key or not. +*/ + +unsigned +pgp_is_key_secret(pgp_key_t *data) +{ + return data->type != PGP_PTAG_CT_PUBLIC_KEY; +} + +/** + \ingroup HighLevel_KeyGeneral + + \brief Returns the secret key in the given keydata. + + \note This is not a copy, do not free it after use. + + \note This returns a const. If you need to be able to write to this + pointer, use pgp_get_writable_seckey +*/ + +pgp_seckey_t * +pgp_get_seckey(pgp_key_t *data) +{ + return (data->type == PGP_PTAG_CT_SECRET_KEY) ? + &data->key.seckey : NULL; +} + +/** + \ingroup HighLevel_KeyGeneral + + \brief Returns the secret key in the given keydata. + + \note This is not a copy, do not free it after use. + + \note If you do not need to be able to modify this key, there is an + equivalent read-only function pgp_get_seckey. +*/ + +pgp_seckey_t * +pgp_get_writable_seckey(pgp_key_t *data) +{ + return (data->type == PGP_PTAG_CT_SECRET_KEY) ? + &data->key.seckey : NULL; +} + +/* utility function to zero out memory */ +void +pgp_forget(void *vp, unsigned size) +{ + (void) memset(vp, 0x0, size); +} + +typedef struct { + FILE *passfp; + const pgp_key_t *key; + char *passphrase; + pgp_seckey_t *seckey; +} decrypt_t; + +// FIXME : support encrypted seckeys again +// static pgp_cb_ret_t +// decrypt_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) +// { +// const pgp_contents_t *content = &pkt->u; +// decrypt_t *decrypt; +// char pass[MAX_PASSPHRASE_LENGTH]; +// +// decrypt = pgp_callback_arg(cbinfo); +// switch (pkt->tag) { +// case PGP_PARSER_PTAG: +// case PGP_PTAG_CT_USER_ID: +// case PGP_PTAG_CT_SIGNATURE: +// case PGP_PTAG_CT_SIGNATURE_HEADER: +// case PGP_PTAG_CT_SIGNATURE_FOOTER: +// case PGP_PTAG_CT_TRUST: +// break; +// +// case PGP_GET_PASSPHRASE: +// (void) pgp_getpassphrase(decrypt->passfp, pass, sizeof(pass)); +// *content->skey_passphrase.passphrase = netpgp_strdup(pass); +// pgp_forget(pass, (unsigned)sizeof(pass)); +// return PGP_KEEP_MEMORY; +// +// case PGP_PARSER_ERRCODE: +// switch (content->errcode.errcode) { +// case PGP_E_P_MPI_FORMAT_ERROR: +// /* Generally this means a bad passphrase */ +// fprintf(stderr, "Bad passphrase!\n"); +// return PGP_RELEASE_MEMORY; +// +// case PGP_E_P_PACKET_CONSUMED: +// /* And this is because of an error we've accepted */ +// return PGP_RELEASE_MEMORY; +// default: +// break; +// } +// (void) fprintf(stderr, "parse error: %s\n", +// pgp_errcode(content->errcode.errcode)); +// return PGP_FINISHED; +// +// case PGP_PARSER_ERROR: +// fprintf(stderr, "parse error: %s\n", content->error); +// return PGP_FINISHED; +// +// case PGP_PTAG_CT_SECRET_KEY: +// if ((decrypt->seckey = calloc(1, sizeof(*decrypt->seckey))) == NULL) { +// (void) fprintf(stderr, "decrypt_cb: bad alloc\n"); +// return PGP_FINISHED; +// } +// decrypt->seckey->checkhash = calloc(1, PGP_CHECKHASH_SIZE); +// *decrypt->seckey = content->seckey; /* XXX WTF ? */ +// return PGP_KEEP_MEMORY; +// +// case PGP_PARSER_PACKET_END: +// /* nothing to do */ +// break; +// +// default: +// fprintf(stderr, "Unexpected tag %d (0x%x)\n", pkt->tag, +// pkt->tag); +// return PGP_FINISHED; +// } +// +// return PGP_RELEASE_MEMORY; +// } + +// FIXME : support encrypted seckeys again +// /** +// \ingroup Core_Keys +// \brief Decrypts secret key from given keydata with given passphrase +// \param key Key from which to get secret key +// \param passphrase Passphrase to use to decrypt secret key +// \return secret key +// */ +// pgp_seckey_t * +// pgp_decrypt_seckey(const pgp_key_t *key, void *passfp) +// { +// pgp_stream_t *stream; +// const int printerrors = 1; +// decrypt_t decrypt; +// +// (void) memset(&decrypt, 0x0, sizeof(decrypt)); +// decrypt.key = key; +// decrypt.passfp = passfp; +// stream = pgp_new(sizeof(*stream)); +// pgp_keydata_reader_set(stream, key); +// pgp_set_callback(stream, decrypt_cb, &decrypt); +// stream->readinfo.accumulate = 1; +// pgp_parse(stream, !printerrors); +// return decrypt.seckey; +// } + +/* \todo check where userid pointers are copied */ +/** +\ingroup Core_Keys +\brief Copy user id, including contents +\param dst Destination User ID +\param src Source User ID +\note If dst already has a userid, it will be freed. +*/ +uint8_t * +pgp_copy_userid(uint8_t **dst, const uint8_t *src) +{ + size_t len; + + len = strlen((const char *) src); + if (*dst) { + free(*dst); + } + if ((*dst = calloc(1, len + 1)) == NULL) { + (void) fprintf(stderr, "pgp_copy_userid: bad alloc\n"); + } else { + (void) memcpy(*dst, src, len); + } + return *dst; +} + +/* \todo check where pkt pointers are copied */ +/** +\ingroup Core_Keys +\brief Copy packet, including contents +\param dst Destination packet +\param src Source packet +\note If dst already has a packet, it will be freed. +*/ +pgp_subpacket_t * +pgp_copy_packet(pgp_subpacket_t *dst, const pgp_subpacket_t *src) +{ + if (dst->raw) { + free(dst->raw); + } + if ((dst->raw = calloc(1, src->length)) == NULL) { + (void) fprintf(stderr, "pgp_copy_packet: bad alloc\n"); + } else { + dst->length = src->length; + (void) memcpy(dst->raw, src->raw, src->length); + } + + return dst; +} + +#if 0 +/** +\ingroup Core_Keys +\brief Add User ID to key +\param key Key to which to add User ID +\param userid User ID to add +\return Pointer to new User ID +*/ +uint8_t * +pgp_add_userid(pgp_key_t *key, const uint8_t *userid) +{ + uint8_t **uidp; + + EXPAND_ARRAY(key, uid); + /* initialise new entry in array */ + uidp = &key->uids[key->uidc++]; + *uidp = NULL; + /* now copy it */ + return pgp_copy_userid(uidp, userid); +} +#endif + +void print_packet_hex(const pgp_subpacket_t *pkt); + +/** +\ingroup Core_Keys +\brief Add selfsigned User ID to key +\param keydata Key to which to add user ID +\param userid Self-signed User ID to add +\return 1 if OK; else 0 +*/ +unsigned +pgp_add_selfsigned_userid(pgp_key_t *skey, pgp_key_t *pkey, const uint8_t *userid, time_t key_expiry) +{ + pgp_create_sig_t *sig; + pgp_subpacket_t sigpacket; + pgp_memory_t *mem_sig = NULL; + pgp_output_t *sigoutput = NULL; + + /* + * create signature packet for this userid + */ + + /* create sig for this pkt */ + sig = pgp_create_sig_new(); + pgp_sig_start_key_sig(sig, &skey->key.seckey.pubkey, userid, PGP_CERT_POSITIVE); + + pgp_add_creation_time(sig, time(NULL)); + pgp_add_key_expiration_time(sig, key_expiry); + pgp_add_issuer_keyid(sig, skey->pubkeyid); + pgp_add_primary_userid(sig, 1); + pgp_add_key_flags(sig, PGP_KEYFLAG_SIGN_DATA|PGP_KEYFLAG_ENC_COMM); + pgp_add_key_prefs(sig); + pgp_add_key_features(sig); + + pgp_end_hashed_subpkts(sig); + + pgp_setup_memory_write(&sigoutput, &mem_sig, 128); + pgp_write_sig(sigoutput, sig, &skey->key.seckey.pubkey, &skey->key.seckey); + + /* add this packet to key */ + sigpacket.length = pgp_mem_len(mem_sig); + sigpacket.raw = pgp_mem_data(mem_sig); + + /* add user id and signature to key */ + pgp_update_userid(skey, userid, &sigpacket, &sig->sig.info); + if(pkey) + pgp_update_userid(pkey, userid, &sigpacket, &sig->sig.info); + + /* cleanup */ + pgp_create_sig_delete(sig); + pgp_output_delete(sigoutput); + pgp_memory_free(mem_sig); + + return 1; +} + +unsigned +pgp_key_revoke(pgp_key_t *skey, pgp_key_t *pkey, uint8_t code, const char *reason) +{ + pgp_create_sig_t *sig; + pgp_subpacket_t sigpacket; + pgp_memory_t *mem_sig = NULL; + pgp_output_t *sigoutput = NULL; + + sig = pgp_create_sig_new(); + pgp_sig_start_key_rev( + sig, &skey->key.seckey.pubkey, + PGP_SIG_REV_KEY); + + pgp_add_creation_time(sig, time(NULL)); + pgp_add_issuer_keyid(sig, skey->pubkeyid); + pgp_add_revocation_reason(sig, code, reason); + pgp_end_hashed_subpkts(sig); + + pgp_setup_memory_write(&sigoutput, &mem_sig, 128); + pgp_write_sig(sigoutput, sig, &skey->key.seckey.pubkey, &skey->key.seckey); + + sigpacket.length = pgp_mem_len(mem_sig); + sigpacket.raw = pgp_mem_data(mem_sig); + + pgp_add_directsig(skey, &sigpacket, &sig->sig.info); + pgp_add_directsig(pkey, &sigpacket, &sig->sig.info); + + /* cleanup */ + pgp_create_sig_delete(sig); + pgp_output_delete(sigoutput); + pgp_memory_free(mem_sig); + + return 1; +} + +/** +\ingroup Core_Keys +\brief Initialise pgp_key_t +\param keydata Keydata to initialise +\param type PGP_PTAG_CT_PUBLIC_KEY or PGP_PTAG_CT_SECRET_KEY +*/ +void +pgp_keydata_init(pgp_key_t *keydata, const pgp_content_enum type) +{ + if (keydata->type != PGP_PTAG_CT_RESERVED) { + (void) fprintf(stderr, + "pgp_keydata_init: wrong keydata type\n"); + } else if (type != PGP_PTAG_CT_PUBLIC_KEY && + type != PGP_PTAG_CT_SECRET_KEY) { + (void) fprintf(stderr, "pgp_keydata_init: wrong type\n"); + } else { + keydata->type = type; + } +} + +/** + \ingroup HighLevel_KeyringRead + + \brief Reads a keyring from a file + + \param keyring Pointer to an existing pgp_keyring_t struct + \param armour 1 if file is armoured; else 0 + \param filename Filename of keyring to be read + + \return pgp 1 if OK; 0 on error + + \note Keyring struct must already exist. + + \note Can be used with either a public or secret keyring. + + \note You must call pgp_keyring_free() after usage to free alloc-ed memory. + + \note If you call this twice on the same keyring struct, without calling + pgp_keyring_free() between these calls, you will introduce a memory leak. + + \sa pgp_keyring_read_from_mem() + \sa pgp_keyring_free() + +*/ + +unsigned +pgp_keyring_fileread(pgp_io_t *io, + pgp_keyring_t *pubring, + pgp_keyring_t *secring, + const unsigned armour, + const char *filename) +{ + return pgp_filter_keys_fileread( + io, + pubring, + secring, + NULL /*certring -> self cert */, + armour, + filename); +} + +/** + \ingroup HighLevel_KeyringRead + + \brief Reads a keyring from memory + + \param keyring Pointer to existing pgp_keyring_t struct + \param armour 1 if file is armoured; else 0 + \param mem Pointer to a pgp_memory_t struct containing keyring to be read + + \return pgp 1 if OK; 0 on error + + \note Keyring struct must already exist. + + \note Can be used with either a public or secret keyring. + + \note You must call pgp_keyring_free() after usage to free alloc-ed memory. + + \note If you call this twice on the same keyring struct, without calling + pgp_keyring_free() between these calls, you will introduce a memory leak. + + \sa pgp_keyring_fileread + \sa pgp_keyring_free +*/ +unsigned +pgp_keyring_read_from_mem(pgp_io_t *io, + pgp_keyring_t *pubring, + pgp_keyring_t *secring, + const unsigned armour, + pgp_memory_t *mem) +{ + return pgp_filter_keys_from_mem(io, + pubring, + secring, + NULL /* certring -> self certification */, + armour, + mem); +} + +/** + \ingroup HighLevel_KeyringRead + + \brief Frees keyring's contents (but not keyring itself) + + \param keyring Keyring whose data is to be freed + + \note This does not free keyring itself, just the memory alloc-ed in it. + */ +void +pgp_keyring_free(pgp_keyring_t *keyring) +{ + (void)free(keyring->keys); + keyring->keys = NULL; + keyring->keyc = keyring->keyvsize = 0; +} + +void +pgp_keyring_purge(pgp_keyring_t *keyring) +{ + pgp_key_t *keyp; + unsigned c = 0; + for (keyp = keyring->keys; c < keyring->keyc; c++, keyp++) { + pgp_key_free(keyp); + } + pgp_keyring_free(keyring); +} + +static unsigned +deletekey( pgp_keyring_t *keyring, pgp_key_t *key, unsigned from) +{ + /* 'from' is index of key to delete */ + + /* free key internals */ + pgp_key_free(key); + + /* decrement key count, vsize stays the same so no realloc needed */ + keyring->keyc--; + + /* Move following keys to fill the gap */ + for ( ; keyring && from < keyring->keyc; from += 1) { + memcpy(&keyring->keys[from], &keyring->keys[from+1], + sizeof(pgp_key_t)); + } + + return 1; +} + +unsigned key_id_match(const pgp_pubkey_t *key, const uint8_t *keyid, void *refidarg) +{ + uint8_t *refid = refidarg; + return (memcmp(keyid, refid, PGP_KEY_ID_SIZE) == 0); +} +/** + \ingroup HighLevel_KeyringFind + + \brief Finds key in keyring from its Key ID + + \param keyring Keyring to be searched + \param keyid ID of required key + + \return Pointer to key, if found; NULL, if not found + + \note This returns a pointer to the key inside the given keyring, + not a copy. Do not free it after use. + +*/ +pgp_key_t * +pgp_getkeybyid(pgp_io_t *io, const pgp_keyring_t *keyring, + const uint8_t *keyid, unsigned *from, + pgp_pubkey_t **pubkey, + pgp_seckey_t **seckey, + unsigned checkrevoke, + unsigned checkexpiry) +{ + uint8_t nullid[PGP_KEY_ID_SIZE]; + + (void) memset(nullid, 0x0, sizeof(nullid)); + for ( ; keyring && *from < keyring->keyc; *from += 1) { + pgp_key_t *key = &keyring->keys[*from]; + int32_t subkeyidx; + if (pgp_get_debug_level(__FILE__)) { + hexdump(io->errs, "keyring keyid", key->pubkeyid, PGP_KEY_ID_SIZE); + hexdump(io->errs, "keyid", keyid, PGP_KEY_ID_SIZE); + } + + subkeyidx = pgp_key_find_key_conds(key, &key_id_match, + (void*)keyid, NULL, NULL, + checkrevoke, checkexpiry); + + if (subkeyidx != -2) { + if (pubkey) { + *pubkey = key_get_pubkey_from_subidx(key, NULL, subkeyidx); + } + if (seckey) { + *seckey = key_get_seckey_from_subidx(key, NULL, subkeyidx); + } + return key; + } + } + return NULL; +} + +unsigned +pgp_deletekeybyid(pgp_io_t *io, pgp_keyring_t *keyring, + const uint8_t *keyid) +{ + unsigned from = 0; + pgp_key_t *key; + + if ((key = (pgp_key_t *)pgp_getkeybyid(io, keyring, keyid, + &from, NULL, NULL, 0, 0)) == NULL) { + return 0; + } + /* 'from' is now index of key to delete */ + + deletekey(keyring, key, from); + + return 1; +} + +/** + \ingroup HighLevel_KeyringFind + + \brief Finds key in keyring from its Key Fingerprint + + \param keyring Keyring to be searched + \param fpr fingerprint of required key + \param fpr length of required key + + \return Pointer to key, if found; NULL, if not found + + \note This returns a pointer to the key inside the given keyring, + not a copy. Do not free it after use. + +*/ + +pgp_key_t * +pgp_getkeybyfpr(pgp_io_t *io, const pgp_keyring_t *keyring, + const uint8_t *fpr, size_t length, + unsigned *from, + pgp_pubkey_t **pubkey, + unsigned checkrevoke, + unsigned checkexpiry) +{ + + for ( ; keyring && *from < keyring->keyc; *from += 1) { + pgp_key_t *key = &keyring->keys[*from]; + + pgp_fingerprint_t *kfp = &key->pubkeyfpr; + + if (kfp->length == length && + memcmp(kfp->fingerprint, fpr, length) == 0) { + + if(checkrevoke || checkexpiry){ + int32_t subkeyidx; + + subkeyidx = pgp_key_find_key_conds(key, + NULL, NULL, + NULL, NULL, + checkrevoke, checkexpiry); + + if (subkeyidx == -2) return NULL; + } + if (pubkey) { + *pubkey = &key->key.pubkey; + } + return key; + } + } + return NULL; +} + +unsigned +pgp_deletekeybyfpr(pgp_io_t *io, pgp_keyring_t *keyring, + const uint8_t *fpr, size_t length) +{ + unsigned from = 0; + pgp_key_t *key; + + if ((key = (pgp_key_t *)pgp_getkeybyfpr(io, keyring, fpr, length, + &from, NULL,0,0)) == NULL) { + return 0; + } + /* 'from' is now index of key to delete */ + + deletekey(keyring, key, from); + + return 1; +} + +#if 0 +/* convert a string keyid into a binary keyid */ +static void +str2keyid(const char *userid, uint8_t *keyid, size_t len) +{ + static const char *uppers = "0123456789ABCDEF"; + static const char *lowers = "0123456789abcdef"; + const char *hi; + const char *lo; + uint8_t hichar; + uint8_t lochar; + size_t j; + int i; + + for (i = 0, j = 0 ; j < len && userid[i] && userid[i + 1] ; i += 2, j++) { + if ((hi = strchr(uppers, userid[i])) == NULL) { + if ((hi = strchr(lowers, userid[i])) == NULL) { + break; + } + hichar = (uint8_t)(hi - lowers); + } else { + hichar = (uint8_t)(hi - uppers); + } + if ((lo = strchr(uppers, userid[i + 1])) == NULL) { + if ((lo = strchr(lowers, userid[i + 1])) == NULL) { + break; + } + lochar = (uint8_t)(lo - lowers); + } else { + lochar = (uint8_t)(lo - uppers); + } + keyid[j] = (hichar << 4) | (lochar); + } + keyid[j] = 0x0; +} +#endif + +/* return the next key which matches, starting searching at *from */ +#if 0 ////// +static const pgp_key_t * +getkeybyname(pgp_io_t *io, + const pgp_keyring_t *keyring, + const char *name, + unsigned *from) +{ + //const pgp_key_t *kp; + uint8_t **uidp; + unsigned i = 0; + pgp_key_t *keyp; + // unsigned savedstart; + regex_t r; + //uint8_t keyid[PGP_KEY_ID_SIZE + 1]; + size_t len; + + if (!keyring || !name || !from) { + return NULL; + } + len = strlen(name); + if (pgp_get_debug_level(__FILE__)) { + (void) fprintf(io->outs, "[%u] name '%s', len %zu\n", + *from, name, len); + } + + /* first try name as a keyid */ + // (void) memset(keyid, 0x0, sizeof(keyid)); + // str2keyid(name, keyid, sizeof(keyid)); + // if (pgp_get_debug_level(__FILE__)) { + // hexdump(io->outs, "keyid", keyid, 4); + // } + // savedstart = *from; + // if ((kp = pgp_getkeybyid(io, keyring, keyid, from, + // NULL, NULL, 0, 0)) != NULL) { + // return kp; + // } + // *from = savedstart; + + if (pgp_get_debug_level(__FILE__) && name != NULL) { + (void) fprintf(io->outs, "regex match '%s' from %u\n", + name, *from); + } + /* match on full name or email address as a + - NOSUB only success/failure, no match content + - LITERAL ignore special chars in given string + - ICASE ignore case + */ + if (name != NULL) { + (void) regcomp(&r, name, REG_NOSUB | REG_LITERAL | REG_ICASE); + } + if(keyring->keys != NULL) + for (keyp = &keyring->keys[*from]; *from < keyring->keyc; *from += 1, keyp++) { + uidp = keyp->uids; + if (name == NULL) { + return keyp; + } else { + for (i = 0 ; i < keyp->uidc; i++, uidp++) { + if (regexec(&r, (char *)*uidp, 0, NULL, 0) == 0) { + if (pgp_get_debug_level(__FILE__)) { + (void) fprintf(io->outs, + "MATCHED keyid \"%s\" len %" PRIsize "u\n", + (char *) *uidp, len); + } + regfree(&r); + return keyp; + } + } + } + } + regfree(&r); + return NULL; +} +#endif ////// + +/** + \ingroup HighLevel_KeyringFind + + \brief Finds key from its User ID + + \param keyring Keyring to be searched + \param userid User ID of required key + + \return Pointer to Key, if found; NULL, if not found + + \note This returns a pointer to the key inside the keyring, not a + copy. Do not free it. + +*/ +#if 0 ////// +const pgp_key_t * +pgp_getkeybyname(pgp_io_t *io, + const pgp_keyring_t *keyring, + const char *name) +{ + unsigned from; + + from = 0; + return getkeybyname(io, keyring, name, &from); +} +#endif ////// + +#if 0 ////// +const pgp_key_t * +pgp_getnextkeybyname(pgp_io_t *io, + const pgp_keyring_t *keyring, + const char *name, + unsigned *n) +{ + return getkeybyname(io, keyring, name, n); +} +#endif ////// + +/* this interface isn't right - hook into callback for getting passphrase */ +#if 0 ////// +char * +pgp_export_key(pgp_io_t *io, const pgp_key_t *keydata, uint8_t *passphrase) +{ + pgp_output_t *output; + pgp_memory_t *mem; + char *cp; + + __PGP_USED(io); + pgp_setup_memory_write(&output, &mem, 128); + pgp_write_xfer_key(output, keydata, 1); + + /* TODO deal with passphrase again + pgp_write_xfer_seckey(output, keydata, passphrase, + strlen((char *)passphrase), 1); + */ + cp = netpgp_strdup(pgp_mem_data(mem)); + pgp_teardown_memory_write(output, mem); + return cp; +} +#endif ////// + +/* lowlevel add to keyring */ +int +pgp_keyring_add(pgp_keyring_t *dst, const pgp_key_t *src) +{ + pgp_key_t *key; + + EXPAND_ARRAY(dst, key); + key = &dst->keys[dst->keyc++]; + memcpy(key, src, sizeof(*key)); + return 1; +} + +pgp_key_t *pgp_ensure_pubkey( + pgp_keyring_t *keyring, + pgp_pubkey_t *pubkey, + uint8_t *pubkeyid) +{ + pgp_key_t *key; + unsigned c; + + if(keyring == NULL) return NULL; + + /* try to find key in keyring */ + for (c = 0; c < keyring->keyc; c += 1) { + if (memcmp(keyring->keys[c].pubkeyid, + pubkeyid, PGP_KEY_ID_SIZE) == 0) { + return &keyring->keys[c]; + } + } + + /* if key doesn't already exist in keyring, create it */ + EXPAND_ARRAY(keyring, key); + key = &keyring->keys[keyring->keyc++]; + (void) memset(key, 0x0, sizeof(*key)); + + /* fill in what we already know */ + key->type = PGP_PTAG_CT_PUBLIC_KEY; + pgp_pubkey_dup(&key->key.pubkey, pubkey); + (void) memcpy(&key->pubkeyid, pubkeyid, PGP_KEY_ID_SIZE); + pgp_fingerprint(&key->pubkeyfpr, pubkey, keyring->hashtype); + + return key; +} + +pgp_key_t *pgp_ensure_seckey( + pgp_keyring_t *keyring, + pgp_seckey_t *seckey, + uint8_t *pubkeyid) +{ + pgp_key_t *key; + unsigned c; + + if (keyring == NULL) return NULL; + + /* try to find key in keyring */ + for (c = 0; c < keyring->keyc; c += 1) { + if (memcmp(keyring->keys[c].pubkeyid, + pubkeyid, PGP_KEY_ID_SIZE) == 0) { + return &keyring->keys[c]; + } + } + + /* if key doesn't already exist in keyring, create it */ + EXPAND_ARRAY(keyring, key); + key = &keyring->keys[keyring->keyc++]; + (void) memset(key, 0x0, sizeof(*key)); + + /* fill in what we already know */ + key->type = PGP_PTAG_CT_SECRET_KEY; + pgp_seckey_dup(&key->key.seckey, seckey); + (void) memcpy(&key->pubkeyid, pubkeyid, PGP_KEY_ID_SIZE); + pgp_fingerprint(&key->pubkeyfpr, &seckey->pubkey, keyring->hashtype); + + return key; +} + +unsigned pgp_add_directsig( + pgp_key_t *key, + const pgp_subpacket_t *sigpkt, + pgp_sig_info_t *siginfo) +{ + pgp_directsig_t *directsigp; + unsigned directsigidx; + + /* Detect duplicate direct sig */ + directsigp = key->directsigs; + for (directsigidx = 0 ; directsigidx < key->directsigc; + directsigidx++, directsigp++) + { + if( directsigp->packet.length == sigpkt->length && + memcmp(directsigp->packet.raw, sigpkt->raw, sigpkt->length) == 0) + { + /* signature already exist */ + return 1; + } + } + + + EXPAND_ARRAY(key, directsig); + directsigp = &key->directsigs[key->directsigc++]; + + copy_sig_info(&directsigp->siginfo, + siginfo); + pgp_copy_packet(&directsigp->packet, sigpkt); + + return 0; +} + +unsigned pgp_update_userid( + pgp_key_t *key, + const uint8_t *userid, + const pgp_subpacket_t *sigpkt, + pgp_sig_info_t *siginfo) +{ + unsigned uididx = 0; + unsigned uidsigidx = 0; + uint8_t **uidp; + pgp_uidsig_t *uidsigp; + + /* Try to find identical userID */ + uidp = key->uids; + for (uididx = 0 ; uididx < key->uidc; uididx++, uidp++) + { + if (strcmp((char *)*uidp, (char *)userid) == 0) + { + /* Found one. check for duplicate uidsig */ + uidsigp = key->uidsigs; + for (uidsigidx = 0 ; uidsigidx < key->uidsigc; + uidsigidx++, uidsigp++) + { + if(uidsigp->uid == uididx && + uidsigp->packet.length == sigpkt->length && + memcmp(uidsigp->packet.raw, sigpkt->raw, + sigpkt->length) == 0) + { + /* signature already exists */ + return 1; + } + } + break; + } + } + + /* Add a new one if none found */ + if(uididx==key->uidc){ + EXPAND_ARRAY(key, uid); + uidp = &key->uids[key->uidc++]; + *uidp = NULL; + pgp_copy_userid(uidp, userid); + } + + /* Add uid sig info, pointing to that uid */ + EXPAND_ARRAY(key, uidsig); + uidsigp = &key->uidsigs[key->uidsigc++]; + uidsigp->uid = uididx; + + /* store sig info and packet */ + copy_sig_info(&uidsigp->siginfo, siginfo); + pgp_copy_packet(&uidsigp->packet, sigpkt); + + return 0; +} + +unsigned pgp_update_subkey( + pgp_key_t *key, + pgp_content_enum subkeytype, + pgp_keydata_key_t *subkey, + const pgp_subpacket_t *sigpkt, + pgp_sig_info_t *siginfo) +{ + unsigned subkeyidx = 0; + unsigned subkeysigidx = 0; + pgp_subkey_t *subkeyp; + pgp_subkeysig_t *subkeysigp; + uint8_t subkeyid[PGP_KEY_ID_SIZE]; + + pgp_keyid(subkeyid, PGP_KEY_ID_SIZE, + (subkeytype == PGP_PTAG_CT_PUBLIC_KEY) ? + &subkey->pubkey: + &subkey->seckey.pubkey, PGP_HASH_SHA1); + + /* Try to find identical subkey ID */ + subkeyp = key->subkeys; + for (subkeyidx = 0 ; subkeyidx < key->subkeyc; subkeyidx++, subkeyp++) + { + if(memcmp(subkeyid, subkeyp->id, PGP_KEY_ID_SIZE) == 0 ) + { + /* Found same subkey. Detect duplicate sig */ + subkeysigp = key->subkeysigs; + for (subkeysigidx = 0 ; subkeysigidx < key->subkeysigc; + subkeysigidx++, subkeysigp++) + { + if(subkeysigp->subkey == subkeyidx && + subkeysigp->packet.length == sigpkt->length && + memcmp(subkeysigp->packet.raw, sigpkt->raw, + sigpkt->length) == 0) + { + /* signature already exists */ + return 1; + } + } + + break; + } + } + /* Add a new one if none found */ + if(subkeyidx==key->subkeyc){ + if(subkeytype == PGP_PTAG_CT_PUBLIC_KEY && + key->type != PGP_PTAG_CT_PUBLIC_KEY){ + /* cannot create secret subkey from public */ + /* and may not insert public subkey in seckey */ + return 1; + } + + EXPAND_ARRAY(key, subkey); + subkeyp = &key->subkeys[key->subkeyc++]; + /* copy subkey material */ + if(key->type == PGP_PTAG_CT_PUBLIC_KEY) { + pgp_pubkey_dup(&subkeyp->key.pubkey, + (subkeytype == PGP_PTAG_CT_PUBLIC_KEY) ? + &subkey->pubkey: + &subkey->seckey.pubkey); + } else { + pgp_seckey_dup(&subkeyp->key.seckey, &subkey->seckey); + } + /* copy subkeyID */ + memcpy(subkeyp->id, subkeyid, PGP_KEY_ID_SIZE); + } + + /* Add subkey sig info, pointing to that subkey */ + EXPAND_ARRAY(key, subkeysig); + subkeysigp = &key->subkeysigs[key->subkeysigc++]; + subkeysigp->subkey = subkeyidx; + + /* store sig info and packet */ + copy_sig_info(&subkeysigp->siginfo, + siginfo); + pgp_copy_packet(&subkeysigp->packet, sigpkt); + + return 0; +} + +/* append one keyring to another */ +int +pgp_append_keyring(pgp_keyring_t *keyring, pgp_keyring_t *newring) +{ + unsigned i; + + for (i = 0 ; i < newring->keyc ; i++) { + EXPAND_ARRAY(keyring, key); + (void) memcpy(&keyring->keys[keyring->keyc], &newring->keys[i], + sizeof(newring->keys[i])); + keyring->keyc += 1; + } + return 1; +} diff --git a/libs/netpgp/misc.c b/libs/netpgp/src/misc.c similarity index 90% rename from libs/netpgp/misc.c rename to libs/netpgp/src/misc.c index a610681f..256d1c33 100644 --- a/libs/netpgp/misc.c +++ b/libs/netpgp/src/misc.c @@ -49,7 +49,7 @@ /** \file */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -57,7 +57,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: misc.c,v 1.41 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -78,123 +78,24 @@ __RCSID("$NetBSD: misc.c,v 1.41 2012/03/05 02:20:18 christos Exp $"); #include #endif -#include "errors-netpgp.h" -#include "packet-netpgp.h" -#include "crypto-netpgp.h" -#include "create-netpgp.h" -#include "packet-parse.h" -#include "packet-show.h" -#include "signature-netpgp.h" -#include "netpgpsdk.h" -#include "netpgpdefs.h" -#include "memory-netpgp.h" -#include "readerwriter-netpgp.h" -#include "version-netpgp.h" -#include "netpgpdigest.h" +#include "netpgp/errors.h" +#include "netpgp/packet.h" +#include "netpgp/crypto.h" +#include "netpgp/create.h" +#include "netpgp/packet-parse.h" +#include "netpgp/packet-show.h" +#include "netpgp/signature.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/memory.h" +#include "netpgp/readerwriter.h" +#include "netpgp/version.h" +#include "netpgp/netpgpdigest.h" #ifdef WIN32 #define vsnprintf _vsnprintf #endif - -typedef struct { - pgp_keyring_t *keyring; -} accumulate_t; - -/** - * \ingroup Core_Callbacks - */ -static pgp_cb_ret_t -accumulate_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) -{ - const pgp_contents_t *content = &pkt->u; - pgp_keyring_t *keyring; - accumulate_t *accumulate; - - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(stderr, "accumulate callback: packet tag %u\n", pkt->tag); - } - accumulate = pgp_callback_arg(cbinfo); - keyring = accumulate->keyring; - switch (pkt->tag) { - case PGP_PTAG_CT_PUBLIC_KEY: - case PGP_PTAG_CT_PUBLIC_SUBKEY: - pgp_add_to_pubring(keyring, &content->pubkey, pkt->tag); - return PGP_KEEP_MEMORY; - case PGP_PTAG_CT_SECRET_KEY: - case PGP_PTAG_CT_ENCRYPTED_SECRET_KEY: - pgp_add_to_secring(keyring, &content->seckey); - return PGP_KEEP_MEMORY; - case PGP_PTAG_CT_USER_ID: - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(stderr, "User ID: %s for key %d\n", - content->userid, - keyring->keyc - 1); - } - if (keyring->keyc == 0) { - PGP_ERROR_1(cbinfo->errors, PGP_E_P_NO_USERID, "%s", - "No userid found"); - } else { - pgp_add_userid(&keyring->keys[keyring->keyc - 1], content->userid); - } - return PGP_KEEP_MEMORY; - case PGP_PARSER_PACKET_END: - if (keyring->keyc > 0) { - pgp_add_subpacket(&keyring->keys[keyring->keyc - 1], - &content->packet); - return PGP_KEEP_MEMORY; - } - return PGP_RELEASE_MEMORY; - case PGP_PARSER_ERROR: - (void) fprintf(stderr, "Error: %s\n", content->error); - return PGP_FINISHED; - case PGP_PARSER_ERRCODE: - (void) fprintf(stderr, "parse error: %s\n", - pgp_errcode(content->errcode.errcode)); - break; - default: - break; - } - /* XXX: we now exclude so many things, we should either drop this or */ - /* do something to pass on copies of the stuff we keep */ - return pgp_stacked_callback(pkt, cbinfo); -} - -/** - * \ingroup Core_Parse - * - * Parse packets from an input stream until EOF or error. - * - * Key data found in the parsed data is added to #keyring. - * - * \param keyring Pointer to an existing keyring - * \param parse Options to use when parsing -*/ -int -pgp_parse_and_accumulate(pgp_keyring_t *keyring, pgp_stream_t *parse) -{ - accumulate_t accumulate; - const int printerrors = 1; - int ret; - - if (parse->readinfo.accumulate) { - (void) fprintf(stderr, - "pgp_parse_and_accumulate: already init\n"); - return 0; - } - - (void) memset(&accumulate, 0x0, sizeof(accumulate)); - - accumulate.keyring = keyring; - - pgp_callback_push(parse, accumulate_cb, &accumulate); - parse->readinfo.accumulate = 1; - ret = pgp_parse(parse, !printerrors); - - return ret; -} - - /** \file * \brief Error Handling */ @@ -597,7 +498,7 @@ pgp_hash_add_int(pgp_hash_t *hash, unsigned n, unsigned length) \param hash Hash to set up \param alg Hash algorithm to use */ -void +unsigned pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg) { switch (alg) { @@ -627,7 +528,9 @@ pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg) default: (void) fprintf(stderr, "pgp_hash_any: bad algorithm\n"); + return 0; } + return 1; } /** diff --git a/libs/netpgp/src/netpgp.c b/libs/netpgp/src/netpgp.c new file mode 100644 index 00000000..5e68e60b --- /dev/null +++ b/libs/netpgp/src/netpgp.c @@ -0,0 +1,570 @@ +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Alistair Crooks (agc@NetBSD.org) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "netpgp/config-netpgp.h" + +#ifdef HAVE_SYS_CDEFS_H +#include +#endif + +#if defined(__NetBSD__) +__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); +__RCSID("$NetBSD$"); +#endif + +#include +#include +#include +#include + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +#ifdef HAVE_LIMITS_H +#include +#endif + +#include "netpgp.h" + +#include "netpgp/packet.h" +#include "netpgp/packet-parse.h" +#include "netpgp/keyring.h" +#include "netpgp/errors.h" +#include "netpgp/packet-show.h" +#include "netpgp/create.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/memory.h" +#include "netpgp/validate.h" +#include "netpgp/readerwriter.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/crypto.h" +#include "netpgp/defs.h" + +/* read any gpg config file */ +static int +conffile(netpgp_t *netpgp, char *homedir, char *userid, size_t length) +{ + regmatch_t matchv[10]; + regex_t keyre; + char buf[BUFSIZ]; + FILE *fp; + + __PGP_USED(netpgp); + (void) snprintf(buf, sizeof(buf), "%s/gpg.conf", homedir); + if ((fp = fopen(buf, "r")) == NULL) { + return 0; + } + (void) memset(&keyre, 0x0, sizeof(keyre)); + (void) regcomp(&keyre, "^[ \t]*default-key[ \t]+([0-9a-zA-F]+)", + REG_EXTENDED); + while (fgets(buf, (int)sizeof(buf), fp) != NULL) { + if (regexec(&keyre, buf, 10, matchv, 0) == 0) { + (void) memcpy(userid, &buf[(int)matchv[1].rm_so], + MIN((unsigned)(matchv[1].rm_eo - + matchv[1].rm_so), length)); + if (netpgp->passfp == NULL) { + (void) fprintf(stderr, + "netpgp: default key set to \"%.*s\"\n", + (int)(matchv[1].rm_eo - matchv[1].rm_so), + &buf[(int)matchv[1].rm_so]); + } + } + } + (void) fclose(fp); + regfree(&keyre); + return 1; +} + +/* check there's enough space in the arrays */ +static int +size_arrays(netpgp_t *netpgp, unsigned needed) +{ + char **temp; + + if (netpgp->size == 0) { + /* only get here first time around */ + netpgp->size = needed; + if ((netpgp->name = calloc(sizeof(char *), needed)) == NULL) { + (void) fprintf(stderr, "size_arrays: bad alloc\n"); + return 0; + } + if ((netpgp->value = calloc(sizeof(char *), needed)) == NULL) { + free(netpgp->name); + (void) fprintf(stderr, "size_arrays: bad alloc\n"); + return 0; + } + } else if (netpgp->c == netpgp->size) { + /* only uses 'needed' when filled array */ + netpgp->size += needed; + temp = realloc(netpgp->name, sizeof(char *) * needed); + if (temp == NULL) { + (void) fprintf(stderr, "size_arrays: bad alloc\n"); + return 0; + } + netpgp->name = temp; + temp = realloc(netpgp->value, sizeof(char *) * needed); + if (temp == NULL) { + (void) fprintf(stderr, "size_arrays: bad alloc\n"); + return 0; + } + netpgp->value = temp; + } + return 1; +} + +/* find the name in the array */ +static int +findvar(netpgp_t *netpgp, const char *name) +{ + unsigned i; + + for (i = 0 ; i < netpgp->c && strcmp(netpgp->name[i], name) != 0; i++) { + } + return (i == netpgp->c) ? -1 : (int)i; +} + +/* read a keyring and return it */ +static unsigned +readkeyring(netpgp_t *netpgp, + const char *name, + pgp_keyring_t *pubring, + pgp_keyring_t *secring) +{ + const unsigned noarmor = 0; + char *filename; + char f[MAXPATHLEN]; + + if ((filename = netpgp_getvar(netpgp, name)) == NULL) { + char *homedir; + homedir = netpgp_getvar(netpgp, "homedir"); + (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); + filename = f; + } + if (!pgp_keyring_fileread(netpgp->io, pubring, secring, noarmor, filename)) { + (void) fprintf(stderr, "Can't read %s %s\n", name, filename); + return 0; + } + netpgp_setvar(netpgp, name, filename); + return 1; +} + +/* get the uid of the first key in the keyring */ +static int +get_first_ring(pgp_keyring_t *ring, char *id, size_t len, int last) +{ + uint8_t *src; + int i; + int n; + + if (ring == NULL) { + return 0; + } + (void) memset(id, 0x0, len); + src = ring->keys[(last) ? ring->keyc - 1 : 0].pubkeyid; + for (i = 0, n = 0 ; i < PGP_KEY_ID_SIZE ; i += 2) { + n += snprintf(&id[n], len - n, "%02x%02x", src[i], src[i + 1]); + } + id[n] = 0x0; + return 1; +} +/***************************************************************************/ +/* exported functions start here */ +/***************************************************************************/ + +/* initialise a netpgp_t structure */ +int +netpgp_init(netpgp_t *netpgp) +{ + pgp_io_t *io; + time_t t; + char id[MAX_ID_LENGTH]; + char *homedir; + char *userid; + char *stream; + char *passfd; + char *results; + int coredumps; + +#ifdef HAVE_SYS_RESOURCE_H + struct rlimit limit; + + coredumps = netpgp_getvar(netpgp, "coredumps") != NULL; + if (!coredumps) { + (void) memset(&limit, 0x0, sizeof(limit)); + if (setrlimit(RLIMIT_CORE, &limit) != 0) { + (void) fprintf(stderr, + "netpgp: warning - can't turn off core dumps\n"); + coredumps = 1; + } + } +#else + coredumps = 1; +#endif + if ((io = calloc(1, sizeof(*io))) == NULL) { + (void) fprintf(stderr, "netpgp_init: bad alloc\n"); + return 0; + } + io->outs = stdout; + if ((stream = netpgp_getvar(netpgp, "outs")) != NULL && + strcmp(stream, "") == 0) { + io->outs = stderr; + } + io->errs = stderr; + if ((stream = netpgp_getvar(netpgp, "errs")) != NULL && + strcmp(stream, "") == 0) { + io->errs = stdout; + } + if ((results = netpgp_getvar(netpgp, "res")) == NULL) { + io->res = io->errs; + } else if (strcmp(results, "") == 0) { + io->res = stdout; + } else if (strcmp(results, "") == 0) { + io->res = stderr; + } else { + if ((io->res = fopen(results, "w")) == NULL) { + (void) fprintf(io->errs, "Can't open results %s for writing\n", + results); + free(io); + return 0; + } + } + netpgp->io = io; + /* get passphrase from an fd */ + if ((passfd = netpgp_getvar(netpgp, "pass-fd")) != NULL && + (netpgp->passfp = fdopen(atoi(passfd), "r")) == NULL) { + (void) fprintf(io->errs, "Can't open fd %s for reading\n", + passfd); + return 0; + } + /* warn if core dumps are enabled */ + if (coredumps) { + (void) fprintf(io->errs, + "netpgp: warning: core dumps enabled\n"); + } + /* get home directory - where keyrings are in a subdir */ + if ((homedir = netpgp_getvar(netpgp, "homedir")) == NULL) { + (void) fprintf(io->errs, "netpgp: bad homedir\n"); + return 0; + } + + if ((netpgp->pubring = calloc(1, sizeof(pgp_keyring_t))) == NULL) { + (void) fprintf(io->errs, "Can't alloc pubring\n"); + return 0; + } + if ((netpgp->secring = calloc(1, sizeof(pgp_keyring_t))) == NULL) { + (void) fprintf(io->errs, "Can't alloc secring\n"); + return 0; + } + + if (!readkeyring(netpgp, + "pubring", + netpgp->pubring, + netpgp->secring)) { + (void) fprintf(io->errs, "Can't read pub keyring\n"); + // return 0; + } + /* if a userid has been given, we'll use it */ + if ((userid = netpgp_getvar(netpgp, "userid")) == NULL) { + /* also search in config file for default id */ + (void) memset(id, 0x0, sizeof(id)); + (void) conffile(netpgp, homedir, id, sizeof(id)); + if (id[0] != 0x0) { + netpgp_setvar(netpgp, "userid", userid = id); + } + } + /* only read secret keys if we need to */ + if (netpgp_getvar(netpgp, "need seckey")) { + /* read the secret ring */ + if (!readkeyring(netpgp, + "secring", + netpgp->pubring, + netpgp->secring)) { + (void) fprintf(io->errs, "Can't read sec keyring\n"); + // return 0; + } + /* now, if we don't have a valid user, use the first in secring */ + if (!userid && netpgp_getvar(netpgp, "need userid") != NULL) { + /* signing - need userid and sec key */ + (void) memset(id, 0x0, sizeof(id)); + if (get_first_ring(netpgp->secring, id, sizeof(id), 0)) { + netpgp_setvar(netpgp, "userid", userid = id); + } + } + } else if (netpgp_getvar(netpgp, "need userid") != NULL) { + /* encrypting - get first in pubring */ + if (!userid && get_first_ring(netpgp->pubring, id, sizeof(id), 0)) { + (void) netpgp_setvar(netpgp, "userid", userid = id); + } + } + if (!userid && netpgp_getvar(netpgp, "need userid")) { + /* if we don't have a user id, and we need one, fail */ + (void) fprintf(io->errs, "Cannot find user id\n"); + return 0; + } + t = time(NULL); + netpgp_setvar(netpgp, "initialised", ctime(&t)); + return 1; +} + +/* finish off with the netpgp_t struct */ +int +netpgp_end(netpgp_t *netpgp) +{ + unsigned i; + + for (i = 0 ; i < netpgp->c ; i++) { + if (netpgp->name[i] != NULL) { + free(netpgp->name[i]); + } + if (netpgp->value[i] != NULL) { + free(netpgp->value[i]); + } + } + if (netpgp->name != NULL) { + free(netpgp->name); + } + if (netpgp->value != NULL) { + free(netpgp->value); + } + if (netpgp->pubring != NULL) { + pgp_keyring_free(netpgp->pubring); + } + if (netpgp->secring != NULL) { + pgp_keyring_free(netpgp->secring); + } + free(netpgp->io); + return 1; +} + +static int +netpgp_save_ring(netpgp_t *netpgp, + pgp_keyring_t *keyring, + char *name) +{ + pgp_io_t *io; + pgp_key_t *key; + unsigned n; + pgp_output_t *output; + int fd; + int err = 0; + char swpfile[MAXPATHLEN]; + char backup[MAXPATHLEN]; + char *ringfile; + int cur; + time_t curtime; + char f[MAXPATHLEN]; + + io = netpgp->io; + + /* file names */ + if ((ringfile = netpgp_getvar(netpgp, name)) == NULL) { + char *homedir; + homedir = netpgp_getvar(netpgp, "homedir"); + (void) snprintf(f, sizeof(f), "%s/%s.gpg", homedir, name); + ringfile = f; + } + curtime = time(NULL); + if (snprintf(swpfile, sizeof(swpfile), + "%s.swp", ringfile) >= sizeof(swpfile) || + (cur = snprintf(backup, sizeof(backup), + "%s.backup_", ringfile)) >= sizeof(backup) || + strftime(&backup[cur], sizeof(backup)-cur, + "%F.%T", localtime(&curtime)) >= sizeof(backup)-cur){ + (void) fprintf(io->errs, + "netpgp_save_%s : file path too long\n", name); + return 0; + } + + /* ensure temporary file isn't already existing */ + unlink(swpfile); + + if ((fd = pgp_setup_file_write(&output, swpfile, 0)) < 0) { + (void) fprintf(io->errs, + "netpgp_save_%s : can't setup write for %s\n", name, swpfile); + return 0; + } + + for (n = 0, key = keyring->keys; n < keyring->keyc; ++n, ++key) { + pgp_write_xfer_key(output, key, 0); + } + + pgp_teardown_file_write(output, fd); + + if(err){ + unlink(swpfile); + return 0; + } + + /* save ring if "backup rings" variable is set */ + if (netpgp_getvar(netpgp, "backup rings") != NULL) { + rename(ringfile, backup); + } + + /* replace ring file with swap file */ + rename(swpfile, ringfile); + + netpgp_setvar(netpgp, name, ringfile); + + return 1; +} + +int +netpgp_save_pubring(netpgp_t *netpgp) +{ + return netpgp_save_ring(netpgp, netpgp->pubring, "pubring"); +} + +int +netpgp_save_secring(netpgp_t *netpgp) +{ + return netpgp_save_ring(netpgp, netpgp->secring, "secring"); +} + +/* set a variable */ +int +netpgp_setvar(netpgp_t *netpgp, const char *name, const char *value) +{ + char *newval; + int i; + + /* protect against the case where 'value' is netpgp->value[i] */ + newval = netpgp_strdup(value); + if ((i = findvar(netpgp, name)) < 0) { + /* add the element to the array */ + if (size_arrays(netpgp, netpgp->size + 15)) { + netpgp->name[i = netpgp->c++] = netpgp_strdup(name); + } + } else { + /* replace the element in the array */ + if (netpgp->value[i]) { + free(netpgp->value[i]); + netpgp->value[i] = NULL; + } + } + /* sanity checks for range of values */ + if (strcmp(name, "hash") == 0 || strcmp(name, "algorithm") == 0) { + if (pgp_str_to_hash_alg(newval) == PGP_HASH_UNKNOWN) { + free(newval); + return 0; + } + } + netpgp->value[i] = newval; + return 1; +} + +/* unset a variable */ +int +netpgp_unsetvar(netpgp_t *netpgp, const char *name) +{ + int i; + + if ((i = findvar(netpgp, name)) >= 0) { + if (netpgp->value[i]) { + free(netpgp->value[i]); + netpgp->value[i] = NULL; + } + netpgp->value[i] = NULL; + return 1; + } + return 0; +} + +/* get a variable's value (NULL if not set) */ +char * +netpgp_getvar(netpgp_t *netpgp, const char *name) +{ + int i; + + return ((i = findvar(netpgp, name)) < 0) ? NULL : netpgp->value[i]; +} + +/* increment a value */ +int +netpgp_incvar(netpgp_t *netpgp, const char *name, const int delta) +{ + char *cp; + char num[16]; + int val; + + val = 0; + if ((cp = netpgp_getvar(netpgp, name)) != NULL) { + val = atoi(cp); + } + (void) snprintf(num, sizeof(num), "%d", val + delta); + netpgp_setvar(netpgp, name, num); + return 1; +} + +/* set the home directory value to "home/subdir" */ +int +netpgp_set_homedir(netpgp_t *netpgp, char *home, const char *subdir, const int quiet) +{ + struct stat st; + char d[MAXPATHLEN]; + + if (home == NULL) { + if (!quiet) { + (void) fprintf(stderr, "NULL HOME directory\n"); + } + return 0; + } + (void) snprintf(d, sizeof(d), "%s%s", home, (subdir) ? subdir : ""); + if (stat(d, &st) == 0) { + if ((st.st_mode & S_IFMT) == S_IFDIR) { + netpgp_setvar(netpgp, "homedir", d); + return 1; + } + (void) fprintf(stderr, "netpgp: homedir \"%s\" is not a dir\n", + d); + return 0; + } + if (!quiet) { + (void) fprintf(stderr, + "netpgp: warning homedir \"%s\" not found\n", d); + } + netpgp_setvar(netpgp, "homedir", d); + return 1; +} diff --git a/libs/netpgp/openssl_crypto.c b/libs/netpgp/src/openssl_crypto.c similarity index 82% rename from libs/netpgp/openssl_crypto.c rename to libs/netpgp/src/openssl_crypto.c index 8c75eb26..6df937bb 100644 --- a/libs/netpgp/openssl_crypto.c +++ b/libs/netpgp/src/openssl_crypto.c @@ -49,7 +49,7 @@ /** \file */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -57,7 +57,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: openssl_crypto.c,v 1.33 2010/11/07 08:39:59 agc Exp $"); +__RCSID("$NetBSD$"); #endif #ifdef HAVE_OPENSSL_DSA_H @@ -82,25 +82,28 @@ __RCSID("$NetBSD: openssl_crypto.c,v 1.33 2010/11/07 08:39:59 agc Exp $"); #include #endif -#include "crypto-netpgp.h" -#include "keyring-netpgp.h" -#include "readerwriter-netpgp.h" -#include "netpgpdefs.h" -#include "netpgpdigest.h" -#include "packet-netpgp.h" +#include "netpgp/crypto.h" +#include "netpgp/keyring.h" +#include "netpgp/readerwriter.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/netpgpdigest.h" +#include "netpgp/packet.h" +#include "netpgp/openssl11stub.h" static void test_seckey(const pgp_seckey_t *seckey) { - RSA *test = RSA_new(); + RSA *test = RSA_new(); - test->n = BN_dup(seckey->pubkey.key.rsa.n); - test->e = BN_dup(seckey->pubkey.key.rsa.e); + RSA_set0_key(test, + BN_dup(seckey->pubkey.key.rsa.n), + BN_dup(seckey->pubkey.key.rsa.e), + BN_dup(seckey->key.rsa.d)); - test->d = BN_dup(seckey->key.rsa.d); - test->p = BN_dup(seckey->key.rsa.p); - test->q = BN_dup(seckey->key.rsa.q); + RSA_set0_factors(test, + BN_dup(seckey->key.rsa.p), + BN_dup(seckey->key.rsa.q)); if (RSA_check_key(test) != 1) { (void) fprintf(stderr, @@ -440,20 +443,25 @@ pgp_dsa_verify(const uint8_t *hash, size_t hash_length, int ret; osig = DSA_SIG_new(); - osig->r = sig->r; - osig->s = sig->s; + DSA_SIG_set0(osig, + BN_dup(sig->r), + BN_dup(sig->s)); odsa = DSA_new(); - odsa->p = dsa->p; - odsa->q = dsa->q; - odsa->g = dsa->g; - odsa->pub_key = dsa->y; + DSA_set0_pqg(odsa, + BN_dup(dsa->p), + BN_dup(dsa->q), + BN_dup(dsa->g)); + + DSA_set0_key(odsa, + BN_dup(dsa->y), + NULL); if (pgp_get_debug_level(__FILE__)) { hexdump(stderr, "input hash", hash, hash_length); - (void) fprintf(stderr, "Q=%d\n", BN_num_bytes(odsa->q)); + (void) fprintf(stderr, "Q=%d\n", BN_num_bytes(dsa->q)); } - if ((qlen = (unsigned)BN_num_bytes(odsa->q)) < hash_length) { + if ((qlen = (unsigned)BN_num_bytes(dsa->q)) < hash_length) { hash_length = qlen; } ret = DSA_do_verify(hash, (int)hash_length, osig, odsa); @@ -465,10 +473,8 @@ pgp_dsa_verify(const uint8_t *hash, size_t hash_length, return 0; } - odsa->p = odsa->q = odsa->g = odsa->pub_key = NULL; DSA_free(odsa); - osig->r = osig->s = NULL; DSA_SIG_free(osig); return (unsigned)ret; @@ -493,12 +499,14 @@ pgp_rsa_public_decrypt(uint8_t *out, int n; orsa = RSA_new(); - orsa->n = pubkey->n; - orsa->e = pubkey->e; + RSA_set0_key(orsa, + BN_dup(pubkey->n), + BN_dup(pubkey->e), + NULL); + n = RSA_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING); - orsa->n = orsa->e = NULL; RSA_free(orsa); return n; @@ -525,20 +533,19 @@ pgp_rsa_private_encrypt(uint8_t *out, int n; orsa = RSA_new(); - orsa->n = BN_dup(pubkey->n); - orsa->d = seckey->d; - orsa->p = seckey->q; /* p and q are round the other way in openssl */ - orsa->q = seckey->p; + + RSA_set0_key(orsa, + BN_dup(pubkey->n), + BN_dup(pubkey->e), + BN_dup(seckey->d)); + + /* p and q are round the other way in openssl */ + RSA_set0_factors(orsa, + /* q */ BN_dup(seckey->p), + /* p */ BN_dup(seckey->q)); + /* debug */ - orsa->e = BN_dup(pubkey->e); - /* If this isn't set, it's very likely that the programmer hasn't */ - /* decrypted the secret key. RSA_check_key segfaults in that case. */ - /* Use pgp_decrypt_seckey() to do that. */ - if (orsa->d == NULL) { - (void) fprintf(stderr, "orsa is not set\n"); - return 0; - } if (RSA_check_key(orsa) != 1) { (void) fprintf(stderr, "RSA_check_key is not set\n"); return 0; @@ -547,7 +554,6 @@ pgp_rsa_private_encrypt(uint8_t *out, n = RSA_private_encrypt((int)length, in, out, orsa, RSA_NO_PADDING); - orsa->n = orsa->d = orsa->p = orsa->q = NULL; RSA_free(orsa); return n; @@ -575,13 +581,16 @@ pgp_rsa_private_decrypt(uint8_t *out, char errbuf[1024]; keypair = RSA_new(); - keypair->n = pubkey->n; /* XXX: do we need n? */ - keypair->d = seckey->d; - keypair->p = seckey->q; - keypair->q = seckey->p; + RSA_set0_key(keypair, + BN_dup(pubkey->n), + BN_dup(pubkey->e), + BN_dup(seckey->d)); + + RSA_set0_factors(keypair, + BN_dup(seckey->p), + BN_dup(seckey->q)); /* debug */ - keypair->e = pubkey->e; if (RSA_check_key(keypair) != 1) { (void) fprintf(stderr, "RSA_check_key is not set\n"); return 0; @@ -601,7 +610,6 @@ pgp_rsa_private_decrypt(uint8_t *out, ERR_error_string(err, &errbuf[0]); (void) fprintf(stderr, "openssl error : %s\n", errbuf); } - keypair->n = keypair->d = keypair->p = keypair->q = NULL; RSA_free(keypair); return n; @@ -627,8 +635,10 @@ pgp_rsa_public_encrypt(uint8_t *out, /* printf("pgp_rsa_public_encrypt: length=%ld\n", length); */ orsa = RSA_new(); - orsa->n = pubkey->n; - orsa->e = pubkey->e; + RSA_set0_key(orsa, + BN_dup(pubkey->n), + BN_dup(pubkey->e), + NULL); /* printf("len: %ld\n", length); */ /* pgp_print_bn("n: ", orsa->n); */ @@ -641,7 +651,6 @@ pgp_rsa_public_encrypt(uint8_t *out, fd_out = BIO_new_fd(fileno(stderr), BIO_NOCLOSE); ERR_print_errors(fd_out); } - orsa->n = orsa->e = NULL; RSA_free(orsa); return n; @@ -656,8 +665,8 @@ pgp_rsa_public_encrypt(uint8_t *out, void pgp_crypto_finish(void) { - CRYPTO_cleanup_all_ex_data(); - ERR_remove_state((unsigned long)0); + // No cleanup since OpenSSL 1.1.0 + // CRYPTO_cleanup_all_ex_data(); } /** @@ -682,17 +691,25 @@ pgp_text_from_hash(pgp_hash_t *hash) \note It is the caller's responsibility to call pgp_keydata_free(keydata) */ unsigned -rsa_generate_keypair(pgp_key_t *keydata, +pgp_rsa_generate_keypair(pgp_key_t *keydata, const int numbits, const unsigned long e__, const char *hashalg, - const char *cipher) + const char *cipher, + const uint8_t *passphrase, + const size_t pplen) { pgp_seckey_t *seckey; - RSA *rsa = RSA_new(); + RSA *rsa; BN_CTX *ctx; pgp_output_t *output; pgp_memory_t *mem; + int res; + const BIGNUM *_n = NULL; + const BIGNUM *_e = NULL; + const BIGNUM *_d = NULL; + const BIGNUM *_p = NULL; + const BIGNUM *_q = NULL; ctx = BN_CTX_new(); pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY); @@ -700,14 +717,29 @@ rsa_generate_keypair(pgp_key_t *keydata, /* generate the key pair */ - //rsa = RSA_generate_key(numbits, e, NULL, NULL); - /* generate key */ - BIGNUM* e = BN_new(); - BN_set_word(e, e__); - if( RSA_generate_key_ex(rsa, numbits, e, 0) != 1 ) { + BIGNUM *exp = BN_new(); + BN_set_word(exp, e__); + /* +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + exp = BN_bin2bn((const unsigned char *)&e, sizeof(e), NULL); +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + exp = BN_lebin2bn((const unsigned char *)&e, sizeof(e), NULL); +#else +#error Unsupported endian +#endif + if (!exp) + return 0; + */ + + rsa = RSA_new(); + res = RSA_generate_key_ex(rsa, numbits, exp, NULL); + + BN_free(exp); + + if (!res){ + RSA_free(rsa); return 0; - } - BN_free(e); + }; /* populate pgp key from ssl key */ @@ -716,11 +748,14 @@ rsa_generate_keypair(pgp_key_t *keydata, seckey->pubkey.days_valid = 0; seckey->pubkey.alg = PGP_PKA_RSA; - seckey->pubkey.key.rsa.n = BN_dup(rsa->n); - seckey->pubkey.key.rsa.e = BN_dup(rsa->e); + RSA_get0_key(rsa, &_n, &_e, &_d); - seckey->s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; - seckey->s2k_specifier = PGP_S2KS_SALTED; + seckey->pubkey.key.rsa.n = BN_dup(_n); + seckey->pubkey.key.rsa.e = BN_dup(_e); + + /* seckey->s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; */ + seckey->s2k_usage = PGP_S2KU_NONE; + /* seckey->s2k_specifier = PGP_S2KS_SALTED;*/ /* seckey->s2k_specifier=PGP_S2KS_SIMPLE; */ if ((seckey->hash_alg = pgp_str_to_hash_alg(hashalg)) == PGP_HASH_UNKNOWN) { seckey->hash_alg = PGP_HASH_SHA1; @@ -729,20 +764,22 @@ rsa_generate_keypair(pgp_key_t *keydata, seckey->octetc = 0; seckey->checksum = 0; - seckey->key.rsa.d = BN_dup(rsa->d); - seckey->key.rsa.p = BN_dup(rsa->p); - seckey->key.rsa.q = BN_dup(rsa->q); - seckey->key.rsa.u = BN_mod_inverse(NULL, rsa->p, rsa->q, ctx); + RSA_get0_factors(rsa, &_p, &_q); + seckey->key.rsa.d = BN_dup(_d); + seckey->key.rsa.p = BN_dup(_p); + seckey->key.rsa.q = BN_dup(_q); + seckey->key.rsa.u = BN_mod_inverse(NULL, _p, _q, ctx); if (seckey->key.rsa.u == NULL) { - //(void) fprintf(stderr, "seckey->key.rsa.u is NULL\n"); + RSA_free(rsa); + (void) fprintf(stderr, "seckey->key.rsa.u is NULL\n"); return 0; } BN_CTX_free(ctx); RSA_free(rsa); - pgp_keyid(keydata->sigid, PGP_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); - pgp_fingerprint(&keydata->sigfingerprint, &keydata->key.seckey.pubkey, seckey->hash_alg); + pgp_keyid(keydata->pubkeyid, PGP_KEY_ID_SIZE, &keydata->key.seckey.pubkey, seckey->hash_alg); + pgp_fingerprint(&keydata->pubkeyfpr, &keydata->key.seckey.pubkey, seckey->hash_alg); /* Generate checksum */ @@ -797,7 +834,7 @@ rsa_generate_keypair(pgp_key_t *keydata, \return The new keypair or NULL \note It is the caller's responsibility to call pgp_keydata_free(keydata) - \sa rsa_generate_keypair() + \sa pgp_rsa_generate_keypair() \sa pgp_keydata_free() */ pgp_key_t * @@ -810,15 +847,16 @@ pgp_rsa_new_selfsign_key(const int numbits, pgp_key_t *keydata; keydata = pgp_keydata_new(); - if (!rsa_generate_keypair(keydata, numbits, e, hashalg, cipher) || - !pgp_add_selfsigned_userid(keydata, userid)) { + if (!pgp_rsa_generate_keypair(keydata, numbits, e, hashalg, cipher, + (const uint8_t *) "", (const size_t) 0) || + !pgp_add_selfsigned_userid(keydata, NULL, userid, 0 /*never expire*/)) { pgp_keydata_free(keydata); return NULL; } return keydata; } -DSA_SIG * +pgp_dsa_sig_t * pgp_dsa_sign(uint8_t *hashbuf, unsigned hashsize, const pgp_dsa_seckey_t *secdsa, @@ -826,64 +864,37 @@ pgp_dsa_sign(uint8_t *hashbuf, { DSA_SIG *dsasig; DSA *odsa; + pgp_dsa_sig_t *pgpdsasig; + const BIGNUM *pr = NULL; + const BIGNUM *ps = NULL; odsa = DSA_new(); - odsa->p = pubdsa->p; - odsa->q = pubdsa->q; - odsa->g = pubdsa->g; - odsa->pub_key = pubdsa->y; - odsa->priv_key = secdsa->x; + DSA_set0_pqg(odsa, + BN_dup(pubdsa->p), + BN_dup(pubdsa->q), + BN_dup(pubdsa->g)); + + DSA_set0_key(odsa, + BN_dup(pubdsa->y), + BN_dup(secdsa->x)); dsasig = DSA_do_sign(hashbuf, (int)hashsize, odsa); - odsa->p = odsa->q = odsa->g = odsa->pub_key = odsa->priv_key = NULL; DSA_free(odsa); - return dsasig; + + DSA_SIG_get0(dsasig, &pr, &ps); + + pgpdsasig = calloc(1,sizeof(pgp_dsa_sig_t)); + if(pgpdsasig != NULL){ + pgpdsasig->r = BN_dup(pr); + pgpdsasig->s = BN_dup(ps); + } + + DSA_SIG_free(dsasig); + return pgpdsasig; } -int -openssl_read_pem_seckey(const char *f, pgp_key_t *key, const char *type, int verbose) -{ - FILE *fp; - char prompt[BUFSIZ]; - char *pass; - DSA *dsa; - RSA *rsa; - int ok; - - OpenSSL_add_all_algorithms(); - if ((fp = fopen(f, "r")) == NULL) { - if (verbose) { - (void) fprintf(stderr, "can't open '%s'\n", f); - } - return 0; - } - ok = 1; - if (strcmp(type, "ssh-rsa") == 0) { - if ((rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) { - (void) snprintf(prompt, sizeof(prompt), "netpgp PEM %s passphrase: ", f); - do { - pass = getpass(prompt); - rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, pass); - } while (rsa == NULL); - } - key->key.seckey.key.rsa.d = rsa->d; - key->key.seckey.key.rsa.p = rsa->p; - key->key.seckey.key.rsa.q = rsa->q; - key->key.seckey.key.rsa.d = rsa->d; - } else if (strcmp(type, "ssh-dss") == 0) { - if ((dsa = PEM_read_DSAPrivateKey(fp, NULL, NULL, NULL)) == NULL) { - ok = 0; - } else { - key->key.seckey.key.dsa.x = dsa->priv_key; - } - } else { - ok = 0; - } - (void) fclose(fp); - return ok; -} /* * Decide the number of bits in the random componont k diff --git a/libs/netpgp/packet-parse.c b/libs/netpgp/src/packet-parse.c similarity index 91% rename from libs/netpgp/packet-parse.c rename to libs/netpgp/src/packet-parse.c index 754d67a7..dbf24506 100644 --- a/libs/netpgp/packet-parse.c +++ b/libs/netpgp/src/packet-parse.c @@ -50,7 +50,7 @@ /** \file * \brief Parser for OpenPGP packets */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -58,7 +58,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: packet-parse.c,v 1.51 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -80,16 +80,16 @@ __RCSID("$NetBSD: packet-parse.c,v 1.51 2012/03/05 02:20:18 christos Exp $"); #include #endif -#include "packet-netpgp.h" -#include "packet-parse.h" -#include "keyring-netpgp.h" -#include "errors-netpgp.h" -#include "packet-show.h" -#include "create-netpgp.h" -#include "readerwriter-netpgp.h" -#include "netpgpdefs.h" -#include "crypto-netpgp.h" -#include "netpgpdigest.h" +#include "netpgp/packet.h" +#include "netpgp/packet-parse.h" +#include "netpgp/keyring.h" +#include "netpgp/errors.h" +#include "netpgp/packet-show.h" +#include "netpgp/create.h" +#include "netpgp/readerwriter.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/crypto.h" +#include "netpgp/netpgpdigest.h" #define ERRP(cbinfo, cont, err) do { \ cont.u.error = err; \ @@ -189,6 +189,30 @@ pgp_init_subregion(pgp_region_t *subregion, pgp_region_t *region) * XXX: replace pgp_ptag_t with something more appropriate for limiting reads */ +/* data from partial blocks is queued up in virtual block in stream */ +static int +read_partial_data(pgp_stream_t *stream, + pgp_reader_t *readinfo, + void *dest, size_t length) +{ + unsigned n; + + if (pgp_get_debug_level(__FILE__)) { + (void) fprintf(stderr, "fd_reader: coalesced data, off %d\n", + readinfo->virtualoff); + } + n = MIN(readinfo->virtualc - readinfo->virtualoff, (unsigned)length); + (void) memcpy(dest, &readinfo->virtualpkt[readinfo->virtualoff], n); + readinfo->virtualoff += n; + if (readinfo->virtualoff == readinfo->virtualc) { + free(readinfo->virtualpkt); + readinfo->virtualpkt = NULL; + readinfo->virtualc = readinfo->virtualoff = 0; + } + return (int)n; +} + + /** * low-level function to read data from reader function * @@ -231,8 +255,13 @@ sub_base_read(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **err for (n = 0; n < length;) { int r; - r = readinfo->reader(stream, (char *) dest + n, length - n, errors, - readinfo, cbinfo); + if (!readinfo->coalescing && readinfo->virtualc && readinfo->virtualoff < readinfo->virtualc) { + r = read_partial_data(stream, readinfo, (char*) dest + n, length - n); + }else{ + r = readinfo->reader(stream, (char *) dest + n, + length - n, errors, + readinfo, cbinfo); + } if (r > (int)(length - n)) { (void) fprintf(stderr, "sub_base_read: bad read\n"); return 0; @@ -454,6 +483,7 @@ limread(uint8_t *dest, unsigned length, &info->readinfo, &info->cbinfo); } +#if 0 static unsigned exact_limread(uint8_t *dest, unsigned len, pgp_region_t *region, @@ -466,6 +496,7 @@ exact_limread(uint8_t *dest, unsigned len, stream->exact_read = 0; return ret; } +#endif /** Skip over length bytes of this packet. * @@ -655,10 +686,10 @@ limread_mpi(BIGNUM **pbn, pgp_region_t *region, pgp_stream_t *stream) unsigned nonzero; unsigned ret; - stream->reading_mpi_len = 1; + //stream->reading_mpi_len = 1; ret = (unsigned)limread_scalar(&length, 2, region, stream); - stream->reading_mpi_len = 0; + //stream->reading_mpi_len = 0; if (!ret) return 0; @@ -704,11 +735,12 @@ static void streamread(pgp_stream_t *stream, unsigned c) { int cc; + pgp_reader_t *readinfo = &stream->readinfo; - stream->virtualpkt = realloc(stream->virtualpkt, stream->virtualc + c); - cc = stream->readinfo.reader(stream, &stream->virtualpkt[stream->virtualc], - c, &stream->errors, &stream->readinfo, &stream->cbinfo); - stream->virtualc += cc; + readinfo->virtualpkt = realloc(readinfo->virtualpkt, readinfo->virtualc + c); + cc = readinfo->reader(stream, &readinfo->virtualpkt[readinfo->virtualc], + c, &stream->errors, readinfo, &stream->cbinfo); + readinfo->virtualc += cc; } /* coalesce all the partial blocks together */ @@ -716,17 +748,20 @@ static int coalesce_blocks(pgp_stream_t *stream, unsigned length) { unsigned c; + unsigned r; + + pgp_reader_t *readinfo = &stream->readinfo; + readinfo->coalescing = 1; - stream->coalescing = 1; /* already read a partial block length - prime the array */ streamread(stream, length); - while (read_new_length(&c, stream) && stream->partial_read) { + while ((r = read_new_length(&c, stream)) && readinfo->partial_read) { /* length we read is partial - add to end of array */ streamread(stream, c); } /* not partial - add the last extent to the end of the array */ - streamread(stream, c); - stream->coalescing = 0; + if(r > 0) streamread(stream, c); + readinfo->coalescing = 0; return 1; } @@ -744,8 +779,9 @@ static unsigned read_new_length(unsigned *length, pgp_stream_t *stream) { uint8_t c; + pgp_reader_t *readinfo = &stream->readinfo; - stream->partial_read = 0; + readinfo->partial_read = 0; if (base_read(&c, 1, stream) != 1) { return 0; } @@ -766,13 +802,13 @@ read_new_length(unsigned *length, pgp_stream_t *stream) } if (c < 255) { /* 3. Partial Body Length */ - stream->partial_read = 1; + readinfo->partial_read = 1; *length = 1 << (c & 0x1f); - if (!stream->coalescing) { + if (!readinfo->coalescing) { /* we have been called from coalesce_blocks - * just return with the partial length */ coalesce_blocks(stream, *length); - *length = stream->virtualc; + *length = readinfo->virtualc; } return 1; } @@ -802,6 +838,7 @@ limited_read_new_length(unsigned *length, pgp_region_t *region, pgp_stream_t *stream) { uint8_t c = 0x0; + pgp_reader_t *readinfo = &stream->readinfo; if (!limread(&c, 1, region, stream)) { return 0; @@ -820,13 +857,13 @@ limited_read_new_length(unsigned *length, pgp_region_t *region, return 1; } if (c < 255) { - stream->partial_read = 1; + readinfo->partial_read = 1; *length = 1 << (c & 0x1f); - if (!stream->coalescing) { + if (!readinfo->coalescing) { /* we have been called from coalesce_blocks - * just return with the partial length */ coalesce_blocks(stream, *length); - *length = stream->virtualc; + *length = readinfo->virtualc; } return 1; } @@ -845,6 +882,14 @@ pgp_data_free(pgp_data_t *data) data->len = 0; } +void +pgp_data_dup(pgp_data_t *dst, const pgp_data_t *src) +{ + dst->contents = calloc(1, src->len); + memcpy(dst->contents, src->contents, src->len); + dst->len = src->len; +} + /** \ingroup Core_Create \brief Free allocated memory @@ -920,28 +965,37 @@ free_BN(BIGNUM **pp) *pp = NULL; } -/** - * \ingroup Core_Create - * \brief Free the memory used when parsing a signature - * \param sig - */ static void -sig_free(pgp_sig_t *sig) +dup_BN(BIGNUM **dst, const BIGNUM *src) { - switch (sig->info.key_alg) { + *dst = BN_dup(src); +} + +void +copy_sig_info(pgp_sig_info_t *dst, const pgp_sig_info_t *src) +{ + (void) memcpy(dst, src, sizeof(*src)); + + if ((dst->v4_hashed = calloc(1, src->v4_hashlen)) == NULL) { + (void) fprintf(stderr, "copy_sig_info: bad alloc\n"); + } else { + (void) memcpy(dst->v4_hashed, src->v4_hashed, src->v4_hashlen); + } + + switch (src->key_alg) { case PGP_PKA_RSA: case PGP_PKA_RSA_SIGN_ONLY: - free_BN(&sig->info.sig.rsa.sig); + dup_BN(&dst->sig.rsa.sig, src->sig.rsa.sig); break; case PGP_PKA_DSA: - free_BN(&sig->info.sig.dsa.r); - free_BN(&sig->info.sig.dsa.s); + dup_BN(&dst->sig.dsa.r, src->sig.dsa.r); + dup_BN(&dst->sig.dsa.s, src->sig.dsa.s); break; case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: - free_BN(&sig->info.sig.elgamal.r); - free_BN(&sig->info.sig.elgamal.s); + dup_BN(&dst->sig.elgamal.r, src->sig.elgamal.r); + dup_BN(&dst->sig.elgamal.s, src->sig.elgamal.s); break; case PGP_PKA_PRIVATE00: @@ -955,13 +1009,65 @@ sig_free(pgp_sig_t *sig) case PGP_PKA_PRIVATE08: case PGP_PKA_PRIVATE09: case PGP_PKA_PRIVATE10: - pgp_data_free(&sig->info.sig.unknown); + pgp_data_dup(&dst->sig.unknown, &src->sig.unknown); break; default: - (void) fprintf(stderr, "sig_free: bad sig type\n"); + (void) fprintf(stderr, "sig_dup: bad sig type\n"); } } +/** + * \ingroup Core_Create + * \brief Free the memory used when parsing a signature + * \param sig + */ +void +pgp_free_sig_info(pgp_sig_info_t *info) +{ + free(info->v4_hashed); + + switch (info->key_alg) { + case PGP_PKA_RSA: + case PGP_PKA_RSA_SIGN_ONLY: + free_BN(&info->sig.rsa.sig); + break; + + case PGP_PKA_DSA: + free_BN(&info->sig.dsa.r); + free_BN(&info->sig.dsa.s); + break; + + case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: + free_BN(&info->sig.elgamal.r); + free_BN(&info->sig.elgamal.s); + break; + + case PGP_PKA_PRIVATE00: + case PGP_PKA_PRIVATE01: + case PGP_PKA_PRIVATE02: + case PGP_PKA_PRIVATE03: + case PGP_PKA_PRIVATE04: + case PGP_PKA_PRIVATE05: + case PGP_PKA_PRIVATE06: + case PGP_PKA_PRIVATE07: + case PGP_PKA_PRIVATE08: + case PGP_PKA_PRIVATE09: + case PGP_PKA_PRIVATE10: + pgp_data_free(&info->sig.unknown); + break; + + default: + (void) fprintf(stderr, "info-free: bad info-type\n"); + } + memset(info, 0, sizeof(pgp_sig_info_t)); +} + +static void +sig_free(pgp_sig_t *sig) +{ + pgp_free_sig_info(&sig->info); +} + /** \ingroup Core_Create @@ -1188,8 +1294,48 @@ pgp_pubkey_free(pgp_pubkey_t *p) default: (void) fprintf(stderr, "pgp_pubkey_free: bad alg\n"); } + memset(p, 0, sizeof(*p)); } +int +pgp_pubkey_dup(pgp_pubkey_t *dst, pgp_pubkey_t *src) +{ + memcpy(dst, src, sizeof(*src)); + + switch (src->alg) { + case PGP_PKA_RSA: + case PGP_PKA_RSA_ENCRYPT_ONLY: + case PGP_PKA_RSA_SIGN_ONLY: + dup_BN(&dst->key.rsa.n, src->key.rsa.n); + dup_BN(&dst->key.rsa.e, src->key.rsa.e); + break; + + case PGP_PKA_DSA: + dup_BN(&dst->key.dsa.p, src->key.dsa.p); + dup_BN(&dst->key.dsa.q, src->key.dsa.q); + dup_BN(&dst->key.dsa.g, src->key.dsa.g); + dup_BN(&dst->key.dsa.y, src->key.dsa.y); + break; + + case PGP_PKA_ELGAMAL: + case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: + dup_BN(&dst->key.elgamal.p, src->key.elgamal.p); + dup_BN(&dst->key.elgamal.g, src->key.elgamal.g); + dup_BN(&dst->key.elgamal.y, src->key.elgamal.y); + break; + + case PGP_PKA_NOTHING: + /* nothing to dup */ + break; + + default: + (void) fprintf(stderr, "pgp_pubkey_dup: bad alg\n"); + return 0; + } + + /*TODO alloc error handling */ + return 1; +} /** \ingroup Core_ReadPackets */ @@ -1606,6 +1752,10 @@ parse_one_sig_subpacket(pgp_sig_t *sig, sig->info.duration = pkt.u.ss_time; sig->info.duration_set = 1; } + if (pkt.tag == PGP_PTAG_SS_KEY_EXPIRY) { + sig->info.key_expiry = pkt.u.ss_time; + sig->info.key_expiry_set = 1; + } break; case PGP_PTAG_SS_TRUST: @@ -1653,12 +1803,18 @@ parse_one_sig_subpacket(pgp_sig_t *sig, return 0; } pkt.u.ss_primary_userid = !!bools; + sig->info.primary_userid = pkt.u.ss_primary_userid; break; case PGP_PTAG_SS_KEY_FLAGS: if (!read_data(&pkt.u.ss_key_flags, &subregion, stream)) { return 0; } + if(pkt.u.ss_key_flags.len > 0){ + /* Only one byte is defined in rfc4880 for now */ + sig->info.key_flags = pkt.u.ss_key_flags.contents[0]; + sig->info.key_flags_set = 1; + } break; case PGP_PTAG_SS_KEYSERV_PREFS: @@ -1817,6 +1973,7 @@ parse_one_sig_subpacket(pgp_sig_t *sig, PGP_ERROR_1(&stream->errors, PGP_E_R_UNCONSUMED_DATA, "Unconsumed data (%d)", subregion.length - subregion.readc); + pgp_parser_content_free(&pkt); return 0; } CALLBACK(pkt.tag, &stream->cbinfo, &pkt); @@ -1968,24 +2125,24 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream) if (!stream->readinfo.accumulate) { /* We must accumulate, else we can't check the signature */ fprintf(stderr, "*** ERROR: must set accumulate to 1\n"); - return 0; + goto error_unalloc_v4_hashed; } (void) memcpy(pkt.u.sig.info.v4_hashed, stream->readinfo.accumulated + pkt.u.sig.v4_hashstart, pkt.u.sig.info.v4_hashlen); if (!parse_sig_subpkts(&pkt.u.sig, region, stream)) { - return 0; + goto error_unalloc_v4_hashed; } if (!limread(pkt.u.sig.hash2, 2, region, stream)) { - return 0; + goto error_unalloc_v4_hashed; } switch (pkt.u.sig.info.key_alg) { case PGP_PKA_RSA: if (!limread_mpi(&pkt.u.sig.info.sig.rsa.sig, region, stream)) { - return 0; + goto error_unalloc_v4_hashed; } if (pgp_get_debug_level(__FILE__)) { (void) fprintf(stderr, "parse_v4_sig: RSA: sig is\n"); @@ -2004,7 +2161,7 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream) (void) fprintf(stderr, "Error reading DSA r field in signature"); } - return 0; + goto error_unalloc_v4_hashed; } if (!limread_mpi(&pkt.u.sig.info.sig.dsa.s, region, stream)) { ERRP(&stream->cbinfo, pkt, @@ -2017,7 +2174,7 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream) stream) || !limread_mpi(&pkt.u.sig.info.sig.elgamal.s, region, stream)) { - return 0; + goto error_unalloc_v4_hashed; } break; @@ -2033,7 +2190,7 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream) case PGP_PKA_PRIVATE09: case PGP_PKA_PRIVATE10: if (!read_data(&pkt.u.sig.info.sig.unknown, region, stream)) { - return 0; + goto error_unalloc_v4_hashed; } break; @@ -2041,16 +2198,21 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream) PGP_ERROR_1(&stream->errors, PGP_E_ALG_UNSUPPORTED_SIGNATURE_ALG, "Bad v4 signature key algorithm (%s)", pgp_show_pka(pkt.u.sig.info.key_alg)); - return 0; + goto error_unalloc_v4_hashed; } if (region->readc != region->length) { PGP_ERROR_1(&stream->errors, PGP_E_R_UNCONSUMED_DATA, "Unconsumed data (%d)", region->length - region->readc); - return 0; + goto error_unalloc_v4_hashed; } CALLBACK(PGP_PTAG_CT_SIGNATURE_FOOTER, &stream->cbinfo, &pkt); return 1; + +error_unalloc_v4_hashed: + free(pkt.u.sig.info.v4_hashed); + return 0; + } /** @@ -2306,6 +2468,50 @@ pgp_seckey_free(pgp_seckey_t *key) pgp_show_pka(key->pubkey.alg)); } free(key->checkhash); + pgp_pubkey_free(&key->pubkey); + memset(key, 0, sizeof(*key)); +} + +int +pgp_seckey_dup(pgp_seckey_t *dst, pgp_seckey_t *src) +{ + memcpy(dst, src, sizeof(*src)); + + switch (src->pubkey.alg) { + case PGP_PKA_RSA: + case PGP_PKA_RSA_ENCRYPT_ONLY: + case PGP_PKA_RSA_SIGN_ONLY: + dup_BN(&dst->key.rsa.d, src->key.rsa.d); + dup_BN(&dst->key.rsa.p, src->key.rsa.p); + dup_BN(&dst->key.rsa.q, src->key.rsa.q); + dup_BN(&dst->key.rsa.u, src->key.rsa.u); + break; + + case PGP_PKA_DSA: + dup_BN(&dst->key.dsa.x, src->key.dsa.x); + break; + + default: + (void) fprintf(stderr, + "pgp_seckey_dup: Unknown algorithm: %d (%s)\n", + src->pubkey.alg, + pgp_show_pka(src->pubkey.alg)); + return 0; + } + + if(src->checkhash) { + if ((dst->checkhash = calloc(1, PGP_CHECKHASH_SIZE)) == NULL) { + (void) fprintf(stderr, "pgp_seckey_dup: bad alloc\n"); + return 0; + }else{ + memcpy(dst->checkhash, src->checkhash, PGP_CHECKHASH_SIZE); + } + } + + pgp_pubkey_dup(&dst->pubkey, &src->pubkey); + + /*TODO alloc error handling */ + return 1; } static int @@ -2339,7 +2545,7 @@ consume_packet(pgp_region_t *region, pgp_stream_t *stream, unsigned warn) * \brief Parse a secret key */ static int -parse_seckey(pgp_region_t *region, pgp_stream_t *stream) +parse_seckey(pgp_content_enum tag, pgp_region_t *region, pgp_stream_t *stream) { pgp_packet_t pkt; pgp_region_t encregion; @@ -2364,9 +2570,14 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream) } if (pgp_get_debug_level(__FILE__)) { fprintf(stderr, "parse_seckey: public key parsed\n"); - pgp_print_pubkey(&pkt.u.seckey.pubkey); + //pgp_print_pubkey(&pkt.u.seckey.pubkey); } - stream->reading_v3_secret = (pkt.u.seckey.pubkey.version != PGP_V4); + //stream->reading_v3_secret = (pkt.u.seckey.pubkey.version != PGP_V4); + if (pkt.u.seckey.pubkey.version != PGP_V4){ + (void) fprintf(stderr, + "parse_seckey: Only V4 is supported\n"); + return 0; + } if (!limread(&c, 1, region, stream)) { return 0; @@ -2576,9 +2787,10 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream) if (pgp_get_debug_level(__FILE__)) { fprintf(stderr, "parse_seckey: end of crypted passphrase\n"); } + + /* XXX - Hard-coded SHA1 here ?? Check */ if (pkt.u.seckey.s2k_usage == PGP_S2KU_ENCRYPTED_AND_HASHED) { - /* XXX - Hard-coded SHA1 here ?? Check */ - pkt.u.seckey.checkhash = calloc(1, PGP_SHA1_HASH_SIZE); + pkt.u.seckey.checkhash = calloc(1, PGP_SHA1_HASH_SIZE); if (pkt.u.seckey.checkhash == NULL) { (void) fprintf(stderr, "parse_seckey: bad alloc\n"); return 0; @@ -2627,7 +2839,7 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream) if (pgp_get_debug_level(__FILE__)) { (void) fprintf(stderr, "4 MPIs read\n"); } - stream->reading_v3_secret = 0; + //stream->reading_v3_secret = 0; if (pkt.u.seckey.s2k_usage == PGP_S2KU_ENCRYPTED_AND_HASHED) { uint8_t hash[PGP_CHECKHASH_SIZE]; @@ -2687,7 +2899,7 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream) if (!ret) { return 0; } - CALLBACK(PGP_PTAG_CT_SECRET_KEY, &stream->cbinfo, &pkt); + CALLBACK(tag, &stream->cbinfo, &pkt); if (pgp_get_debug_level(__FILE__)) { (void) fprintf(stderr, "--- end of parse_seckey\n\n"); } @@ -2869,6 +3081,7 @@ parse_pk_sesskey(pgp_region_t *region, return 1; } +#if 0 static int decrypt_se_data(pgp_content_enum tag, pgp_region_t *region, pgp_stream_t *stream) @@ -2928,6 +3141,7 @@ decrypt_se_data(pgp_content_enum tag, pgp_region_t *region, return r; } +#endif static int decrypt_se_ip_data(pgp_content_enum tag, pgp_region_t *region, @@ -2977,6 +3191,7 @@ decrypt_se_ip_data(pgp_content_enum tag, pgp_region_t *region, return r; } +#if 0 /** \ingroup Core_ReadPackets \brief Read a Symmetrically Encrypted packet @@ -2995,6 +3210,7 @@ parse_se_data(pgp_region_t *region, pgp_stream_t *stream) */ return decrypt_se_data(PGP_PTAG_CT_SE_DATA_BODY, region, stream); } +#endif /** \ingroup Core_ReadPackets @@ -3021,7 +3237,7 @@ parse_se_ip_data(pgp_region_t *region, pgp_stream_t *stream) if (pgp_get_debug_level(__FILE__)) { (void) fprintf(stderr, "parse_se_ip_data: region %d,%d\n", region->readc, region->length); - hexdump(stderr, "compressed region", stream->virtualpkt, stream->virtualc); + hexdump(stderr, "compressed region", stream->readinfo.virtualpkt, stream->readinfo.virtualc); } /* * The content of an encrypted data packet is more OpenPGP packets @@ -3104,7 +3320,6 @@ parse_packet(pgp_stream_t *stream, uint32_t *pktlen) } else { unsigned rb; - rb = 0; pkt.u.ptag.type = ((unsigned)ptag & PGP_PTAG_OF_CONTENT_TAG_MASK) >> PGP_PTAG_OF_CONTENT_TAG_SHIFT; @@ -3177,11 +3392,8 @@ parse_packet(pgp_stream_t *stream, uint32_t *pktlen) break; case PGP_PTAG_CT_SECRET_KEY: - ret = parse_seckey(®ion, stream); - break; - case PGP_PTAG_CT_SECRET_SUBKEY: - ret = parse_seckey(®ion, stream); + ret = parse_seckey((pgp_content_enum)pkt.u.ptag.type, ®ion, stream); break; case PGP_PTAG_CT_PK_SESSION_KEY: @@ -3189,7 +3401,9 @@ parse_packet(pgp_stream_t *stream, uint32_t *pktlen) break; case PGP_PTAG_CT_SE_DATA: - ret = parse_se_data(®ion, stream); + // SE_DATA CURRENTLY BROKEN + ret = 0; + //ret = parse_se_data(®ion, stream); break; case PGP_PTAG_CT_SE_IP_DATA: @@ -3347,11 +3561,15 @@ pgp_stream_delete(pgp_stream_t *stream) { pgp_cbdata_t *cbinfo; pgp_cbdata_t *next; + pgp_cryptinfo_t *cryptinfo = &stream->cbinfo.cryptinfo; for (cbinfo = stream->cbinfo.next; cbinfo; cbinfo = next) { next = cbinfo->next; free(cbinfo); } + + FREE_ARRAY(cryptinfo, recipients_key_ids); + if (stream->readinfo.destroyer) { stream->readinfo.destroyer(&stream->readinfo); } diff --git a/libs/netpgp/packet-show.c b/libs/netpgp/src/packet-show.c similarity index 59% rename from libs/netpgp/packet-show.c rename to libs/netpgp/src/packet-show.c index 1efcf061..fdc4909c 100644 --- a/libs/netpgp/packet-show.c +++ b/libs/netpgp/src/packet-show.c @@ -52,7 +52,7 @@ * Creates printable text strings from packet contents * */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -60,16 +60,16 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: packet-show.c,v 1.21 2011/08/14 11:19:51 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include #include -#include "packet-show.h" +#include "netpgp/packet-show.h" -#include "netpgpsdk.h" -#include "netpgpdefs.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/netpgpdefs.h" /* @@ -271,50 +271,11 @@ static pgp_map_t compression_alg_map[] = {0x00, NULL}, /* this is the end-of-array marker */ }; -static pgp_bit_map_t ss_notation_map_byte0[] = -{ - {0x80, "Human-readable"}, - {0x00, NULL}, -}; - -static pgp_bit_map_t *ss_notation_map[] = -{ - ss_notation_map_byte0, -}; - -static pgp_bit_map_t ss_feature_map_byte0[] = -{ - {0x01, "Modification Detection"}, - {0x00, NULL}, -}; - -static pgp_bit_map_t *ss_feature_map[] = -{ - ss_feature_map_byte0, -}; - -static pgp_bit_map_t ss_key_flags_map[] = -{ - {0x01, "May be used to certify other keys"}, - {0x02, "May be used to sign data"}, - {0x04, "May be used to encrypt communications"}, - {0x08, "May be used to encrypt storage"}, - {0x10, "Private component may have been split by a secret-sharing mechanism"}, - {0x80, "Private component may be in possession of more than one person"}, - {0x00, NULL}, -}; - -static pgp_bit_map_t ss_key_server_prefs_map[] = -{ - {0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server"}, - {0x00, NULL}, -}; - /* * Private functions */ -static void +static void list_init(pgp_list_t *list) { list->size = 0; @@ -322,7 +283,7 @@ list_init(pgp_list_t *list) list->strings = NULL; } -static void +static void list_free_strings(pgp_list_t *list) { unsigned i; @@ -333,7 +294,7 @@ list_free_strings(pgp_list_t *list) } } -static void +static void list_free(pgp_list_t *list) { if (list->strings) @@ -341,37 +302,6 @@ list_free(pgp_list_t *list) list_init(list); } -static unsigned -list_resize(pgp_list_t *list) -{ - /* - * We only resize in one direction - upwards. Algorithm used : double - * the current size then add 1 - */ - char **newstrings; - int newsize; - - newsize = (list->size * 2) + 1; - newstrings = realloc(list->strings, newsize * sizeof(char *)); - if (newstrings) { - list->strings = newstrings; - list->size = newsize; - return 1; - } - (void) fprintf(stderr, "list_resize - bad alloc\n"); - return 0; -} - -static unsigned -add_str(pgp_list_t *list, const char *str) -{ - if (list->size == list->used && !list_resize(list)) { - return 0; - } - list->strings[list->used++] = __UNCONST(str); - return 1; -} - /* find a bitfield in a map - serial search */ static const char * find_bitfield(pgp_bit_map_t *map, uint8_t octet) @@ -384,7 +314,7 @@ find_bitfield(pgp_bit_map_t *map, uint8_t octet) } /* ! generic function to initialise pgp_text_t structure */ -void +void pgp_text_init(pgp_text_t *text) { list_init(&text->known); @@ -398,7 +328,7 @@ pgp_text_init(pgp_text_t *text) * * \param text Pointer to a previously allocated structure. This structure and its contents will be freed. */ -void +void pgp_text_free(pgp_text_t *text) { /* Strings in "known" array will be constants, so don't free them */ @@ -414,161 +344,6 @@ pgp_text_free(pgp_text_t *text) free(text); } -/* XXX: should this (and many others) be unsigned? */ -/* ! generic function which adds text derived from single octet map to text */ -static unsigned -add_str_from_octet_map(pgp_text_t *map, char *str, uint8_t octet) -{ - if (str && !add_str(&map->known, str)) { - /* - * value recognised, but there was a problem adding it to the - * list - */ - /* XXX - should print out error msg here, Ben? - rachel */ - return 0; - } else if (!str) { - /* - * value not recognised and there was a problem adding it to - * the unknown list - */ - unsigned len = 2 + 2 + 1; /* 2 for "0x", 2 for - * single octet in hex - * format, 1 for NUL */ - if ((str = calloc(1, len)) == NULL) { - (void) fprintf(stderr, "add_str_from_octet_map: bad alloc\n"); - return 0; - } - (void) snprintf(str, len, "0x%x", octet); - if (!add_str(&map->unknown, str)) { - return 0; - } - free(str); - } - return 1; -} - -/* ! generic function which adds text derived from single bit map to text */ -static unsigned -add_bitmap_entry(pgp_text_t *map, const char *str, uint8_t bit) -{ - - if (str && !add_str(&map->known, str)) { - /* - * value recognised, but there was a problem adding it to the - * list - */ - /* XXX - should print out error msg here, Ben? - rachel */ - return 0; - } else if (!str) { - /* - * value not recognised and there was a problem adding it to - * the unknown list - * 2 chars of the string are the format definition, this will - * be replaced in the output by 2 chars of hex, so the length - * will be correct - */ - char *newstr; - if (pgp_asprintf(&newstr, "Unknown bit(0x%x)", bit) == -1) { - (void) fprintf(stderr, "add_bitmap_entry: bad alloc\n"); - return 0; - } - if (!add_str(&map->unknown, newstr)) { - return 0; - } - free(newstr); - } - return 1; -} - -/** - * Produce a structure containing human-readable textstrings - * representing the recognised and unrecognised contents - * of this byte array. text_fn() will be called on each octet in turn. - * Each octet will generate one string representing the whole byte. - * - */ - -static pgp_text_t * -text_from_bytemapped_octets(const pgp_data_t *data, - const char *(*text_fn)(uint8_t octet)) -{ - pgp_text_t *text; - const char *str; - unsigned i; - - /* - * ! allocate and initialise pgp_text_t structure to store derived - * strings - */ - if ((text = calloc(1, sizeof(*text))) == NULL) { - return NULL; - } - - pgp_text_init(text); - - /* ! for each octet in field ... */ - for (i = 0; i < data->len; i++) { - /* ! derive string from octet */ - str = (*text_fn) (data->contents[i]); - - /* ! and add to text */ - if (!add_str_from_octet_map(text, netpgp_strdup(str), - data->contents[i])) { - pgp_text_free(text); - return NULL; - } - } - /* - * ! All values have been added to either the known or the unknown - * list - */ - return text; -} - -/** - * Produce a structure containing human-readable textstrings - * representing the recognised and unrecognised contents - * of this byte array, derived from each bit of each octet. - * - */ -static pgp_text_t * -showall_octets_bits(pgp_data_t *data, pgp_bit_map_t **map, size_t nmap) -{ - pgp_text_t *text; - const char *str; - unsigned i; - uint8_t mask, bit; - int j = 0; - - /* - * ! allocate and initialise pgp_text_t structure to store derived - * strings - */ - if ((text = calloc(1, sizeof(pgp_text_t))) == NULL) { - return NULL; - } - - pgp_text_init(text); - - /* ! for each octet in field ... */ - for (i = 0; i < data->len; i++) { - /* ! for each bit in octet ... */ - mask = 0x80; - for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) { - bit = data->contents[i] & mask; - if (bit) { - str = (i >= nmap) ? "Unknown" : - find_bitfield(map[i], bit); - if (!add_bitmap_entry(text, str, bit)) { - pgp_text_free(text); - return NULL; - } - } - } - } - return text; -} - /* * Public Functions */ @@ -655,22 +430,6 @@ pgp_show_ss_zpref(uint8_t octet) return pgp_str_from_map(octet, compression_alg_map); } -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Compression Algorithms - * \param ss_zpref Array of Preferred Compression Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -pgp_text_t * -pgp_showall_ss_zpref(const pgp_data_t *ss_zpref) -{ - return text_from_bytemapped_octets(ss_zpref, - &pgp_show_ss_zpref); -} - - /** * \ingroup Core_Print * @@ -684,21 +443,6 @@ pgp_show_hash_alg(uint8_t hash) return pgp_str_from_map(hash, hash_alg_map); } -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Hash Algorithms - * \param ss_hashpref Array of Preferred Hash Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -pgp_text_t * -pgp_showall_ss_hashpref(const pgp_data_t *ss_hashpref) -{ - return text_from_bytemapped_octets(ss_hashpref, - &pgp_show_hash_alg); -} - const char * pgp_show_symm_alg(uint8_t hash) { @@ -717,76 +461,6 @@ pgp_show_ss_skapref(uint8_t octet) return pgp_str_from_map(octet, symm_alg_map); } -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Symmetric Key Algorithms - * \param ss_skapref Array of Preferred Symmetric Key Algorithms - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -pgp_text_t * -pgp_showall_ss_skapref(const pgp_data_t *ss_skapref) -{ - return text_from_bytemapped_octets(ss_skapref, - &pgp_show_ss_skapref); -} - -/** - * \ingroup Core_Print - * returns description of one SS Feature - * \param octet - * \return string or "Unknown" -*/ -static const char * -show_ss_feature(uint8_t octet, unsigned offset) -{ - if (offset >= PGP_ARRAY_SIZE(ss_feature_map)) { - return "Unknown"; - } - return find_bitfield(ss_feature_map[offset], octet); -} - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given SS Features - * \param ss_features Signature Sub-Packet Features - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -/* XXX: shouldn't this use show_all_octets_bits? */ -pgp_text_t * -pgp_showall_ss_features(pgp_data_t ss_features) -{ - pgp_text_t *text; - const char *str; - unsigned i; - uint8_t mask, bit; - int j; - - if ((text = calloc(1, sizeof(*text))) == NULL) { - return NULL; - } - - pgp_text_init(text); - - for (i = 0; i < ss_features.len; i++) { - mask = 0x80; - for (j = 0; j < 8; j++, mask = (unsigned)mask >> 1) { - bit = ss_features.contents[i] & mask; - if (bit) { - str = show_ss_feature(bit, i); - if (!add_bitmap_entry(text, str, bit)) { - pgp_text_free(text); - return NULL; - } - } - } - } - return text; -} - /** * \ingroup Core_Print * returns description of SS Key Flag @@ -800,46 +474,6 @@ pgp_show_ss_key_flag(uint8_t octet, pgp_bit_map_t *map) return find_bitfield(map, octet); } -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given Preferred Key Flags - * \param ss_key_flags Array of Key Flags - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -pgp_text_t * -pgp_showall_ss_key_flags(const pgp_data_t *ss_key_flags) -{ - pgp_text_t *text; - const char *str; - uint8_t mask, bit; - int i; - - if ((text = calloc(1, sizeof(*text))) == NULL) { - return NULL; - } - - pgp_text_init(text); - - /* xxx - TBD: extend to handle multiple octets of bits - rachel */ - for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) { - bit = ss_key_flags->contents[0] & mask; - if (bit) { - str = pgp_show_ss_key_flag(bit, ss_key_flags_map); - if (!add_bitmap_entry(text, netpgp_strdup(str), bit)) { - pgp_text_free(text); - return NULL; - } - } - } - /* - * xxx - must add error text if more than one octet. Only one - * currently specified -- rachel - */ - return text; -} - /** * \ingroup Core_Print * @@ -855,60 +489,3 @@ pgp_show_keyserv_pref(uint8_t prefs, pgp_bit_map_t *map) return find_bitfield(map, prefs); } -/** - * \ingroup Core_Print - * returns set of descriptions of given Key Server Preferences - * \param ss_key_server_prefs - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - * -*/ -pgp_text_t * -pgp_show_keyserv_prefs(const pgp_data_t *prefs) -{ - pgp_text_t *text; - const char *str; - uint8_t mask, bit; - int i = 0; - - if ((text = calloc(1, sizeof(*text))) == NULL) { - return NULL; - } - - pgp_text_init(text); - - /* xxx - TBD: extend to handle multiple octets of bits - rachel */ - - for (i = 0, mask = 0x80; i < 8; i++, mask = (unsigned)mask >> 1) { - bit = prefs->contents[0] & mask; - if (bit) { - str = pgp_show_keyserv_pref(bit, - ss_key_server_prefs_map); - if (!add_bitmap_entry(text, netpgp_strdup(str), bit)) { - pgp_text_free(text); - return NULL; - } - } - } - /* - * xxx - must add error text if more than one octet. Only one - * currently specified -- rachel - */ - return text; -} - -/** - * \ingroup Core_Print - * - * returns set of descriptions of the given SS Notation Data Flags - * \param ss_notation Signature Sub-Packet Notation Data - * \return NULL if cannot allocate memory or other error - * \return pointer to structure, if no error - */ -pgp_text_t * -pgp_showall_notation(pgp_ss_notation_t ss_notation) -{ - return showall_octets_bits(&ss_notation.flags, - ss_notation_map, - PGP_ARRAY_SIZE(ss_notation_map)); -} diff --git a/libs/netpgp/reader.c b/libs/netpgp/src/reader.c similarity index 92% rename from libs/netpgp/reader.c rename to libs/netpgp/src/reader.c index d0afc748..68bc1a4d 100644 --- a/libs/netpgp/reader.c +++ b/libs/netpgp/src/reader.c @@ -46,7 +46,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -54,7 +54,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: reader.c,v 1.49 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -120,39 +120,20 @@ __RCSID("$NetBSD: reader.c,v 1.49 2012/03/05 02:20:18 christos Exp $"); #include #endif -#include "errors-netpgp.h" -#include "crypto-netpgp.h" -#include "create-netpgp.h" -#include "signature-netpgp.h" -#include "packet-netpgp.h" -#include "packet-parse.h" -#include "packet-show.h" -#include "keyring-netpgp.h" -#include "readerwriter-netpgp.h" -#include "netpgpsdk.h" -#include "netpgpdefs.h" -#include "netpgpdigest.h" +#include "netpgp/errors.h" +#include "netpgp/crypto.h" +#include "netpgp/create.h" +#include "netpgp/signature.h" +#include "netpgp/packet.h" +#include "netpgp/packet-parse.h" +#include "netpgp/packet-show.h" +#include "netpgp/packet.h" +#include "netpgp/keyring.h" +#include "netpgp/readerwriter.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/netpgpdigest.h" -/* data from partial blocks is queued up in virtual block in stream */ -static int -read_partial_data(pgp_stream_t *stream, void *dest, size_t length) -{ - unsigned n; - - if (pgp_get_debug_level(__FILE__)) { - (void) fprintf(stderr, "fd_reader: coalesced data, off %d\n", - stream->virtualoff); - } - n = MIN(stream->virtualc - stream->virtualoff, (unsigned)length); - (void) memcpy(dest, &stream->virtualpkt[stream->virtualoff], n); - stream->virtualoff += n; - if (stream->virtualoff == stream->virtualc) { - free(stream->virtualpkt); - stream->virtualpkt = NULL; - stream->virtualc = stream->virtualoff = 0; - } - return (int)n; -} /* get a pass phrase from the user */ int @@ -233,6 +214,10 @@ pgp_reader_pop(pgp_stream_t *stream) { pgp_reader_t *next = stream->readinfo.next; + if (stream->readinfo.accumulate && stream->readinfo.asize > 0) { + free(stream->readinfo.accumulated); + } + stream->readinfo = *next; free(next); } @@ -448,6 +433,9 @@ read_char(pgp_stream_t *stream, dearmour_t *dearmour, do { if (dearmour->pushbackc) { + if (!dearmour->pushback) { + return -1; + } c = dearmour->pushback[--dearmour->pushbackc]; if (dearmour->pushbackc == 0) { free(dearmour->pushback); @@ -844,8 +832,8 @@ read4(pgp_stream_t *stream, dearmour_t *dearmour, pgp_error_t **errors, pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo, int *pc, unsigned *pn, uint32_t *pl) { - int n, c; - uint32_t l = 0; + int n = 0, c = 0; + uint32_t l = 0; for (n = 0; n < 4; ++n) { c = read_char(stream, dearmour, errors, readinfo, cbinfo, 1); @@ -1398,7 +1386,7 @@ typedef struct { size_t off; pgp_crypt_t *decrypt; pgp_region_t *region; - unsigned prevplain:1; + // unsigned prevplain:1; } encrypted_t; static int @@ -1414,6 +1402,8 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest, encrypted = pgp_reader_get_arg(readinfo); saved = (int)length; + +#if 0 /* * V3 MPIs have the count plain and the cipher is reset after each * count @@ -1430,13 +1420,15 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest, readinfo->parent->reading_mpi_len) { encrypted->prevplain = 1; } +#endif + while (length > 0) { if (encrypted->c) { unsigned n; /* * if we are reading v3 we should never read - * more than we're asked for */ + * more than we're asked for if (length < encrypted->c && (readinfo->parent->reading_v3_secret || readinfo->parent->exact_read)) { @@ -1444,6 +1436,7 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest, "encrypted_data_reader: bad v3 read\n"); return 0; } + */ n = (int)MIN(length, encrypted->c); (void) memcpy(dest, encrypted->decrypted + encrypted->off, n); @@ -1475,18 +1468,19 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest, /* * we can only read as much as we're asked for * in v3 keys because they're partially - * unencrypted! */ + * unencrypted! if ((readinfo->parent->reading_v3_secret || readinfo->parent->exact_read) && n > length) { n = (unsigned)length; } + */ if (!pgp_stacked_limited_read(stream, buffer, n, encrypted->region, errors, readinfo, cbinfo)) { return -1; } - if (!readinfo->parent->reading_v3_secret || - !readinfo->parent->reading_mpi_len) { + //if (!readinfo->parent->reading_v3_secret || + // !readinfo->parent->reading_mpi_len) { encrypted->c = pgp_decrypt_se_ip(encrypted->decrypt, encrypted->decrypted, buffer, n); @@ -1495,11 +1489,11 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest, hexdump(stderr, "encrypted", buffer, 16); hexdump(stderr, "decrypted", encrypted->decrypted, 16); } - } else { - (void) memcpy( - &encrypted->decrypted[encrypted->off], buffer, n); - encrypted->c = n; - } + //} else { + // (void) memcpy( + //&encrypted->decrypted[encrypted->off], buffer, n); + //encrypted->c = n; + //} if (encrypted->c == 0) { (void) fprintf(stderr, @@ -1780,11 +1774,9 @@ fd_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors, __PGP_USED(cbinfo); reader = pgp_reader_get_arg(readinfo); - if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) { - n = read_partial_data(stream, dest, length); - } else { - n = (int)read(reader->fd, dest, length); - } + + n = (int)read(reader->fd, dest, length); + if (n == 0) { return 0; } @@ -1837,20 +1829,18 @@ mem_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors __PGP_USED(cbinfo); __PGP_USED(errors); - if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) { - n = read_partial_data(stream, dest, length); - } else { - if (reader->offset + length > reader->length) { - n = (unsigned)(reader->length - reader->offset); - } else { - n = (unsigned)length; - } - if (n == (unsigned)0) { - return 0; - } - memcpy(dest, reader->buffer + reader->offset, n); - reader->offset += n; - } + + if (reader->offset + length > reader->length) { + n = (unsigned)(reader->length - reader->offset); + } else { + n = (unsigned)length; + } + if (n == (unsigned)0) { + return 0; + } + memcpy(dest, reader->buffer + reader->offset, n); + reader->offset += n; + return n; } @@ -2124,7 +2114,7 @@ pgp_litdata_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) if (pgp_get_debug_level(__FILE__)) { printf("pgp_litdata_cb: "); - pgp_print_packet(&cbinfo->printstate, pkt); + //pgp_print_packet(&cbinfo->printstate, pkt); } /* Read data from packet into static buffer */ switch (pkt->tag) { @@ -2161,7 +2151,7 @@ pgp_pk_sesskey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) io = cbinfo->io; if (pgp_get_debug_level(__FILE__)) { - pgp_print_packet(&cbinfo->printstate, pkt); + //pgp_print_packet(&cbinfo->printstate, pkt); } /* Read data from packet into static buffer */ switch (pkt->tag) { @@ -2177,7 +2167,8 @@ pgp_pk_sesskey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) from = 0; cbinfo->cryptinfo.keydata = pgp_getkeybyid(io, cbinfo->cryptinfo.secring, - content->pk_sesskey.key_id, &from, NULL); + content->pk_sesskey.key_id, &from, NULL, NULL, + 0, 0); /* accepts revoked and expired */ if (!cbinfo->cryptinfo.keydata) { break; } @@ -2208,55 +2199,67 @@ pgp_cb_ret_t pgp_get_seckey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) { const pgp_contents_t *content = &pkt->u; - const pgp_seckey_t *secret; - const pgp_key_t *pubkey; - const pgp_key_t *keypair; + pgp_seckey_t *secret; + // const pgp_key_t *pubkey; + //const pgp_key_t *keypair; unsigned from; pgp_io_t *io; - int i; + //int i; + + pgp_cryptinfo_t *cryptinfo = &cbinfo->cryptinfo; + key_id_t *key_id; io = cbinfo->io; if (pgp_get_debug_level(__FILE__)) { - pgp_print_packet(&cbinfo->printstate, pkt); + //pgp_print_packet(&cbinfo->printstate, pkt); } switch (pkt->tag) { case PGP_GET_SECKEY: /* print key from pubring */ - from = 0; - pubkey = pgp_getkeybyid(io, cbinfo->cryptinfo.pubring, - content->get_seckey.pk_sesskey->key_id, - &from, NULL); - /* validate key from secring */ + // from = 0; + // pubkey = pgp_getkeybyid(io, cbinfo->cryptinfo.pubring, + // content->get_seckey.pk_sesskey->key_id, + // &from, NULL); + // /* validate key from secring */ + + EXPAND_ARRAY(cryptinfo, recipients_key_ids); + key_id = &cryptinfo->recipients_key_idss[cryptinfo->recipients_key_idsc++]; + memcpy(key_id, content->get_seckey.pk_sesskey->key_id, sizeof(key_id_t)); + from = 0; cbinfo->cryptinfo.keydata = pgp_getkeybyid(io, cbinfo->cryptinfo.secring, content->get_seckey.pk_sesskey->key_id, - &from, NULL); + &from, NULL, &secret, 0, 0); if (!cbinfo->cryptinfo.keydata || + !secret || !pgp_is_key_secret(cbinfo->cryptinfo.keydata)) { return (pgp_cb_ret_t)0; } - keypair = cbinfo->cryptinfo.keydata; - if (pubkey == NULL) { - pubkey = keypair; - } - secret = NULL; - cbinfo->gotpass = 0; - for (i = 0 ; cbinfo->numtries == -1 || i < cbinfo->numtries ; i++) { - /* print out the user id */ - pgp_print_keydata(io, cbinfo->cryptinfo.pubring, pubkey, - "signature ", &pubkey->key.pubkey, 0); - /* now decrypt key */ - secret = pgp_decrypt_seckey(keypair, cbinfo->passfp); - if (secret != NULL) { - break; - } - (void) fprintf(io->errs, "Bad passphrase\n"); - } - if (secret == NULL) { - (void) fprintf(io->errs, "Exhausted passphrase attempts\n"); - return (pgp_cb_ret_t)PGP_RELEASE_MEMORY; - } + + // FIXME : support encrypted seckeys again + // keypair = cbinfo->cryptinfo.keydata; + // if (pubkey == NULL) { + // pubkey = keypair; + // } + // secret = NULL; + // cbinfo->gotpass = 0; + // for (i = 0 ; cbinfo->numtries == -1 || i < cbinfo->numtries ; i++) { + // /* print out the user id */ + // pgp_print_keydata(io, cbinfo->cryptinfo.pubring, pubkey, + // "signature ", &pubkey->key.pubkey, 0); + // /* now decrypt key */ + // pgp_decrypt_seckey(keypair, cbinfo->passfp); + // if (secret != NULL) { + // break; + // } + // (void) fprintf(io->errs, "Bad passphrase\n"); + // } + // if (secret == NULL) { + // (void) fprintf(io->errs, "Exhausted passphrase attempts\n"); + // return (pgp_cb_ret_t)PGP_RELEASE_MEMORY; + // } + cbinfo->gotpass = 1; *content->get_seckey.seckey = secret; break; @@ -2268,39 +2271,6 @@ pgp_get_seckey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) return PGP_RELEASE_MEMORY; } -/** - \ingroup HighLevel_Callbacks - \brief Callback to use when you need to prompt user for passphrase - \param contents - \param cbinfo -*/ -pgp_cb_ret_t -get_passphrase_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) -{ - const pgp_contents_t *content = &pkt->u; - pgp_io_t *io; - - io = cbinfo->io; - if (pgp_get_debug_level(__FILE__)) { - pgp_print_packet(&cbinfo->printstate, pkt); - } - if (cbinfo->cryptinfo.keydata == NULL) { - (void) fprintf(io->errs, "get_passphrase_cb: NULL keydata\n"); - } else { - pgp_print_keydata(io, cbinfo->cryptinfo.pubring, cbinfo->cryptinfo.keydata, "signature ", - &cbinfo->cryptinfo.keydata->key.pubkey, 0); - } - switch (pkt->tag) { - case PGP_GET_PASSPHRASE: - *(content->skey_passphrase.passphrase) = - netpgp_strdup(getpass("netpgp passphrase: ")); - return PGP_KEEP_MEMORY; - default: - break; - } - return PGP_RELEASE_MEMORY; -} - unsigned pgp_reader_set_accumulate(pgp_stream_t *stream, unsigned state) { @@ -2363,15 +2333,12 @@ mmap_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **error __PGP_USED(errors); __PGP_USED(cbinfo); - if (!stream->coalescing && stream->virtualc && stream->virtualoff < stream->virtualc) { - n = read_partial_data(stream, dest, length); - } else { - n = (unsigned)MIN(length, (unsigned)(mem->size - mem->offset)); - if (n > 0) { - (void) memcpy(dest, &cmem[(int)mem->offset], (unsigned)n); - mem->offset += n; - } - } + + n = (unsigned)MIN(length, (unsigned)(mem->size - mem->offset)); + if (n > 0) { + (void) memcpy(dest, &cmem[(int)mem->offset], (unsigned)n); + mem->offset += n; + } return (int)n; } diff --git a/libs/netpgp/signature.c b/libs/netpgp/src/signature.c similarity index 84% rename from libs/netpgp/signature.c rename to libs/netpgp/src/signature.c index e9887582..94a4366c 100644 --- a/libs/netpgp/signature.c +++ b/libs/netpgp/src/signature.c @@ -49,7 +49,7 @@ /** \file */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -57,7 +57,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: signature.c,v 1.34 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -77,29 +77,16 @@ __RCSID("$NetBSD: signature.c,v 1.34 2012/03/05 02:20:18 christos Exp $"); #include #endif -#include "signature-netpgp.h" -#include "crypto-netpgp.h" -#include "create-netpgp.h" -#include "netpgpsdk.h" -#include "readerwriter-netpgp.h" -#include "validate-netpgp.h" -#include "netpgpdefs.h" -#include "netpgpdigest.h" +#include "netpgp/signature.h" +#include "netpgp/crypto.h" +#include "netpgp/create.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/readerwriter.h" +#include "netpgp/validate.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/netpgpdigest.h" -/** \ingroup Core_Create - * needed for signature creation - */ -struct pgp_create_sig_t { - pgp_hash_t hash; - pgp_sig_t sig; - pgp_memory_t *mem; - pgp_output_t *output; /* how to do the writing */ - unsigned hashoff; /* hashed count offset */ - unsigned hashlen; - unsigned unhashoff; -}; - /** \ingroup Core_Signature Creates new pgp_create_sig_t @@ -149,6 +136,11 @@ static uint8_t prefix_sha256[] = { 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; +static uint8_t prefix_sha512[] = { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 +}; /* XXX: both this and verify would be clearer if the signature were */ /* treated as an MPI. */ @@ -174,11 +166,16 @@ rsa_sign(pgp_hash_t *hash, prefix = prefix_sha1; prefixsize = sizeof(prefix_sha1); expected = PGP_SHA1_HASH_SIZE; - } else { + } else if (strcmp(hash->name, "SHA256") == 0) { hashsize = PGP_SHA256_HASH_SIZE + sizeof(prefix_sha256); prefix = prefix_sha256; prefixsize = sizeof(prefix_sha256); expected = PGP_SHA256_HASH_SIZE; + } else { + hashsize = PGP_SHA512_HASH_SIZE + sizeof(prefix_sha512); + prefix = prefix_sha512; + prefixsize = sizeof(prefix_sha512); + expected = PGP_SHA512_HASH_SIZE; } keysize = (BN_num_bits(pubrsa->n) + 7) / 8; if (keysize > sizeof(hashbuf)) { @@ -231,7 +228,7 @@ dsa_sign(pgp_hash_t *hash, unsigned hashsize; unsigned t; uint8_t hashbuf[NETPGP_BUFSIZ]; - DSA_SIG *dsasig; + pgp_dsa_sig_t *pgpdsasig; /* hashsize must be "equal in size to the number of bits of q, */ /* the group generated by the DSA key's generator value */ @@ -249,12 +246,18 @@ dsa_sign(pgp_hash_t *hash, pgp_write(output, &hashbuf[0], 2); /* write signature to buf */ - dsasig = pgp_dsa_sign(hashbuf, hashsize, sdsa, dsa); + pgpdsasig = pgp_dsa_sign(hashbuf, hashsize, sdsa, dsa); + + if(pgpdsasig == NULL) + return 0; /* convert and write the sig out to memory */ - pgp_write_mpi(output, dsasig->r); - pgp_write_mpi(output, dsasig->s); - DSA_SIG_free(dsasig); + pgp_write_mpi(output, pgpdsasig->r); + pgp_write_mpi(output, pgpdsasig->s); + + BN_free(pgpdsasig->r); + BN_free(pgpdsasig->s); + free(pgpdsasig); return 1; } @@ -273,8 +276,6 @@ rsa_verify(pgp_hash_alg_t type, uint8_t sigbuf[NETPGP_BUFSIZ]; uint8_t hashbuf_from_sig[NETPGP_BUFSIZ]; - plen = 0; - prefix = (const uint8_t *) ""; keysize = BN_num_bytes(pubrsa->n); /* RSA key can't be bigger than 65535 bits, so... */ if (keysize > sizeof(hashbuf_from_sig)) { @@ -315,6 +316,10 @@ rsa_verify(pgp_hash_alg_t type, prefix = prefix_sha256; plen = sizeof(prefix_sha256); break; + case PGP_HASH_SHA512: + prefix = prefix_sha512; + plen = sizeof(prefix_sha512); + break; default: (void) fprintf(stderr, "Unknown hash algorithm: %d\n", type); return 0; @@ -356,6 +361,7 @@ hash_add_key(pgp_hash_t *hash, const pgp_pubkey_t *key) pgp_hash_add_int(hash, 0x99, 1); pgp_hash_add_int(hash, (unsigned)len, 2); hash->add(hash, pgp_mem_data(mem), (unsigned)len); + pgp_memory_free(mem); } @@ -380,12 +386,11 @@ init_key_sig(pgp_hash_t *hash, const pgp_sig_t *sig, } static void -hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig, - const uint8_t *raw_packet) +hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig) { if (sig->info.version == PGP_V4) { - if (raw_packet) { - hash->add(hash, raw_packet + sig->v4_hashstart, + if (sig->info.v4_hashlen) { + hash->add(hash, sig->info.v4_hashed, (unsigned)sig->info.v4_hashlen); } pgp_hash_add_int(hash, (unsigned)sig->info.version, 1); @@ -416,8 +421,8 @@ pgp_check_sig(const uint8_t *hash, unsigned length, if (pgp_get_debug_level(__FILE__)) { hexdump(stdout, "hash", hash, length); } - ret = 0; - switch (sig->info.key_alg) { + + switch (sig->info.key_alg) { case PGP_PKA_DSA: ret = pgp_dsa_verify(hash, length, &sig->info.sig.dsa, &signer->key.dsa); @@ -452,10 +457,9 @@ hash_and_check_sig(pgp_hash_t *hash, static unsigned finalise_sig(pgp_hash_t *hash, const pgp_sig_t *sig, - const pgp_pubkey_t *signer, - const uint8_t *raw_packet) + const pgp_pubkey_t *signer) { - hash_add_trailer(hash, sig, raw_packet); + hash_add_trailer(hash, sig); return hash_and_check_sig(hash, sig, signer); } @@ -475,8 +479,7 @@ unsigned pgp_check_useridcert_sig(const pgp_pubkey_t *key, const uint8_t *id, const pgp_sig_t *sig, - const pgp_pubkey_t *signer, - const uint8_t *raw_packet) + const pgp_pubkey_t *signer) { pgp_hash_t hash; size_t userid_len; @@ -488,7 +491,7 @@ pgp_check_useridcert_sig(const pgp_pubkey_t *key, pgp_hash_add_int(&hash, (unsigned)userid_len, 4); } hash.add(&hash, id, (unsigned)userid_len); - return finalise_sig(&hash, sig, signer, raw_packet); + return finalise_sig(&hash, sig, signer); } /** @@ -507,8 +510,7 @@ unsigned pgp_check_userattrcert_sig(const pgp_pubkey_t *key, const pgp_data_t *attribute, const pgp_sig_t *sig, - const pgp_pubkey_t *signer, - const uint8_t *raw_packet) + const pgp_pubkey_t *signer) { pgp_hash_t hash; @@ -518,7 +520,7 @@ pgp_check_userattrcert_sig(const pgp_pubkey_t *key, pgp_hash_add_int(&hash, (unsigned)attribute->len, 4); } hash.add(&hash, attribute->contents, (unsigned)attribute->len); - return finalise_sig(&hash, sig, signer, raw_packet); + return finalise_sig(&hash, sig, signer); } /** @@ -537,15 +539,14 @@ unsigned pgp_check_subkey_sig(const pgp_pubkey_t *key, const pgp_pubkey_t *subkey, const pgp_sig_t *sig, - const pgp_pubkey_t *signer, - const uint8_t *raw_packet) + const pgp_pubkey_t *signer) { pgp_hash_t hash; unsigned ret; init_key_sig(&hash, sig, key); hash_add_key(&hash, subkey); - ret = finalise_sig(&hash, sig, signer, raw_packet); + ret = finalise_sig(&hash, sig, signer); return ret; } @@ -563,14 +564,13 @@ pgp_check_subkey_sig(const pgp_pubkey_t *key, unsigned pgp_check_direct_sig(const pgp_pubkey_t *key, const pgp_sig_t *sig, - const pgp_pubkey_t *signer, - const uint8_t *raw_packet) + const pgp_pubkey_t *signer) { pgp_hash_t hash; unsigned ret; init_key_sig(&hash, sig, key); - ret = finalise_sig(&hash, sig, signer, raw_packet); + ret = finalise_sig(&hash, sig, signer); return ret; } @@ -592,7 +592,7 @@ pgp_check_hash_sig(pgp_hash_t *hash, const pgp_pubkey_t *signer) { return (sig->info.hash_alg == hash->alg) ? - finalise_sig(hash, sig, signer, NULL) : + finalise_sig(hash, sig, signer) : 0; } @@ -649,6 +649,22 @@ pgp_sig_start_key_sig(pgp_create_sig_t *sig, start_sig_in_mem(sig); } +void +pgp_sig_start_key_rev(pgp_create_sig_t *sig, + const pgp_pubkey_t *key, + pgp_sig_type_t type) +{ + sig->output = pgp_output_new(); + + sig->sig.info.version = PGP_V4; + sig->sig.info.hash_alg = PGP_HASH_SHA1; + sig->sig.info.key_alg = key->alg; + sig->sig.info.type = type; + sig->hashlen = (unsigned)-1; + init_key_sig(&sig->hash, &sig->sig, key); + start_sig_in_mem(sig); +} + /** * \ingroup Core_Signature * @@ -831,17 +847,100 @@ pgp_write_sig(pgp_output_t *output, return ret; } -/* add a time stamp to the output */ unsigned -pgp_add_time(pgp_create_sig_t *sig, int64_t when, const char *type) +pgp_add_creation_time(pgp_create_sig_t *sig, time_t when) { pgp_content_enum tag; - tag = (strcmp(type, "birth") == 0) ? - PGP_PTAG_SS_CREATION_TIME : PGP_PTAG_SS_EXPIRATION_TIME; - /* just do 32-bit timestamps for just now - it's in the protocol */ + tag = PGP_PTAG_SS_CREATION_TIME; + + sig->sig.info.birthtime = when; + sig->sig.info.birthtime_set = 1; + + return pgp_write_ss_header(sig->output, 5, tag) && + pgp_write_scalar(sig->output, (unsigned int)when, 4); +} + +unsigned +pgp_add_sig_expiration_time(pgp_create_sig_t *sig, time_t duration) +{ + pgp_content_enum tag; + + tag = PGP_PTAG_SS_EXPIRATION_TIME; + + sig->sig.info.duration = duration; + sig->sig.info.duration_set = 1; + + return pgp_write_ss_header(sig->output, 5, tag) && + pgp_write_scalar(sig->output, (unsigned int)duration, 4); +} + +unsigned +pgp_add_key_expiration_time(pgp_create_sig_t *sig, time_t duration) +{ + pgp_content_enum tag; + + tag = PGP_PTAG_SS_KEY_EXPIRY; + + sig->sig.info.key_expiry = duration; + sig->sig.info.key_expiry_set = 1; + return pgp_write_ss_header(sig->output, 5, tag) && - pgp_write_scalar(sig->output, (uint32_t)when, (unsigned)sizeof(uint32_t)); + pgp_write_scalar(sig->output, (unsigned int)duration, 4); +} + +unsigned +pgp_add_key_flags(pgp_create_sig_t *sig, uint8_t flags) +{ + pgp_content_enum tag; + + tag = PGP_PTAG_SS_KEY_FLAGS; + + sig->sig.info.key_flags = flags; + sig->sig.info.key_flags_set = 1; + + return pgp_write_ss_header(sig->output, 2, tag) && + pgp_write_scalar(sig->output, (unsigned int)flags, 1); +} + +unsigned +pgp_add_key_prefs(pgp_create_sig_t *sig) +{ + + /* Mimic of GPG default settings, limited to supported algos */ + + return + /* Symmetric algo prefs */ + pgp_write_ss_header(sig->output, 6, PGP_PTAG_SS_PREFERRED_SKA) && + pgp_write_scalar(sig->output, PGP_SA_AES_256, 1) && + pgp_write_scalar(sig->output, PGP_SA_AES_128, 1) && + pgp_write_scalar(sig->output, PGP_SA_CAST5, 1) && + pgp_write_scalar(sig->output, PGP_SA_TRIPLEDES, 1) && + pgp_write_scalar(sig->output, PGP_SA_IDEA, 1) && + + /* Hash algo prefs */ + pgp_write_ss_header(sig->output, 6, PGP_PTAG_SS_PREFERRED_HASH) && + pgp_write_scalar(sig->output, PGP_HASH_SHA256, 1) && + pgp_write_scalar(sig->output, PGP_HASH_SHA1, 1) && + pgp_write_scalar(sig->output, PGP_HASH_SHA384, 1) && + pgp_write_scalar(sig->output, PGP_HASH_SHA512, 1) && + pgp_write_scalar(sig->output, PGP_HASH_SHA224, 1) && + + /* Compression algo prefs */ + pgp_write_ss_header(sig->output, 3, PGP_PTAG_SS_PREF_COMPRESS) && + pgp_write_scalar(sig->output, PGP_C_ZLIB, 1) && + pgp_write_scalar(sig->output, PGP_C_BZIP2, 1); +} + +unsigned +pgp_add_key_features(pgp_create_sig_t *sig) +{ + pgp_content_enum tag; + + tag = PGP_PTAG_SS_FEATURES; + + return pgp_write_ss_header(sig->output, 2, tag) && + pgp_write_scalar(sig->output, 0x01, 1); } /** @@ -877,6 +976,19 @@ pgp_add_primary_userid(pgp_create_sig_t *sig, unsigned primary) pgp_write_scalar(sig->output, primary, 1); } +unsigned +pgp_add_revocation_reason( + pgp_create_sig_t *sig, + uint8_t code, const char *reason) +{ + size_t rlen = reason ? strlen(reason) : 0; + return pgp_write_ss_header( + sig->output, rlen + 1, + PGP_PTAG_SS_REVOCATION_REASON) && + pgp_write_scalar(sig->output, code, 1) && + pgp_write(sig->output, reason, (unsigned int)rlen); +} + /** * \ingroup Core_Signature * @@ -937,8 +1049,8 @@ pgp_sign_file(pgp_io_t *io, const char *outname, const pgp_seckey_t *seckey, const char *hashname, - const int64_t from, - const uint64_t duration, + const time_t from, + const time_t duration, const unsigned armored, const unsigned cleartext, const unsigned overwrite) @@ -958,7 +1070,6 @@ pgp_sign_file(pgp_io_t *io, infile = NULL; output = NULL; hash = NULL; - fd_out = 0; /* find the hash algorithm */ hash_alg = pgp_str_to_hash_alg(hashname); @@ -1006,8 +1117,8 @@ pgp_sign_file(pgp_io_t *io, /* - creation time */ /* - key id */ ret = pgp_writer_use_armored_sig(output) && - pgp_add_time(sig, (int64_t)from, "birth") && - pgp_add_time(sig, (int64_t)duration, "expiration"); + pgp_add_creation_time(sig, from) && + pgp_add_sig_expiration_time(sig, duration); if (ret == 0) { pgp_teardown_file_write(output, fd_out); return 0; @@ -1053,8 +1164,8 @@ pgp_sign_file(pgp_io_t *io, #endif /* add creation time to signature */ - pgp_add_time(sig, (int64_t)from, "birth"); - pgp_add_time(sig, (int64_t)duration, "expiration"); + pgp_add_creation_time(sig, from); + pgp_add_sig_expiration_time(sig, duration); /* add key id to signature */ pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg); pgp_add_issuer_keyid(sig, keyid); @@ -1090,8 +1201,8 @@ pgp_sign_buf(pgp_io_t *io, const void *input, const size_t insize, const pgp_seckey_t *seckey, - const int64_t from, - const uint64_t duration, + const time_t from, + const time_t duration, const char *hashname, const unsigned armored, const unsigned cleartext) @@ -1111,7 +1222,6 @@ pgp_sign_buf(pgp_io_t *io, output = NULL; mem = pgp_memory_new(); hash = NULL; - ret = 0; hash_alg = pgp_str_to_hash_alg(hashname); if (hash_alg == PGP_HASH_UNKNOWN) { @@ -1147,8 +1257,8 @@ pgp_sign_buf(pgp_io_t *io, ret = pgp_writer_push_clearsigned(output, sig) && pgp_write(output, input, (unsigned)insize) && pgp_writer_use_armored_sig(output) && - pgp_add_time(sig, from, "birth") && - pgp_add_time(sig, (int64_t)duration, "expiration"); + pgp_add_creation_time(sig, from) && + pgp_add_sig_expiration_time(sig, duration); if (ret == 0) { return NULL; } @@ -1178,8 +1288,8 @@ pgp_sign_buf(pgp_io_t *io, } /* add creation time to signature */ - pgp_add_time(sig, from, "birth"); - pgp_add_time(sig, (int64_t)duration, "expiration"); + pgp_add_creation_time(sig, from); + pgp_add_sig_expiration_time(sig, duration); /* add key id to signature */ pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg); pgp_add_issuer_keyid(sig, keyid); @@ -1200,10 +1310,10 @@ int pgp_sign_detached(pgp_io_t *io, const char *f, char *sigfile, - pgp_seckey_t *seckey, + const pgp_seckey_t *seckey, const char *hash, - const int64_t from, - const uint64_t duration, + const time_t from, + const time_t duration, const unsigned armored, const unsigned overwrite) { pgp_create_sig_t *sig; @@ -1246,14 +1356,13 @@ pgp_sign_detached(pgp_io_t *io, pgp_memory_free(mem); /* calculate the signature */ - pgp_add_time(sig, from, "birth"); - pgp_add_time(sig, (int64_t)duration, "expiration"); + pgp_add_creation_time(sig, from); + pgp_add_sig_expiration_time(sig, duration); pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg); pgp_add_issuer_keyid(sig, keyid); pgp_end_hashed_subpkts(sig); pgp_write_sig(output, sig, &seckey->pubkey, seckey); pgp_teardown_file_write(output, fd); - pgp_seckey_free(seckey); return 1; } diff --git a/libs/netpgp/symmetric.c b/libs/netpgp/src/symmetric.c similarity index 98% rename from libs/netpgp/symmetric.c rename to libs/netpgp/src/symmetric.c index bacdc4c9..033d1d04 100644 --- a/libs/netpgp/symmetric.c +++ b/libs/netpgp/src/symmetric.c @@ -46,7 +46,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -54,11 +54,11 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: symmetric.c,v 1.18 2010/11/07 08:39:59 agc Exp $"); +__RCSID("$NetBSD$"); #endif -#include "crypto-netpgp.h" -#include "packet-show.h" +#include "netpgp/crypto.h" +#include "netpgp/packet-show.h" #include @@ -82,8 +82,8 @@ __RCSID("$NetBSD: symmetric.c,v 1.18 2010/11/07 08:39:59 agc Exp $"); #include #endif -#include "crypto-netpgp.h" -#include "netpgpdefs.h" +#include "netpgp/crypto.h" +#include "netpgp/netpgpdefs.h" static void diff --git a/libs/netpgp/validate.c b/libs/netpgp/src/validate.c similarity index 54% rename from libs/netpgp/validate.c rename to libs/netpgp/src/validate.c index 3f07a882..084a96c6 100644 --- a/libs/netpgp/validate.c +++ b/libs/netpgp/src/validate.c @@ -46,7 +46,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -54,7 +54,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: validate.c,v 1.44 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -72,76 +72,67 @@ __RCSID("$NetBSD: validate.c,v 1.44 2012/03/05 02:20:18 christos Exp $"); #include #endif -#include "packet-parse.h" -#include "packet-show.h" -#include "keyring-netpgp.h" -#include "signature-netpgp.h" -#include "netpgpsdk.h" -#include "readerwriter-netpgp.h" -#include "netpgpdefs.h" -#include "memory-netpgp.h" -#include "packet-netpgp.h" -#include "crypto-netpgp.h" -#include "validate-netpgp.h" +#include "netpgp/packet-parse.h" +#include "netpgp/packet-show.h" +#include "netpgp/keyring.h" +#include "netpgp/signature.h" +#include "netpgp/netpgpsdk.h" +#include "netpgp/readerwriter.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/memory.h" +#include "netpgp/packet.h" +#include "netpgp/crypto.h" +#include "netpgp/validate.h" #ifdef HAVE_FCNTL_H #include #endif - -static int -keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors, - pgp_reader_t *readinfo, - pgp_cbdata_t *cbinfo) -{ - validate_reader_t *reader = pgp_reader_get_arg(readinfo); - - __PGP_USED(stream); - __PGP_USED(errors); - __PGP_USED(cbinfo); - if (reader->offset == reader->key->packets[reader->packet].length) { - reader->packet += 1; - reader->offset = 0; - } - if (reader->packet == reader->key->packetc) { - return 0; - } - - /* - * we should never be asked to cross a packet boundary in a single - * read - */ - if (reader->key->packets[reader->packet].length < - reader->offset + length) { - (void) fprintf(stderr, "keydata_reader: weird length\n"); - return 0; - } - - (void) memcpy(dest, - &reader->key->packets[reader->packet].raw[reader->offset], - length); - reader->offset += (unsigned)length; - - return (int)length; -} +// FIXME to support seckey decryption again. +// +// static int +// keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors, +// pgp_reader_t *readinfo, +// pgp_cbdata_t *cbinfo) +// { +// validate_reader_t *reader = pgp_reader_get_arg(readinfo); +// +// __PGP_USED(stream); +// __PGP_USED(errors); +// __PGP_USED(cbinfo); +// if (reader->offset == reader->key->packets[reader->packet].length) { +// reader->packet += 1; +// reader->offset = 0; +// } +// if (reader->packet == reader->key->packetc) { +// return 0; +// } +// +// /* +// * we should never be asked to cross a packet boundary in a single +// * read +// */ +// if (reader->key->packets[reader->packet].length < +// reader->offset + length) { +// (void) fprintf(stderr, "keydata_reader: weird length\n"); +// return 0; +// } +// +// (void) memcpy(dest, +// &reader->key->packets[reader->packet].raw[reader->offset], +// length); +// reader->offset += (unsigned)length; +// +// return (int)length; +// } static void free_sig_info(pgp_sig_info_t *sig) { - free(sig->v4_hashed); + pgp_free_sig_info(sig); free(sig); } -static void -copy_sig_info(pgp_sig_info_t *dst, const pgp_sig_info_t *src) -{ - (void) memcpy(dst, src, sizeof(*src)); - if ((dst->v4_hashed = calloc(1, src->v4_hashlen)) == NULL) { - (void) fprintf(stderr, "copy_sig_info: bad alloc\n"); - } else { - (void) memcpy(dst->v4_hashed, src->v4_hashed, src->v4_hashlen); - } -} static int add_sig_to_list(const pgp_sig_info_t *sig, pgp_sig_info_t **sigs, @@ -232,16 +223,36 @@ check_binary_sig(const uint8_t *data, return pgp_check_sig(hashout, n, sig, signer); } +static void validate_key_cb_free (validate_key_cb_t *vdata){ + + /* Free according to previous allocated type */ + if (vdata->type == PGP_PTAG_CT_PUBLIC_KEY) { + pgp_pubkey_free(&vdata->key.pubkey); + pgp_pubkey_free(&vdata->subkey.pubkey); + } else if (vdata->type == PGP_PTAG_CT_SECRET_KEY) { + pgp_seckey_free(&vdata->key.seckey); + if(vdata->subkey.seckey.pubkey.alg) + pgp_seckey_free(&vdata->subkey.seckey); + } + memset(&vdata->key, 0, sizeof(vdata->key)); + memset(&vdata->subkey, 0, sizeof(vdata->subkey)); + vdata->type = PGP_PTAG_CT_RESERVED; /* 0 */ + + pgp_userid_free(&vdata->userid); + pgp_data_free(&vdata->userattr); + + if(vdata->valid_sig_info.key_alg) { + pgp_free_sig_info(&vdata->valid_sig_info); + } +} + pgp_cb_ret_t pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) { const pgp_contents_t *content = &pkt->u; - const pgp_key_t *signer; - validate_key_cb_t *key; - pgp_pubkey_t *sigkey; + validate_key_cb_t *vdata; pgp_error_t **errors; pgp_io_t *io; - unsigned from; unsigned valid = 0; io = cbinfo->io; @@ -249,175 +260,270 @@ pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) (void) fprintf(io->errs, "%s\n", pgp_show_packet_tag(pkt->tag)); } - key = pgp_callback_arg(cbinfo); + vdata = pgp_callback_arg(cbinfo); errors = pgp_callback_errors(cbinfo); + + vdata->sig_is_valid &= pkt->tag == PGP_PARSER_PACKET_END; + switch (pkt->tag) { case PGP_PTAG_CT_PUBLIC_KEY: - if (key->pubkey.version != 0) { - (void) fprintf(io->errs, - "pgp_validate_key_cb: version bad\n"); - return PGP_FINISHED; - } - key->pubkey = content->pubkey; - return PGP_KEEP_MEMORY; + validate_key_cb_free(vdata); + vdata->key.pubkey = content->pubkey; + pgp_keyid(vdata->pubkeyid, PGP_KEY_ID_SIZE, + &vdata->key.pubkey, PGP_HASH_SHA1); /* TODO v3*/ - case PGP_PTAG_CT_PUBLIC_SUBKEY: - if (key->subkey.version) { - pgp_pubkey_free(&key->subkey); - } - key->subkey = content->pubkey; + vdata->last_seen = LS_PRIMARY; + vdata->type = PGP_PTAG_CT_PUBLIC_KEY; + vdata->not_commited = 1; return PGP_KEEP_MEMORY; case PGP_PTAG_CT_SECRET_KEY: - key->seckey = content->seckey; - key->pubkey = key->seckey.pubkey; + /* TODO + * check pubkey seckey consistency */ + validate_key_cb_free(vdata); + vdata->key.seckey = content->seckey; + pgp_keyid(vdata->pubkeyid, PGP_KEY_ID_SIZE, + &vdata->key.seckey.pubkey, PGP_HASH_SHA1); /* TODO v3*/ + vdata->last_seen = LS_PRIMARY; + vdata->type = PGP_PTAG_CT_SECRET_KEY; + vdata->not_commited = 1; return PGP_KEEP_MEMORY; + case PGP_PTAG_CT_PUBLIC_SUBKEY: + if(vdata->type == PGP_PTAG_CT_PUBLIC_KEY && ( + vdata->last_seen == LS_ID || + vdata->last_seen == LS_ATTRIBUTE)){ + pgp_pubkey_free(&vdata->subkey.pubkey); + vdata->subkey.pubkey = content->pubkey; + vdata->last_seen = LS_SUBKEY; + return PGP_KEEP_MEMORY; + }else{ + (void) fprintf(io->errs, + "pgp_validate_key_cb: unexpected public subkey packet"); + vdata->last_seen = LS_UNKNOWN; + return PGP_RELEASE_MEMORY; + } + + case PGP_PTAG_CT_SECRET_SUBKEY: + /* TODO + * check pubkey seckey consistency */ + if(vdata->type == PGP_PTAG_CT_SECRET_KEY && ( + vdata->last_seen == LS_ID || + vdata->last_seen == LS_ATTRIBUTE)){ + if(vdata->subkey.seckey.pubkey.alg) + pgp_seckey_free(&vdata->subkey.seckey); + vdata->subkey.seckey = content->seckey; + vdata->last_seen = LS_SUBKEY; + return PGP_KEEP_MEMORY; + }else{ + (void) fprintf(io->errs, + "pgp_validate_key_cb: unexpected secret subkey packet"); + vdata->last_seen = LS_UNKNOWN; + return PGP_RELEASE_MEMORY; + } + case PGP_PTAG_CT_USER_ID: - if (key->userid) { - pgp_userid_free(&key->userid); - } - key->userid = content->userid; - key->last_seen = ID; - return PGP_KEEP_MEMORY; + if(vdata->last_seen == LS_PRIMARY || + vdata->last_seen == LS_ATTRIBUTE || + vdata->last_seen == LS_ID){ + if (vdata->userid) { + pgp_userid_free(&vdata->userid); + } + vdata->userid = content->userid; + vdata->last_seen = LS_ID; + return PGP_KEEP_MEMORY; + }else{ + (void) fprintf(io->errs, + "pgp_validate_key_cb: unexpected userID packet"); + vdata->last_seen = LS_UNKNOWN; + return PGP_RELEASE_MEMORY; + } case PGP_PTAG_CT_USER_ATTR: - if (content->userattr.len == 0) { + if(vdata->last_seen == LS_PRIMARY || + vdata->last_seen == LS_ATTRIBUTE || + vdata->last_seen == LS_ID){ + if (content->userattr.len == 0) { + (void) fprintf(io->errs, + "pgp_validate_key_cb: user attribute length 0"); + vdata->last_seen = LS_UNKNOWN; + return PGP_RELEASE_MEMORY; + } + (void) fprintf(io->outs, "user attribute, length=%d\n", + (int) content->userattr.len); + if (vdata->userattr.len) { + pgp_data_free(&vdata->userattr); + } + vdata->userattr = content->userattr; + vdata->last_seen = LS_ATTRIBUTE; + return PGP_KEEP_MEMORY; + }else{ (void) fprintf(io->errs, - "pgp_validate_key_cb: user attribute length 0"); - return PGP_FINISHED; - } - (void) fprintf(io->outs, "user attribute, length=%d\n", - (int) content->userattr.len); - if (key->userattr.len) { - pgp_data_free(&key->userattr); - } - key->userattr = content->userattr; - key->last_seen = ATTRIBUTE; - return PGP_KEEP_MEMORY; - + "pgp_validate_key_cb: unexpected user attribute\n"); + vdata->last_seen = LS_UNKNOWN; + return PGP_RELEASE_MEMORY; + } case PGP_PTAG_CT_SIGNATURE: /* V3 sigs */ - case PGP_PTAG_CT_SIGNATURE_FOOTER: /* V4 sigs */ - from = 0; - signer = pgp_getkeybyid(io, key->keyring, - content->sig.info.signer_id, - &from, &sigkey); - if (!signer) { - if (!add_sig_to_list(&content->sig.info, - &key->result->unknown_sigs, - &key->result->unknownc)) { - (void) fprintf(io->errs, - "pgp_validate_key_cb: user attribute length 0"); - return PGP_FINISHED; - } - break; - } - if (sigkey == &signer->enckey) { - (void) fprintf(io->errs, - "WARNING: signature made with encryption key\n"); - } + case PGP_PTAG_CT_SIGNATURE_FOOTER:{ /* V4 sigs */ + pgp_pubkey_t *sigkey = NULL; + pgp_pubkey_t *primary_pubkey; + + if(vdata->last_seen == LS_UNKNOWN) + break; + + primary_pubkey = + (vdata->type == PGP_PTAG_CT_PUBLIC_KEY) ? + &vdata->key.pubkey: + &vdata->key.seckey.pubkey; + + if(vdata->keyring){ + unsigned from; + from = 0; + /* Returned key ignored, care about ID-targeted pubkey only */ + pgp_getkeybyid(io, vdata->keyring, + content->sig.info.signer_id, + &from, &sigkey, NULL, + 1, 0); /* reject revoked, accept expired */ + } else { + /* If no keyring is given to check against + * then this is a self certification check. + * First ensure signature issuer ID is pubkey's ID*/ + if(memcmp(vdata->pubkeyid, + content->sig.info.signer_id, + PGP_KEY_ID_SIZE) == 0){ + sigkey = primary_pubkey; + } + } + if (!sigkey) { + if (vdata->result && !add_sig_to_list(&content->sig.info, + &vdata->result->unknown_sigs, + &vdata->result->unknownc)) { + (void) fprintf(io->errs, + "pgp_validate_key_cb: out of memory"); + return PGP_FINISHED; + } + break; + } switch (content->sig.info.type) { case PGP_CERT_GENERIC: case PGP_CERT_PERSONA: case PGP_CERT_CASUAL: case PGP_CERT_POSITIVE: case PGP_SIG_REV_CERT: - valid = (key->last_seen == ID) ? - pgp_check_useridcert_sig(&key->pubkey, - key->userid, + if(vdata->last_seen == LS_ID){ + valid = pgp_check_useridcert_sig( + primary_pubkey, + vdata->userid, &content->sig, - pgp_get_pubkey(signer), - key->reader->key->packets[ - key->reader->packet].raw) : - pgp_check_userattrcert_sig(&key->pubkey, - &key->userattr, + sigkey); + } else if(vdata->last_seen == LS_ATTRIBUTE) { + valid = pgp_check_userattrcert_sig( + primary_pubkey, + &vdata->userattr, &content->sig, - pgp_get_pubkey(signer), - key->reader->key->packets[ - key->reader->packet].raw); + sigkey); + } break; + case PGP_SIG_REV_SUBKEY: case PGP_SIG_SUBKEY: /* - * XXX: we should also check that the signer is the - * key we are validating, I think. + * we ensure that the signing key is the + * primary key we are validating, "vdata->pubkey". */ - valid = pgp_check_subkey_sig(&key->pubkey, - &key->subkey, - &content->sig, - pgp_get_pubkey(signer), - key->reader->key->packets[ - key->reader->packet].raw); + if(vdata->last_seen == LS_SUBKEY && + memcmp(vdata->pubkeyid, + content->sig.info.signer_id, + PGP_KEY_ID_SIZE) == 0 ) + { + valid = pgp_check_subkey_sig( + primary_pubkey, + (vdata->type == PGP_PTAG_CT_PUBLIC_KEY) ? + &vdata->subkey.pubkey: + &vdata->subkey.seckey.pubkey, + &content->sig, + primary_pubkey); + } break; + case PGP_SIG_REV_KEY: case PGP_SIG_DIRECT: - valid = pgp_check_direct_sig(&key->pubkey, - &content->sig, - pgp_get_pubkey(signer), - key->reader->key->packets[ - key->reader->packet].raw); + if(vdata->last_seen == LS_PRIMARY){ + valid = pgp_check_direct_sig( + primary_pubkey, + &content->sig, + sigkey); + } break; case PGP_SIG_STANDALONE: case PGP_SIG_PRIMARY: - case PGP_SIG_REV_KEY: - case PGP_SIG_REV_SUBKEY: case PGP_SIG_TIMESTAMP: case PGP_SIG_3RD_PARTY: - PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, - "Sig Verification type 0x%02x not done yet\n", - content->sig.info.type); - break; + if (vdata->result){ + PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, + "Sig Verification type 0x%02x not done yet\n", + content->sig.info.type); + break; + } default: - PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, - "Unexpected signature type 0x%02x\n", - content->sig.info.type); + if (vdata->result){ + PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, + "Unexpected signature type 0x%02x\n", + content->sig.info.type); + } } if (valid) { - if (!add_sig_to_list(&content->sig.info, - &key->result->valid_sigs, - &key->result->validc)) { + if (vdata->result && !add_sig_to_list(&content->sig.info, + &vdata->result->valid_sigs, + &vdata->result->validc)) { PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s", - "Can't add good sig to list\n"); + "Can't add valid sig to list\n"); } - } else { + vdata->sig_is_valid = 1; + copy_sig_info(&vdata->valid_sig_info, + &content->sig.info); + } else if (vdata->result){ PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE, "%s", "Bad Sig"); if (!add_sig_to_list(&content->sig.info, - &key->result->invalid_sigs, - &key->result->invalidc)) { + &vdata->result->invalid_sigs, + &vdata->result->invalidc)) { PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s", - "Can't add good sig to list\n"); + "Can't add invalid sig to list\n"); } } break; + } + case PGP_PARSER_PACKET_END: + if(vdata->sig_is_valid){ + pgp_cb_ret_t ret = PGP_RELEASE_MEMORY; + if(vdata->on_valid){ + ret = vdata->on_valid(vdata, &content->packet); + } + vdata->sig_is_valid = 0; + vdata->not_commited = 0; + return ret; + } + return PGP_RELEASE_MEMORY; - /* ignore these */ + /* ignore these */ case PGP_PARSER_PTAG: case PGP_PTAG_CT_SIGNATURE_HEADER: - case PGP_PARSER_PACKET_END: - break; - - case PGP_GET_PASSPHRASE: - if (key->getpassphrase) { - return key->getpassphrase(pkt, cbinfo); - } - break; - case PGP_PTAG_CT_TRUST: - /* 1 byte for level (depth), 1 byte for trust amount */ - printf("trust dump\n"); - printf("Got trust\n"); - //hexdump(stdout, (const uint8_t *)content->trust.data, 10, " "); - //hexdump(stdout, (const uint8_t *)&content->ss_trust, 2, " "); - //printf("Trust level %d, amount %d\n", key->trust.level, key->trust.amount); break; + // case PGP_GET_PASSPHRASE: + // if (vdata->getpassphrase) { + // return vdata->getpassphrase(pkt, cbinfo); + // } + // break; + default: - (void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag); - return PGP_FINISHED; + // (void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag); + return PGP_RELEASE_MEMORY; } return PGP_RELEASE_MEMORY; } @@ -426,7 +532,7 @@ pgp_cb_ret_t validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) { const pgp_contents_t *content = &pkt->u; - const pgp_key_t *signer; + pgp_key_t *signer; validate_data_cb_t *data; pgp_pubkey_t *sigkey; pgp_error_t **errors; @@ -480,9 +586,11 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) sizeof(content->sig.info.signer_id)); } from = 0; + sigkey = NULL; signer = pgp_getkeybyid(io, data->keyring, - content->sig.info.signer_id, &from, &sigkey); - if (!signer) { + content->sig.info.signer_id, &from, &sigkey, NULL, + 0, 0); /* check neither revocation nor expiry */ + if (!signer || !sigkey) { PGP_ERROR_1(errors, PGP_E_V_UNKNOWN_SIGNER, "%s", "Unknown Signer"); if (!add_sig_to_list(&content->sig.info, @@ -493,10 +601,6 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) } break; } - if (sigkey == &signer->enckey) { - (void) fprintf(io->errs, - "WARNING: signature made with encryption key\n"); - } if (content->sig.info.birthtime_set) { data->result->birthtime = content->sig.info.birthtime; } @@ -506,8 +610,8 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) switch (content->sig.info.type) { case PGP_SIG_BINARY: case PGP_SIG_TEXT: - if (pgp_mem_len(data->mem) == 0 && - data->detachname) { + if (pgp_mem_len(data->mem) == 0){ + if(data->detachname) { /* check we have seen some data */ /* if not, need to read from detached name */ (void) fprintf(io->errs, @@ -515,7 +619,8 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) data->detachname); data->mem = pgp_memory_new(); pgp_mem_readfile(data->mem, data->detachname); - } + } + } if (pgp_get_debug_level(__FILE__)) { hexdump(stderr, "sig dump", (const uint8_t *)(const void *)&content->sig, sizeof(content->sig)); @@ -523,7 +628,7 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) valid = check_binary_sig(pgp_mem_data(data->mem), (const unsigned)pgp_mem_len(data->mem), &content->sig, - pgp_get_pubkey(signer)); + sigkey); break; default: @@ -571,27 +676,6 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) return PGP_RELEASE_MEMORY; } -static void -keydata_destroyer(pgp_reader_t *readinfo) -{ - free(pgp_reader_get_arg(readinfo)); -} - -void -pgp_keydata_reader_set(pgp_stream_t *stream, const pgp_key_t *key) -{ - validate_reader_t *data; - - if ((data = calloc(1, sizeof(*data))) == NULL) { - (void) fprintf(stderr, "pgp_keydata_reader_set: bad alloc\n"); - } else { - data->key = key; - data->packet = 0; - data->offset = 0; - pgp_reader_set(stream, keydata_reader, keydata_destroyer, data); - } -} - static char * fmtsecs(int64_t n, char *buf, size_t size) { @@ -669,81 +753,195 @@ validate_result_status(FILE *errs, const char *f, pgp_validation_t *val) return val->validc && !val->invalidc && !val->unknownc; } -/** - * \ingroup HighLevel_Verify - * \brief Validate all signatures on a single key against the given keyring - * \param result Where to put the result - * \param key Key to validate - * \param keyring Keyring to use for validation - * \param cb_get_passphrase Callback to use to get passphrase - * \return 1 if all signatures OK; else 0 - * \note It is the caller's responsiblity to free result after use. - * \sa pgp_validate_result_free() - */ +typedef struct key_filter_cb_t{ + pgp_keyring_t *destpubring; + pgp_keyring_t *destsecring; + pgp_key_t *pubkey; + pgp_key_t *seckey; +} key_filter_cb_t; + +static pgp_cb_ret_t key_filter_cb ( + validate_key_cb_t *vdata, + const pgp_subpacket_t *sigpkt) +{ + pgp_key_t *pubkey; + pgp_key_t *seckey = NULL; + key_filter_cb_t *filter = vdata->on_valid_args; + + if(vdata->not_commited){ + + if((filter->pubkey = pgp_ensure_pubkey(filter->destpubring, + (vdata->type == PGP_PTAG_CT_PUBLIC_KEY) ? + &vdata->key.pubkey : + &vdata->key.seckey.pubkey, + vdata->pubkeyid))==NULL){ + return PGP_RELEASE_MEMORY; + } + + filter->seckey = NULL; + if (vdata->type == PGP_PTAG_CT_SECRET_KEY && filter->destsecring) { + if((filter->seckey = pgp_ensure_seckey( + filter->destsecring, + &vdata->key.seckey, + vdata->pubkeyid))==NULL){ + return PGP_RELEASE_MEMORY; + } + } + /* TODO get seckey by ID id even if given key is public + * in order to update uids an attributes from pubkey */ + } + + pubkey = filter->pubkey; + if(pubkey == NULL) + return PGP_RELEASE_MEMORY; + + if (vdata->type == PGP_PTAG_CT_SECRET_KEY) { + seckey = filter->seckey; + } + + switch(vdata->last_seen){ + case LS_PRIMARY: + + pgp_add_directsig(pubkey, sigpkt, &vdata->valid_sig_info); + + if (seckey) { + pgp_add_directsig(seckey, sigpkt, &vdata->valid_sig_info); + } + break; + case LS_ID: + + pgp_update_userid(pubkey, vdata->userid, sigpkt, &vdata->valid_sig_info); + if (seckey) { + pgp_update_userid(seckey, vdata->userid, sigpkt, &vdata->valid_sig_info); + } + + break; + case LS_ATTRIBUTE: + /* TODO */ + break; + case LS_SUBKEY: + pgp_update_subkey(pubkey, + vdata->type, &vdata->subkey, + sigpkt, &vdata->valid_sig_info); + if (seckey) { + pgp_update_subkey(seckey, + vdata->type, &vdata->subkey, + sigpkt, &vdata->valid_sig_info); + } + + break; + default: + break; + } + return PGP_RELEASE_MEMORY; +} + unsigned -pgp_validate_key_sigs(pgp_validation_t *result, - const pgp_key_t *key, - const pgp_keyring_t *keyring, - pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, - pgp_cbdata_t *)) +pgp_filter_keys_fileread( + pgp_io_t *io, + pgp_keyring_t *destpubring, + pgp_keyring_t *destsecring, + pgp_keyring_t *certring, + const unsigned armour, + const char *filename) { pgp_stream_t *stream; - validate_key_cb_t keysigs; - const int printerrors = 1; + validate_key_cb_t vdata; + key_filter_cb_t filter; + unsigned res = 1; + int fd; - (void) memset(&keysigs, 0x0, sizeof(keysigs)); - keysigs.result = result; - keysigs.getpassphrase = cb_get_passphrase; + (void) memset(&vdata, 0x0, sizeof(vdata)); + vdata.result = NULL; + vdata.getpassphrase = NULL; - stream = pgp_new(sizeof(*stream)); - /* pgp_parse_options(&opt,PGP_PTAG_CT_SIGNATURE,PGP_PARSE_PARSED); */ + (void) memset(&filter, 0x0, sizeof(filter)); + filter.destpubring = destpubring; + filter.destsecring = destsecring; - keysigs.keyring = keyring; + fd = pgp_setup_file_read(io, + &stream,filename, + &vdata, + pgp_validate_key_cb, + 1); - pgp_set_callback(stream, pgp_validate_key_cb, &keysigs); - stream->readinfo.accumulate = 1; - pgp_keydata_reader_set(stream, key); - - /* Note: Coverity incorrectly reports an error that keysigs.reader */ - /* is never used. */ - keysigs.reader = stream->readinfo.arg; - - pgp_parse(stream, !printerrors); - - pgp_pubkey_free(&keysigs.pubkey); - if (keysigs.subkey.version) { - pgp_pubkey_free(&keysigs.subkey); + if (fd < 0) { + perror(filename); + return 0; } - pgp_userid_free(&keysigs.userid); - pgp_data_free(&keysigs.userattr); + + pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); + + if (armour) { + pgp_reader_push_dearmour(stream); + } + + vdata.keyring = certring; + + vdata.on_valid = &key_filter_cb; + vdata.on_valid_args = &filter; + + res = pgp_parse(stream, 0); + + validate_key_cb_free(&vdata); + + if (armour) { + pgp_reader_pop_dearmour(stream); + } + + (void)close(fd); pgp_stream_delete(stream); - return (!result->invalidc && !result->unknownc && result->validc); + return res; } -/** - \ingroup HighLevel_Verify - \param result Where to put the result - \param ring Keyring to use - \param cb_get_passphrase Callback to use to get passphrase - \note It is the caller's responsibility to free result after use. - \sa pgp_validate_result_free() -*/ unsigned -pgp_validate_all_sigs(pgp_validation_t *result, - const pgp_keyring_t *ring, - pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, - pgp_cbdata_t *)) +pgp_filter_keys_from_mem( + pgp_io_t *io, + pgp_keyring_t *destpubring, + pgp_keyring_t *destsecring, + pgp_keyring_t *certring, + const unsigned armour, + pgp_memory_t *mem) { - unsigned n; + pgp_stream_t *stream; + validate_key_cb_t vdata; + key_filter_cb_t filter; + unsigned res; - (void) memset(result, 0x0, sizeof(*result)); - for (n = 0; n < ring->keyc; ++n) { - pgp_validate_key_sigs(result, &ring->keys[n], ring, - cb_get_passphrase); + (void) memset(&vdata, 0x0, sizeof(vdata)); + vdata.result = NULL; + vdata.getpassphrase = NULL; + + (void) memset(&filter, 0x0, sizeof(filter)); + filter.destpubring = destpubring; + filter.destsecring = destsecring; + + stream = pgp_new(sizeof(*stream)); + pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); + pgp_setup_memory_read(io, &stream, mem, &vdata, pgp_validate_key_cb, 1); + + if (armour) { + pgp_reader_push_dearmour(stream); } - return validate_result_status(stderr, "keyring", result); + + vdata.keyring = certring; + + vdata.on_valid = &key_filter_cb; + vdata.on_valid_args = &filter; + + res = pgp_parse(stream, 0); + + validate_key_cb_free(&vdata); + + if (armour) { + pgp_reader_pop_dearmour(stream); + } + + /* don't call teardown_memory_read because memory was passed in */ + pgp_stream_delete(stream); + return res; } /** @@ -846,9 +1044,6 @@ pgp_validate_file(pgp_io_t *io, validation.keyring = keyring; validation.mem = pgp_memory_new(); pgp_memory_init(validation.mem, 128); - /* Note: Coverity incorrectly reports an error that validation.reader */ - /* is never used. */ - validation.reader = parse->readinfo.arg; if (realarmour) { pgp_reader_push_dearmour(parse); @@ -910,20 +1105,21 @@ pgp_validate_file(pgp_io_t *io, \param mem Memory to be validated \param user_says_armoured Treat data as armoured, if set \param keyring Keyring to use + \param detachmem detached memory (free done in this call if provided) \return 1 if signature validates successfully; 0 if not \note After verification, result holds the details of all keys which have passed, failed and not been recognised. \note It is the caller's responsiblity to call pgp_validate_result_free(result) after use. */ - -unsigned -pgp_validate_mem(pgp_io_t *io, +static inline unsigned +_pgp_validate_mem(pgp_io_t *io, pgp_validation_t *result, pgp_memory_t *mem, pgp_memory_t **cat, const int user_says_armoured, - const pgp_keyring_t *keyring) + const pgp_keyring_t *keyring, + pgp_memory_t *detachmem) { validate_data_cb_t validation; pgp_stream_t *stream = NULL; @@ -931,15 +1127,17 @@ pgp_validate_mem(pgp_io_t *io, int realarmour; pgp_setup_memory_read(io, &stream, mem, &validation, validate_data_cb, 1); + /* Set verification reader and handling options */ (void) memset(&validation, 0x0, sizeof(validation)); validation.result = result; validation.keyring = keyring; - validation.mem = pgp_memory_new(); - pgp_memory_init(validation.mem, 128); - /* Note: Coverity incorrectly reports an error that validation.reader */ - /* is never used. */ - validation.reader = stream->readinfo.arg; + if (detachmem) { + validation.mem = detachmem; + }else{ + validation.mem = pgp_memory_new(); + pgp_memory_init(validation.mem, 128); + } if ((realarmour = user_says_armoured) != 0 || strncmp(pgp_mem_data(mem), @@ -964,8 +1162,44 @@ pgp_validate_mem(pgp_io_t *io, /* need to send validated output somewhere */ *cat = validation.mem; } else { - pgp_memory_free(validation.mem); + pgp_memory_free(validation.mem); } return validate_result_status(io->errs, NULL, result); } + +unsigned +pgp_validate_mem(pgp_io_t *io, + pgp_validation_t *result, + pgp_memory_t *mem, + pgp_memory_t **cat, + const int user_says_armoured, + const pgp_keyring_t *keyring) +{ + return _pgp_validate_mem(io, + result, + mem, + cat, + user_says_armoured, + keyring, + NULL); +} + +unsigned +pgp_validate_mem_detached(pgp_io_t *io, + pgp_validation_t *result, + pgp_memory_t *mem, + pgp_memory_t **cat, + const int user_says_armoured, + const pgp_keyring_t *keyring, + pgp_memory_t *detachmem) +{ + return _pgp_validate_mem(io, + result, + mem, + cat, + user_says_armoured, + keyring, + detachmem); +} + diff --git a/libs/netpgp/writer.c b/libs/netpgp/src/writer.c similarity index 92% rename from libs/netpgp/writer.c rename to libs/netpgp/src/writer.c index e9f3a83d..83b4c79b 100644 --- a/libs/netpgp/writer.c +++ b/libs/netpgp/src/writer.c @@ -50,7 +50,7 @@ /** \file * This file contains the base functions used by the writers. */ -#include "config-netpgp.h" +#include "netpgp/config-netpgp.h" #ifdef HAVE_SYS_CDEFS_H #include @@ -58,7 +58,7 @@ #if defined(__NetBSD__) __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: writer.c,v 1.33 2012/03/05 02:20:18 christos Exp $"); +__RCSID("$NetBSD$"); #endif #include @@ -74,17 +74,17 @@ __RCSID("$NetBSD: writer.c,v 1.33 2012/03/05 02:20:18 christos Exp $"); #include #endif -#include "create-netpgp.h" -#include "writer-netpgp.h" -#include "keyring-netpgp.h" -#include "signature-netpgp.h" -#include "packet-netpgp.h" -#include "packet-parse.h" -#include "readerwriter-netpgp.h" -#include "memory-netpgp.h" -#include "netpgpdefs.h" -#include "version-netpgp.h" -#include "netpgpdigest.h" +#include "netpgp/create.h" +#include "netpgp/writer.h" +#include "netpgp/keyring.h" +#include "netpgp/signature.h" +#include "netpgp/packet.h" +#include "netpgp/packet-parse.h" +#include "netpgp/readerwriter.h" +#include "netpgp/memory.h" +#include "netpgp/netpgpdefs.h" +#include "netpgp/version.h" +#include "netpgp/netpgpdigest.h" /* @@ -285,11 +285,13 @@ pgp_writer_push(pgp_output_t *output, { pgp_writer_t *copy; - if ((copy = calloc(1, sizeof(*copy))) == NULL) { - (void) fprintf(stderr, "pgp_writer_push: bad alloc\n"); - } else if (output->writer.writer == NULL) { + if (output->writer.writer == NULL) { (void) fprintf(stderr, "pgp_writer_push: no orig writer\n"); } else { + if ((copy = calloc(1, sizeof(*copy))) == NULL) { + (void) fprintf(stderr, "pgp_writer_push: bad alloc\n"); + return; /* TODO return error */ + } *copy = output->writer; output->writer.next = copy; @@ -910,6 +912,7 @@ pgp_writer_push_armoured(pgp_output_t *output, pgp_armor_type_t type) if ((base64 = calloc(1, sizeof(*base64))) == NULL) { (void) fprintf(stderr, "pgp_writer_push_armoured: bad alloc\n"); + free(linebreak); return; } base64->checksum = CRC24_INIT; @@ -1011,6 +1014,7 @@ pgp_push_enc_crypt(pgp_output_t *output, pgp_crypt_t *pgp_crypt) typedef struct { pgp_crypt_t *crypt; + unsigned raw; } encrypt_se_ip_t; static unsigned encrypt_se_ip_writer(const uint8_t *, @@ -1026,24 +1030,46 @@ static void encrypt_se_ip_destroyer(pgp_writer_t *); \brief Push Encrypted SE IP Writer onto stack */ int -pgp_push_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const char *cipher) +pgp_push_enc_se_ip(pgp_output_t *output, const pgp_keyring_t *pubkeys, const char *cipher, unsigned raw) { + pgp_pk_sesskey_t *initial_sesskey = NULL; pgp_pk_sesskey_t *encrypted_pk_sesskey; encrypt_se_ip_t *se_ip; pgp_crypt_t *encrypted; uint8_t *iv; + unsigned n; if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) { (void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n"); return 0; } - /* Create and write encrypted PK session key */ - if ((encrypted_pk_sesskey = pgp_create_pk_sesskey(pubkey, cipher)) == NULL) { - (void) fprintf(stderr, "pgp_push_enc_se_ip: null pk sesskey\n"); - return 0; - } - pgp_write_pk_sesskey(output, encrypted_pk_sesskey); + for (n = 0; n < pubkeys->keyc; ++n) { + /* Create and write encrypted PK session key */ + if ((encrypted_pk_sesskey = + pgp_create_pk_sesskey(&pubkeys->keys[n], + cipher, initial_sesskey)) == NULL) { + (void) fprintf(stderr, "pgp_push_enc_se_ip: null pk sesskey\n"); + free(se_ip); + return 0; + } + + if (initial_sesskey == NULL) { + initial_sesskey = encrypted_pk_sesskey; + } + + pgp_write_pk_sesskey(output, encrypted_pk_sesskey); + + if(encrypted_pk_sesskey != initial_sesskey){ + free(encrypted_pk_sesskey); + } + } + + if (initial_sesskey == NULL) { + (void) fprintf(stderr, "pgp_push_enc_se_ip: no sesskey\n"); + free(se_ip); + return 0; + } /* Setup the se_ip */ if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) { @@ -1051,7 +1077,7 @@ pgp_push_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const char *ci (void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n"); return 0; } - pgp_crypt_any(encrypted, encrypted_pk_sesskey->symm_alg); + pgp_crypt_any(encrypted, initial_sesskey->symm_alg); if ((iv = calloc(1, encrypted->blocksize)) == NULL) { free(se_ip); free(encrypted); @@ -1059,16 +1085,17 @@ pgp_push_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const char *ci return 0; } encrypted->set_iv(encrypted, iv); - encrypted->set_crypt_key(encrypted, &encrypted_pk_sesskey->key[0]); + encrypted->set_crypt_key(encrypted, &initial_sesskey->key[0]); pgp_encrypt_init(encrypted); se_ip->crypt = encrypted; + se_ip->raw = raw; /* And push writer on stack */ pgp_writer_push(output, encrypt_se_ip_writer, NULL, encrypt_se_ip_destroyer, se_ip); /* tidy up */ - free(encrypted_pk_sesskey); + free(initial_sesskey); free(iv); return 1; } @@ -1089,19 +1116,29 @@ encrypt_se_ip_writer(const uint8_t *src, pgp_memory_t *localmem; unsigned ret = 1; + const uint8_t *zsrc; + unsigned zsrclen; + pgp_setup_memory_write(&litoutput, &litmem, bufsz); pgp_setup_memory_write(&zoutput, &zmem, bufsz); pgp_setup_memory_write(&output, &localmem, bufsz); - /* create literal data packet from source data */ - pgp_write_litdata(litoutput, src, (const int)len, PGP_LDT_BINARY); - if (pgp_mem_len(litmem) <= len) { - (void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n"); - return 0; - } + if (!se_ip->raw) { + /* create literal data packet from source data */ + pgp_write_litdata(litoutput, src, (const int)len, PGP_LDT_BINARY); + if (pgp_mem_len(litmem) <= len) { + (void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n"); + return 0; + } + zsrc = pgp_mem_data(litmem); + zsrclen = (unsigned)pgp_mem_len(litmem); + }else{ + zsrc = src; + zsrclen = len; + } /* create compressed packet from literal data packet */ - pgp_writez(zoutput, pgp_mem_data(litmem), (unsigned)pgp_mem_len(litmem)); + pgp_writez(zoutput, zsrc, zsrclen); /* create SE IP packet set from this compressed literal data */ pgp_write_se_ip_pktset(output, pgp_mem_data(zmem), @@ -1379,6 +1416,60 @@ pgp_push_checksum_writer(pgp_output_t *output, pgp_seckey_t *seckey) /**************************************************************************/ +typedef struct { + uint16_t sum; +} sum16_t; + +static unsigned +sum16_writer(const uint8_t *src, + const unsigned len, + pgp_error_t **errors, + pgp_writer_t *writer) +{ + sum16_t *arg; + unsigned ret = 1; + int n; + + arg = pgp_writer_get_arg(writer); + + for (n = 0; n < len; ++n) { + arg->sum = (arg->sum + src[n]) & 0xffff; + } + + /* write to next stacked writer */ + ret = stacked_write(writer, src, len, errors); + /* tidy up and return */ + return ret; +} + +void +pgp_push_sum16_writer(pgp_output_t *output) +{ + sum16_t *sum; + + if ((sum = calloc(1, sizeof(*sum))) == NULL) { + (void) fprintf(stderr, + "pgp_push_sum16_writer: bad alloc\n"); + } else { + pgp_writer_push(output, sum16_writer, + NULL, NULL, sum); + } +} + +uint16_t +pgp_pop_sum16_writer(pgp_output_t *output) +{ + uint16_t sum; + sum16_t *arg; + arg = pgp_writer_get_arg(&output->writer); + sum = arg->sum; + pgp_writer_pop(output); + free(arg); + return sum; +} + +/**************************************************************************/ + #define MAX_PARTIAL_DATA_LENGTH 1073741824 typedef struct { @@ -1412,7 +1503,7 @@ static void str_enc_se_ip_destroyer(pgp_writer_t *writer); \param pubkey */ void -pgp_push_stream_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const char *cipher) +pgp_push_stream_enc_se_ip(pgp_output_t *output, pgp_key_t *pubkey, const char *cipher) { pgp_pk_sesskey_t *encrypted_pk_sesskey; str_enc_se_ip_t *se_ip; @@ -1425,7 +1516,7 @@ pgp_push_stream_enc_se_ip(pgp_output_t *output, const pgp_key_t *pubkey, const c "pgp_push_stream_enc_se_ip: bad alloc\n"); return; } - encrypted_pk_sesskey = pgp_create_pk_sesskey(pubkey, cipher); + encrypted_pk_sesskey = pgp_create_pk_sesskey(pubkey, cipher, NULL); pgp_write_pk_sesskey(output, encrypted_pk_sesskey); /* Setup the se_ip */ @@ -1701,7 +1792,6 @@ str_enc_se_ip_writer(const uint8_t *src, size_t datalength; se_ip = pgp_writer_get_arg(writer); - ret = 1; if (se_ip->litoutput == NULL) { /* first literal data chunk is not yet written */ diff --git a/src/mre2ee_driver_openssl.c b/src/mre2ee_driver_openssl.c index b54c6412..7170386d 100644 --- a/src/mre2ee_driver_openssl.c +++ b/src/mre2ee_driver_openssl.c @@ -119,9 +119,10 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t /* generate keypair */ keypair = pgp_rsa_new_selfsign_key(2048/*bits*/, 65537UL/*e*/, (const uint8_t*)user_id, NULL, NULL); - /* get public key */ + /* write public key */ + keypair->type = PGP_PTAG_CT_PUBLIC_KEY; // TODO: this seems to me like a hack, PLUS: add a subkey pgp_writer_set_memory(output1, mem1); - if( !pgp_write_xfer_pubkey(output1, keypair, 0/*armoured*/) ) { + if( !pgp_write_xfer_key(output1, keypair, 0/*armoured*/) ) { goto cleanup; } @@ -132,8 +133,9 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t mrkey_set_from_raw(ret_public_key, (const unsigned char*)mem1->buf, mem1->length, MR_PRIVATE); /* write private key */ + keypair->type = PGP_PTAG_CT_SECRET_KEY; // TODO: this seems to me like a hack pgp_writer_set_memory(output2, mem2); - if( !pgp_write_xfer_seckey(output2, keypair, NULL, 0, 0/*armoured*/) ) { + if( !pgp_write_xfer_key(output2, keypair, 0/*armoured*/) ) { goto cleanup; }