1
0
Fork 0
mirror of https://github.com/deltachat/deltachat-core.git synced 2025-10-04 10:19:16 +02:00

Update netpgp.

This commit is contained in:
B. Petersen 2017-05-19 03:33:33 +02:00
parent 15a4434013
commit 11157137ad
46 changed files with 4887 additions and 7217 deletions

View file

@ -54,7 +54,7 @@
<Add directory="libs/libetpan/include" /> <Add directory="libs/libetpan/include" />
<Add directory="libs/libetpan/include/libetpan" /> <Add directory="libs/libetpan/include/libetpan" />
<Add directory="libs/sqlite" /> <Add directory="libs/sqlite" />
<Add directory="libs/netpgp" /> <Add directory="libs/netpgp/include" />
</Compiler> </Compiler>
<Unit filename="README.md" /> <Unit filename="README.md" />
<Unit filename="libs/libetpan/src/data-types/base64.c"> <Unit filename="libs/libetpan/src/data-types/base64.c">
@ -372,58 +372,46 @@
<Unit filename="libs/libetpan/src/main/libetpan_version.c"> <Unit filename="libs/libetpan/src/main/libetpan_version.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/bufgap.c"> <Unit filename="libs/netpgp/src/compress.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/compress.c"> <Unit filename="libs/netpgp/src/create.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/create.c"> <Unit filename="libs/netpgp/src/crypto.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/crypto.c"> <Unit filename="libs/netpgp/src/keyring.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/keyring.c"> <Unit filename="libs/netpgp/src/misc.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/misc.c"> <Unit filename="libs/netpgp/src/netpgp.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/mj.c"> <Unit filename="libs/netpgp/src/openssl_crypto.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/netpgp.c"> <Unit filename="libs/netpgp/src/packet-parse.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/openssl_crypto.c"> <Unit filename="libs/netpgp/src/packet-show.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/packet-parse.c"> <Unit filename="libs/netpgp/src/reader.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/packet-print.c"> <Unit filename="libs/netpgp/src/signature.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/packet-show.c"> <Unit filename="libs/netpgp/src/symmetric.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/reader.c"> <Unit filename="libs/netpgp/src/validate.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/netpgp/signature.c"> <Unit filename="libs/netpgp/src/writer.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="libs/netpgp/ssh2pgp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="libs/netpgp/symmetric.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="libs/netpgp/validate.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="libs/netpgp/writer.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="libs/sqlite/sqlite3.c"> <Unit filename="libs/sqlite/sqlite3.c">

View file

@ -1,12 +1,13 @@
#ifndef __NETPGP_EXTRA_H__ #ifndef __NETPGP_EXTRA_H__
#define __NETPGP_EXTRA_H__ #define __NETPGP_EXTRA_H__
#include "netpgp/config-netpgp.h"
#include <netpgp.h> #include <netpgp.h>
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "errors-netpgp.h" #include "netpgp/errors.h"
#include "netpgpdefs.h" #include "netpgp/defs.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "create-netpgp.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); 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__ #endif // __NETPGP_EXTRA_H__

View file

@ -57,9 +57,6 @@ typedef struct netpgp_t {
int netpgp_init(netpgp_t *); int netpgp_init(netpgp_t *);
int netpgp_end(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 *); const char *netpgp_get_info(const char *);
int netpgp_list_packets(netpgp_t *, char *, int, 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 *); int netpgp_find_key(netpgp_t *, char *);
char *netpgp_get_key(netpgp_t *, const char *, const char *); char *netpgp_get_key(netpgp_t *, const char *, const char *);
char *netpgp_export_key(netpgp_t *, 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_import_key(netpgp_t *, char *);
int netpgp_generate_key(netpgp_t *, char *, int); int netpgp_generate_key(netpgp_t *, char *, int);

View file

@ -0,0 +1,160 @@
//
// config.h
// netpgp
#ifndef netpgp_config_h
#define netpgp_config_h
/* Define to 1 if you have the <bzlib.h> header file. */
#define HAVE_BZLIB_H 1
/* Define to 1 if you have the <CommonCrypto/CommonDigest.h> header file. */
#define HAVE_COMMONCRYPTO_COMMONDIGEST_H 1
/* Define to 1 if you have the <direct.h> header file. */
/* #undef HAVE_DIRECT_H */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <dmalloc.h> header file. */
/* #undef HAVE_DMALLOC_H */
/* Define to 1 if you have the <errno.h> header file. */
#define HAVE_ERRNO_H 1
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <limits.h> 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 <malloc.h> header file. */
/* #undef HAVE_MALLOC_H */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <openssl/aes.h> header file. */
#define HAVE_OPENSSL_AES_H 1
/* Define to 1 if you have the <openssl/bn.h> header file. */
#define HAVE_OPENSSL_BN_H 1
/* Define to 1 if you have the <openssl/camellia.h> header file. */
/* #undef HAVE_OPENSSL_CAMELLIA_H */
/* Define to 1 if you have the <openssl/cast.h> header file. */
#define HAVE_OPENSSL_CAST_H 1
/* Define to 1 if you have the <openssl/des.h> header file. */
#define HAVE_OPENSSL_DES_H 1
/* Define to 1 if you have the <openssl/dsa.h> header file. */
#define HAVE_OPENSSL_DSA_H 1
/* Define to 1 if you have the <openssl/err.h> header file. */
#define HAVE_OPENSSL_ERR_H 1
/* Define to 1 if you have the <openssl/idea.h> header file. */
/* #undef HAVE_OPENSSL_IDEA_H */
/* Define to 1 if you have the <openssl/md5.h> header file. */
#define HAVE_OPENSSL_MD5_H 1
/* Define to 1 if you have the <openssl/rand.h> header file. */
#define HAVE_OPENSSL_RAND_H 1
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#define HAVE_OPENSSL_RSA_H 1
/* Define to 1 if you have the <openssl/sha.h> 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 <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/cdefs.h> header file. */
#define HAVE_SYS_CDEFS_H 1
/* Define to 1 if you have the <sys/file.h> header file. */
#define HAVE_SYS_FILE_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/resource.h> header file. */
#define HAVE_SYS_RESOURCE_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
#define HAVE_SYS_UIO_H 1
/* Define to 1 if you have the <unistd.h> 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 <zlib.h> 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 <netpgp@pep-project.org> "
/* 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

View file

@ -52,13 +52,13 @@
#ifndef CREATE_H_ #ifndef CREATE_H_
#define CREATE_H_ #define CREATE_H_
#include "types-netpgp.h" #include "types.h"
#include "packet-netpgp.h" #include "packet.h"
#include "crypto-netpgp.h" #include "crypto.h"
#include "errors-netpgp.h" #include "errors.h"
#include "keyring-netpgp.h" #include "keyring.h"
#include "writer-netpgp.h" #include "writer.h"
#include "memory-netpgp.h" #include "memory.h"
/** /**
* \ingroup Create * \ingroup Create
@ -78,11 +78,17 @@ 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_calc_sesskey_checksum(pgp_pk_sesskey_t *, uint8_t *);
unsigned pgp_write_struct_userid(pgp_output_t *, const 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 *, unsigned pgp_write_struct_seckey(const pgp_seckey_t *,
const uint8_t *, const uint8_t *,
const size_t, const size_t,
pgp_output_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 *, unsigned pgp_write_one_pass_sig(pgp_output_t *,
const pgp_seckey_t *, const pgp_seckey_t *,
const pgp_hash_alg_t, const pgp_hash_alg_t,
@ -91,15 +97,11 @@ unsigned pgp_write_litdata(pgp_output_t *,
const uint8_t *, const uint8_t *,
const int, const int,
const pgp_litdata_enum); 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_pk_sesskey(pgp_output_t *, pgp_pk_sesskey_t *);
unsigned pgp_write_xfer_pubkey(pgp_output_t *, unsigned pgp_write_xfer_key(pgp_output_t *output,
const pgp_key_t *, const unsigned); const pgp_key_t *key,
unsigned pgp_write_xfer_seckey(pgp_output_t *, const unsigned armoured);
const pgp_key_t *,
const uint8_t *,
const size_t,
const unsigned);
void pgp_fast_create_userid(uint8_t **, uint8_t *); void pgp_fast_create_userid(uint8_t **, uint8_t *);
unsigned pgp_write_userid(const uint8_t *, pgp_output_t *); unsigned pgp_write_userid(const uint8_t *, pgp_output_t *);

View file

@ -53,9 +53,9 @@
#ifndef CRYPTO_H_ #ifndef CRYPTO_H_
#define CRYPTO_H_ #define CRYPTO_H_
#include "keyring-netpgp.h" #include "keyring.h"
#include "packet-netpgp.h" #include "packet.h"
#include "memory-netpgp.h" #include "memory.h"
#include "packet-parse.h" #include "packet-parse.h"
#include <openssl/dsa.h> #include <openssl/dsa.h>
@ -100,6 +100,17 @@ struct pgp_crypt_t {
void *decrypt_key; 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_crypto_finish(void);
void pgp_hash_md5(pgp_hash_t *); void pgp_hash_md5(pgp_hash_t *);
void pgp_hash_sha1(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_sha512(pgp_hash_t *);
void pgp_hash_sha384(pgp_hash_t *); void pgp_hash_sha384(pgp_hash_t *);
void pgp_hash_sha224(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 *); pgp_hash_alg_t pgp_str_to_hash_alg(const char *);
const char *pgp_text_from_hash(pgp_hash_t *); const char *pgp_text_from_hash(pgp_hash_t *);
unsigned pgp_hash_size(pgp_hash_alg_t); unsigned pgp_hash_size(pgp_hash_alg_t);
@ -190,8 +201,8 @@ unsigned pgp_decrypt_file(pgp_io_t *,
pgp_memory_t * pgp_memory_t *
pgp_encrypt_buf(pgp_io_t *, const void *, const size_t, pgp_encrypt_buf(pgp_io_t *, const void *, const size_t,
const pgp_key_t *, const pgp_keyring_t *,
const unsigned, const char *); const unsigned, const char *, unsigned);
pgp_memory_t * pgp_memory_t *
pgp_decrypt_buf(pgp_io_t *, pgp_decrypt_buf(pgp_io_t *,
const void *, const void *,
@ -204,18 +215,35 @@ pgp_decrypt_buf(pgp_io_t *,
int, int,
pgp_cbfunc_t *); 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 */ /* Keys */
pgp_key_t *pgp_rsa_new_selfsign_key(const int, pgp_key_t *pgp_rsa_new_selfsign_key(const int,
const unsigned long, const uint8_t *, const char *, const unsigned long, const uint8_t *, const char *,
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 *); 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_seckey_t *,
const pgp_dsa_pubkey_t *); const pgp_dsa_pubkey_t *);
int openssl_read_pem_seckey(const char *, pgp_key_t *, const char *, int);
/** pgp_reader_t */ /** pgp_reader_t */
struct pgp_reader_t { struct pgp_reader_t {
pgp_reader_func_t *reader; /* reader func to get parse data */ pgp_reader_func_t *reader; /* reader func to get parse data */
@ -228,6 +256,13 @@ struct pgp_reader_t {
unsigned position; /* reader-specific offset */ unsigned position; /* reader-specific offset */
pgp_reader_t *next; pgp_reader_t *next;
pgp_stream_t *parent;/* parent parse_info structure */ 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 { struct pgp_cryptinfo_t {
char *passphrase; char *passphrase;
pgp_keyring_t *secring; pgp_keyring_t *secring;
const pgp_key_t *keydata; pgp_key_t *keydata;
pgp_cbfunc_t *getpassphrase; pgp_cbfunc_t *getpassphrase;
pgp_keyring_t *pubring; pgp_keyring_t *pubring;
DYNARRAY(key_id_t, recipients_key_ids);
}; };
/** pgp_cbdata_t */ /** pgp_cbdata_t */
@ -301,15 +337,10 @@ struct pgp_stream_t {
pgp_cryptinfo_t cryptinfo; pgp_cryptinfo_t cryptinfo;
size_t hashc; size_t hashc;
pgp_hashtype_t *hashes; pgp_hashtype_t *hashes;
unsigned reading_v3_secret:1; //unsigned reading_v3_secret:1;
unsigned reading_mpi_len:1; //unsigned reading_mpi_len:1;
unsigned exact_read:1; //unsigned exact_read:1;
unsigned partial_read:1;
unsigned coalescing:1;
/* used for partial length coalescing */
unsigned virtualc;
unsigned virtualoff;
uint8_t *virtualpkt;
}; };
#endif /* CRYPTO_H_ */ #endif /* CRYPTO_H_ */

View file

@ -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. * Copyright (c) 2009 The NetBSD Foundation, Inc.

View file

@ -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_ */

View file

@ -54,7 +54,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "packet-netpgp.h" #include "packet.h"
/** pgp_memory_t /** pgp_memory_t
*/ */

View file

@ -65,8 +65,4 @@ void *pgp_new(size_t);
} \ } \
} while(/* CONSTCOND */0) } while(/* CONSTCOND */0)
#ifndef MIN
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
#endif /* !NETPGPDEFS_H_ */ #endif /* !NETPGPDEFS_H_ */

View file

@ -50,6 +50,7 @@
/* SHA1 Hash Size */ /* SHA1 Hash Size */
#define PGP_SHA1_HASH_SIZE SHA_DIGEST_LENGTH #define PGP_SHA1_HASH_SIZE SHA_DIGEST_LENGTH
#define PGP_SHA256_HASH_SIZE SHA256_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 #define PGP_CHECKHASH_SIZE PGP_SHA1_HASH_SIZE
#endif /* NETPGPDIGEST_H_ */ #endif /* NETPGPDIGEST_H_ */

View file

@ -29,34 +29,17 @@
#ifndef NETPGPSDK_H_ #ifndef NETPGPSDK_H_
#define NETPGPSDK_H_ #define NETPGPSDK_H_
#include "keyring-netpgp.h" #include "keyring.h"
#include "crypto-netpgp.h" #include "crypto.h"
#include "signature-netpgp.h" #include "signature.h"
#include "packet-show.h" #include "packet-show.h"
#ifndef __printflike #ifndef __printflike
#define __printflike(n, m) __attribute__((format(printf,n,m))) #define __printflike(n, m) __attribute__((format(printf,n,m)))
#endif #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 *); 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 unsigned
pgp_validate_all_sigs(pgp_validation_t *, pgp_validate_all_sigs(pgp_validation_t *,
const pgp_keyring_t *, const pgp_keyring_t *,
@ -74,5 +57,4 @@ void netpgp_log(const char *, ...) __printflike(1, 2);
int netpgp_strcasecmp(const char *, const char *); int netpgp_strcasecmp(const char *, const char *);
char *netpgp_strdup(const char *); char *netpgp_strdup(const char *);
#endif #endif

View file

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

View file

@ -54,8 +54,8 @@
#ifndef PACKET_PARSE_H_ #ifndef PACKET_PARSE_H_
#define PACKET_PARSE_H_ #define PACKET_PARSE_H_
#include "types-netpgp.h" #include "types.h"
#include "packet-netpgp.h" #include "packet.h"
/** pgp_region_t */ /** pgp_region_t */
typedef struct 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 *, unsigned pgp_writez(pgp_output_t *, const uint8_t *,
const unsigned); const unsigned);
void
copy_sig_info(pgp_sig_info_t *dst, const pgp_sig_info_t *src);
#endif /* PACKET_PARSE_H_ */ #endif /* PACKET_PARSE_H_ */

View file

@ -53,7 +53,7 @@
#ifndef PACKET_SHOW_H_ #ifndef PACKET_SHOW_H_
#define PACKET_SHOW_H_ #define PACKET_SHOW_H_
#include "packet-netpgp.h" #include "packet.h"
/** pgp_list_t /** 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_sig_type(pgp_sig_type_t);
const char *pgp_show_pka(pgp_pubkey_alg_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); 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_hash_alg(uint8_t);
const char *pgp_show_symm_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_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 *); 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 *); const char *pgp_show_keyserv_pref(uint8_t, pgp_bit_map_t *);
pgp_text_t *pgp_showall_notation(pgp_ss_notation_t); pgp_text_t *pgp_showall_notation(pgp_ss_notation_t);

View file

@ -54,16 +54,16 @@
#ifndef PACKET_H_ #ifndef PACKET_H_
#define PACKET_H_ #define PACKET_H_
#include "config-netpgp.h"
#include <time.h> #include <time.h>
#ifdef HAVE_OPENSSL_BN_H #ifdef HAVE_OPENSSL_BN_H
#include <openssl/bn.h> #include <openssl/bn.h>
#endif #endif
#include "types-netpgp.h" #include <openssl/ossl_typ.h>
#include "errors-netpgp.h"
#include "types.h"
#include "errors.h"
/* structure to keep track of printing state variables */ /* structure to keep track of printing state variables */
typedef struct pgp_printstate_t { typedef struct pgp_printstate_t {
@ -620,6 +620,8 @@ typedef struct pgp_sig_info_t {
pgp_sig_type_t type; /* signature type value */ pgp_sig_type_t type; /* signature type value */
time_t birthtime; /* creation time of the signature */ time_t birthtime; /* creation time of the signature */
time_t duration; /* number of seconds it's valid for */ 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 uint8_t signer_id[PGP_KEY_ID_SIZE]; /* Eight-octet key ID
* of signer */ * of signer */
pgp_pubkey_alg_t key_alg; /* public key algorithm number */ 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 birthtime_set:1;
unsigned signer_id_set:1; unsigned signer_id_set:1;
unsigned duration_set:1; unsigned duration_set:1;
unsigned key_expiry_set:1;
unsigned key_flags_set:1;
unsigned primary_userid:1;
} pgp_sig_info_t; } 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 */ /** Struct used when parsing a signature */
typedef struct pgp_sig_t { typedef struct pgp_sig_t {
pgp_sig_info_t info; /* The signature information */ pgp_sig_info_t info; /* The signature information */
@ -789,9 +804,10 @@ typedef union {
} pgp_pk_sesskey_params_t; } pgp_pk_sesskey_params_t;
/** pgp_pk_sesskey_t */ /** pgp_pk_sesskey_t */
typedef uint8_t key_id_t[PGP_KEY_ID_SIZE];
typedef struct { typedef struct {
unsigned version; unsigned version;
uint8_t key_id[PGP_KEY_ID_SIZE]; key_id_t key_id;
pgp_pubkey_alg_t alg; pgp_pubkey_alg_t alg;
pgp_pk_sesskey_params_t params; pgp_pk_sesskey_params_t params;
pgp_symm_alg_t symm_alg; 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_finish(void);
void pgp_pubkey_free(pgp_pubkey_t *); 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_userid_free(uint8_t **);
void pgp_data_free(pgp_data_t *); void pgp_data_free(pgp_data_t *);
void pgp_sig_free(pgp_sig_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_subpacket_free(pgp_subpacket_t *);
void pgp_parser_content_free(pgp_packet_t *); void pgp_parser_content_free(pgp_packet_t *);
void pgp_seckey_free(pgp_seckey_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 *); void pgp_pk_sesskey_free(pgp_pk_sesskey_t *);
int pgp_print_packet(pgp_printstate_t *, const pgp_packet_t *);
#define DYNARRAY(type, arr) \ #define DYNARRAY(type, arr) \
unsigned arr##c; unsigned arr##vsize; type *arr##s 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) } 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 /** pgp_keydata_key_t
*/ */
typedef union { typedef union {
@ -928,47 +959,59 @@ typedef union {
pgp_seckey_t seckey; pgp_seckey_t seckey;
} pgp_keydata_key_t; } pgp_keydata_key_t;
/** userid signature subpackets */
/* sigpacket_t */ typedef struct pgp_uidsig_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 {
uint32_t uid; /* index in userid array in key */ 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 trustlevel; /* level of trust */
uint8_t trustamount; /* amount 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 */ /* describes a user's key */
struct pgp_key_t { 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_content_enum type; /* type of key */
pgp_keydata_key_t key; /* pubkey/seckey data */ pgp_keydata_key_t key; /* pubkey/seckey data */
pgp_pubkey_t sigkey; /* signature key */
uint8_t sigid[PGP_KEY_ID_SIZE]; DYNARRAY(pgp_directsig_t, directsig); /* direct signatures */
pgp_fingerprint_t sigfingerprint; /* pgp signature fingerprint */
pgp_pubkey_t enckey; /* encryption key */ DYNARRAY(uint8_t *, uid); /* array of user ids */
uint8_t encid[PGP_KEY_ID_SIZE]; DYNARRAY(pgp_uidsig_t, uidsig); /* array of signature for user ids */
pgp_fingerprint_t encfingerprint; /* pgp encryption id fingerprint */
uint32_t uid0; /* primary uid index in uids array */ /* TODO user attributes */
uint8_t revoked; /* key has been revoked */
pgp_revoke_t revocation; /* revocation reason */ 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_ */ #endif /* PACKET_H_ */

View file

@ -50,9 +50,9 @@
#ifndef READERWRITER_H_ #ifndef READERWRITER_H_
#define 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 */ /* if this is defined, we'll use mmap in preference to file ops */
#define USE_MMAP_FOR_FILES 1 #define USE_MMAP_FOR_FILES 1
@ -75,7 +75,7 @@ unsigned pgp_write_se_ip_pktset(pgp_output_t *, const uint8_t *,
const unsigned, const unsigned,
pgp_crypt_t *); pgp_crypt_t *);
void pgp_push_enc_crypt(pgp_output_t *, 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 */ /* Secret Key checksum */
void pgp_push_checksum_writer(pgp_output_t *, pgp_seckey_t *); void pgp_push_checksum_writer(pgp_output_t *, pgp_seckey_t *);

View file

@ -57,9 +57,9 @@
#include <inttypes.h> #include <inttypes.h>
#include "packet-netpgp.h" #include "packet.h"
#include "create-netpgp.h" #include "create.h"
#include "memory-netpgp.h" #include "memory.h"
typedef struct pgp_create_sig_t pgp_create_sig_t; 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 *, unsigned pgp_check_useridcert_sig(const pgp_pubkey_t *,
const uint8_t *, const uint8_t *,
const pgp_sig_t *, const pgp_sig_t *,
const pgp_pubkey_t *, const pgp_pubkey_t *);
const uint8_t *);
unsigned pgp_check_userattrcert_sig(const pgp_pubkey_t *, unsigned pgp_check_userattrcert_sig(const pgp_pubkey_t *,
const pgp_data_t *, const pgp_data_t *,
const pgp_sig_t *, const pgp_sig_t *,
const pgp_pubkey_t *, const pgp_pubkey_t *);
const uint8_t *);
unsigned pgp_check_subkey_sig(const pgp_pubkey_t *, unsigned pgp_check_subkey_sig(const pgp_pubkey_t *,
const pgp_pubkey_t *, const pgp_pubkey_t *,
const pgp_sig_t *, const pgp_sig_t *,
const pgp_pubkey_t *, const pgp_pubkey_t *);
const uint8_t *);
unsigned pgp_check_direct_sig(const pgp_pubkey_t *, unsigned pgp_check_direct_sig(const pgp_pubkey_t *,
const pgp_sig_t *, const pgp_sig_t *,
const pgp_pubkey_t *, const pgp_pubkey_t *);
const uint8_t *);
unsigned pgp_check_hash_sig(pgp_hash_t *, unsigned pgp_check_hash_sig(pgp_hash_t *,
const pgp_sig_t *, const pgp_sig_t *,
const pgp_pubkey_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_end_hashed_subpkts(pgp_create_sig_t *);
unsigned pgp_write_sig(pgp_output_t *, pgp_create_sig_t *, unsigned pgp_write_sig(pgp_output_t *, pgp_create_sig_t *,
const pgp_pubkey_t *, const pgp_seckey_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 *, unsigned pgp_add_issuer_keyid(pgp_create_sig_t *,
const uint8_t *); const uint8_t *);
void pgp_add_primary_userid(pgp_create_sig_t *, unsigned); 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 */ /* Standard Interface */
unsigned pgp_sign_file(pgp_io_t *, unsigned pgp_sign_file(pgp_io_t *,
const char *, const char *,
const char *, const char *,
const pgp_seckey_t *, const pgp_seckey_t *,
const char *, const char *,
const int64_t, const time_t,
const uint64_t, const time_t,
const unsigned, const unsigned,
const unsigned, const unsigned,
const unsigned); const unsigned);
@ -122,10 +130,10 @@ unsigned pgp_sign_file(pgp_io_t *,
int pgp_sign_detached(pgp_io_t *, int pgp_sign_detached(pgp_io_t *,
const char *, const char *,
char *, char *,
pgp_seckey_t *, const pgp_seckey_t *,
const char *, const char *,
const int64_t, const time_t,
const uint64_t, const time_t,
const unsigned, const unsigned,
const unsigned); const unsigned);
@ -157,15 +165,33 @@ pgp_memory_t *pgp_sign_buf(pgp_io_t *,
const void *, const void *,
const size_t, const size_t,
const pgp_seckey_t *, const pgp_seckey_t *,
const int64_t, const time_t,
const uint64_t, const time_t,
const char *, const char *,
const unsigned, const unsigned,
const unsigned); const unsigned);
unsigned pgp_keyring_read_from_mem(pgp_io_t *, /** \ingroup Core_Create
pgp_keyring_t *, * needed for signature creation
const unsigned, */
pgp_memory_t *); 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_ */ #endif /* SIGNATURE_H_ */

View file

@ -49,8 +49,6 @@
#ifndef TYPES_H_ #ifndef TYPES_H_
#define TYPES_H_ #define TYPES_H_
#include "config-netpgp.h"
#ifdef HAVE_INTTYPES_H #ifdef HAVE_INTTYPES_H
#include <inttypes.h> #include <inttypes.h>
#endif #endif

View file

@ -49,29 +49,36 @@
#ifndef VALIDATE_H_ #ifndef VALIDATE_H_
#define VALIDATE_H_ 1 #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 */ /** Struct used with the validate_key_cb callback */
typedef struct { typedef struct validate_key_cb_t{
pgp_pubkey_t pubkey; pgp_content_enum type; /* type of key */
pgp_pubkey_t subkey; pgp_keydata_key_t key; /* pubkey/seckey data */
pgp_seckey_t seckey; pgp_keydata_key_t subkey;
uint8_t pubkeyid[PGP_KEY_ID_SIZE];
enum { enum {
ATTRIBUTE = 1, LS_UNKNOWN = 0,
ID LS_ATTRIBUTE,
LS_ID,
LS_SUBKEY,
LS_PRIMARY,
} last_seen; } last_seen;
uint8_t *userid; uint8_t *userid;
pgp_data_t userattr; pgp_data_t userattr;
uint8_t hash[PGP_MAX_HASH_SIZE]; uint8_t hash[PGP_MAX_HASH_SIZE];
const pgp_keyring_t *keyring; const pgp_keyring_t *keyring;
validate_reader_t *reader;
pgp_validation_t *result; pgp_validation_t *result;
pgp_cb_ret_t(*getpassphrase) (const pgp_packet_t *, pgp_cb_ret_t(*getpassphrase) (const pgp_packet_t *,
pgp_cbdata_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; } validate_key_cb_t;
/** Struct use with the validate_data_cb callback */ /** Struct use with the validate_data_cb callback */
@ -87,13 +94,10 @@ typedef struct {
uint8_t hash[PGP_MAX_HASH_SIZE]; uint8_t hash[PGP_MAX_HASH_SIZE];
pgp_memory_t *mem; pgp_memory_t *mem;
const pgp_keyring_t *keyring; const pgp_keyring_t *keyring;
validate_reader_t *reader;/* reader-specific arg */
pgp_validation_t *result; pgp_validation_t *result;
char *detachname; char *detachname;
} validate_data_cb_t; } 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 *); pgp_cb_ret_t pgp_validate_key_cb(const pgp_packet_t *, pgp_cbdata_t *);
unsigned check_binary_sig(const uint8_t *, unsigned check_binary_sig(const uint8_t *,
@ -115,6 +119,30 @@ unsigned pgp_validate_mem(pgp_io_t *,
const int, const int,
const pgp_keyring_t *); 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_ */ #endif /* !VALIDATE_H_ */

View file

@ -58,9 +58,9 @@
#endif #endif
/* development versions have .99 suffix */ /* 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 \ #define NETPGP_VERSION_STRING \
NETPGP_VERSION_CAT(NETPGP_BASE_VERSION, NETPGP_AUTOCONF_VERSION) NETPGP_VERSION_CAT(NETPGP_BASE_VERSION, NETPGP_AUTOCONF_VERSION)

View file

@ -53,11 +53,11 @@
#ifndef WRITER_H_ #ifndef WRITER_H_
#define WRITER_H_ #define WRITER_H_
#include "types-netpgp.h" #include "types.h"
#include "packet-netpgp.h" #include "packet.h"
#include "crypto-netpgp.h" #include "crypto.h"
#include "errors-netpgp.h" #include "errors.h"
#include "keyring-netpgp.h" #include "keyring.h"
/** /**
* \ingroup Writer * \ingroup Writer
@ -114,6 +114,10 @@ unsigned pgp_write_mpi(pgp_output_t *, const BIGNUM *);
void pgp_writer_info_delete(pgp_writer_t *); void pgp_writer_info_delete(pgp_writer_t *);
unsigned pgp_writer_info_finalise(pgp_error_t **, 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_ */ #endif /* WRITER_H_ */

View file

@ -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_ */

File diff suppressed because it is too large Load diff

View file

@ -1,653 +0,0 @@
/*-
* Copyright (c) 2010 Alistair Crooks <agc@NetBSD.org>
* 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 <sys/types.h>
#include <inttypes.h>
#include <regex.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}
}

View file

@ -1,79 +0,0 @@
/*-
* Copyright (c) 2010,2011 Alistair Crooks <agc@NetBSD.org>
* 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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -49,7 +49,7 @@
/** \file /** \file
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -57,7 +57,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#ifdef HAVE_ZLIB_H #ifdef HAVE_ZLIB_H
@ -70,12 +70,12 @@ __RCSID("$NetBSD: compress.c,v 1.23 2012/03/05 02:20:18 christos Exp $");
#include <string.h> #include <string.h>
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "errors-netpgp.h" #include "netpgp/errors.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "memory-netpgp.h" #include "netpgp/memory.h"
#include "writer-netpgp.h" #include "netpgp/writer.h"
#define DECOMPRESS_BUFFER 1024 #define DECOMPRESS_BUFFER 1024
@ -188,8 +188,9 @@ zlib_compressed_data_reader(pgp_stream_t *stream, void *dest, size_t length,
return 0; return 0;
} }
len = (size_t)(z->zstream.next_out - &z->out[z->offset]); len = (size_t)(z->zstream.next_out - &z->out[z->offset]);
if (len > length) { size_t left_in_cdest = length - cc;
len = length; if (len > left_in_cdest) {
len = left_in_cdest;
} }
(void) memcpy(&cdest[cc], &z->out[z->offset], len); (void) memcpy(&cdest[cc], &z->out[z->offset], len);
z->offset += len; z->offset += len;

View file

@ -49,7 +49,7 @@
/** \file /** \file
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -57,7 +57,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -78,15 +78,15 @@ __RCSID("$NetBSD: create.c,v 1.38 2010/11/15 08:03:39 agc Exp $");
#include <openssl/cast.h> #include <openssl/cast.h>
#endif #endif
#include "create-netpgp.h" #include "netpgp/create.h"
#include "keyring-netpgp.h" #include "netpgp/keyring.h"
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "writer-netpgp.h" #include "netpgp/writer.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "memory-netpgp.h" #include "netpgp/memory.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "netpgpdigest.h" #include "netpgp/netpgpdigest.h"
/** /**
* \ingroup Core_Create * \ingroup Core_Create
@ -98,10 +98,10 @@ __RCSID("$NetBSD: create.c,v 1.38 2010/11/15 08:03:39 agc Exp $");
unsigned unsigned
pgp_write_ss_header(pgp_output_t *output, pgp_write_ss_header(pgp_output_t *output,
unsigned length, size_t length,
pgp_content_enum type) pgp_content_enum type)
{ {
return pgp_write_length(output, length) && return pgp_write_length(output, (unsigned int)length) &&
pgp_write_scalar(output, (unsigned)(type - pgp_write_scalar(output, (unsigned)(type -
(unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1); (unsigned)PGP_PTAG_SIG_SUBPKT_BASE), 1);
} }
@ -176,6 +176,11 @@ pubkey_length(const pgp_pubkey_t *key)
case PGP_PKA_RSA: case PGP_PKA_RSA:
return mpi_length(key->key.rsa.n) + mpi_length(key->key.rsa.e); 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: default:
(void) fprintf(stderr, (void) fprintf(stderr,
"pubkey_length: unknown key algorithm\n"); "pubkey_length: unknown key algorithm\n");
@ -188,7 +193,6 @@ seckey_length(const pgp_seckey_t *key)
{ {
int len; int len;
len = 0;
switch (key->pubkey.alg) { switch (key->pubkey.alg) {
case PGP_PKA_DSA: case PGP_PKA_DSA:
return (unsigned)(mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey)); 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); mpi_length(key->key.rsa.q) + mpi_length(key->key.rsa.u);
return (unsigned)(len + pubkey_length(&key->pubkey)); return (unsigned)(len + pubkey_length(&key->pubkey));
case PGP_PKA_ELGAMAL:
return (unsigned)(
mpi_length(key->key.dsa.x) + pubkey_length(&key->pubkey));
default: default:
(void) fprintf(stderr, (void) fprintf(stderr,
"seckey_length: unknown key algorithm\n"); "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 * Note that we support v3 keys here because they're needed for
* verification. * verification.
*/ */
unsigned static unsigned
write_seckey_body(const pgp_seckey_t *key, write_seckey_body(const pgp_seckey_t *key,
const uint8_t *passphrase, const uint8_t *passphrase,
const size_t pplen, const size_t pplen,
@ -285,17 +294,17 @@ write_seckey_body(const pgp_seckey_t *key,
pgp_hash_t hash; pgp_hash_t hash;
unsigned done = 0; unsigned done = 0;
unsigned i = 0; unsigned i = 0;
uint8_t *hashed;
uint8_t sesskey[CAST_KEY_LENGTH]; uint8_t sesskey[CAST_KEY_LENGTH];
if (!write_pubkey_body(&key->pubkey, output)) { if (!write_pubkey_body(&key->pubkey, output)) {
return 0; return 0;
} }
if (key->s2k_usage != PGP_S2KU_ENCRYPTED_AND_HASHED) { if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) {
(void) fprintf(stderr, "write_seckey_body: s2k usage\n");
return 0; return 0;
} }
if (!pgp_write_scalar(output, (unsigned)key->s2k_usage, 1)) { 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; return 0;
} }
@ -365,6 +374,7 @@ write_seckey_body(const pgp_seckey_t *key,
unsigned needed; unsigned needed;
unsigned size; unsigned size;
uint8_t zero = 0; uint8_t zero = 0;
uint8_t *hashed;
/* Hard-coded SHA1 for session key */ /* Hard-coded SHA1 for session key */
pgp_hash_any(&hash, PGP_HASH_SHA1); pgp_hash_any(&hash, PGP_HASH_SHA1);
@ -377,6 +387,7 @@ write_seckey_body(const pgp_seckey_t *key,
} }
if (!hash.init(&hash)) { if (!hash.init(&hash)) {
(void) fprintf(stderr, "write_seckey_body: bad alloc\n"); (void) fprintf(stderr, "write_seckey_body: bad alloc\n");
free(hashed);
return 0; return 0;
} }
@ -405,6 +416,7 @@ write_seckey_body(const pgp_seckey_t *key,
(void) memcpy(&sesskey[i * hashsize], (void) memcpy(&sesskey[i * hashsize],
hashed, (unsigned)size); hashed, (unsigned)size);
done += (unsigned)size; done += (unsigned)size;
free(hashed);
if (done > CAST_KEY_LENGTH) { if (done > CAST_KEY_LENGTH) {
(void) fprintf(stderr, (void) fprintf(stderr,
"write_seckey_body: short add\n"); "write_seckey_body: short add\n");
@ -439,6 +451,9 @@ write_seckey_body(const pgp_seckey_t *key,
(void) fprintf(stderr, "\nturning encryption on...\n"); (void) fprintf(stderr, "\nturning encryption on...\n");
} }
pgp_push_enc_crypt(output, &crypted); pgp_push_enc_crypt(output, &crypted);
}else{
pgp_push_sum16_writer(output);
}
switch (key->pubkey.alg) { switch (key->pubkey.alg) {
case PGP_PKA_RSA: case PGP_PKA_RSA:
@ -463,11 +478,19 @@ write_seckey_body(const pgp_seckey_t *key,
return 0; return 0;
} }
if (key->s2k_usage != PGP_S2KU_NONE) {
if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) { if (!pgp_write(output, key->checkhash, PGP_CHECKHASH_SIZE)) {
return 0; return 0;
} }
pgp_writer_pop(output); pgp_writer_pop(output);
}else{
uint16_t checksum = pgp_pop_sum16_writer(output);
if (!pgp_write_scalar(output, checksum, 2)) {
return 0;
}
}
return 1; return 1;
} }
@ -480,13 +503,20 @@ write_seckey_body(const pgp_seckey_t *key,
* \return 1 if OK, otherwise 0 * \return 1 if OK, otherwise 0
*/ */
unsigned 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)) && pgp_write_length(output, 1 + 4 + 1 + pubkey_length(key)) &&
write_pubkey_body(key, output); 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 \ingroup HighLevel_KeyWrite
@ -500,40 +530,104 @@ write_struct_pubkey(pgp_output_t *output, const pgp_pubkey_t *key)
*/ */
unsigned unsigned
pgp_write_xfer_pubkey(pgp_output_t *output, pgp_write_xfer_key(pgp_output_t *output,
const pgp_key_t *key, const pgp_key_t *key,
const unsigned armoured) 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) { if (armoured) {
pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK); pgp_writer_push_armoured(output, PGP_PGP_PUBLIC_KEY_BLOCK);
} }
/* public key */
if (!write_struct_pubkey(output, &key->key.pubkey)) { /* primary key */
if (key->type == PGP_PTAG_CT_PUBLIC_KEY) {
if (!pgp_write_struct_pubkey(output, &key->key.pubkey)) {
return 0; return 0;
} }
}else{
/* TODO: revocation signatures go here */ if (!pgp_write_struct_seckey(&key->key.seckey, (const uint8_t *)"", 0, output)) {
/* user ids and corresponding signatures */
for (i = 0; i < key->uidc; i++) {
if (!pgp_write_struct_userid(output, key->uids[i])) {
return 0; return 0;
} }
for (j = 0; j < key->packetc; j++) { }
if (!pgp_write(output, key->packets[j].raw, (unsigned)key->packets[j].length)) {
directsigp = key->directsigs;
for (directsigidx = 0 ; directsigidx < key->directsigc;
directsigidx++, directsigp++)
{
if (!pgp_write(output, directsigp->packet.raw,
(unsigned)directsigp->packet.length)) {
return 0;
}
}
/* 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; return 0;
} }
} }
} }
}
/* TODO: user attributes and corresponding signatures */ /* TODO attibutes */
/* /* Loop over key's subkeys */
* subkey packets and corresponding signatures and optional subkeyp = key->subkeys;
* revocation 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) { if (armoured) {
pgp_writer_info_finalise(&output->errors, &output->writer); pgp_writer_info_finalise(&output->errors, &output->writer);
@ -554,53 +648,15 @@ pgp_write_xfer_pubkey(pgp_output_t *output,
\param output Output stream \param output Output stream
*/ */
/* TODO have encrypted key export again
unsigned unsigned
pgp_write_xfer_seckey(pgp_output_t *output, pgp_write_xfer_seckey(pgp_output_t *output,
const pgp_key_t *key, const pgp_key_t *key,
const uint8_t *passphrase, const uint8_t *passphrase,
const size_t pplen, const size_t pplen,
unsigned armoured) 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 * \ingroup Core_WritePackets
* \brief Writes one RSA public key packet. * \brief Writes one RSA public key packet.
@ -620,7 +676,7 @@ pgp_write_rsa_pubkey(time_t t, const BIGNUM *n,
pgp_pubkey_t key; pgp_pubkey_t key;
pgp_fast_create_rsa_pubkey(&key, t, __UNCONST(n), __UNCONST(e)); 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 * \return 1 if OK; else 0
*/ */
unsigned 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 uint8_t *passphrase,
const size_t pplen, const size_t pplen,
pgp_output_t *output) pgp_output_t *output,
pgp_content_enum ptag)
{ {
int length = 0; int length = 0;
@ -709,7 +766,7 @@ pgp_write_struct_seckey(const pgp_seckey_t *key,
/* Ref: RFC4880 Section 5.5.3 */ /* Ref: RFC4880 Section 5.5.3 */
/* pubkey, excluding MPIs */ /* pubkey, excluding MPIs */
length += 1 + 4 + 1 + 1; length += 1 + 4 + 1;
/* s2k usage */ /* s2k usage */
length += 1; length += 1;
@ -776,12 +833,21 @@ pgp_write_struct_seckey(const pgp_seckey_t *key,
/* secret key and public key MPIs */ /* secret key and public key MPIs */
length += (unsigned)seckey_length(key); 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,1+4+1+1+seckey_length(key)+2) && */
pgp_write_length(output, (unsigned)length) && pgp_write_length(output, (unsigned)length) &&
write_seckey_body(key, passphrase, pplen, output); 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 * \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 \note Currently hard-coded to use RSA
*/ */
pgp_pk_sesskey_t * 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 * 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 * can be any, we're hardcoding RSA for now
*/ */
const pgp_pubkey_t *pubkey; pgp_pubkey_t *pubkey;
pgp_pk_sesskey_t *sesskey; pgp_pk_sesskey_t *sesskey;
pgp_symm_alg_t cipher; pgp_symm_alg_t cipher;
const uint8_t *id; 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; uint8_t *encoded_m_buf;
size_t sz_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_key_get_enckey(key, &id);
pubkey = pgp_get_pubkey(key);
id = key->sigid;
} else {
pubkey = &key->enckey;
id = key->encid;
}
/* allocate unencoded_m_buf here */ /* allocate unencoded_m_buf here */
(void) memset(&cipherinfo, 0x0, sizeof(cipherinfo)); (void) memset(&cipherinfo, 0x0, sizeof(cipherinfo));
pgp_crypt_any(&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->alg = pubkey->alg;
sesskey->symm_alg = cipher; sesskey->symm_alg = cipher;
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); pgp_random(sesskey->key, cipherinfo.keysize);
}
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
hexdump(stderr, "sesskey created", sesskey->key, hexdump(stderr, "sesskey created", sesskey->key,

View file

@ -46,7 +46,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -54,7 +54,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -66,12 +66,14 @@ __RCSID("$NetBSD: crypto.c,v 1.36 2014/02/17 07:39:19 agc Exp $");
#include <string.h> #include <string.h>
#include "types-netpgp.h" #include "netpgp/types.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "memory-netpgp.h" #include "netpgp/memory.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "netpgp/netpgpsdk.h"
#include "netpgp/validate.h"
/** /**
\ingroup Core_MPI \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__)) { if (pgp_get_debug_level(__FILE__)) {
printf("write_parsed_cb: "); 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) { if (pkt->tag != PGP_PTAG_CT_UNARMOURED_TEXT && cbinfo->printstate.skipping) {
puts("...end of skip"); 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); return pgp_get_seckey_cb(pkt, cbinfo);
case PGP_GET_PASSPHRASE: case PGP_GET_PASSPHRASE:
if (cbinfo->cryptinfo.getpassphrase) {
return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo);
}
break;
case PGP_PTAG_CT_LITDATA_BODY: case PGP_PTAG_CT_LITDATA_BODY:
return pgp_litdata_cb(pkt, cbinfo); return pgp_litdata_cb(pkt, cbinfo);
@ -356,6 +361,7 @@ pgp_encrypt_file(pgp_io_t *io,
{ {
pgp_output_t *output; pgp_output_t *output;
pgp_memory_t *inmem; pgp_memory_t *inmem;
pgp_keyring_t *rcpts;
int fd_out; int fd_out;
__PGP_USED(io); __PGP_USED(io);
@ -374,11 +380,23 @@ pgp_encrypt_file(pgp_io_t *io,
pgp_writer_push_armor_msg(output); 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 */ /* 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); pgp_memory_free(inmem);
return 0; return 0;
} }
pgp_keyring_free(rcpts);
/* This does the writing */ /* This does the writing */
pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem)); 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, pgp_encrypt_buf(pgp_io_t *io,
const void *input, const void *input,
const size_t insize, const size_t insize,
const pgp_key_t *pubkey, const pgp_keyring_t *pubkeys,
const unsigned use_armour, const unsigned use_armour,
const char *cipher) const char *cipher,
unsigned raw)
{ {
pgp_output_t *output; pgp_output_t *output;
pgp_memory_t *outmem; pgp_memory_t *outmem;
@ -417,7 +436,7 @@ pgp_encrypt_buf(pgp_io_t *io,
} }
/* Push the encrypted writer */ /* 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 */ /* This does the writing */
pgp_write(output, input, (unsigned)insize); 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 */ /* if we didn't get the passphrase, return NULL */
return (parse->cbinfo.gotpass) ? outmem : 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;
}

1644
libs/netpgp/src/keyring.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -49,7 +49,7 @@
/** \file /** \file
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -57,7 +57,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -78,123 +78,24 @@ __RCSID("$NetBSD: misc.c,v 1.41 2012/03/05 02:20:18 christos Exp $");
#include <openssl/rand.h> #include <openssl/rand.h>
#endif #endif
#include "errors-netpgp.h" #include "netpgp/errors.h"
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "create-netpgp.h" #include "netpgp/create.h"
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "packet-show.h" #include "netpgp/packet-show.h"
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "netpgpsdk.h" #include "netpgp/netpgpsdk.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "memory-netpgp.h" #include "netpgp/memory.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "version-netpgp.h" #include "netpgp/version.h"
#include "netpgpdigest.h" #include "netpgp/netpgpdigest.h"
#ifdef WIN32 #ifdef WIN32
#define vsnprintf _vsnprintf #define vsnprintf _vsnprintf
#endif #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 /** \file
* \brief Error Handling * \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 hash Hash to set up
\param alg Hash algorithm to use \param alg Hash algorithm to use
*/ */
void unsigned
pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg) pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg)
{ {
switch (alg) { switch (alg) {
@ -627,7 +528,9 @@ pgp_hash_any(pgp_hash_t *hash, pgp_hash_alg_t alg)
default: default:
(void) fprintf(stderr, "pgp_hash_any: bad algorithm\n"); (void) fprintf(stderr, "pgp_hash_any: bad algorithm\n");
return 0;
} }
return 1;
} }
/** /**

570
libs/netpgp/src/netpgp.c Normal file
View file

@ -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 <sys/cdefs.h>
#endif
#if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved.");
__RCSID("$NetBSD$");
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/mman.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include <errno.h>
#include <regex.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#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, "<stderr>") == 0) {
io->outs = stderr;
}
io->errs = stderr;
if ((stream = netpgp_getvar(netpgp, "errs")) != NULL &&
strcmp(stream, "<stdout>") == 0) {
io->errs = stdout;
}
if ((results = netpgp_getvar(netpgp, "res")) == NULL) {
io->res = io->errs;
} else if (strcmp(results, "<stdout>") == 0) {
io->res = stdout;
} else if (strcmp(results, "<stderr>") == 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;
}

View file

@ -49,7 +49,7 @@
/** \file /** \file
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -57,7 +57,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#ifdef HAVE_OPENSSL_DSA_H #ifdef HAVE_OPENSSL_DSA_H
@ -82,12 +82,13 @@ __RCSID("$NetBSD: openssl_crypto.c,v 1.33 2010/11/07 08:39:59 agc Exp $");
#include <unistd.h> #include <unistd.h>
#endif #endif
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "keyring-netpgp.h" #include "netpgp/keyring.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "netpgpdigest.h" #include "netpgp/netpgpdigest.h"
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "netpgp/openssl11stub.h"
static void static void
@ -95,12 +96,14 @@ test_seckey(const pgp_seckey_t *seckey)
{ {
RSA *test = RSA_new(); RSA *test = RSA_new();
test->n = BN_dup(seckey->pubkey.key.rsa.n); RSA_set0_key(test,
test->e = BN_dup(seckey->pubkey.key.rsa.e); 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); RSA_set0_factors(test,
test->p = BN_dup(seckey->key.rsa.p); BN_dup(seckey->key.rsa.p),
test->q = BN_dup(seckey->key.rsa.q); BN_dup(seckey->key.rsa.q));
if (RSA_check_key(test) != 1) { if (RSA_check_key(test) != 1) {
(void) fprintf(stderr, (void) fprintf(stderr,
@ -440,20 +443,25 @@ pgp_dsa_verify(const uint8_t *hash, size_t hash_length,
int ret; int ret;
osig = DSA_SIG_new(); osig = DSA_SIG_new();
osig->r = sig->r; DSA_SIG_set0(osig,
osig->s = sig->s; BN_dup(sig->r),
BN_dup(sig->s));
odsa = DSA_new(); odsa = DSA_new();
odsa->p = dsa->p; DSA_set0_pqg(odsa,
odsa->q = dsa->q; BN_dup(dsa->p),
odsa->g = dsa->g; BN_dup(dsa->q),
odsa->pub_key = dsa->y; BN_dup(dsa->g));
DSA_set0_key(odsa,
BN_dup(dsa->y),
NULL);
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
hexdump(stderr, "input hash", hash, hash_length); 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; hash_length = qlen;
} }
ret = DSA_do_verify(hash, (int)hash_length, osig, odsa); 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; return 0;
} }
odsa->p = odsa->q = odsa->g = odsa->pub_key = NULL;
DSA_free(odsa); DSA_free(odsa);
osig->r = osig->s = NULL;
DSA_SIG_free(osig); DSA_SIG_free(osig);
return (unsigned)ret; return (unsigned)ret;
@ -493,12 +499,14 @@ pgp_rsa_public_decrypt(uint8_t *out,
int n; int n;
orsa = RSA_new(); orsa = RSA_new();
orsa->n = pubkey->n; RSA_set0_key(orsa,
orsa->e = pubkey->e; BN_dup(pubkey->n),
BN_dup(pubkey->e),
NULL);
n = RSA_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING); n = RSA_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING);
orsa->n = orsa->e = NULL;
RSA_free(orsa); RSA_free(orsa);
return n; return n;
@ -525,20 +533,19 @@ pgp_rsa_private_encrypt(uint8_t *out,
int n; int n;
orsa = RSA_new(); orsa = RSA_new();
orsa->n = BN_dup(pubkey->n);
orsa->d = seckey->d; RSA_set0_key(orsa,
orsa->p = seckey->q; /* p and q are round the other way in openssl */ BN_dup(pubkey->n),
orsa->q = seckey->p; 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 */ /* 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) { if (RSA_check_key(orsa) != 1) {
(void) fprintf(stderr, "RSA_check_key is not set\n"); (void) fprintf(stderr, "RSA_check_key is not set\n");
return 0; 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); n = RSA_private_encrypt((int)length, in, out, orsa, RSA_NO_PADDING);
orsa->n = orsa->d = orsa->p = orsa->q = NULL;
RSA_free(orsa); RSA_free(orsa);
return n; return n;
@ -575,13 +581,16 @@ pgp_rsa_private_decrypt(uint8_t *out,
char errbuf[1024]; char errbuf[1024];
keypair = RSA_new(); keypair = RSA_new();
keypair->n = pubkey->n; /* XXX: do we need n? */ RSA_set0_key(keypair,
keypair->d = seckey->d; BN_dup(pubkey->n),
keypair->p = seckey->q; BN_dup(pubkey->e),
keypair->q = seckey->p; BN_dup(seckey->d));
RSA_set0_factors(keypair,
BN_dup(seckey->p),
BN_dup(seckey->q));
/* debug */ /* debug */
keypair->e = pubkey->e;
if (RSA_check_key(keypair) != 1) { if (RSA_check_key(keypair) != 1) {
(void) fprintf(stderr, "RSA_check_key is not set\n"); (void) fprintf(stderr, "RSA_check_key is not set\n");
return 0; return 0;
@ -601,7 +610,6 @@ pgp_rsa_private_decrypt(uint8_t *out,
ERR_error_string(err, &errbuf[0]); ERR_error_string(err, &errbuf[0]);
(void) fprintf(stderr, "openssl error : %s\n", errbuf); (void) fprintf(stderr, "openssl error : %s\n", errbuf);
} }
keypair->n = keypair->d = keypair->p = keypair->q = NULL;
RSA_free(keypair); RSA_free(keypair);
return n; return n;
@ -627,8 +635,10 @@ pgp_rsa_public_encrypt(uint8_t *out,
/* printf("pgp_rsa_public_encrypt: length=%ld\n", length); */ /* printf("pgp_rsa_public_encrypt: length=%ld\n", length); */
orsa = RSA_new(); orsa = RSA_new();
orsa->n = pubkey->n; RSA_set0_key(orsa,
orsa->e = pubkey->e; BN_dup(pubkey->n),
BN_dup(pubkey->e),
NULL);
/* printf("len: %ld\n", length); */ /* printf("len: %ld\n", length); */
/* pgp_print_bn("n: ", orsa->n); */ /* 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); fd_out = BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
ERR_print_errors(fd_out); ERR_print_errors(fd_out);
} }
orsa->n = orsa->e = NULL;
RSA_free(orsa); RSA_free(orsa);
return n; return n;
@ -656,8 +665,8 @@ pgp_rsa_public_encrypt(uint8_t *out,
void void
pgp_crypto_finish(void) pgp_crypto_finish(void)
{ {
CRYPTO_cleanup_all_ex_data(); // No cleanup since OpenSSL 1.1.0
ERR_remove_state((unsigned long)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) \note It is the caller's responsibility to call pgp_keydata_free(keydata)
*/ */
unsigned unsigned
rsa_generate_keypair(pgp_key_t *keydata, pgp_rsa_generate_keypair(pgp_key_t *keydata,
const int numbits, const int numbits,
const unsigned long e__, const unsigned long e__,
const char *hashalg, const char *hashalg,
const char *cipher) const char *cipher,
const uint8_t *passphrase,
const size_t pplen)
{ {
pgp_seckey_t *seckey; pgp_seckey_t *seckey;
RSA *rsa = RSA_new(); RSA *rsa;
BN_CTX *ctx; BN_CTX *ctx;
pgp_output_t *output; pgp_output_t *output;
pgp_memory_t *mem; 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(); ctx = BN_CTX_new();
pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY); pgp_keydata_init(keydata, PGP_PTAG_CT_SECRET_KEY);
@ -700,14 +717,29 @@ rsa_generate_keypair(pgp_key_t *keydata,
/* generate the key pair */ /* generate the key pair */
//rsa = RSA_generate_key(numbits, e, NULL, NULL); BIGNUM *exp = BN_new();
/* generate key */ BN_set_word(exp, e__);
BIGNUM* e = BN_new(); /*
BN_set_word(e, e__); #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
if( RSA_generate_key_ex(rsa, numbits, e, 0) != 1 ) { 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; return 0;
} */
BN_free(e);
rsa = RSA_new();
res = RSA_generate_key_ex(rsa, numbits, exp, NULL);
BN_free(exp);
if (!res){
RSA_free(rsa);
return 0;
};
/* populate pgp key from ssl key */ /* populate pgp key from ssl key */
@ -716,11 +748,14 @@ rsa_generate_keypair(pgp_key_t *keydata,
seckey->pubkey.days_valid = 0; seckey->pubkey.days_valid = 0;
seckey->pubkey.alg = PGP_PKA_RSA; seckey->pubkey.alg = PGP_PKA_RSA;
seckey->pubkey.key.rsa.n = BN_dup(rsa->n); RSA_get0_key(rsa, &_n, &_e, &_d);
seckey->pubkey.key.rsa.e = BN_dup(rsa->e);
seckey->s2k_usage = PGP_S2KU_ENCRYPTED_AND_HASHED; seckey->pubkey.key.rsa.n = BN_dup(_n);
seckey->s2k_specifier = PGP_S2KS_SALTED; 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; */ /* seckey->s2k_specifier=PGP_S2KS_SIMPLE; */
if ((seckey->hash_alg = pgp_str_to_hash_alg(hashalg)) == PGP_HASH_UNKNOWN) { if ((seckey->hash_alg = pgp_str_to_hash_alg(hashalg)) == PGP_HASH_UNKNOWN) {
seckey->hash_alg = PGP_HASH_SHA1; seckey->hash_alg = PGP_HASH_SHA1;
@ -729,20 +764,22 @@ rsa_generate_keypair(pgp_key_t *keydata,
seckey->octetc = 0; seckey->octetc = 0;
seckey->checksum = 0; seckey->checksum = 0;
seckey->key.rsa.d = BN_dup(rsa->d); RSA_get0_factors(rsa, &_p, &_q);
seckey->key.rsa.p = BN_dup(rsa->p); seckey->key.rsa.d = BN_dup(_d);
seckey->key.rsa.q = BN_dup(rsa->q); seckey->key.rsa.p = BN_dup(_p);
seckey->key.rsa.u = BN_mod_inverse(NULL, rsa->p, rsa->q, ctx); seckey->key.rsa.q = BN_dup(_q);
seckey->key.rsa.u = BN_mod_inverse(NULL, _p, _q, ctx);
if (seckey->key.rsa.u == NULL) { 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; return 0;
} }
BN_CTX_free(ctx); BN_CTX_free(ctx);
RSA_free(rsa); RSA_free(rsa);
pgp_keyid(keydata->sigid, PGP_KEY_ID_SIZE, &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->sigfingerprint, &keydata->key.seckey.pubkey, seckey->hash_alg); pgp_fingerprint(&keydata->pubkeyfpr, &keydata->key.seckey.pubkey, seckey->hash_alg);
/* Generate checksum */ /* Generate checksum */
@ -797,7 +834,7 @@ rsa_generate_keypair(pgp_key_t *keydata,
\return The new keypair or NULL \return The new keypair or NULL
\note It is the caller's responsibility to call pgp_keydata_free(keydata) \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() \sa pgp_keydata_free()
*/ */
pgp_key_t * pgp_key_t *
@ -810,15 +847,16 @@ pgp_rsa_new_selfsign_key(const int numbits,
pgp_key_t *keydata; pgp_key_t *keydata;
keydata = pgp_keydata_new(); keydata = pgp_keydata_new();
if (!rsa_generate_keypair(keydata, numbits, e, hashalg, cipher) || if (!pgp_rsa_generate_keypair(keydata, numbits, e, hashalg, cipher,
!pgp_add_selfsigned_userid(keydata, userid)) { (const uint8_t *) "", (const size_t) 0) ||
!pgp_add_selfsigned_userid(keydata, NULL, userid, 0 /*never expire*/)) {
pgp_keydata_free(keydata); pgp_keydata_free(keydata);
return NULL; return NULL;
} }
return keydata; return keydata;
} }
DSA_SIG * pgp_dsa_sig_t *
pgp_dsa_sign(uint8_t *hashbuf, pgp_dsa_sign(uint8_t *hashbuf,
unsigned hashsize, unsigned hashsize,
const pgp_dsa_seckey_t *secdsa, const pgp_dsa_seckey_t *secdsa,
@ -826,64 +864,37 @@ pgp_dsa_sign(uint8_t *hashbuf,
{ {
DSA_SIG *dsasig; DSA_SIG *dsasig;
DSA *odsa; DSA *odsa;
pgp_dsa_sig_t *pgpdsasig;
const BIGNUM *pr = NULL;
const BIGNUM *ps = NULL;
odsa = DSA_new(); odsa = DSA_new();
odsa->p = pubdsa->p; DSA_set0_pqg(odsa,
odsa->q = pubdsa->q; BN_dup(pubdsa->p),
odsa->g = pubdsa->g; BN_dup(pubdsa->q),
odsa->pub_key = pubdsa->y; BN_dup(pubdsa->g));
odsa->priv_key = secdsa->x;
DSA_set0_key(odsa,
BN_dup(pubdsa->y),
BN_dup(secdsa->x));
dsasig = DSA_do_sign(hashbuf, (int)hashsize, odsa); dsasig = DSA_do_sign(hashbuf, (int)hashsize, odsa);
odsa->p = odsa->q = odsa->g = odsa->pub_key = odsa->priv_key = NULL;
DSA_free(odsa); 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);
} }
int DSA_SIG_free(dsasig);
openssl_read_pem_seckey(const char *f, pgp_key_t *key, const char *type, int verbose) return pgpdsasig;
{ }
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 * Decide the number of bits in the random componont k

View file

@ -50,7 +50,7 @@
/** \file /** \file
* \brief Parser for OpenPGP packets * \brief Parser for OpenPGP packets
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -58,7 +58,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -80,16 +80,16 @@ __RCSID("$NetBSD: packet-parse.c,v 1.51 2012/03/05 02:20:18 christos Exp $");
#include <limits.h> #include <limits.h>
#endif #endif
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "keyring-netpgp.h" #include "netpgp/keyring.h"
#include "errors-netpgp.h" #include "netpgp/errors.h"
#include "packet-show.h" #include "netpgp/packet-show.h"
#include "create-netpgp.h" #include "netpgp/create.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "netpgpdigest.h" #include "netpgp/netpgpdigest.h"
#define ERRP(cbinfo, cont, err) do { \ #define ERRP(cbinfo, cont, err) do { \
cont.u.error = err; \ 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 * 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 * 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;) { for (n = 0; n < length;) {
int r; int r;
r = readinfo->reader(stream, (char *) dest + n, length - n, errors, 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); readinfo, cbinfo);
}
if (r > (int)(length - n)) { if (r > (int)(length - n)) {
(void) fprintf(stderr, "sub_base_read: bad read\n"); (void) fprintf(stderr, "sub_base_read: bad read\n");
return 0; return 0;
@ -454,6 +483,7 @@ limread(uint8_t *dest, unsigned length,
&info->readinfo, &info->cbinfo); &info->readinfo, &info->cbinfo);
} }
#if 0
static unsigned static unsigned
exact_limread(uint8_t *dest, unsigned len, exact_limread(uint8_t *dest, unsigned len,
pgp_region_t *region, pgp_region_t *region,
@ -466,6 +496,7 @@ exact_limread(uint8_t *dest, unsigned len,
stream->exact_read = 0; stream->exact_read = 0;
return ret; return ret;
} }
#endif
/** Skip over length bytes of this packet. /** 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 nonzero;
unsigned ret; unsigned ret;
stream->reading_mpi_len = 1; //stream->reading_mpi_len = 1;
ret = (unsigned)limread_scalar(&length, 2, region, stream); ret = (unsigned)limread_scalar(&length, 2, region, stream);
stream->reading_mpi_len = 0; //stream->reading_mpi_len = 0;
if (!ret) if (!ret)
return 0; return 0;
@ -704,11 +735,12 @@ static void
streamread(pgp_stream_t *stream, unsigned c) streamread(pgp_stream_t *stream, unsigned c)
{ {
int cc; int cc;
pgp_reader_t *readinfo = &stream->readinfo;
stream->virtualpkt = realloc(stream->virtualpkt, stream->virtualc + c); readinfo->virtualpkt = realloc(readinfo->virtualpkt, readinfo->virtualc + c);
cc = stream->readinfo.reader(stream, &stream->virtualpkt[stream->virtualc], cc = readinfo->reader(stream, &readinfo->virtualpkt[readinfo->virtualc],
c, &stream->errors, &stream->readinfo, &stream->cbinfo); c, &stream->errors, readinfo, &stream->cbinfo);
stream->virtualc += cc; readinfo->virtualc += cc;
} }
/* coalesce all the partial blocks together */ /* coalesce all the partial blocks together */
@ -716,17 +748,20 @@ static int
coalesce_blocks(pgp_stream_t *stream, unsigned length) coalesce_blocks(pgp_stream_t *stream, unsigned length)
{ {
unsigned c; 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 */ /* already read a partial block length - prime the array */
streamread(stream, length); 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 */ /* length we read is partial - add to end of array */
streamread(stream, c); streamread(stream, c);
} }
/* not partial - add the last extent to the end of the array */ /* not partial - add the last extent to the end of the array */
streamread(stream, c); if(r > 0) streamread(stream, c);
stream->coalescing = 0; readinfo->coalescing = 0;
return 1; return 1;
} }
@ -744,8 +779,9 @@ static unsigned
read_new_length(unsigned *length, pgp_stream_t *stream) read_new_length(unsigned *length, pgp_stream_t *stream)
{ {
uint8_t c; uint8_t c;
pgp_reader_t *readinfo = &stream->readinfo;
stream->partial_read = 0; readinfo->partial_read = 0;
if (base_read(&c, 1, stream) != 1) { if (base_read(&c, 1, stream) != 1) {
return 0; return 0;
} }
@ -766,13 +802,13 @@ read_new_length(unsigned *length, pgp_stream_t *stream)
} }
if (c < 255) { if (c < 255) {
/* 3. Partial Body Length */ /* 3. Partial Body Length */
stream->partial_read = 1; readinfo->partial_read = 1;
*length = 1 << (c & 0x1f); *length = 1 << (c & 0x1f);
if (!stream->coalescing) { if (!readinfo->coalescing) {
/* we have been called from coalesce_blocks - /* we have been called from coalesce_blocks -
* just return with the partial length */ * just return with the partial length */
coalesce_blocks(stream, *length); coalesce_blocks(stream, *length);
*length = stream->virtualc; *length = readinfo->virtualc;
} }
return 1; return 1;
} }
@ -802,6 +838,7 @@ limited_read_new_length(unsigned *length, pgp_region_t *region,
pgp_stream_t *stream) pgp_stream_t *stream)
{ {
uint8_t c = 0x0; uint8_t c = 0x0;
pgp_reader_t *readinfo = &stream->readinfo;
if (!limread(&c, 1, region, stream)) { if (!limread(&c, 1, region, stream)) {
return 0; return 0;
@ -820,13 +857,13 @@ limited_read_new_length(unsigned *length, pgp_region_t *region,
return 1; return 1;
} }
if (c < 255) { if (c < 255) {
stream->partial_read = 1; readinfo->partial_read = 1;
*length = 1 << (c & 0x1f); *length = 1 << (c & 0x1f);
if (!stream->coalescing) { if (!readinfo->coalescing) {
/* we have been called from coalesce_blocks - /* we have been called from coalesce_blocks -
* just return with the partial length */ * just return with the partial length */
coalesce_blocks(stream, *length); coalesce_blocks(stream, *length);
*length = stream->virtualc; *length = readinfo->virtualc;
} }
return 1; return 1;
} }
@ -845,6 +882,14 @@ pgp_data_free(pgp_data_t *data)
data->len = 0; 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 \ingroup Core_Create
\brief Free allocated memory \brief Free allocated memory
@ -920,28 +965,37 @@ free_BN(BIGNUM **pp)
*pp = NULL; *pp = NULL;
} }
/**
* \ingroup Core_Create
* \brief Free the memory used when parsing a signature
* \param sig
*/
static void 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:
case PGP_PKA_RSA_SIGN_ONLY: case PGP_PKA_RSA_SIGN_ONLY:
free_BN(&sig->info.sig.rsa.sig); dup_BN(&dst->sig.rsa.sig, src->sig.rsa.sig);
break; break;
case PGP_PKA_DSA: case PGP_PKA_DSA:
free_BN(&sig->info.sig.dsa.r); dup_BN(&dst->sig.dsa.r, src->sig.dsa.r);
free_BN(&sig->info.sig.dsa.s); dup_BN(&dst->sig.dsa.s, src->sig.dsa.s);
break; break;
case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN: case PGP_PKA_ELGAMAL_ENCRYPT_OR_SIGN:
free_BN(&sig->info.sig.elgamal.r); dup_BN(&dst->sig.elgamal.r, src->sig.elgamal.r);
free_BN(&sig->info.sig.elgamal.s); dup_BN(&dst->sig.elgamal.s, src->sig.elgamal.s);
break; break;
case PGP_PKA_PRIVATE00: case PGP_PKA_PRIVATE00:
@ -955,13 +1009,65 @@ sig_free(pgp_sig_t *sig)
case PGP_PKA_PRIVATE08: case PGP_PKA_PRIVATE08:
case PGP_PKA_PRIVATE09: case PGP_PKA_PRIVATE09:
case PGP_PKA_PRIVATE10: case PGP_PKA_PRIVATE10:
pgp_data_free(&sig->info.sig.unknown); pgp_data_dup(&dst->sig.unknown, &src->sig.unknown);
break; break;
default: 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 \ingroup Core_Create
@ -1188,8 +1294,48 @@ pgp_pubkey_free(pgp_pubkey_t *p)
default: default:
(void) fprintf(stderr, "pgp_pubkey_free: bad alg\n"); (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 \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 = pkt.u.ss_time;
sig->info.duration_set = 1; 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; break;
case PGP_PTAG_SS_TRUST: case PGP_PTAG_SS_TRUST:
@ -1653,11 +1803,17 @@ parse_one_sig_subpacket(pgp_sig_t *sig,
return 0; return 0;
} }
pkt.u.ss_primary_userid = !!bools; pkt.u.ss_primary_userid = !!bools;
sig->info.primary_userid = pkt.u.ss_primary_userid;
break; break;
case PGP_PTAG_SS_KEY_FLAGS: case PGP_PTAG_SS_KEY_FLAGS:
if (!read_data(&pkt.u.ss_key_flags, &subregion, stream)) { if (!read_data(&pkt.u.ss_key_flags, &subregion, stream)) {
return 0; 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; break;
@ -1817,6 +1973,7 @@ parse_one_sig_subpacket(pgp_sig_t *sig,
PGP_ERROR_1(&stream->errors, PGP_E_R_UNCONSUMED_DATA, PGP_ERROR_1(&stream->errors, PGP_E_R_UNCONSUMED_DATA,
"Unconsumed data (%d)", "Unconsumed data (%d)",
subregion.length - subregion.readc); subregion.length - subregion.readc);
pgp_parser_content_free(&pkt);
return 0; return 0;
} }
CALLBACK(pkt.tag, &stream->cbinfo, &pkt); 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) { if (!stream->readinfo.accumulate) {
/* We must accumulate, else we can't check the signature */ /* We must accumulate, else we can't check the signature */
fprintf(stderr, "*** ERROR: must set accumulate to 1\n"); fprintf(stderr, "*** ERROR: must set accumulate to 1\n");
return 0; goto error_unalloc_v4_hashed;
} }
(void) memcpy(pkt.u.sig.info.v4_hashed, (void) memcpy(pkt.u.sig.info.v4_hashed,
stream->readinfo.accumulated + pkt.u.sig.v4_hashstart, stream->readinfo.accumulated + pkt.u.sig.v4_hashstart,
pkt.u.sig.info.v4_hashlen); pkt.u.sig.info.v4_hashlen);
if (!parse_sig_subpkts(&pkt.u.sig, region, stream)) { 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)) { if (!limread(pkt.u.sig.hash2, 2, region, stream)) {
return 0; goto error_unalloc_v4_hashed;
} }
switch (pkt.u.sig.info.key_alg) { switch (pkt.u.sig.info.key_alg) {
case PGP_PKA_RSA: case PGP_PKA_RSA:
if (!limread_mpi(&pkt.u.sig.info.sig.rsa.sig, region, stream)) { 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__)) { if (pgp_get_debug_level(__FILE__)) {
(void) fprintf(stderr, "parse_v4_sig: RSA: sig is\n"); (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, (void) fprintf(stderr,
"Error reading DSA r field in signature"); "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)) { if (!limread_mpi(&pkt.u.sig.info.sig.dsa.s, region, stream)) {
ERRP(&stream->cbinfo, pkt, ERRP(&stream->cbinfo, pkt,
@ -2017,7 +2174,7 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream)
stream) || stream) ||
!limread_mpi(&pkt.u.sig.info.sig.elgamal.s, region, !limread_mpi(&pkt.u.sig.info.sig.elgamal.s, region,
stream)) { stream)) {
return 0; goto error_unalloc_v4_hashed;
} }
break; break;
@ -2033,7 +2190,7 @@ parse_v4_sig(pgp_region_t *region, pgp_stream_t *stream)
case PGP_PKA_PRIVATE09: case PGP_PKA_PRIVATE09:
case PGP_PKA_PRIVATE10: case PGP_PKA_PRIVATE10:
if (!read_data(&pkt.u.sig.info.sig.unknown, region, stream)) { if (!read_data(&pkt.u.sig.info.sig.unknown, region, stream)) {
return 0; goto error_unalloc_v4_hashed;
} }
break; 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, PGP_ERROR_1(&stream->errors, PGP_E_ALG_UNSUPPORTED_SIGNATURE_ALG,
"Bad v4 signature key algorithm (%s)", "Bad v4 signature key algorithm (%s)",
pgp_show_pka(pkt.u.sig.info.key_alg)); pgp_show_pka(pkt.u.sig.info.key_alg));
return 0; goto error_unalloc_v4_hashed;
} }
if (region->readc != region->length) { if (region->readc != region->length) {
PGP_ERROR_1(&stream->errors, PGP_E_R_UNCONSUMED_DATA, PGP_ERROR_1(&stream->errors, PGP_E_R_UNCONSUMED_DATA,
"Unconsumed data (%d)", "Unconsumed data (%d)",
region->length - region->readc); region->length - region->readc);
return 0; goto error_unalloc_v4_hashed;
} }
CALLBACK(PGP_PTAG_CT_SIGNATURE_FOOTER, &stream->cbinfo, &pkt); CALLBACK(PGP_PTAG_CT_SIGNATURE_FOOTER, &stream->cbinfo, &pkt);
return 1; 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)); pgp_show_pka(key->pubkey.alg));
} }
free(key->checkhash); 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 static int
@ -2339,7 +2545,7 @@ consume_packet(pgp_region_t *region, pgp_stream_t *stream, unsigned warn)
* \brief Parse a secret key * \brief Parse a secret key
*/ */
static int 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_packet_t pkt;
pgp_region_t encregion; pgp_region_t encregion;
@ -2364,9 +2570,14 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream)
} }
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
fprintf(stderr, "parse_seckey: public key parsed\n"); 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);
if (pkt.u.seckey.pubkey.version != PGP_V4){
(void) fprintf(stderr,
"parse_seckey: Only V4 is supported\n");
return 0;
} }
stream->reading_v3_secret = (pkt.u.seckey.pubkey.version != PGP_V4);
if (!limread(&c, 1, region, stream)) { if (!limread(&c, 1, region, stream)) {
return 0; return 0;
@ -2576,8 +2787,9 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream)
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
fprintf(stderr, "parse_seckey: end of crypted passphrase\n"); fprintf(stderr, "parse_seckey: end of crypted passphrase\n");
} }
if (pkt.u.seckey.s2k_usage == PGP_S2KU_ENCRYPTED_AND_HASHED) {
/* XXX - Hard-coded SHA1 here ?? Check */ /* XXX - Hard-coded SHA1 here ?? Check */
if (pkt.u.seckey.s2k_usage == PGP_S2KU_ENCRYPTED_AND_HASHED) {
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) { if (pkt.u.seckey.checkhash == NULL) {
(void) fprintf(stderr, "parse_seckey: bad alloc\n"); (void) fprintf(stderr, "parse_seckey: bad alloc\n");
@ -2627,7 +2839,7 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream)
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
(void) fprintf(stderr, "4 MPIs read\n"); (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) { if (pkt.u.seckey.s2k_usage == PGP_S2KU_ENCRYPTED_AND_HASHED) {
uint8_t hash[PGP_CHECKHASH_SIZE]; uint8_t hash[PGP_CHECKHASH_SIZE];
@ -2687,7 +2899,7 @@ parse_seckey(pgp_region_t *region, pgp_stream_t *stream)
if (!ret) { if (!ret) {
return 0; return 0;
} }
CALLBACK(PGP_PTAG_CT_SECRET_KEY, &stream->cbinfo, &pkt); CALLBACK(tag, &stream->cbinfo, &pkt);
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
(void) fprintf(stderr, "--- end of parse_seckey\n\n"); (void) fprintf(stderr, "--- end of parse_seckey\n\n");
} }
@ -2869,6 +3081,7 @@ parse_pk_sesskey(pgp_region_t *region,
return 1; return 1;
} }
#if 0
static int static int
decrypt_se_data(pgp_content_enum tag, pgp_region_t *region, decrypt_se_data(pgp_content_enum tag, pgp_region_t *region,
pgp_stream_t *stream) pgp_stream_t *stream)
@ -2928,6 +3141,7 @@ decrypt_se_data(pgp_content_enum tag, pgp_region_t *region,
return r; return r;
} }
#endif
static int static int
decrypt_se_ip_data(pgp_content_enum tag, pgp_region_t *region, 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; return r;
} }
#if 0
/** /**
\ingroup Core_ReadPackets \ingroup Core_ReadPackets
\brief Read a Symmetrically Encrypted packet \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); return decrypt_se_data(PGP_PTAG_CT_SE_DATA_BODY, region, stream);
} }
#endif
/** /**
\ingroup Core_ReadPackets \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__)) { if (pgp_get_debug_level(__FILE__)) {
(void) fprintf(stderr, "parse_se_ip_data: region %d,%d\n", (void) fprintf(stderr, "parse_se_ip_data: region %d,%d\n",
region->readc, region->length); 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 * 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 { } else {
unsigned rb; unsigned rb;
rb = 0;
pkt.u.ptag.type = ((unsigned)ptag & pkt.u.ptag.type = ((unsigned)ptag &
PGP_PTAG_OF_CONTENT_TAG_MASK) PGP_PTAG_OF_CONTENT_TAG_MASK)
>> PGP_PTAG_OF_CONTENT_TAG_SHIFT; >> PGP_PTAG_OF_CONTENT_TAG_SHIFT;
@ -3177,11 +3392,8 @@ parse_packet(pgp_stream_t *stream, uint32_t *pktlen)
break; break;
case PGP_PTAG_CT_SECRET_KEY: case PGP_PTAG_CT_SECRET_KEY:
ret = parse_seckey(&region, stream);
break;
case PGP_PTAG_CT_SECRET_SUBKEY: case PGP_PTAG_CT_SECRET_SUBKEY:
ret = parse_seckey(&region, stream); ret = parse_seckey((pgp_content_enum)pkt.u.ptag.type, &region, stream);
break; break;
case PGP_PTAG_CT_PK_SESSION_KEY: case PGP_PTAG_CT_PK_SESSION_KEY:
@ -3189,7 +3401,9 @@ parse_packet(pgp_stream_t *stream, uint32_t *pktlen)
break; break;
case PGP_PTAG_CT_SE_DATA: case PGP_PTAG_CT_SE_DATA:
ret = parse_se_data(&region, stream); // SE_DATA CURRENTLY BROKEN
ret = 0;
//ret = parse_se_data(&region, stream);
break; break;
case PGP_PTAG_CT_SE_IP_DATA: 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 *cbinfo;
pgp_cbdata_t *next; pgp_cbdata_t *next;
pgp_cryptinfo_t *cryptinfo = &stream->cbinfo.cryptinfo;
for (cbinfo = stream->cbinfo.next; cbinfo; cbinfo = next) { for (cbinfo = stream->cbinfo.next; cbinfo; cbinfo = next) {
next = cbinfo->next; next = cbinfo->next;
free(cbinfo); free(cbinfo);
} }
FREE_ARRAY(cryptinfo, recipients_key_ids);
if (stream->readinfo.destroyer) { if (stream->readinfo.destroyer) {
stream->readinfo.destroyer(&stream->readinfo); stream->readinfo.destroyer(&stream->readinfo);
} }

View file

@ -52,7 +52,7 @@
* Creates printable text strings from packet contents * Creates printable text strings from packet contents
* *
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -60,16 +60,16 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "packet-show.h" #include "netpgp/packet-show.h"
#include "netpgpsdk.h" #include "netpgp/netpgpsdk.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
/* /*
@ -271,45 +271,6 @@ static pgp_map_t compression_alg_map[] =
{0x00, NULL}, /* this is the end-of-array marker */ {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 * Private functions
*/ */
@ -341,37 +302,6 @@ list_free(pgp_list_t *list)
list_init(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 */ /* find a bitfield in a map - serial search */
static const char * static const char *
find_bitfield(pgp_bit_map_t *map, uint8_t octet) find_bitfield(pgp_bit_map_t *map, uint8_t octet)
@ -414,161 +344,6 @@ pgp_text_free(pgp_text_t *text)
free(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 * Public Functions
*/ */
@ -655,22 +430,6 @@ pgp_show_ss_zpref(uint8_t octet)
return pgp_str_from_map(octet, compression_alg_map); 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 * \ingroup Core_Print
* *
@ -684,21 +443,6 @@ pgp_show_hash_alg(uint8_t hash)
return pgp_str_from_map(hash, hash_alg_map); 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 * const char *
pgp_show_symm_alg(uint8_t hash) 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); 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 * \ingroup Core_Print
* returns description of SS Key Flag * 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); 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 * \ingroup Core_Print
* *
@ -855,60 +489,3 @@ pgp_show_keyserv_pref(uint8_t prefs, pgp_bit_map_t *map)
return find_bitfield(map, prefs); 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));
}

View file

@ -46,7 +46,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -54,7 +54,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -120,39 +120,20 @@ __RCSID("$NetBSD: reader.c,v 1.49 2012/03/05 02:20:18 christos Exp $");
#include <limits.h> #include <limits.h>
#endif #endif
#include "errors-netpgp.h" #include "netpgp/errors.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "create-netpgp.h" #include "netpgp/create.h"
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "packet-show.h" #include "netpgp/packet-show.h"
#include "keyring-netpgp.h" #include "netpgp/packet.h"
#include "readerwriter-netpgp.h" #include "netpgp/keyring.h"
#include "netpgpsdk.h" #include "netpgp/readerwriter.h"
#include "netpgpdefs.h" #include "netpgp/netpgpsdk.h"
#include "netpgpdigest.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 */ /* get a pass phrase from the user */
int int
@ -233,6 +214,10 @@ pgp_reader_pop(pgp_stream_t *stream)
{ {
pgp_reader_t *next = stream->readinfo.next; pgp_reader_t *next = stream->readinfo.next;
if (stream->readinfo.accumulate && stream->readinfo.asize > 0) {
free(stream->readinfo.accumulated);
}
stream->readinfo = *next; stream->readinfo = *next;
free(next); free(next);
} }
@ -448,6 +433,9 @@ read_char(pgp_stream_t *stream, dearmour_t *dearmour,
do { do {
if (dearmour->pushbackc) { if (dearmour->pushbackc) {
if (!dearmour->pushback) {
return -1;
}
c = dearmour->pushback[--dearmour->pushbackc]; c = dearmour->pushback[--dearmour->pushbackc];
if (dearmour->pushbackc == 0) { if (dearmour->pushbackc == 0) {
free(dearmour->pushback); free(dearmour->pushback);
@ -844,7 +832,7 @@ read4(pgp_stream_t *stream, dearmour_t *dearmour, pgp_error_t **errors,
pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo, pgp_reader_t *readinfo, pgp_cbdata_t *cbinfo,
int *pc, unsigned *pn, uint32_t *pl) int *pc, unsigned *pn, uint32_t *pl)
{ {
int n, c; int n = 0, c = 0;
uint32_t l = 0; uint32_t l = 0;
for (n = 0; n < 4; ++n) { for (n = 0; n < 4; ++n) {
@ -1398,7 +1386,7 @@ typedef struct {
size_t off; size_t off;
pgp_crypt_t *decrypt; pgp_crypt_t *decrypt;
pgp_region_t *region; pgp_region_t *region;
unsigned prevplain:1; // unsigned prevplain:1;
} encrypted_t; } encrypted_t;
static int static int
@ -1414,6 +1402,8 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest,
encrypted = pgp_reader_get_arg(readinfo); encrypted = pgp_reader_get_arg(readinfo);
saved = (int)length; saved = (int)length;
#if 0
/* /*
* V3 MPIs have the count plain and the cipher is reset after each * V3 MPIs have the count plain and the cipher is reset after each
* count * count
@ -1430,13 +1420,15 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest,
readinfo->parent->reading_mpi_len) { readinfo->parent->reading_mpi_len) {
encrypted->prevplain = 1; encrypted->prevplain = 1;
} }
#endif
while (length > 0) { while (length > 0) {
if (encrypted->c) { if (encrypted->c) {
unsigned n; unsigned n;
/* /*
* if we are reading v3 we should never read * 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 && if (length < encrypted->c &&
(readinfo->parent->reading_v3_secret || (readinfo->parent->reading_v3_secret ||
readinfo->parent->exact_read)) { readinfo->parent->exact_read)) {
@ -1444,6 +1436,7 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest,
"encrypted_data_reader: bad v3 read\n"); "encrypted_data_reader: bad v3 read\n");
return 0; return 0;
} }
*/
n = (int)MIN(length, encrypted->c); n = (int)MIN(length, encrypted->c);
(void) memcpy(dest, (void) memcpy(dest,
encrypted->decrypted + encrypted->off, n); 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 * we can only read as much as we're asked for
* in v3 keys because they're partially * in v3 keys because they're partially
* unencrypted! */ * unencrypted!
if ((readinfo->parent->reading_v3_secret || if ((readinfo->parent->reading_v3_secret ||
readinfo->parent->exact_read) && n > length) { readinfo->parent->exact_read) && n > length) {
n = (unsigned)length; n = (unsigned)length;
} }
*/
if (!pgp_stacked_limited_read(stream, buffer, n, if (!pgp_stacked_limited_read(stream, buffer, n,
encrypted->region, errors, readinfo, cbinfo)) { encrypted->region, errors, readinfo, cbinfo)) {
return -1; return -1;
} }
if (!readinfo->parent->reading_v3_secret || //if (!readinfo->parent->reading_v3_secret ||
!readinfo->parent->reading_mpi_len) { // !readinfo->parent->reading_mpi_len) {
encrypted->c = encrypted->c =
pgp_decrypt_se_ip(encrypted->decrypt, pgp_decrypt_se_ip(encrypted->decrypt,
encrypted->decrypted, buffer, n); encrypted->decrypted, buffer, n);
@ -1495,11 +1489,11 @@ encrypted_data_reader(pgp_stream_t *stream, void *dest,
hexdump(stderr, "encrypted", buffer, 16); hexdump(stderr, "encrypted", buffer, 16);
hexdump(stderr, "decrypted", encrypted->decrypted, 16); hexdump(stderr, "decrypted", encrypted->decrypted, 16);
} }
} else { //} else {
(void) memcpy( // (void) memcpy(
&encrypted->decrypted[encrypted->off], buffer, n); //&encrypted->decrypted[encrypted->off], buffer, n);
encrypted->c = n; //encrypted->c = n;
} //}
if (encrypted->c == 0) { if (encrypted->c == 0) {
(void) fprintf(stderr, (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); __PGP_USED(cbinfo);
reader = pgp_reader_get_arg(readinfo); 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) { if (n == 0) {
return 0; return 0;
} }
@ -1837,9 +1829,7 @@ mem_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors
__PGP_USED(cbinfo); __PGP_USED(cbinfo);
__PGP_USED(errors); __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) { if (reader->offset + length > reader->length) {
n = (unsigned)(reader->length - reader->offset); n = (unsigned)(reader->length - reader->offset);
} else { } else {
@ -1850,7 +1840,7 @@ mem_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors
} }
memcpy(dest, reader->buffer + reader->offset, n); memcpy(dest, reader->buffer + reader->offset, n);
reader->offset += n; reader->offset += n;
}
return 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__)) { if (pgp_get_debug_level(__FILE__)) {
printf("pgp_litdata_cb: "); printf("pgp_litdata_cb: ");
pgp_print_packet(&cbinfo->printstate, pkt); //pgp_print_packet(&cbinfo->printstate, pkt);
} }
/* Read data from packet into static buffer */ /* Read data from packet into static buffer */
switch (pkt->tag) { switch (pkt->tag) {
@ -2161,7 +2151,7 @@ pgp_pk_sesskey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
io = cbinfo->io; io = cbinfo->io;
if (pgp_get_debug_level(__FILE__)) { 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 */ /* Read data from packet into static buffer */
switch (pkt->tag) { switch (pkt->tag) {
@ -2177,7 +2167,8 @@ pgp_pk_sesskey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
from = 0; from = 0;
cbinfo->cryptinfo.keydata = cbinfo->cryptinfo.keydata =
pgp_getkeybyid(io, cbinfo->cryptinfo.secring, 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) { if (!cbinfo->cryptinfo.keydata) {
break; break;
} }
@ -2208,55 +2199,67 @@ pgp_cb_ret_t
pgp_get_seckey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) pgp_get_seckey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
{ {
const pgp_contents_t *content = &pkt->u; const pgp_contents_t *content = &pkt->u;
const pgp_seckey_t *secret; pgp_seckey_t *secret;
const pgp_key_t *pubkey; // const pgp_key_t *pubkey;
const pgp_key_t *keypair; //const pgp_key_t *keypair;
unsigned from; unsigned from;
pgp_io_t *io; pgp_io_t *io;
int i; //int i;
pgp_cryptinfo_t *cryptinfo = &cbinfo->cryptinfo;
key_id_t *key_id;
io = cbinfo->io; io = cbinfo->io;
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
pgp_print_packet(&cbinfo->printstate, pkt); //pgp_print_packet(&cbinfo->printstate, pkt);
} }
switch (pkt->tag) { switch (pkt->tag) {
case PGP_GET_SECKEY: case PGP_GET_SECKEY:
/* print key from pubring */ /* print key from pubring */
from = 0; // from = 0;
pubkey = pgp_getkeybyid(io, cbinfo->cryptinfo.pubring, // pubkey = pgp_getkeybyid(io, cbinfo->cryptinfo.pubring,
content->get_seckey.pk_sesskey->key_id, // content->get_seckey.pk_sesskey->key_id,
&from, NULL); // &from, NULL);
/* validate key from secring */ // /* 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; from = 0;
cbinfo->cryptinfo.keydata = cbinfo->cryptinfo.keydata =
pgp_getkeybyid(io, cbinfo->cryptinfo.secring, pgp_getkeybyid(io, cbinfo->cryptinfo.secring,
content->get_seckey.pk_sesskey->key_id, content->get_seckey.pk_sesskey->key_id,
&from, NULL); &from, NULL, &secret, 0, 0);
if (!cbinfo->cryptinfo.keydata || if (!cbinfo->cryptinfo.keydata ||
!secret ||
!pgp_is_key_secret(cbinfo->cryptinfo.keydata)) { !pgp_is_key_secret(cbinfo->cryptinfo.keydata)) {
return (pgp_cb_ret_t)0; return (pgp_cb_ret_t)0;
} }
keypair = cbinfo->cryptinfo.keydata;
if (pubkey == NULL) { // FIXME : support encrypted seckeys again
pubkey = keypair; // keypair = cbinfo->cryptinfo.keydata;
} // if (pubkey == NULL) {
secret = NULL; // pubkey = keypair;
cbinfo->gotpass = 0; // }
for (i = 0 ; cbinfo->numtries == -1 || i < cbinfo->numtries ; i++) { // secret = NULL;
/* print out the user id */ // cbinfo->gotpass = 0;
pgp_print_keydata(io, cbinfo->cryptinfo.pubring, pubkey, // for (i = 0 ; cbinfo->numtries == -1 || i < cbinfo->numtries ; i++) {
"signature ", &pubkey->key.pubkey, 0); // /* print out the user id */
/* now decrypt key */ // pgp_print_keydata(io, cbinfo->cryptinfo.pubring, pubkey,
secret = pgp_decrypt_seckey(keypair, cbinfo->passfp); // "signature ", &pubkey->key.pubkey, 0);
if (secret != NULL) { // /* now decrypt key */
break; // pgp_decrypt_seckey(keypair, cbinfo->passfp);
} // if (secret != NULL) {
(void) fprintf(io->errs, "Bad passphrase\n"); // break;
} // }
if (secret == NULL) { // (void) fprintf(io->errs, "Bad passphrase\n");
(void) fprintf(io->errs, "Exhausted passphrase attempts\n"); // }
return (pgp_cb_ret_t)PGP_RELEASE_MEMORY; // if (secret == NULL) {
} // (void) fprintf(io->errs, "Exhausted passphrase attempts\n");
// return (pgp_cb_ret_t)PGP_RELEASE_MEMORY;
// }
cbinfo->gotpass = 1; cbinfo->gotpass = 1;
*content->get_seckey.seckey = secret; *content->get_seckey.seckey = secret;
break; break;
@ -2268,39 +2271,6 @@ pgp_get_seckey_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
return PGP_RELEASE_MEMORY; 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 unsigned
pgp_reader_set_accumulate(pgp_stream_t *stream, unsigned state) 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(errors);
__PGP_USED(cbinfo); __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)); n = (unsigned)MIN(length, (unsigned)(mem->size - mem->offset));
if (n > 0) { if (n > 0) {
(void) memcpy(dest, &cmem[(int)mem->offset], (unsigned)n); (void) memcpy(dest, &cmem[(int)mem->offset], (unsigned)n);
mem->offset += n; mem->offset += n;
} }
}
return (int)n; return (int)n;
} }

View file

@ -49,7 +49,7 @@
/** \file /** \file
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -57,7 +57,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -77,29 +77,16 @@ __RCSID("$NetBSD: signature.c,v 1.34 2012/03/05 02:20:18 christos Exp $");
#include <openssl/dsa.h> #include <openssl/dsa.h>
#endif #endif
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "create-netpgp.h" #include "netpgp/create.h"
#include "netpgpsdk.h" #include "netpgp/netpgpsdk.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "validate-netpgp.h" #include "netpgp/validate.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "netpgpdigest.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 \ingroup Core_Signature
Creates new pgp_create_sig_t Creates new pgp_create_sig_t
@ -149,6 +136,11 @@ static uint8_t prefix_sha256[] = {
0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 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 */ /* XXX: both this and verify would be clearer if the signature were */
/* treated as an MPI. */ /* treated as an MPI. */
@ -174,11 +166,16 @@ rsa_sign(pgp_hash_t *hash,
prefix = prefix_sha1; prefix = prefix_sha1;
prefixsize = sizeof(prefix_sha1); prefixsize = sizeof(prefix_sha1);
expected = PGP_SHA1_HASH_SIZE; expected = PGP_SHA1_HASH_SIZE;
} else { } else if (strcmp(hash->name, "SHA256") == 0) {
hashsize = PGP_SHA256_HASH_SIZE + sizeof(prefix_sha256); hashsize = PGP_SHA256_HASH_SIZE + sizeof(prefix_sha256);
prefix = prefix_sha256; prefix = prefix_sha256;
prefixsize = sizeof(prefix_sha256); prefixsize = sizeof(prefix_sha256);
expected = PGP_SHA256_HASH_SIZE; 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; keysize = (BN_num_bits(pubrsa->n) + 7) / 8;
if (keysize > sizeof(hashbuf)) { if (keysize > sizeof(hashbuf)) {
@ -231,7 +228,7 @@ dsa_sign(pgp_hash_t *hash,
unsigned hashsize; unsigned hashsize;
unsigned t; unsigned t;
uint8_t hashbuf[NETPGP_BUFSIZ]; 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, */ /* hashsize must be "equal in size to the number of bits of q, */
/* the group generated by the DSA key's generator value */ /* 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); pgp_write(output, &hashbuf[0], 2);
/* write signature to buf */ /* 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 */ /* convert and write the sig out to memory */
pgp_write_mpi(output, dsasig->r); pgp_write_mpi(output, pgpdsasig->r);
pgp_write_mpi(output, dsasig->s); pgp_write_mpi(output, pgpdsasig->s);
DSA_SIG_free(dsasig);
BN_free(pgpdsasig->r);
BN_free(pgpdsasig->s);
free(pgpdsasig);
return 1; return 1;
} }
@ -273,8 +276,6 @@ rsa_verify(pgp_hash_alg_t type,
uint8_t sigbuf[NETPGP_BUFSIZ]; uint8_t sigbuf[NETPGP_BUFSIZ];
uint8_t hashbuf_from_sig[NETPGP_BUFSIZ]; uint8_t hashbuf_from_sig[NETPGP_BUFSIZ];
plen = 0;
prefix = (const uint8_t *) "";
keysize = BN_num_bytes(pubrsa->n); keysize = BN_num_bytes(pubrsa->n);
/* RSA key can't be bigger than 65535 bits, so... */ /* RSA key can't be bigger than 65535 bits, so... */
if (keysize > sizeof(hashbuf_from_sig)) { if (keysize > sizeof(hashbuf_from_sig)) {
@ -315,6 +316,10 @@ rsa_verify(pgp_hash_alg_t type,
prefix = prefix_sha256; prefix = prefix_sha256;
plen = sizeof(prefix_sha256); plen = sizeof(prefix_sha256);
break; break;
case PGP_HASH_SHA512:
prefix = prefix_sha512;
plen = sizeof(prefix_sha512);
break;
default: default:
(void) fprintf(stderr, "Unknown hash algorithm: %d\n", type); (void) fprintf(stderr, "Unknown hash algorithm: %d\n", type);
return 0; 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, 0x99, 1);
pgp_hash_add_int(hash, (unsigned)len, 2); pgp_hash_add_int(hash, (unsigned)len, 2);
hash->add(hash, pgp_mem_data(mem), (unsigned)len); hash->add(hash, pgp_mem_data(mem), (unsigned)len);
pgp_memory_free(mem); pgp_memory_free(mem);
} }
@ -380,12 +386,11 @@ init_key_sig(pgp_hash_t *hash, const pgp_sig_t *sig,
} }
static void static void
hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig, hash_add_trailer(pgp_hash_t *hash, const pgp_sig_t *sig)
const uint8_t *raw_packet)
{ {
if (sig->info.version == PGP_V4) { if (sig->info.version == PGP_V4) {
if (raw_packet) { if (sig->info.v4_hashlen) {
hash->add(hash, raw_packet + sig->v4_hashstart, hash->add(hash, sig->info.v4_hashed,
(unsigned)sig->info.v4_hashlen); (unsigned)sig->info.v4_hashlen);
} }
pgp_hash_add_int(hash, (unsigned)sig->info.version, 1); pgp_hash_add_int(hash, (unsigned)sig->info.version, 1);
@ -416,7 +421,7 @@ pgp_check_sig(const uint8_t *hash, unsigned length,
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
hexdump(stdout, "hash", hash, length); hexdump(stdout, "hash", hash, length);
} }
ret = 0;
switch (sig->info.key_alg) { switch (sig->info.key_alg) {
case PGP_PKA_DSA: case PGP_PKA_DSA:
ret = pgp_dsa_verify(hash, length, &sig->info.sig.dsa, ret = pgp_dsa_verify(hash, length, &sig->info.sig.dsa,
@ -452,10 +457,9 @@ hash_and_check_sig(pgp_hash_t *hash,
static unsigned static unsigned
finalise_sig(pgp_hash_t *hash, finalise_sig(pgp_hash_t *hash,
const pgp_sig_t *sig, const pgp_sig_t *sig,
const pgp_pubkey_t *signer, const pgp_pubkey_t *signer)
const uint8_t *raw_packet)
{ {
hash_add_trailer(hash, sig, raw_packet); hash_add_trailer(hash, sig);
return hash_and_check_sig(hash, sig, signer); return hash_and_check_sig(hash, sig, signer);
} }
@ -475,8 +479,7 @@ unsigned
pgp_check_useridcert_sig(const pgp_pubkey_t *key, pgp_check_useridcert_sig(const pgp_pubkey_t *key,
const uint8_t *id, const uint8_t *id,
const pgp_sig_t *sig, const pgp_sig_t *sig,
const pgp_pubkey_t *signer, const pgp_pubkey_t *signer)
const uint8_t *raw_packet)
{ {
pgp_hash_t hash; pgp_hash_t hash;
size_t userid_len; 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); pgp_hash_add_int(&hash, (unsigned)userid_len, 4);
} }
hash.add(&hash, id, (unsigned)userid_len); 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, pgp_check_userattrcert_sig(const pgp_pubkey_t *key,
const pgp_data_t *attribute, const pgp_data_t *attribute,
const pgp_sig_t *sig, const pgp_sig_t *sig,
const pgp_pubkey_t *signer, const pgp_pubkey_t *signer)
const uint8_t *raw_packet)
{ {
pgp_hash_t hash; 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); pgp_hash_add_int(&hash, (unsigned)attribute->len, 4);
} }
hash.add(&hash, attribute->contents, (unsigned)attribute->len); 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, pgp_check_subkey_sig(const pgp_pubkey_t *key,
const pgp_pubkey_t *subkey, const pgp_pubkey_t *subkey,
const pgp_sig_t *sig, const pgp_sig_t *sig,
const pgp_pubkey_t *signer, const pgp_pubkey_t *signer)
const uint8_t *raw_packet)
{ {
pgp_hash_t hash; pgp_hash_t hash;
unsigned ret; unsigned ret;
init_key_sig(&hash, sig, key); init_key_sig(&hash, sig, key);
hash_add_key(&hash, subkey); hash_add_key(&hash, subkey);
ret = finalise_sig(&hash, sig, signer, raw_packet); ret = finalise_sig(&hash, sig, signer);
return ret; return ret;
} }
@ -563,14 +564,13 @@ pgp_check_subkey_sig(const pgp_pubkey_t *key,
unsigned unsigned
pgp_check_direct_sig(const pgp_pubkey_t *key, pgp_check_direct_sig(const pgp_pubkey_t *key,
const pgp_sig_t *sig, const pgp_sig_t *sig,
const pgp_pubkey_t *signer, const pgp_pubkey_t *signer)
const uint8_t *raw_packet)
{ {
pgp_hash_t hash; pgp_hash_t hash;
unsigned ret; unsigned ret;
init_key_sig(&hash, sig, key); init_key_sig(&hash, sig, key);
ret = finalise_sig(&hash, sig, signer, raw_packet); ret = finalise_sig(&hash, sig, signer);
return ret; return ret;
} }
@ -592,7 +592,7 @@ pgp_check_hash_sig(pgp_hash_t *hash,
const pgp_pubkey_t *signer) const pgp_pubkey_t *signer)
{ {
return (sig->info.hash_alg == hash->alg) ? return (sig->info.hash_alg == hash->alg) ?
finalise_sig(hash, sig, signer, NULL) : finalise_sig(hash, sig, signer) :
0; 0;
} }
@ -649,6 +649,22 @@ pgp_sig_start_key_sig(pgp_create_sig_t *sig,
start_sig_in_mem(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 * \ingroup Core_Signature
* *
@ -831,17 +847,100 @@ pgp_write_sig(pgp_output_t *output,
return ret; return ret;
} }
/* add a time stamp to the output */
unsigned 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; pgp_content_enum tag;
tag = (strcmp(type, "birth") == 0) ? tag = PGP_PTAG_SS_CREATION_TIME;
PGP_PTAG_SS_CREATION_TIME : PGP_PTAG_SS_EXPIRATION_TIME;
/* just do 32-bit timestamps for just now - it's in the protocol */ sig->sig.info.birthtime = when;
sig->sig.info.birthtime_set = 1;
return pgp_write_ss_header(sig->output, 5, tag) && 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)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, (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); 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 * \ingroup Core_Signature
* *
@ -937,8 +1049,8 @@ pgp_sign_file(pgp_io_t *io,
const char *outname, const char *outname,
const pgp_seckey_t *seckey, const pgp_seckey_t *seckey,
const char *hashname, const char *hashname,
const int64_t from, const time_t from,
const uint64_t duration, const time_t duration,
const unsigned armored, const unsigned armored,
const unsigned cleartext, const unsigned cleartext,
const unsigned overwrite) const unsigned overwrite)
@ -958,7 +1070,6 @@ pgp_sign_file(pgp_io_t *io,
infile = NULL; infile = NULL;
output = NULL; output = NULL;
hash = NULL; hash = NULL;
fd_out = 0;
/* find the hash algorithm */ /* find the hash algorithm */
hash_alg = pgp_str_to_hash_alg(hashname); hash_alg = pgp_str_to_hash_alg(hashname);
@ -1006,8 +1117,8 @@ pgp_sign_file(pgp_io_t *io,
/* - creation time */ /* - creation time */
/* - key id */ /* - key id */
ret = pgp_writer_use_armored_sig(output) && ret = pgp_writer_use_armored_sig(output) &&
pgp_add_time(sig, (int64_t)from, "birth") && pgp_add_creation_time(sig, from) &&
pgp_add_time(sig, (int64_t)duration, "expiration"); pgp_add_sig_expiration_time(sig, duration);
if (ret == 0) { if (ret == 0) {
pgp_teardown_file_write(output, fd_out); pgp_teardown_file_write(output, fd_out);
return 0; return 0;
@ -1053,8 +1164,8 @@ pgp_sign_file(pgp_io_t *io,
#endif #endif
/* add creation time to signature */ /* add creation time to signature */
pgp_add_time(sig, (int64_t)from, "birth"); pgp_add_creation_time(sig, from);
pgp_add_time(sig, (int64_t)duration, "expiration"); pgp_add_sig_expiration_time(sig, duration);
/* add key id to signature */ /* add key id to signature */
pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg); pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
pgp_add_issuer_keyid(sig, keyid); pgp_add_issuer_keyid(sig, keyid);
@ -1090,8 +1201,8 @@ pgp_sign_buf(pgp_io_t *io,
const void *input, const void *input,
const size_t insize, const size_t insize,
const pgp_seckey_t *seckey, const pgp_seckey_t *seckey,
const int64_t from, const time_t from,
const uint64_t duration, const time_t duration,
const char *hashname, const char *hashname,
const unsigned armored, const unsigned armored,
const unsigned cleartext) const unsigned cleartext)
@ -1111,7 +1222,6 @@ pgp_sign_buf(pgp_io_t *io,
output = NULL; output = NULL;
mem = pgp_memory_new(); mem = pgp_memory_new();
hash = NULL; hash = NULL;
ret = 0;
hash_alg = pgp_str_to_hash_alg(hashname); hash_alg = pgp_str_to_hash_alg(hashname);
if (hash_alg == PGP_HASH_UNKNOWN) { if (hash_alg == PGP_HASH_UNKNOWN) {
@ -1147,8 +1257,8 @@ pgp_sign_buf(pgp_io_t *io,
ret = pgp_writer_push_clearsigned(output, sig) && ret = pgp_writer_push_clearsigned(output, sig) &&
pgp_write(output, input, (unsigned)insize) && pgp_write(output, input, (unsigned)insize) &&
pgp_writer_use_armored_sig(output) && pgp_writer_use_armored_sig(output) &&
pgp_add_time(sig, from, "birth") && pgp_add_creation_time(sig, from) &&
pgp_add_time(sig, (int64_t)duration, "expiration"); pgp_add_sig_expiration_time(sig, duration);
if (ret == 0) { if (ret == 0) {
return NULL; return NULL;
} }
@ -1178,8 +1288,8 @@ pgp_sign_buf(pgp_io_t *io,
} }
/* add creation time to signature */ /* add creation time to signature */
pgp_add_time(sig, from, "birth"); pgp_add_creation_time(sig, from);
pgp_add_time(sig, (int64_t)duration, "expiration"); pgp_add_sig_expiration_time(sig, duration);
/* add key id to signature */ /* add key id to signature */
pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg); pgp_keyid(keyid, PGP_KEY_ID_SIZE, &seckey->pubkey, hash_alg);
pgp_add_issuer_keyid(sig, keyid); pgp_add_issuer_keyid(sig, keyid);
@ -1200,10 +1310,10 @@ int
pgp_sign_detached(pgp_io_t *io, pgp_sign_detached(pgp_io_t *io,
const char *f, const char *f,
char *sigfile, char *sigfile,
pgp_seckey_t *seckey, const pgp_seckey_t *seckey,
const char *hash, const char *hash,
const int64_t from, const time_t from,
const uint64_t duration, const time_t duration,
const unsigned armored, const unsigned overwrite) const unsigned armored, const unsigned overwrite)
{ {
pgp_create_sig_t *sig; pgp_create_sig_t *sig;
@ -1246,14 +1356,13 @@ pgp_sign_detached(pgp_io_t *io,
pgp_memory_free(mem); pgp_memory_free(mem);
/* calculate the signature */ /* calculate the signature */
pgp_add_time(sig, from, "birth"); pgp_add_creation_time(sig, from);
pgp_add_time(sig, (int64_t)duration, "expiration"); pgp_add_sig_expiration_time(sig, duration);
pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg); pgp_keyid(keyid, sizeof(keyid), &seckey->pubkey, hash_alg);
pgp_add_issuer_keyid(sig, keyid); pgp_add_issuer_keyid(sig, keyid);
pgp_end_hashed_subpkts(sig); pgp_end_hashed_subpkts(sig);
pgp_write_sig(output, sig, &seckey->pubkey, seckey); pgp_write_sig(output, sig, &seckey->pubkey, seckey);
pgp_teardown_file_write(output, fd); pgp_teardown_file_write(output, fd);
pgp_seckey_free(seckey);
return 1; return 1;
} }

View file

@ -46,7 +46,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -54,11 +54,11 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "packet-show.h" #include "netpgp/packet-show.h"
#include <string.h> #include <string.h>
@ -82,8 +82,8 @@ __RCSID("$NetBSD: symmetric.c,v 1.18 2010/11/07 08:39:59 agc Exp $");
#include <openssl/camellia.h> #include <openssl/camellia.h>
#endif #endif
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
static void static void

View file

@ -46,7 +46,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -54,7 +54,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -72,76 +72,67 @@ __RCSID("$NetBSD: validate.c,v 1.44 2012/03/05 02:20:18 christos Exp $");
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "packet-show.h" #include "netpgp/packet-show.h"
#include "keyring-netpgp.h" #include "netpgp/keyring.h"
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "netpgpsdk.h" #include "netpgp/netpgpsdk.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "memory-netpgp.h" #include "netpgp/memory.h"
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "crypto-netpgp.h" #include "netpgp/crypto.h"
#include "validate-netpgp.h" #include "netpgp/validate.h"
#ifdef HAVE_FCNTL_H #ifdef HAVE_FCNTL_H
#include <fcntl.h> #include <fcntl.h>
#endif #endif
// FIXME to support seckey decryption again.
static int //
keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors, // static int
pgp_reader_t *readinfo, // keydata_reader(pgp_stream_t *stream, void *dest, size_t length, pgp_error_t **errors,
pgp_cbdata_t *cbinfo) // pgp_reader_t *readinfo,
{ // pgp_cbdata_t *cbinfo)
validate_reader_t *reader = pgp_reader_get_arg(readinfo); // {
// validate_reader_t *reader = pgp_reader_get_arg(readinfo);
__PGP_USED(stream); //
__PGP_USED(errors); // __PGP_USED(stream);
__PGP_USED(cbinfo); // __PGP_USED(errors);
if (reader->offset == reader->key->packets[reader->packet].length) { // __PGP_USED(cbinfo);
reader->packet += 1; // if (reader->offset == reader->key->packets[reader->packet].length) {
reader->offset = 0; // reader->packet += 1;
} // reader->offset = 0;
if (reader->packet == reader->key->packetc) { // }
return 0; // if (reader->packet == reader->key->packetc) {
} // return 0;
// }
/* //
* we should never be asked to cross a packet boundary in a single // /*
* read // * we should never be asked to cross a packet boundary in a single
*/ // * read
if (reader->key->packets[reader->packet].length < // */
reader->offset + length) { // if (reader->key->packets[reader->packet].length <
(void) fprintf(stderr, "keydata_reader: weird length\n"); // reader->offset + length) {
return 0; // (void) fprintf(stderr, "keydata_reader: weird length\n");
} // return 0;
// }
(void) memcpy(dest, //
&reader->key->packets[reader->packet].raw[reader->offset], // (void) memcpy(dest,
length); // &reader->key->packets[reader->packet].raw[reader->offset],
reader->offset += (unsigned)length; // length);
// reader->offset += (unsigned)length;
return (int)length; //
} // return (int)length;
// }
static void static void
free_sig_info(pgp_sig_info_t *sig) free_sig_info(pgp_sig_info_t *sig)
{ {
free(sig->v4_hashed); pgp_free_sig_info(sig);
free(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 static int
add_sig_to_list(const pgp_sig_info_t *sig, pgp_sig_info_t **sigs, 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); 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_cb_ret_t
pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) pgp_validate_key_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
{ {
const pgp_contents_t *content = &pkt->u; const pgp_contents_t *content = &pkt->u;
const pgp_key_t *signer; validate_key_cb_t *vdata;
validate_key_cb_t *key;
pgp_pubkey_t *sigkey;
pgp_error_t **errors; pgp_error_t **errors;
pgp_io_t *io; pgp_io_t *io;
unsigned from;
unsigned valid = 0; unsigned valid = 0;
io = cbinfo->io; 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", (void) fprintf(io->errs, "%s\n",
pgp_show_packet_tag(pkt->tag)); pgp_show_packet_tag(pkt->tag));
} }
key = pgp_callback_arg(cbinfo); vdata = pgp_callback_arg(cbinfo);
errors = pgp_callback_errors(cbinfo); errors = pgp_callback_errors(cbinfo);
vdata->sig_is_valid &= pkt->tag == PGP_PARSER_PACKET_END;
switch (pkt->tag) { switch (pkt->tag) {
case PGP_PTAG_CT_PUBLIC_KEY: case PGP_PTAG_CT_PUBLIC_KEY:
if (key->pubkey.version != 0) { validate_key_cb_free(vdata);
(void) fprintf(io->errs, vdata->key.pubkey = content->pubkey;
"pgp_validate_key_cb: version bad\n"); pgp_keyid(vdata->pubkeyid, PGP_KEY_ID_SIZE,
return PGP_FINISHED; &vdata->key.pubkey, PGP_HASH_SHA1); /* TODO v3*/
}
key->pubkey = content->pubkey;
return PGP_KEEP_MEMORY;
case PGP_PTAG_CT_PUBLIC_SUBKEY: vdata->last_seen = LS_PRIMARY;
if (key->subkey.version) { vdata->type = PGP_PTAG_CT_PUBLIC_KEY;
pgp_pubkey_free(&key->subkey); vdata->not_commited = 1;
}
key->subkey = content->pubkey;
return PGP_KEEP_MEMORY; return PGP_KEEP_MEMORY;
case PGP_PTAG_CT_SECRET_KEY: case PGP_PTAG_CT_SECRET_KEY:
key->seckey = content->seckey; /* TODO
key->pubkey = key->seckey.pubkey; * 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; 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: case PGP_PTAG_CT_USER_ID:
if (key->userid) { if(vdata->last_seen == LS_PRIMARY ||
pgp_userid_free(&key->userid); vdata->last_seen == LS_ATTRIBUTE ||
vdata->last_seen == LS_ID){
if (vdata->userid) {
pgp_userid_free(&vdata->userid);
} }
key->userid = content->userid; vdata->userid = content->userid;
key->last_seen = ID; vdata->last_seen = LS_ID;
return PGP_KEEP_MEMORY; 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: case PGP_PTAG_CT_USER_ATTR:
if(vdata->last_seen == LS_PRIMARY ||
vdata->last_seen == LS_ATTRIBUTE ||
vdata->last_seen == LS_ID){
if (content->userattr.len == 0) { if (content->userattr.len == 0) {
(void) fprintf(io->errs, (void) fprintf(io->errs,
"pgp_validate_key_cb: user attribute length 0"); "pgp_validate_key_cb: user attribute length 0");
return PGP_FINISHED; vdata->last_seen = LS_UNKNOWN;
return PGP_RELEASE_MEMORY;
} }
(void) fprintf(io->outs, "user attribute, length=%d\n", (void) fprintf(io->outs, "user attribute, length=%d\n",
(int) content->userattr.len); (int) content->userattr.len);
if (key->userattr.len) { if (vdata->userattr.len) {
pgp_data_free(&key->userattr); pgp_data_free(&vdata->userattr);
} }
key->userattr = content->userattr; vdata->userattr = content->userattr;
key->last_seen = ATTRIBUTE; vdata->last_seen = LS_ATTRIBUTE;
return PGP_KEEP_MEMORY; return PGP_KEEP_MEMORY;
}else{
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, (void) fprintf(io->errs,
"pgp_validate_key_cb: user attribute length 0"); "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 */
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; return PGP_FINISHED;
} }
break; break;
} }
if (sigkey == &signer->enckey) {
(void) fprintf(io->errs,
"WARNING: signature made with encryption key\n");
}
switch (content->sig.info.type) { switch (content->sig.info.type) {
case PGP_CERT_GENERIC: case PGP_CERT_GENERIC:
case PGP_CERT_PERSONA: case PGP_CERT_PERSONA:
case PGP_CERT_CASUAL: case PGP_CERT_CASUAL:
case PGP_CERT_POSITIVE: case PGP_CERT_POSITIVE:
case PGP_SIG_REV_CERT: case PGP_SIG_REV_CERT:
valid = (key->last_seen == ID) ? if(vdata->last_seen == LS_ID){
pgp_check_useridcert_sig(&key->pubkey, valid = pgp_check_useridcert_sig(
key->userid, primary_pubkey,
vdata->userid,
&content->sig, &content->sig,
pgp_get_pubkey(signer), sigkey);
key->reader->key->packets[ } else if(vdata->last_seen == LS_ATTRIBUTE) {
key->reader->packet].raw) : valid = pgp_check_userattrcert_sig(
pgp_check_userattrcert_sig(&key->pubkey, primary_pubkey,
&key->userattr, &vdata->userattr,
&content->sig, &content->sig,
pgp_get_pubkey(signer), sigkey);
key->reader->key->packets[ }
key->reader->packet].raw);
break; break;
case PGP_SIG_REV_SUBKEY:
case PGP_SIG_SUBKEY: case PGP_SIG_SUBKEY:
/* /*
* XXX: we should also check that the signer is the * we ensure that the signing key is the
* key we are validating, I think. * primary key we are validating, "vdata->pubkey".
*/ */
valid = pgp_check_subkey_sig(&key->pubkey, if(vdata->last_seen == LS_SUBKEY &&
&key->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, &content->sig,
pgp_get_pubkey(signer), primary_pubkey);
key->reader->key->packets[ }
key->reader->packet].raw);
break; break;
case PGP_SIG_REV_KEY:
case PGP_SIG_DIRECT: case PGP_SIG_DIRECT:
valid = pgp_check_direct_sig(&key->pubkey, if(vdata->last_seen == LS_PRIMARY){
valid = pgp_check_direct_sig(
primary_pubkey,
&content->sig, &content->sig,
pgp_get_pubkey(signer), sigkey);
key->reader->key->packets[ }
key->reader->packet].raw);
break; break;
case PGP_SIG_STANDALONE: case PGP_SIG_STANDALONE:
case PGP_SIG_PRIMARY: case PGP_SIG_PRIMARY:
case PGP_SIG_REV_KEY:
case PGP_SIG_REV_SUBKEY:
case PGP_SIG_TIMESTAMP: case PGP_SIG_TIMESTAMP:
case PGP_SIG_3RD_PARTY: case PGP_SIG_3RD_PARTY:
if (vdata->result){
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED,
"Sig Verification type 0x%02x not done yet\n", "Sig Verification type 0x%02x not done yet\n",
content->sig.info.type); content->sig.info.type);
break; break;
}
default: default:
if (vdata->result){
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED,
"Unexpected signature type 0x%02x\n", "Unexpected signature type 0x%02x\n",
content->sig.info.type); content->sig.info.type);
}
} }
if (valid) { if (valid) {
if (!add_sig_to_list(&content->sig.info, if (vdata->result && !add_sig_to_list(&content->sig.info,
&key->result->valid_sigs, &vdata->result->valid_sigs,
&key->result->validc)) { &vdata->result->validc)) {
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s", 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", PGP_ERROR_1(errors, PGP_E_V_BAD_SIGNATURE, "%s",
"Bad Sig"); "Bad Sig");
if (!add_sig_to_list(&content->sig.info, if (!add_sig_to_list(&content->sig.info,
&key->result->invalid_sigs, &vdata->result->invalid_sigs,
&key->result->invalidc)) { &vdata->result->invalidc)) {
PGP_ERROR_1(errors, PGP_E_UNIMPLEMENTED, "%s", 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; 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_PARSER_PTAG:
case PGP_PTAG_CT_SIGNATURE_HEADER: 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: 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; break;
// case PGP_GET_PASSPHRASE:
// if (vdata->getpassphrase) {
// return vdata->getpassphrase(pkt, cbinfo);
// }
// break;
default: default:
(void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag); // (void) fprintf(stderr, "unexpected tag=0x%x\n", pkt->tag);
return PGP_FINISHED; return PGP_RELEASE_MEMORY;
} }
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) validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
{ {
const pgp_contents_t *content = &pkt->u; const pgp_contents_t *content = &pkt->u;
const pgp_key_t *signer; pgp_key_t *signer;
validate_data_cb_t *data; validate_data_cb_t *data;
pgp_pubkey_t *sigkey; pgp_pubkey_t *sigkey;
pgp_error_t **errors; 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)); sizeof(content->sig.info.signer_id));
} }
from = 0; from = 0;
sigkey = NULL;
signer = pgp_getkeybyid(io, data->keyring, signer = pgp_getkeybyid(io, data->keyring,
content->sig.info.signer_id, &from, &sigkey); content->sig.info.signer_id, &from, &sigkey, NULL,
if (!signer) { 0, 0); /* check neither revocation nor expiry */
if (!signer || !sigkey) {
PGP_ERROR_1(errors, PGP_E_V_UNKNOWN_SIGNER, PGP_ERROR_1(errors, PGP_E_V_UNKNOWN_SIGNER,
"%s", "Unknown Signer"); "%s", "Unknown Signer");
if (!add_sig_to_list(&content->sig.info, 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; break;
} }
if (sigkey == &signer->enckey) {
(void) fprintf(io->errs,
"WARNING: signature made with encryption key\n");
}
if (content->sig.info.birthtime_set) { if (content->sig.info.birthtime_set) {
data->result->birthtime = content->sig.info.birthtime; 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) { switch (content->sig.info.type) {
case PGP_SIG_BINARY: case PGP_SIG_BINARY:
case PGP_SIG_TEXT: case PGP_SIG_TEXT:
if (pgp_mem_len(data->mem) == 0 && if (pgp_mem_len(data->mem) == 0){
data->detachname) { if(data->detachname) {
/* check we have seen some data */ /* check we have seen some data */
/* if not, need to read from detached name */ /* if not, need to read from detached name */
(void) fprintf(io->errs, (void) fprintf(io->errs,
@ -515,6 +619,7 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
data->detachname); data->detachname);
data->mem = pgp_memory_new(); data->mem = pgp_memory_new();
pgp_mem_readfile(data->mem, data->detachname); pgp_mem_readfile(data->mem, data->detachname);
}
} }
if (pgp_get_debug_level(__FILE__)) { if (pgp_get_debug_level(__FILE__)) {
hexdump(stderr, "sig dump", (const uint8_t *)(const void *)&content->sig, hexdump(stderr, "sig dump", (const uint8_t *)(const void *)&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), valid = check_binary_sig(pgp_mem_data(data->mem),
(const unsigned)pgp_mem_len(data->mem), (const unsigned)pgp_mem_len(data->mem),
&content->sig, &content->sig,
pgp_get_pubkey(signer)); sigkey);
break; break;
default: default:
@ -571,27 +676,6 @@ validate_data_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo)
return PGP_RELEASE_MEMORY; 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 * static char *
fmtsecs(int64_t n, char *buf, size_t size) 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; return val->validc && !val->invalidc && !val->unknownc;
} }
/** typedef struct key_filter_cb_t{
* \ingroup HighLevel_Verify pgp_keyring_t *destpubring;
* \brief Validate all signatures on a single key against the given keyring pgp_keyring_t *destsecring;
* \param result Where to put the result pgp_key_t *pubkey;
* \param key Key to validate pgp_key_t *seckey;
* \param keyring Keyring to use for validation } key_filter_cb_t;
* \param cb_get_passphrase Callback to use to get passphrase
* \return 1 if all signatures OK; else 0 static pgp_cb_ret_t key_filter_cb (
* \note It is the caller's responsiblity to free result after use. validate_key_cb_t *vdata,
* \sa pgp_validate_result_free() 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 unsigned
pgp_validate_key_sigs(pgp_validation_t *result, pgp_filter_keys_fileread(
const pgp_key_t *key, pgp_io_t *io,
const pgp_keyring_t *keyring, pgp_keyring_t *destpubring,
pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, pgp_keyring_t *destsecring,
pgp_cbdata_t *)) pgp_keyring_t *certring,
const unsigned armour,
const char *filename)
{ {
pgp_stream_t *stream; pgp_stream_t *stream;
validate_key_cb_t keysigs; validate_key_cb_t vdata;
const int printerrors = 1; key_filter_cb_t filter;
unsigned res = 1;
int fd;
(void) memset(&keysigs, 0x0, sizeof(keysigs)); (void) memset(&vdata, 0x0, sizeof(vdata));
keysigs.result = result; vdata.result = NULL;
keysigs.getpassphrase = cb_get_passphrase; vdata.getpassphrase = NULL;
stream = pgp_new(sizeof(*stream)); (void) memset(&filter, 0x0, sizeof(filter));
/* pgp_parse_options(&opt,PGP_PTAG_CT_SIGNATURE,PGP_PARSE_PARSED); */ 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); if (fd < 0) {
stream->readinfo.accumulate = 1; perror(filename);
pgp_keydata_reader_set(stream, key); return 0;
/* 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);
} }
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); 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 unsigned
pgp_validate_all_sigs(pgp_validation_t *result, pgp_filter_keys_from_mem(
const pgp_keyring_t *ring, pgp_io_t *io,
pgp_cb_ret_t cb_get_passphrase(const pgp_packet_t *, pgp_keyring_t *destpubring,
pgp_cbdata_t *)) 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)); (void) memset(&vdata, 0x0, sizeof(vdata));
for (n = 0; n < ring->keyc; ++n) { vdata.result = NULL;
pgp_validate_key_sigs(result, &ring->keys[n], ring, vdata.getpassphrase = NULL;
cb_get_passphrase);
(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.keyring = keyring;
validation.mem = pgp_memory_new(); validation.mem = pgp_memory_new();
pgp_memory_init(validation.mem, 128); 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) { if (realarmour) {
pgp_reader_push_dearmour(parse); pgp_reader_push_dearmour(parse);
@ -910,20 +1105,21 @@ pgp_validate_file(pgp_io_t *io,
\param mem Memory to be validated \param mem Memory to be validated
\param user_says_armoured Treat data as armoured, if set \param user_says_armoured Treat data as armoured, if set
\param keyring Keyring to use \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 \return 1 if signature validates successfully; 0 if not
\note After verification, result holds the details of all keys which \note After verification, result holds the details of all keys which
have passed, failed and not been recognised. have passed, failed and not been recognised.
\note It is the caller's responsiblity to call \note It is the caller's responsiblity to call
pgp_validate_result_free(result) after use. pgp_validate_result_free(result) after use.
*/ */
static inline unsigned
unsigned _pgp_validate_mem(pgp_io_t *io,
pgp_validate_mem(pgp_io_t *io,
pgp_validation_t *result, pgp_validation_t *result,
pgp_memory_t *mem, pgp_memory_t *mem,
pgp_memory_t **cat, pgp_memory_t **cat,
const int user_says_armoured, const int user_says_armoured,
const pgp_keyring_t *keyring) const pgp_keyring_t *keyring,
pgp_memory_t *detachmem)
{ {
validate_data_cb_t validation; validate_data_cb_t validation;
pgp_stream_t *stream = NULL; pgp_stream_t *stream = NULL;
@ -931,15 +1127,17 @@ pgp_validate_mem(pgp_io_t *io,
int realarmour; int realarmour;
pgp_setup_memory_read(io, &stream, mem, &validation, validate_data_cb, 1); pgp_setup_memory_read(io, &stream, mem, &validation, validate_data_cb, 1);
/* Set verification reader and handling options */ /* Set verification reader and handling options */
(void) memset(&validation, 0x0, sizeof(validation)); (void) memset(&validation, 0x0, sizeof(validation));
validation.result = result; validation.result = result;
validation.keyring = keyring; validation.keyring = keyring;
if (detachmem) {
validation.mem = detachmem;
}else{
validation.mem = pgp_memory_new(); validation.mem = pgp_memory_new();
pgp_memory_init(validation.mem, 128); pgp_memory_init(validation.mem, 128);
/* Note: Coverity incorrectly reports an error that validation.reader */ }
/* is never used. */
validation.reader = stream->readinfo.arg;
if ((realarmour = user_says_armoured) != 0 || if ((realarmour = user_says_armoured) != 0 ||
strncmp(pgp_mem_data(mem), strncmp(pgp_mem_data(mem),
@ -969,3 +1167,39 @@ pgp_validate_mem(pgp_io_t *io,
return validate_result_status(io->errs, NULL, result); 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);
}

View file

@ -50,7 +50,7 @@
/** \file /** \file
* This file contains the base functions used by the writers. * This file contains the base functions used by the writers.
*/ */
#include "config-netpgp.h" #include "netpgp/config-netpgp.h"
#ifdef HAVE_SYS_CDEFS_H #ifdef HAVE_SYS_CDEFS_H
#include <sys/cdefs.h> #include <sys/cdefs.h>
@ -58,7 +58,7 @@
#if defined(__NetBSD__) #if defined(__NetBSD__)
__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); __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 #endif
#include <sys/types.h> #include <sys/types.h>
@ -74,17 +74,17 @@ __RCSID("$NetBSD: writer.c,v 1.33 2012/03/05 02:20:18 christos Exp $");
#include <openssl/cast.h> #include <openssl/cast.h>
#endif #endif
#include "create-netpgp.h" #include "netpgp/create.h"
#include "writer-netpgp.h" #include "netpgp/writer.h"
#include "keyring-netpgp.h" #include "netpgp/keyring.h"
#include "signature-netpgp.h" #include "netpgp/signature.h"
#include "packet-netpgp.h" #include "netpgp/packet.h"
#include "packet-parse.h" #include "netpgp/packet-parse.h"
#include "readerwriter-netpgp.h" #include "netpgp/readerwriter.h"
#include "memory-netpgp.h" #include "netpgp/memory.h"
#include "netpgpdefs.h" #include "netpgp/netpgpdefs.h"
#include "version-netpgp.h" #include "netpgp/version.h"
#include "netpgpdigest.h" #include "netpgp/netpgpdigest.h"
/* /*
@ -285,11 +285,13 @@ pgp_writer_push(pgp_output_t *output,
{ {
pgp_writer_t *copy; pgp_writer_t *copy;
if ((copy = calloc(1, sizeof(*copy))) == NULL) { if (output->writer.writer == NULL) {
(void) fprintf(stderr, "pgp_writer_push: bad alloc\n");
} else if (output->writer.writer == NULL) {
(void) fprintf(stderr, "pgp_writer_push: no orig writer\n"); (void) fprintf(stderr, "pgp_writer_push: no orig writer\n");
} else { } else {
if ((copy = calloc(1, sizeof(*copy))) == NULL) {
(void) fprintf(stderr, "pgp_writer_push: bad alloc\n");
return; /* TODO return error */
}
*copy = output->writer; *copy = output->writer;
output->writer.next = copy; 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) { if ((base64 = calloc(1, sizeof(*base64))) == NULL) {
(void) fprintf(stderr, (void) fprintf(stderr,
"pgp_writer_push_armoured: bad alloc\n"); "pgp_writer_push_armoured: bad alloc\n");
free(linebreak);
return; return;
} }
base64->checksum = CRC24_INIT; base64->checksum = CRC24_INIT;
@ -1011,6 +1014,7 @@ pgp_push_enc_crypt(pgp_output_t *output, pgp_crypt_t *pgp_crypt)
typedef struct { typedef struct {
pgp_crypt_t *crypt; pgp_crypt_t *crypt;
unsigned raw;
} encrypt_se_ip_t; } encrypt_se_ip_t;
static unsigned encrypt_se_ip_writer(const uint8_t *, static unsigned encrypt_se_ip_writer(const uint8_t *,
@ -1026,32 +1030,54 @@ static void encrypt_se_ip_destroyer(pgp_writer_t *);
\brief Push Encrypted SE IP Writer onto stack \brief Push Encrypted SE IP Writer onto stack
*/ */
int 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; pgp_pk_sesskey_t *encrypted_pk_sesskey;
encrypt_se_ip_t *se_ip; encrypt_se_ip_t *se_ip;
pgp_crypt_t *encrypted; pgp_crypt_t *encrypted;
uint8_t *iv; uint8_t *iv;
unsigned n;
if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) { if ((se_ip = calloc(1, sizeof(*se_ip))) == NULL) {
(void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n"); (void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n");
return 0; return 0;
} }
for (n = 0; n < pubkeys->keyc; ++n) {
/* Create and write encrypted PK session key */ /* Create and write encrypted PK session key */
if ((encrypted_pk_sesskey = pgp_create_pk_sesskey(pubkey, cipher)) == NULL) { 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"); (void) fprintf(stderr, "pgp_push_enc_se_ip: null pk sesskey\n");
free(se_ip);
return 0; return 0;
} }
if (initial_sesskey == NULL) {
initial_sesskey = encrypted_pk_sesskey;
}
pgp_write_pk_sesskey(output, 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 */ /* Setup the se_ip */
if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) { if ((encrypted = calloc(1, sizeof(*encrypted))) == NULL) {
free(se_ip); free(se_ip);
(void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n"); (void) fprintf(stderr, "pgp_push_enc_se_ip: bad alloc\n");
return 0; 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) { if ((iv = calloc(1, encrypted->blocksize)) == NULL) {
free(se_ip); free(se_ip);
free(encrypted); 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; return 0;
} }
encrypted->set_iv(encrypted, iv); 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); pgp_encrypt_init(encrypted);
se_ip->crypt = encrypted; se_ip->crypt = encrypted;
se_ip->raw = raw;
/* And push writer on stack */ /* And push writer on stack */
pgp_writer_push(output, encrypt_se_ip_writer, NULL, pgp_writer_push(output, encrypt_se_ip_writer, NULL,
encrypt_se_ip_destroyer, se_ip); encrypt_se_ip_destroyer, se_ip);
/* tidy up */ /* tidy up */
free(encrypted_pk_sesskey); free(initial_sesskey);
free(iv); free(iv);
return 1; return 1;
} }
@ -1089,19 +1116,29 @@ encrypt_se_ip_writer(const uint8_t *src,
pgp_memory_t *localmem; pgp_memory_t *localmem;
unsigned ret = 1; unsigned ret = 1;
const uint8_t *zsrc;
unsigned zsrclen;
pgp_setup_memory_write(&litoutput, &litmem, bufsz); pgp_setup_memory_write(&litoutput, &litmem, bufsz);
pgp_setup_memory_write(&zoutput, &zmem, bufsz); pgp_setup_memory_write(&zoutput, &zmem, bufsz);
pgp_setup_memory_write(&output, &localmem, bufsz); pgp_setup_memory_write(&output, &localmem, bufsz);
if (!se_ip->raw) {
/* create literal data packet from source data */ /* create literal data packet from source data */
pgp_write_litdata(litoutput, src, (const int)len, PGP_LDT_BINARY); pgp_write_litdata(litoutput, src, (const int)len, PGP_LDT_BINARY);
if (pgp_mem_len(litmem) <= len) { if (pgp_mem_len(litmem) <= len) {
(void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n"); (void) fprintf(stderr, "encrypt_se_ip_writer: bad len\n");
return 0; 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 */ /* 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 */ /* create SE IP packet set from this compressed literal data */
pgp_write_se_ip_pktset(output, pgp_mem_data(zmem), 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 #define MAX_PARTIAL_DATA_LENGTH 1073741824
typedef struct { typedef struct {
@ -1412,7 +1503,7 @@ static void str_enc_se_ip_destroyer(pgp_writer_t *writer);
\param pubkey \param pubkey
*/ */
void 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; pgp_pk_sesskey_t *encrypted_pk_sesskey;
str_enc_se_ip_t *se_ip; 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"); "pgp_push_stream_enc_se_ip: bad alloc\n");
return; 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); pgp_write_pk_sesskey(output, encrypted_pk_sesskey);
/* Setup the se_ip */ /* Setup the se_ip */
@ -1701,7 +1792,6 @@ str_enc_se_ip_writer(const uint8_t *src,
size_t datalength; size_t datalength;
se_ip = pgp_writer_get_arg(writer); se_ip = pgp_writer_get_arg(writer);
ret = 1;
if (se_ip->litoutput == NULL) { if (se_ip->litoutput == NULL) {
/* first literal data chunk is not yet written */ /* first literal data chunk is not yet written */

View file

@ -119,9 +119,10 @@ int mre2ee_driver_create_keypair(mrmailbox_t* mailbox, const char* addr, mrkey_t
/* generate keypair */ /* generate keypair */
keypair = pgp_rsa_new_selfsign_key(2048/*bits*/, 65537UL/*e*/, (const uint8_t*)user_id, NULL, NULL); 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); 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; 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); mrkey_set_from_raw(ret_public_key, (const unsigned char*)mem1->buf, mem1->length, MR_PRIVATE);
/* write private key */ /* write private key */
keypair->type = PGP_PTAG_CT_SECRET_KEY; // TODO: this seems to me like a hack
pgp_writer_set_memory(output2, mem2); 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; goto cleanup;
} }