mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
added compilable version of openpgp sdk
git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-OpenPGP@5048 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
8cb15bdbef
commit
7d06d19e40
33
openpgpsdk/include/openpgpsdk/accumulate.h
Normal file
33
openpgpsdk/include/openpgpsdk/accumulate.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 OPS_ACCUMULATE_H
|
||||
#define OPS_ACCUMULATE_H
|
||||
#endif
|
||||
|
||||
#include "keyring.h"
|
||||
#include "packet-parse.h"
|
||||
|
||||
int ops_parse_and_accumulate(ops_keyring_t *keyring,
|
||||
ops_parse_info_t *parse_info);
|
54
openpgpsdk/include/openpgpsdk/armour.h
Normal file
54
openpgpsdk/include/openpgpsdk/armour.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPS_ARMOUR_H__
|
||||
#define __OPS_ARMOUR_H__
|
||||
|
||||
#include "packet-parse.h"
|
||||
#include "signature.h"
|
||||
|
||||
unsigned ops_crc24(unsigned checksum,unsigned char c);
|
||||
|
||||
void ops_reader_push_dearmour(ops_parse_info_t *parse_info);
|
||||
|
||||
void ops_reader_pop_dearmour(ops_parse_info_t *parse_info);
|
||||
ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
|
||||
ops_create_signature_t *sig);
|
||||
void ops_writer_push_armoured_message(ops_create_info_t *info);
|
||||
ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OPS_PGP_MESSAGE=1,
|
||||
OPS_PGP_PUBLIC_KEY_BLOCK,
|
||||
OPS_PGP_PRIVATE_KEY_BLOCK,
|
||||
OPS_PGP_MULTIPART_MESSAGE_PART_X_OF_Y,
|
||||
OPS_PGP_MULTIPART_MESSAGE_PART_X,
|
||||
OPS_PGP_SIGNATURE
|
||||
} ops_armor_type_t;
|
||||
|
||||
void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type);
|
||||
|
||||
#define CRC24_INIT 0xb704ceL
|
||||
|
||||
#endif /* __OPS_ARMOUR_H__ */
|
||||
|
||||
// EOF
|
37
openpgpsdk/include/openpgpsdk/callback.h
Normal file
37
openpgpsdk/include/openpgpsdk/callback.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPS_CALLBACK_H__
|
||||
#define __OPS_CALLBACK_H__
|
||||
|
||||
#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if(ops_parse_cb((pc),(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
|
||||
/*#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)*/
|
||||
//#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
|
||||
|
||||
#define CBP(info,t,pc) CB(&(info)->cbinfo,t,pc)
|
||||
|
||||
#define ERR(cbinfo,err,code) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,(cbinfo)); OPS_ERROR(errors,code,err); return -1; } while(0)
|
||||
/*#define ERR(err) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,cbinfo); return -1; } while(0)*/
|
||||
|
||||
#define ERRP(info,err) do { C.error.error=err; CBP(info,OPS_PARSER_ERROR,&content); return ops_false; } while(0)
|
||||
|
||||
|
||||
#endif /*__OPS_CALLBACK_H__*/
|
32
openpgpsdk/include/openpgpsdk/compress.h
Normal file
32
openpgpsdk/include/openpgpsdk/compress.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "packet-parse.h"
|
||||
|
||||
int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
|
||||
ops_compression_type_t type);
|
||||
|
||||
ops_boolean_t ops_write_compressed(const unsigned char* data,
|
||||
const unsigned int len,
|
||||
ops_create_info_t *cinfo);
|
7
openpgpsdk/include/openpgpsdk/configure.h
Normal file
7
openpgpsdk/include/openpgpsdk/configure.h
Normal file
@ -0,0 +1,7 @@
|
||||
/* generated by configure from include/openpgpsdk/configure.h.template. Don't edit. */
|
||||
|
||||
#define HAVE_ALLOCA_H 0
|
||||
#define TIME_T_FMT "%ld"
|
||||
|
||||
/* for silencing unused parameter warnings */
|
||||
#define OPS_USED(x) (x)=(x)
|
82
openpgpsdk/include/openpgpsdk/create.h
Normal file
82
openpgpsdk/include/openpgpsdk/create.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 OPS_CREATE_H
|
||||
#define OPS_CREATE_H
|
||||
|
||||
#include <openpgpsdk/types.h>
|
||||
#include <openpgpsdk/packet.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/memory.h>
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/writer.h>
|
||||
|
||||
/**
|
||||
* \ingroup Create
|
||||
* This struct contains the required information about how to write this stream
|
||||
*/
|
||||
struct ops_create_info
|
||||
{
|
||||
ops_writer_info_t winfo;
|
||||
ops_error_t *errors; /*!< an error stack */
|
||||
};
|
||||
|
||||
ops_create_info_t *ops_create_info_new(void);
|
||||
void ops_create_info_delete(ops_create_info_t *info);
|
||||
|
||||
ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum);
|
||||
int ops_write_file_from_buf(const char *filename, const char* buf, const size_t len, const ops_boolean_t overwrite);
|
||||
|
||||
ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, unsigned char *cs);
|
||||
void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key,
|
||||
ops_boolean_t make_packet);
|
||||
ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id,
|
||||
ops_create_info_t *info);
|
||||
ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key,
|
||||
ops_create_info_t *info);
|
||||
|
||||
ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type,
|
||||
ops_create_info_t *info);
|
||||
ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key,
|
||||
const unsigned char* passphrase,
|
||||
const size_t pplen,
|
||||
ops_create_info_t *info);
|
||||
ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey,
|
||||
const ops_hash_algorithm_t hash_alg,
|
||||
const ops_sig_type_t sig_type,
|
||||
ops_create_info_t* info);
|
||||
ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data,
|
||||
const int maxlen,
|
||||
const ops_literal_data_type_t type,
|
||||
ops_create_info_t *info);
|
||||
ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key);
|
||||
ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info,
|
||||
ops_pk_session_key_t *pksk);
|
||||
ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *key, ops_boolean_t armoured, ops_create_info_t *info);
|
||||
ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *key, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info);
|
||||
|
||||
#endif /*OPS_CREATE_H*/
|
||||
|
||||
// eof
|
176
openpgpsdk/include/openpgpsdk/crypto.h
Normal file
176
openpgpsdk/include/openpgpsdk/crypto.h
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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 OPS_CRYPTO_H
|
||||
#define OPS_CRYPTO_H
|
||||
|
||||
#include "keyring.h"
|
||||
#include "util.h"
|
||||
#include "packet.h"
|
||||
#include "packet-parse.h"
|
||||
#include <openssl/dsa.h>
|
||||
|
||||
#define OPS_MIN_HASH_SIZE 16
|
||||
|
||||
typedef void ops_hash_init_t(ops_hash_t *hash);
|
||||
typedef void ops_hash_add_t(ops_hash_t *hash,const unsigned char *data,
|
||||
unsigned length);
|
||||
typedef unsigned ops_hash_finish_t(ops_hash_t *hash,unsigned char *out);
|
||||
|
||||
/** _ops_hash_t */
|
||||
struct _ops_hash_t
|
||||
{
|
||||
ops_hash_algorithm_t algorithm;
|
||||
size_t size;
|
||||
const char *name;
|
||||
ops_hash_init_t *init;
|
||||
ops_hash_add_t *add;
|
||||
ops_hash_finish_t *finish;
|
||||
void *data;
|
||||
};
|
||||
|
||||
typedef void ops_crypt_set_iv_t(ops_crypt_t *crypt,
|
||||
const unsigned char *iv);
|
||||
typedef void ops_crypt_set_key_t(ops_crypt_t *crypt,
|
||||
const unsigned char *key);
|
||||
typedef void ops_crypt_init_t(ops_crypt_t *crypt);
|
||||
typedef void ops_crypt_resync_t(ops_crypt_t *crypt);
|
||||
typedef void ops_crypt_block_encrypt_t(ops_crypt_t *crypt,void *out,
|
||||
const void *in);
|
||||
typedef void ops_crypt_block_decrypt_t(ops_crypt_t *crypt,void *out,
|
||||
const void *in);
|
||||
typedef void ops_crypt_cfb_encrypt_t(ops_crypt_t *crypt,void *out,
|
||||
const void *in, size_t count);
|
||||
typedef void ops_crypt_cfb_decrypt_t(ops_crypt_t *crypt,void *out,
|
||||
const void *in, size_t count);
|
||||
typedef void ops_crypt_finish_t(ops_crypt_t *crypt);
|
||||
|
||||
/** _ops_crypt_t */
|
||||
struct _ops_crypt_t
|
||||
{
|
||||
ops_symmetric_algorithm_t algorithm;
|
||||
size_t blocksize;
|
||||
size_t keysize;
|
||||
ops_crypt_set_iv_t *set_iv; /* Call this before decrypt init! */
|
||||
ops_crypt_set_key_t *set_key; /* Call this before init! */
|
||||
ops_crypt_init_t *base_init;
|
||||
ops_crypt_resync_t *decrypt_resync;
|
||||
// encrypt/decrypt one block
|
||||
ops_crypt_block_encrypt_t *block_encrypt;
|
||||
ops_crypt_block_decrypt_t *block_decrypt;
|
||||
|
||||
// Standard CFB encrypt/decrypt (as used by Sym Enc Int Prot packets)
|
||||
ops_crypt_cfb_encrypt_t *cfb_encrypt;
|
||||
ops_crypt_cfb_decrypt_t *cfb_decrypt;
|
||||
|
||||
ops_crypt_finish_t *decrypt_finish;
|
||||
unsigned char iv[OPS_MAX_BLOCK_SIZE];
|
||||
unsigned char civ[OPS_MAX_BLOCK_SIZE];
|
||||
unsigned char siv[OPS_MAX_BLOCK_SIZE]; /* Needed for weird v3 resync */
|
||||
unsigned char key[OPS_MAX_KEY_SIZE];
|
||||
size_t num; /* Offset - see openssl _encrypt doco */
|
||||
void *encrypt_key;
|
||||
void *decrypt_key;
|
||||
};
|
||||
|
||||
void ops_crypto_init(void);
|
||||
void ops_crypto_finish(void);
|
||||
void ops_hash_md5(ops_hash_t *hash);
|
||||
void ops_hash_sha1(ops_hash_t *hash);
|
||||
void ops_hash_sha256(ops_hash_t *hash);
|
||||
void ops_hash_sha512(ops_hash_t *hash);
|
||||
void ops_hash_sha384(ops_hash_t *hash);
|
||||
void ops_hash_sha224(ops_hash_t *hash);
|
||||
void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg);
|
||||
ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash);
|
||||
const char *ops_text_from_hash(ops_hash_t *hash);
|
||||
unsigned ops_hash_size(ops_hash_algorithm_t alg);
|
||||
unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in,
|
||||
size_t length);
|
||||
|
||||
void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length);
|
||||
|
||||
ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
|
||||
const ops_dsa_signature_t *sig,
|
||||
const ops_dsa_public_key_t *dsa);
|
||||
int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_public_key_t *rsa);
|
||||
int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_public_key_t *rsa);
|
||||
int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_secret_key_t *srsa,
|
||||
const ops_rsa_public_key_t *rsa);
|
||||
int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_secret_key_t *srsa,
|
||||
const ops_rsa_public_key_t *rsa);
|
||||
|
||||
unsigned ops_block_size(ops_symmetric_algorithm_t alg);
|
||||
unsigned ops_key_size(ops_symmetric_algorithm_t alg);
|
||||
|
||||
int ops_decrypt_data(ops_content_tag_t tag,ops_region_t *region,
|
||||
ops_parse_info_t *parse_info);
|
||||
|
||||
int ops_crypt_any(ops_crypt_t *decrypt,ops_symmetric_algorithm_t alg);
|
||||
void ops_decrypt_init(ops_crypt_t *decrypt);
|
||||
void ops_encrypt_init(ops_crypt_t *encrypt);
|
||||
size_t ops_decrypt_se(ops_crypt_t *decrypt,void *out,const void *in,
|
||||
size_t count);
|
||||
size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out,const void *in,
|
||||
size_t count);
|
||||
size_t ops_decrypt_se_ip(ops_crypt_t *decrypt,void *out,const void *in,
|
||||
size_t count);
|
||||
size_t ops_encrypt_se_ip(ops_crypt_t *encrypt,void *out,const void *in,
|
||||
size_t count);
|
||||
ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg);
|
||||
|
||||
void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt,
|
||||
ops_region_t *region);
|
||||
void ops_reader_pop_decrypt(ops_parse_info_t *pinfo);
|
||||
|
||||
// Hash everything that's read
|
||||
void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash);
|
||||
void ops_reader_pop_hash(ops_parse_info_t *pinfo);
|
||||
|
||||
int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM *encmpi,
|
||||
const ops_secret_key_t *skey);
|
||||
ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *buf, const size_t buflen,
|
||||
const ops_public_key_t *pkey,
|
||||
ops_pk_session_key_parameters_t *spk);
|
||||
|
||||
|
||||
// Encrypt everything that's written
|
||||
struct ops_key_data;
|
||||
void ops_writer_push_encrypt(ops_create_info_t *info,
|
||||
const struct ops_key_data *key);
|
||||
|
||||
ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_filename, const ops_keydata_t *pub_key, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite);
|
||||
ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_filename, ops_keyring_t *keyring, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite,ops_parse_cb_t* cb_get_passphrase);
|
||||
|
||||
// Keys
|
||||
ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata);
|
||||
ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid);
|
||||
|
||||
int ops_dsa_size(const ops_dsa_public_key_t *dsa);
|
||||
DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa);
|
||||
#endif
|
37
openpgpsdk/include/openpgpsdk/defs.h
Normal file
37
openpgpsdk/include/openpgpsdk/defs.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 OPS_DEFS_H
|
||||
#define OPS_DEFS_H
|
||||
|
||||
#define OPS_ARMOURED ops_true
|
||||
#define OPS_UNARMOURED ops_false
|
||||
|
||||
#define OPS_OVERWRITE_YES ops_true
|
||||
#define OPS_OVERWRITE_NO ops_false
|
||||
|
||||
#define OPS_ACCUMULATE_YES ops_true
|
||||
#define OPS_ACCUMULATE_NO ops_false
|
||||
|
||||
#endif /* OPS_DEFS_H */
|
125
openpgpsdk/include/openpgpsdk/errors.h
Normal file
125
openpgpsdk/include/openpgpsdk/errors.h
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 OPS_ERRORS
|
||||
#define OPS_ERRORS
|
||||
|
||||
#include "openpgpsdk/types.h"
|
||||
#include <errno.h>
|
||||
|
||||
/** error codes */
|
||||
// Remember to add names to map in errors.c
|
||||
typedef enum
|
||||
{
|
||||
OPS_E_OK=0x0000, /* no error */
|
||||
OPS_E_FAIL=0x0001, /* general error */
|
||||
OPS_E_SYSTEM_ERROR=0x0002, /* system error, look at errno for details */
|
||||
OPS_E_UNIMPLEMENTED=0x0003, /* feature not yet implemented */
|
||||
|
||||
/* reader errors */
|
||||
OPS_E_R=0x1000, /* general reader error */
|
||||
OPS_E_R_READ_FAILED =OPS_E_R+1,
|
||||
OPS_E_R_EARLY_EOF =OPS_E_R+2,
|
||||
OPS_E_R_BAD_FORMAT =OPS_E_R+3, // For example, malformed armour
|
||||
OPS_E_R_UNSUPPORTED =OPS_E_R+4,
|
||||
OPS_E_R_UNCONSUMED_DATA =OPS_E_R+5,
|
||||
|
||||
/* writer errors */
|
||||
OPS_E_W=0x2000, /* general writer error */
|
||||
OPS_E_W_WRITE_FAILED = OPS_E_W+1,
|
||||
OPS_E_W_WRITE_TOO_SHORT = OPS_E_W+2,
|
||||
|
||||
/* parser errors */
|
||||
OPS_E_P=0x3000, /* general parser error */
|
||||
OPS_E_P_NOT_ENOUGH_DATA =OPS_E_P+1,
|
||||
OPS_E_P_UNKNOWN_TAG =OPS_E_P+2,
|
||||
OPS_E_P_PACKET_CONSUMED =OPS_E_P+3,
|
||||
OPS_E_P_MPI_FORMAT_ERROR =OPS_E_P+4,
|
||||
OPS_E_P_PACKET_NOT_CONSUMED =OPS_E_P+5,
|
||||
OPS_E_P_DECOMPRESSION_ERROR =OPS_E_P+6,
|
||||
OPS_E_P_NO_USERID =OPS_E_P+7,
|
||||
|
||||
/* creator errors */
|
||||
OPS_E_C=0x4000, /* general creator error */
|
||||
|
||||
/* validation errors */
|
||||
OPS_E_V=0x5000, /* general validation error */
|
||||
OPS_E_V_BAD_SIGNATURE =OPS_E_V+1,
|
||||
OPS_E_V_NO_SIGNATURE =OPS_E_V+2,
|
||||
OPS_E_V_UNKNOWN_SIGNER =OPS_E_V+3,
|
||||
OPS_E_V_BAD_HASH =OPS_E_V+4,
|
||||
|
||||
/* Algorithm support errors */
|
||||
OPS_E_ALG=0x6000, /* general algorithm error */
|
||||
OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG =OPS_E_ALG+1,
|
||||
OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG =OPS_E_ALG+2,
|
||||
OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG =OPS_E_ALG+3,
|
||||
OPS_E_ALG_UNSUPPORTED_HASH_ALG =OPS_E_ALG+4,
|
||||
OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG =OPS_E_ALG+5,
|
||||
|
||||
/* Protocol errors */
|
||||
OPS_E_PROTO=0x7000, /* general protocol error */
|
||||
OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT =OPS_E_PROTO+2,
|
||||
OPS_E_PROTO_UNKNOWN_SS =OPS_E_PROTO+3,
|
||||
OPS_E_PROTO_CRITICAL_SS_IGNORED =OPS_E_PROTO+4,
|
||||
OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN =OPS_E_PROTO+5,
|
||||
OPS_E_PROTO_BAD_SIGNATURE_VRSN =OPS_E_PROTO+6,
|
||||
OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN =OPS_E_PROTO+7,
|
||||
OPS_E_PROTO_BAD_PKSK_VRSN =OPS_E_PROTO+8,
|
||||
OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN =OPS_E_PROTO+9,
|
||||
OPS_E_PROTO_BAD_SK_CHECKSUM =OPS_E_PROTO+10,
|
||||
} ops_errcode_t;
|
||||
|
||||
/** ops_errcode_name_map_t */
|
||||
typedef ops_map_t ops_errcode_name_map_t;
|
||||
|
||||
/** one entry in a linked list of errors */
|
||||
typedef struct ops_error
|
||||
{
|
||||
ops_errcode_t errcode;
|
||||
int sys_errno; /*!< irrelevent unless errcode == OPS_E_SYSTEM_ERROR */
|
||||
char *comment;
|
||||
const char *file;
|
||||
int line;
|
||||
struct ops_error *next;
|
||||
} ops_error_t;
|
||||
|
||||
char *ops_errcode(const ops_errcode_t errcode);
|
||||
|
||||
void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
|
||||
const char *file,int line,const char *comment,...);
|
||||
void ops_print_error(ops_error_t *err);
|
||||
void ops_print_errors(ops_error_t *errstack);
|
||||
void ops_free_errors(ops_error_t *errstack);
|
||||
int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode);
|
||||
|
||||
#define OPS_SYSTEM_ERROR_1(err,code,syscall,fmt,arg) do { ops_push_error(err,OPS_E_SYSTEM_ERROR,errno,__FILE__,__LINE__,syscall); ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
|
||||
#define OPS_MEMORY_ERROR(err) {fprintf(stderr, "Memory error\n");} // \todo placeholder for better error handling
|
||||
#define OPS_ERROR(err,code,fmt) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt); } while(0)
|
||||
#define OPS_ERROR_1(err,code,fmt,arg) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
|
||||
#define OPS_ERROR_2(err,code,fmt,arg,arg2) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2); } while(0)
|
||||
#define OPS_ERROR_3(err,code,fmt,arg,arg2,arg3) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3); } while(0)
|
||||
#define OPS_ERROR_4(err,code,fmt,arg,arg2,arg3,arg4) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3,arg4); } while(0)
|
||||
|
||||
#endif /* OPS_ERRORS */
|
27
openpgpsdk/include/openpgpsdk/final.h
Normal file
27
openpgpsdk/include/openpgpsdk/final.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* A header that is always included last, for things that need to come last */
|
||||
|
||||
#ifdef DMALLOC
|
||||
# include <dmalloc.h>
|
||||
#endif
|
||||
|
29
openpgpsdk/include/openpgpsdk/hash.h
Normal file
29
openpgpsdk/include/openpgpsdk/hash.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPS_HASH_H__
|
||||
#define __OPS_HASH_H__
|
||||
#include "openpgpsdk/packet.h"
|
||||
|
||||
void ops_calc_mdc_hash(const unsigned char* preamble, const size_t sz_preamble, const unsigned char* plaintext, const unsigned int sz_plaintext, unsigned char *hashed);
|
||||
ops_boolean_t ops_is_hash_alg_supported(const ops_hash_algorithm_t *hash_alg);
|
||||
|
||||
#endif /*__OPS_HASH_H__*/
|
88
openpgpsdk/include/openpgpsdk/keyring.h
Normal file
88
openpgpsdk/include/openpgpsdk/keyring.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 OPS_KEYRING_H
|
||||
#define OPS_KEYRING_H
|
||||
|
||||
#include "packet.h"
|
||||
#include "memory.h"
|
||||
|
||||
typedef struct ops_keydata ops_keydata_t;
|
||||
|
||||
/** \struct ops_keyring_t
|
||||
* A keyring
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int nkeys; // while we are constructing a key, this is the offset
|
||||
int nkeys_allocated;
|
||||
ops_keydata_t *keys;
|
||||
} ops_keyring_t;
|
||||
|
||||
const ops_keydata_t *
|
||||
ops_keyring_find_key_by_id(const ops_keyring_t *keyring,
|
||||
const unsigned char keyid[OPS_KEY_ID_SIZE]);
|
||||
const ops_keydata_t *
|
||||
ops_keyring_find_key_by_userid(const ops_keyring_t *keyring,
|
||||
const char* userid);
|
||||
void ops_keydata_free(ops_keydata_t *key);
|
||||
void ops_keyring_free(ops_keyring_t *keyring);
|
||||
void ops_dump_keyring(const ops_keyring_t *keyring);
|
||||
const ops_public_key_t *
|
||||
ops_get_public_key_from_data(const ops_keydata_t *data);
|
||||
ops_boolean_t ops_is_key_secret(const ops_keydata_t *data);
|
||||
const ops_secret_key_t *
|
||||
ops_get_secret_key_from_data(const ops_keydata_t *data);
|
||||
ops_secret_key_t *
|
||||
ops_get_writable_secret_key_from_data(ops_keydata_t *data);
|
||||
ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key,
|
||||
const char *pphrase);
|
||||
|
||||
ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename);
|
||||
ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t *mem);
|
||||
|
||||
char *ops_malloc_passphrase(char *passphrase);
|
||||
char *ops_get_passphrase(void);
|
||||
|
||||
void ops_keyring_list(const ops_keyring_t* keyring);
|
||||
|
||||
void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key);
|
||||
|
||||
const unsigned char* ops_get_key_id(const ops_keydata_t *key);
|
||||
unsigned ops_get_user_id_count(const ops_keydata_t *key);
|
||||
const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index);
|
||||
ops_boolean_t ops_is_key_supported(const ops_keydata_t *key);
|
||||
const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index);
|
||||
|
||||
ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid);
|
||||
ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet);
|
||||
void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid, const ops_packet_t* packet);
|
||||
|
||||
ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid);
|
||||
|
||||
ops_keydata_t *ops_keydata_new(void);
|
||||
void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type);
|
||||
|
||||
#endif
|
40
openpgpsdk/include/openpgpsdk/lists.h
Normal file
40
openpgpsdk/include/openpgpsdk/lists.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 OPS_LISTS_H
|
||||
#define OPS_LISTS_H
|
||||
|
||||
/** ops_ulong_list_t */
|
||||
typedef struct
|
||||
{
|
||||
unsigned int size;/* num of array slots allocated */
|
||||
unsigned int used; /* num of array slots currently used */
|
||||
unsigned long *ulongs;
|
||||
} ops_ulong_list_t;
|
||||
|
||||
void ops_ulong_list_init(ops_ulong_list_t *list);
|
||||
void ops_ulong_list_free(ops_ulong_list_t *list);
|
||||
unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong);
|
||||
|
||||
#endif /* OPS_LISTS_H */
|
52
openpgpsdk/include/openpgpsdk/memory.h
Normal file
52
openpgpsdk/include/openpgpsdk/memory.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "packet.h"
|
||||
|
||||
#ifndef OPS_MEMORY_H
|
||||
#define OPS_MEMORY_H
|
||||
|
||||
/** ops_memory_t
|
||||
*/
|
||||
typedef struct ops_memory ops_memory_t;
|
||||
|
||||
ops_memory_t *ops_memory_new(void);
|
||||
void ops_memory_free(ops_memory_t *mem);
|
||||
void ops_memory_init(ops_memory_t *mem,size_t initial_size);
|
||||
void ops_memory_pad(ops_memory_t *mem,size_t length);
|
||||
void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length);
|
||||
void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n,
|
||||
size_t length);
|
||||
void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag);
|
||||
void ops_memory_clear(ops_memory_t *mem);
|
||||
void ops_memory_release(ops_memory_t *mem);
|
||||
|
||||
void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem);
|
||||
|
||||
size_t ops_memory_get_length(const ops_memory_t *mem);
|
||||
void *ops_memory_get_data(ops_memory_t *mem);
|
||||
|
||||
#endif
|
170
openpgpsdk/include/openpgpsdk/packet-parse.h
Normal file
170
openpgpsdk/include/openpgpsdk/packet-parse.h
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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
|
||||
* Parser for OpenPGP packets - headers.
|
||||
*/
|
||||
|
||||
#ifndef OPS_PACKET_PARSE_H
|
||||
#define OPS_PACKET_PARSE_H
|
||||
|
||||
#include "types.h"
|
||||
#include "packet.h"
|
||||
#include "lists.h"
|
||||
|
||||
/** ops_region_t */
|
||||
typedef struct ops_region
|
||||
{
|
||||
struct ops_region *parent;
|
||||
unsigned length;
|
||||
unsigned length_read;
|
||||
unsigned last_read; /*!< length of last read, only valid in deepest child */
|
||||
ops_boolean_t indeterminate:1;
|
||||
} ops_region_t;
|
||||
|
||||
void ops_init_subregion(ops_region_t *subregion,ops_region_t *region);
|
||||
|
||||
#if 0
|
||||
/** Return values for reader functions e.g. ops_packet_reader_t() */
|
||||
enum ops_reader_ret_t
|
||||
{
|
||||
OPS_R_OK =0, /*!< success */
|
||||
OPS_R_EOF =1, /*!< reached end of file, no data has been returned */
|
||||
OPS_R_EARLY_EOF =2, /*!< could not read the requested
|
||||
number of bytes and either
|
||||
OPS_RETURN_LENGTH was not set and at
|
||||
least 1 byte was read, or there was
|
||||
an abnormal end to the file (or
|
||||
armoured block) */
|
||||
OPS_R_PARTIAL_READ =3, /*!< if OPS_RETURN_LENGTH is set and
|
||||
the buffer was not filled */
|
||||
OPS_R_ERROR =4, /*!< if there was an error reading */
|
||||
};
|
||||
#endif
|
||||
|
||||
/** ops_parse_callback_return_t */
|
||||
typedef enum
|
||||
{
|
||||
OPS_RELEASE_MEMORY,
|
||||
OPS_KEEP_MEMORY,
|
||||
OPS_FINISHED
|
||||
} ops_parse_cb_return_t;
|
||||
|
||||
typedef struct ops_parse_cb_info ops_parse_cb_info_t;
|
||||
|
||||
typedef ops_parse_cb_return_t
|
||||
ops_parse_cb_t(const ops_parser_content_t *content,
|
||||
ops_parse_cb_info_t *cbinfo);
|
||||
|
||||
typedef struct ops_parse_info ops_parse_info_t;
|
||||
typedef struct ops_reader_info ops_reader_info_t;
|
||||
typedef struct ops_crypt_info ops_crypt_info_t;
|
||||
|
||||
/*
|
||||
A reader MUST read at least one byte if it can, and should read up
|
||||
to the number asked for. Whether it reads more for efficiency is
|
||||
its own decision, but if it is a stacked reader it should never
|
||||
read more than the length of the region it operates in (which it
|
||||
would have to be given when it is stacked).
|
||||
|
||||
If a read is short because of EOF, then it should return the short
|
||||
read (obviously this will be zero on the second attempt, if not the
|
||||
first). Because a reader is not obliged to do a full read, only a
|
||||
zero return can be taken as an indication of EOF.
|
||||
|
||||
If there is an error, then the callback should be notified, the
|
||||
error stacked, and -1 should be returned.
|
||||
|
||||
Note that although length is a size_t, a reader will never be asked
|
||||
to read more than INT_MAX in one go.
|
||||
|
||||
*/
|
||||
|
||||
typedef int ops_reader_t(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo);
|
||||
|
||||
typedef void ops_reader_destroyer_t(ops_reader_info_t *rinfo);
|
||||
|
||||
ops_parse_info_t *ops_parse_info_new(void);
|
||||
void ops_parse_info_delete(ops_parse_info_t *pinfo);
|
||||
ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo);
|
||||
ops_crypt_t *ops_parse_get_decrypt(ops_parse_info_t *pinfo);
|
||||
|
||||
void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg);
|
||||
void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg);
|
||||
void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo);
|
||||
void *ops_parse_cb_get_errors(ops_parse_cb_info_t *cbinfo);
|
||||
void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg);
|
||||
void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg);
|
||||
void ops_reader_pop(ops_parse_info_t *pinfo);
|
||||
void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo);
|
||||
|
||||
void *ops_reader_get_arg(ops_reader_info_t *rinfo);
|
||||
|
||||
ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content,
|
||||
ops_parse_cb_info_t *cbinfo);
|
||||
ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content,
|
||||
ops_parse_cb_info_t *cbinfo);
|
||||
ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo);
|
||||
|
||||
int ops_parse(ops_parse_info_t *parse_info);
|
||||
int ops_parse_and_print_errors(ops_parse_info_t *parse_info);
|
||||
int ops_parse_and_save_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs);
|
||||
int ops_parse_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs);
|
||||
|
||||
void ops_parse_and_validate(ops_parse_info_t *parse_info);
|
||||
|
||||
/** Used to specify whether subpackets should be returned raw, parsed or ignored.
|
||||
*/
|
||||
enum ops_parse_type_t
|
||||
{
|
||||
OPS_PARSE_RAW, /*!< Callback Raw */
|
||||
OPS_PARSE_PARSED, /*!< Callback Parsed */
|
||||
OPS_PARSE_IGNORE, /*!< Don't callback */
|
||||
};
|
||||
|
||||
void ops_parse_options(ops_parse_info_t *pinfo,ops_content_tag_t tag,
|
||||
ops_parse_type_t type);
|
||||
|
||||
ops_boolean_t ops_limited_read(unsigned char *dest,size_t length,
|
||||
ops_region_t *region,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo);
|
||||
ops_boolean_t ops_stacked_limited_read(unsigned char *dest,unsigned length,
|
||||
ops_region_t *region,
|
||||
ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo);
|
||||
void ops_parse_hash_init(ops_parse_info_t *pinfo,ops_hash_algorithm_t type,
|
||||
const unsigned char *keyid);
|
||||
void ops_parse_hash_data(ops_parse_info_t *pinfo,const void *data,
|
||||
size_t length);
|
||||
void ops_parse_hash_finish(ops_parse_info_t *pinfo);
|
||||
ops_hash_t *ops_parse_hash_find(ops_parse_info_t *pinfo,
|
||||
const unsigned char keyid[OPS_KEY_ID_SIZE]);
|
||||
|
||||
ops_reader_t ops_stacked_read;
|
||||
|
||||
/* vim:set textwidth=120: */
|
||||
/* vim:set ts=8: */
|
||||
|
||||
|
||||
#endif
|
38
openpgpsdk/include/openpgpsdk/packet-show-cast.h
Normal file
38
openpgpsdk/include/openpgpsdk/packet-show-cast.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* Generated from packet-show.cast by ../../util/caster.pl, do not edit. */
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* (line 4) char *show_packet_tag(ops_packet_tag_t packet_tag, packet_tag_map_t *packet_tag_map) -> char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map) */
|
||||
char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map);
|
||||
#define show_packet_tag(packet_tag,packet_tag_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_packet_tag_t , packet_tag),CHECKED_INSTANCE_OF( packet_tag_map_t *, packet_tag_map))
|
||||
typedef char * show_packet_tag_t(ops_packet_tag_t , packet_tag_map_t *);
|
||||
|
||||
/* (line 5) char *show_sig_type(ops_sig_type_t sig_type, sig_type_map_t *sig_type_map) -> char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map) */
|
||||
char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map);
|
||||
#define show_sig_type(sig_type,sig_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_sig_type_t , sig_type),CHECKED_INSTANCE_OF( sig_type_map_t *, sig_type_map))
|
||||
typedef char * show_sig_type_t(ops_sig_type_t , sig_type_map_t *);
|
||||
|
||||
/* (line 6) char *show_pka(ops_public_key_algorithm_t pka, public_key_algorithm_map_t *pka_map) -> char *ops_str_from_map(int pka, ops_map_t *pka_map) */
|
||||
char *ops_str_from_map(int pka, ops_map_t *pka_map);
|
||||
#define show_pka(pka,pka_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_public_key_algorithm_t , pka),CHECKED_INSTANCE_OF( public_key_algorithm_map_t *, pka_map))
|
||||
typedef char * show_pka_t(ops_public_key_algorithm_t , public_key_algorithm_map_t *);
|
||||
|
||||
/* (line 7) char *show_ss_type(ops_ss_type_t ss_type, ss_type_map_t *ss_type_map) -> char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map) */
|
||||
char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map);
|
||||
#define show_ss_type(ss_type,ss_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_type_t , ss_type),CHECKED_INSTANCE_OF( ss_type_map_t *, ss_type_map))
|
||||
typedef char * show_ss_type_t(ops_ss_type_t , ss_type_map_t *);
|
||||
|
||||
/* (line 8) char *show_ss_rr_code(ops_ss_rr_code_t ss_rr_code, ss_rr_code_map_t *ss_rr_code_map) -> char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map) */
|
||||
char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map);
|
||||
#define show_ss_rr_code(ss_rr_code,ss_rr_code_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_rr_code_t , ss_rr_code),CHECKED_INSTANCE_OF( ss_rr_code_map_t *, ss_rr_code_map))
|
||||
typedef char * show_ss_rr_code_t(ops_ss_rr_code_t , ss_rr_code_map_t *);
|
||||
|
||||
/* (line 9) char *show_hash_algorithm(unsigned char hash,+ops_map_t *hash_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map) */
|
||||
char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map);
|
||||
#define show_hash_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, hash_algorithm_map))
|
||||
typedef char * show_hash_algorithm_t(unsigned char );
|
||||
|
||||
/* (line 10) char *show_symmetric_algorithm(unsigned char hash,+ops_map_t *symmetric_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map) */
|
||||
char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map);
|
||||
#define show_symmetric_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, symmetric_algorithm_map))
|
||||
typedef char * show_symmetric_algorithm_t(unsigned char );
|
94
openpgpsdk/include/openpgpsdk/packet-show.h
Normal file
94
openpgpsdk/include/openpgpsdk/packet-show.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 OPS_PACKET_TO_TEXT_H
|
||||
#define OPS_PACKET_TO_TEXT_H
|
||||
|
||||
#ifndef OPS_PACKET_H
|
||||
#include "packet.h"
|
||||
#endif
|
||||
|
||||
/** ops_list_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int size;/* num of array slots allocated */
|
||||
unsigned int used; /* num of array slots currently used */
|
||||
char **strings;
|
||||
} ops_list_t;
|
||||
|
||||
/** ops_text_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ops_list_t known;
|
||||
ops_list_t unknown;
|
||||
} ops_text_t;
|
||||
|
||||
/** ops_bit_map_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned char mask;
|
||||
char *string;
|
||||
} ops_bit_map_t;
|
||||
|
||||
void ops_text_init(ops_text_t *text);
|
||||
void ops_text_free(ops_text_t *text);
|
||||
|
||||
const char *ops_show_packet_tag(ops_packet_tag_t packet_tag);
|
||||
const char *ops_show_ss_type(ops_ss_type_t ss_type);
|
||||
|
||||
const char *ops_show_sig_type(ops_sig_type_t sig_type);
|
||||
const char *ops_show_pka(ops_public_key_algorithm_t pka);
|
||||
|
||||
ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression);
|
||||
const char *ops_show_ss_preferred_compression(unsigned char octet);
|
||||
|
||||
ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash);
|
||||
const char *ops_show_hash_algorithm(unsigned char octet);
|
||||
const char *ops_show_symmetric_algorithm(unsigned char hash);
|
||||
|
||||
ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska);
|
||||
const char *ops_show_ss_preferred_ska(unsigned char octet);
|
||||
|
||||
const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code);
|
||||
|
||||
ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features);
|
||||
|
||||
ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags);
|
||||
const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map);
|
||||
|
||||
ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs);
|
||||
const char *ops_show_ss_key_server_prefs(unsigned char octet,
|
||||
ops_bit_map_t *map);
|
||||
|
||||
ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data);
|
||||
|
||||
char *ops_str_from_map(int code, ops_map_t *map);
|
||||
|
||||
/* vim:set textwidth=120: */
|
||||
/* vim:set ts=8: */
|
||||
|
||||
#endif /* OPS_PACKET_TO_TEXT_H */
|
1053
openpgpsdk/include/openpgpsdk/packet.h
Normal file
1053
openpgpsdk/include/openpgpsdk/packet.h
Normal file
File diff suppressed because it is too large
Load Diff
28
openpgpsdk/include/openpgpsdk/random.h
Normal file
28
openpgpsdk/include/openpgpsdk/random.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void ops_random(void *dest,size_t length);
|
93
openpgpsdk/include/openpgpsdk/readerwriter.h
Normal file
93
openpgpsdk/include/openpgpsdk/readerwriter.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPS_READERWRITER_H__
|
||||
#define __OPS_READERWRITER_H__
|
||||
|
||||
#include <openpgpsdk/memory.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
|
||||
|
||||
void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd);
|
||||
void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer,
|
||||
size_t length);
|
||||
|
||||
// Do a sum mod 65536 of all bytes read (as needed for secret keys)
|
||||
void ops_reader_push_sum16(ops_parse_info_t *pinfo);
|
||||
unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo);
|
||||
|
||||
void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt,
|
||||
ops_region_t *region);
|
||||
void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo);
|
||||
|
||||
//
|
||||
ops_boolean_t ops_write_mdc(const unsigned char *hashed,
|
||||
ops_create_info_t* info);
|
||||
ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
|
||||
const unsigned int len,
|
||||
ops_crypt_t *crypt,
|
||||
ops_create_info_t *info);
|
||||
void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo,
|
||||
ops_crypt_t *crypt);
|
||||
void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo,
|
||||
const ops_keydata_t *pub_key);
|
||||
// Secret Key checksum
|
||||
|
||||
void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey);
|
||||
ops_boolean_t ops_pop_skey_checksum_writer(ops_create_info_t *cinfo);
|
||||
|
||||
|
||||
// memory writing
|
||||
void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz);
|
||||
void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem);
|
||||
|
||||
// memory reading
|
||||
void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem,
|
||||
void* arg,
|
||||
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),ops_boolean_t accumulate);
|
||||
void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem);
|
||||
|
||||
// file writing
|
||||
int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite);
|
||||
void ops_teardown_file_write(ops_create_info_t *cinfo, int fd);
|
||||
|
||||
// file appending
|
||||
int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename);
|
||||
void ops_teardown_file_append(ops_create_info_t *cinfo, int fd);
|
||||
|
||||
// file reading
|
||||
int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename, void* arg,
|
||||
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), ops_boolean_t accumulate);
|
||||
void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd);
|
||||
|
||||
ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state);
|
||||
|
||||
// useful callbacks
|
||||
ops_parse_cb_return_t
|
||||
callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
|
||||
ops_parse_cb_return_t
|
||||
callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
|
||||
ops_parse_cb_return_t
|
||||
callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
|
||||
ops_parse_cb_return_t
|
||||
callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
|
||||
|
||||
#endif /*OPS_READERWRITER_H__*/
|
95
openpgpsdk/include/openpgpsdk/signature.h
Normal file
95
openpgpsdk/include/openpgpsdk/signature.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 OPS_SIGNATURE_H
|
||||
#define OPS_SIGNATURE_H
|
||||
|
||||
#include "packet.h"
|
||||
#include "util.h"
|
||||
#include "create.h"
|
||||
|
||||
typedef struct ops_create_signature ops_create_signature_t;
|
||||
|
||||
ops_create_signature_t *ops_create_signature_new(void);
|
||||
void ops_create_signature_delete(ops_create_signature_t *sig);
|
||||
|
||||
ops_boolean_t
|
||||
ops_check_user_id_certification_signature(const ops_public_key_t *key,
|
||||
const ops_user_id_t *id,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer,
|
||||
const unsigned char *raw_packet);
|
||||
ops_boolean_t
|
||||
ops_check_user_attribute_certification_signature(const ops_public_key_t *key,
|
||||
const ops_user_attribute_t *attribute,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer,
|
||||
const unsigned char *raw_packet);
|
||||
ops_boolean_t
|
||||
ops_check_subkey_signature(const ops_public_key_t *key,
|
||||
const ops_public_key_t *subkey,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer,
|
||||
const unsigned char *raw_packet);
|
||||
ops_boolean_t
|
||||
ops_check_direct_signature(const ops_public_key_t *key,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer,
|
||||
const unsigned char *raw_packet);
|
||||
ops_boolean_t
|
||||
ops_check_hash_signature(ops_hash_t *hash,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer);
|
||||
void ops_signature_start_key_signature(ops_create_signature_t *sig,
|
||||
const ops_public_key_t *key,
|
||||
const ops_user_id_t *id,
|
||||
ops_sig_type_t type);
|
||||
void ops_signature_start_cleartext_signature(ops_create_signature_t *sig,
|
||||
const ops_secret_key_t *key,
|
||||
const ops_hash_algorithm_t hash,
|
||||
const ops_sig_type_t type);
|
||||
void ops_signature_start_message_signature(ops_create_signature_t *sig,
|
||||
const ops_secret_key_t *key,
|
||||
const ops_hash_algorithm_t hash,
|
||||
const ops_sig_type_t type);
|
||||
|
||||
void ops_signature_add_data(ops_create_signature_t *sig,const void *buf,
|
||||
size_t length);
|
||||
ops_hash_t *ops_signature_get_hash(ops_create_signature_t *sig);
|
||||
ops_boolean_t ops_signature_hashed_subpackets_end(ops_create_signature_t *sig);
|
||||
ops_boolean_t ops_write_signature(ops_create_signature_t *sig,const ops_public_key_t *key,
|
||||
const ops_secret_key_t *skey, ops_create_info_t *opt);
|
||||
ops_boolean_t ops_signature_add_creation_time(ops_create_signature_t *sig,time_t when);
|
||||
ops_boolean_t ops_signature_add_issuer_key_id(ops_create_signature_t *sig,
|
||||
const unsigned char keyid[OPS_KEY_ID_SIZE]);
|
||||
void ops_signature_add_primary_user_id(ops_create_signature_t *sig,
|
||||
ops_boolean_t primary);
|
||||
|
||||
// Standard Interface
|
||||
ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t overwrite);
|
||||
ops_boolean_t ops_sign_buf_as_cleartext(const char* input, const size_t len, ops_memory_t** output, const ops_secret_key_t *skey);
|
||||
ops_boolean_t ops_sign_file(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t use_armour, const ops_boolean_t overwrite);
|
||||
ops_memory_t * ops_sign_buf(const void* input, const size_t input_len, const ops_sig_type_t sig_type, const ops_secret_key_t *skey, const ops_boolean_t use_armour);
|
||||
|
||||
#endif
|
47
openpgpsdk/include/openpgpsdk/std_print.h
Normal file
47
openpgpsdk/include/openpgpsdk/std_print.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 OPS_STD_PRINT_H
|
||||
#define OPS_STD_PRINT_H
|
||||
|
||||
#include "openpgpsdk/packet.h"
|
||||
#include "openpgpsdk/packet-parse.h"
|
||||
#include "openpgpsdk/keyring.h"
|
||||
|
||||
void print_bn( const char *name,
|
||||
const BIGNUM *bn);
|
||||
void ops_print_pk_session_key(ops_content_tag_t tag,
|
||||
const ops_pk_session_key_t *key);
|
||||
void ops_print_public_keydata(const ops_keydata_t *key);
|
||||
|
||||
void ops_print_public_keydata_verbose(const ops_keydata_t *key);
|
||||
void ops_print_public_key(const ops_public_key_t *pkey);
|
||||
|
||||
void ops_print_secret_keydata(const ops_keydata_t *key);
|
||||
void ops_print_secret_keydata_verbose(const ops_keydata_t *key);
|
||||
//void ops_print_secret_key(const ops_content_tag_t type, const ops_secret_key_t* skey);
|
||||
int ops_print_packet(const ops_parser_content_t *content_);
|
||||
void ops_list_packets(char *filename, ops_boolean_t armour, ops_keyring_t* pubring, ops_parse_cb_t* cb_get_passphrase);
|
||||
|
||||
#endif
|
30
openpgpsdk/include/openpgpsdk/streamwriter.h
Normal file
30
openpgpsdk/include/openpgpsdk/streamwriter.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __OPS_STREAMWRITER_H__
|
||||
#define __OPS_STREAMWRITER_H__
|
||||
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
|
||||
void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
|
||||
const ops_key_data_t *pub_key);
|
||||
|
||||
#endif /*__OPS_STREAMWRITER_H__*/
|
96
openpgpsdk/include/openpgpsdk/types.h
Normal file
96
openpgpsdk/include/openpgpsdk/types.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 OPS_TYPES_H
|
||||
#define OPS_TYPES_H
|
||||
|
||||
/** Special type for intermediate function casting, avoids warnings on
|
||||
some platforms
|
||||
*/
|
||||
typedef void (*ops_void_fptr)(void);
|
||||
#define ops_fcast(f) ((ops_void_fptr)f)
|
||||
|
||||
/** ops_map_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int type;
|
||||
char *string;
|
||||
} ops_map_t;
|
||||
|
||||
/** Boolean type */
|
||||
typedef unsigned ops_boolean_t;
|
||||
|
||||
/** ops_content_tag_t */
|
||||
typedef enum ops_content_tag_t ops_content_tag_t;
|
||||
|
||||
typedef struct _ops_crypt_t ops_crypt_t;
|
||||
|
||||
/** ops_hash_t */
|
||||
typedef struct _ops_hash_t ops_hash_t;
|
||||
|
||||
/**
|
||||
keep both ops_content_tag_t and ops_packet_tag_t because we might
|
||||
want to introduce some bounds checking i.e. is this really a valid value
|
||||
for a packet tag?
|
||||
*/
|
||||
typedef enum ops_content_tag_t ops_packet_tag_t;
|
||||
/** SS types are a subset of all content types.
|
||||
*/
|
||||
typedef enum ops_content_tag_t ops_ss_type_t;
|
||||
/* typedef enum ops_sig_type_t ops_sig_type_t; */
|
||||
|
||||
/** Revocation Reason type */
|
||||
typedef unsigned char ops_ss_rr_code_t;
|
||||
|
||||
/** ops_parse_type_t */
|
||||
typedef enum ops_parse_type_t ops_parse_type_t;
|
||||
|
||||
/** ops_parser_content_t */
|
||||
typedef struct ops_parser_content_t ops_parser_content_t;
|
||||
|
||||
/** Reader Flags */
|
||||
/*
|
||||
typedef enum
|
||||
{
|
||||
OPS_RETURN_LENGTH=1,
|
||||
} ops_reader_flags_t;
|
||||
typedef enum ops_reader_ret_t ops_reader_ret_t;
|
||||
*/
|
||||
|
||||
/** Writer flags */
|
||||
typedef enum
|
||||
{
|
||||
OPS_WF_DUMMY,
|
||||
} ops_writer_flags_t;
|
||||
/** ops_writer_ret_t */
|
||||
typedef enum ops_writer_ret_t ops_writer_ret_t;
|
||||
|
||||
/**
|
||||
* \ingroup Create
|
||||
* Contains the required information about how to write
|
||||
*/
|
||||
typedef struct ops_create_info ops_create_info_t;
|
||||
|
||||
#endif
|
54
openpgpsdk/include/openpgpsdk/util.h
Normal file
54
openpgpsdk/include/openpgpsdk/util.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 OPS_UTIL_H
|
||||
#define OPS_UTIL_H
|
||||
|
||||
#include "openpgpsdk/types.h"
|
||||
#include "openpgpsdk/create.h"
|
||||
#include "openpgpsdk/packet-parse.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ops_false 0
|
||||
#define ops_true 1
|
||||
|
||||
void hexdump(const unsigned char *src,size_t length);
|
||||
|
||||
/*
|
||||
* These macros code ensures that you are casting what you intend to cast.
|
||||
* It works because in "a ? b : c", b and c must have the same type.
|
||||
* This is a copy of the macro defined in openssl/asn1.h.
|
||||
*/
|
||||
#ifndef CHECKED_PTR_OF
|
||||
#define CHECKED_PTR_OF(type, p) ((void*) (1 ? p : (type *)0))
|
||||
#endif
|
||||
#define CHECKED_INSTANCE_OF(type, p) (1 ? p : (type)0)
|
||||
#define DECONST(type,p) ((type *)CHECKED_PTR_OF(const type, p))
|
||||
|
||||
/* number of elements in an array */
|
||||
#define OPS_ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
|
||||
|
||||
void *ops_mallocz(size_t n);
|
||||
|
||||
#endif
|
102
openpgpsdk/include/openpgpsdk/validate.h
Normal file
102
openpgpsdk/include/openpgpsdk/validate.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int valid_count;
|
||||
ops_signature_info_t * valid_sigs;
|
||||
unsigned int invalid_count;
|
||||
ops_signature_info_t * invalid_sigs;
|
||||
unsigned int unknown_signer_count;
|
||||
ops_signature_info_t * unknown_sigs;
|
||||
} ops_validate_result_t;
|
||||
|
||||
void ops_validate_result_free(ops_validate_result_t *result);
|
||||
|
||||
ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,
|
||||
const ops_keydata_t* keydata,
|
||||
const ops_keyring_t *ring,
|
||||
ops_parse_cb_return_t cb (const ops_parser_content_t *, ops_parse_cb_info_t *));
|
||||
ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result,
|
||||
const ops_keyring_t *ring,
|
||||
ops_parse_cb_return_t (const ops_parser_content_t *, ops_parse_cb_info_t *));
|
||||
|
||||
void ops_keydata_reader_set(ops_parse_info_t *pinfo,
|
||||
const ops_keydata_t *key);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ops_keydata_t *key;
|
||||
unsigned packet;
|
||||
unsigned offset;
|
||||
} validate_reader_arg_t;
|
||||
|
||||
/** Struct used with the validate_key_cb callback */
|
||||
typedef struct
|
||||
{
|
||||
ops_public_key_t pkey;
|
||||
ops_public_key_t subkey;
|
||||
ops_secret_key_t skey;
|
||||
enum
|
||||
{
|
||||
ATTRIBUTE=1,
|
||||
ID,
|
||||
} last_seen;
|
||||
ops_user_id_t user_id;
|
||||
ops_user_attribute_t user_attribute;
|
||||
unsigned char hash[OPS_MAX_HASH_SIZE];
|
||||
const ops_keyring_t *keyring;
|
||||
validate_reader_arg_t *rarg;
|
||||
ops_validate_result_t *result;
|
||||
ops_parse_cb_return_t (*cb_get_passphrase) (const ops_parser_content_t *, ops_parse_cb_info_t *);
|
||||
} validate_key_cb_arg_t;
|
||||
|
||||
/** Struct use with the validate_data_cb callback */
|
||||
typedef struct
|
||||
{
|
||||
enum
|
||||
{
|
||||
LITERAL_DATA,
|
||||
SIGNED_CLEARTEXT
|
||||
} use; /*<! this is set to indicate what kind of data we have */
|
||||
union
|
||||
{
|
||||
ops_literal_data_body_t literal_data_body; /*<! Used to hold Literal Data */
|
||||
ops_signed_cleartext_body_t signed_cleartext_body; /*<! Used to hold Signed Cleartext */
|
||||
} data; /*<! the data itself */
|
||||
unsigned char hash[OPS_MAX_HASH_SIZE]; /*<! the hash */
|
||||
const ops_keyring_t *keyring; /*<! keyring to use */
|
||||
validate_reader_arg_t *rarg; /*<! reader-specific arg */
|
||||
ops_validate_result_t *result; /*<! where to put the result */
|
||||
} validate_data_cb_arg_t; /*<! used with validate_data_cb callback */
|
||||
|
||||
ops_boolean_t ops_check_signature(const unsigned char *hash,
|
||||
unsigned length,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer);
|
||||
ops_parse_cb_return_t
|
||||
ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
|
||||
|
||||
ops_boolean_t ops_validate_file(ops_validate_result_t* result, const char* filename, const int armoured, const ops_keyring_t* keyring);
|
||||
ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring);
|
||||
|
||||
// EOF
|
39
openpgpsdk/include/openpgpsdk/version.h
Normal file
39
openpgpsdk/include/openpgpsdk/version.h
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define OPS_VERSION_MAJOR 0
|
||||
/* Set to the version next to be released */
|
||||
#define OPS_VERSION_MINOR 9
|
||||
/* 0 for development version, 1 for release */
|
||||
#define OPS_VERSION_RELEASE 1
|
||||
|
||||
#define OPS_VERSION ((OPS_VERSION_MAJOR << 16)+(OPS_VERSION_MINOR << 1)+OPS_VERSION_RELEASE)
|
||||
|
||||
#if OPS_VERSION_RELEASE
|
||||
# define OPS_DEV_STRING ""
|
||||
#else
|
||||
# define OPS_DEV_STRING " (dev)"
|
||||
#endif
|
||||
|
||||
|
||||
#define OPS_VERSION_CAT(a,b) "OpenPGP:SDK v" #a "." #b OPS_DEV_STRING
|
||||
#define OPS_VERSION_CAT2(a,b) OPS_VERSION_CAT(a,b)
|
||||
#define OPS_VERSION_STRING OPS_VERSION_CAT2(OPS_VERSION_MAJOR,OPS_VERSION_MINOR)
|
100
openpgpsdk/include/openpgpsdk/writer.h
Normal file
100
openpgpsdk/include/openpgpsdk/writer.h
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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 OPS_WRITER_H
|
||||
#define OPS_WRITER_H
|
||||
|
||||
#include "types.h"
|
||||
#include "packet.h"
|
||||
#include "crypto.h"
|
||||
#include "memory.h"
|
||||
#include "errors.h"
|
||||
#include "keyring.h"
|
||||
|
||||
/**
|
||||
* \ingroup Create
|
||||
* This struct contains the required information about one writer
|
||||
*/
|
||||
/**
|
||||
* \ingroup Writer
|
||||
* the writer function prototype
|
||||
*/
|
||||
|
||||
typedef struct ops_writer_info ops_writer_info_t;
|
||||
typedef ops_boolean_t ops_writer_t(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo);
|
||||
typedef ops_boolean_t ops_writer_finaliser_t(ops_error_t **errors,
|
||||
ops_writer_info_t *winfo);
|
||||
typedef void ops_writer_destroyer_t(ops_writer_info_t *winfo);
|
||||
/** Writer settings */
|
||||
struct ops_writer_info
|
||||
{
|
||||
ops_writer_t *writer; /*!< the writer itself */
|
||||
ops_writer_finaliser_t *finaliser; /*!< the writer's finaliser */
|
||||
ops_writer_destroyer_t *destroyer; /*!< the writer's destroyer */
|
||||
void *arg; /* writer-specific argument */
|
||||
ops_writer_info_t *next; /*!< next writer in the stack */
|
||||
};
|
||||
|
||||
|
||||
void *ops_writer_get_arg(ops_writer_info_t *winfo);
|
||||
ops_boolean_t ops_stacked_write(const void *src,unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo);
|
||||
|
||||
void ops_writer_set(ops_create_info_t *info,
|
||||
ops_writer_t *writer,
|
||||
ops_writer_finaliser_t *finaliser,
|
||||
ops_writer_destroyer_t *destroyer,
|
||||
void *arg);
|
||||
void ops_writer_push(ops_create_info_t *info,
|
||||
ops_writer_t *writer,
|
||||
ops_writer_finaliser_t *finaliser,
|
||||
ops_writer_destroyer_t *destroyer,
|
||||
void *arg);
|
||||
void ops_writer_pop(ops_create_info_t *info);
|
||||
void ops_writer_generic_destroyer(ops_writer_info_t *winfo);
|
||||
ops_boolean_t ops_writer_passthrough(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo);
|
||||
|
||||
void ops_writer_set_fd(ops_create_info_t *info,int fd);
|
||||
ops_boolean_t ops_writer_close(ops_create_info_t *info);
|
||||
|
||||
ops_boolean_t ops_write(const void *src,unsigned length,
|
||||
ops_create_info_t *opt);
|
||||
ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *opt);
|
||||
ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *opt);
|
||||
ops_boolean_t ops_write_scalar(unsigned n,unsigned length,
|
||||
ops_create_info_t *opt);
|
||||
ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *opt);
|
||||
ops_boolean_t ops_write_encrypted_mpi(const BIGNUM *bn, ops_crypt_t* crypt, ops_create_info_t *info);
|
||||
|
||||
void writer_info_delete(ops_writer_info_t *winfo);
|
||||
ops_boolean_t writer_info_finalise(ops_error_t **errors, ops_writer_info_t *winfo);
|
||||
|
||||
#endif
|
31
openpgpsdk/include/openpgpsdk/writer_armoured.h
Normal file
31
openpgpsdk/include/openpgpsdk/writer_armoured.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/armour.h>
|
||||
|
||||
ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
|
||||
ops_create_signature_t *sig);
|
||||
void ops_writer_push_armoured_message(ops_create_info_t *info);
|
||||
ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info);
|
||||
|
||||
void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type);
|
||||
|
||||
// EOF
|
195
openpgpsdk/src/accumulate.c
Normal file
195
openpgpsdk/src/accumulate.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/packet.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/accumulate.h>
|
||||
#include "keyring_local.h"
|
||||
#include "parse_local.h"
|
||||
#include <openpgpsdk/signature.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_keyring_t *keyring;
|
||||
} accumulate_arg_t;
|
||||
|
||||
/**
|
||||
* \ingroup Core_Callbacks
|
||||
*/
|
||||
static ops_parse_cb_return_t
|
||||
accumulate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
accumulate_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
|
||||
const ops_parser_content_union_t *content=&content_->content;
|
||||
ops_keyring_t *keyring=arg->keyring;
|
||||
ops_keydata_t *cur=NULL;
|
||||
const ops_public_key_t *pkey;
|
||||
|
||||
if(keyring->nkeys >= 0)
|
||||
cur=&keyring->keys[keyring->nkeys];
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PTAG_CT_PUBLIC_KEY:
|
||||
case OPS_PTAG_CT_SECRET_KEY:
|
||||
case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
|
||||
// printf("New key\n");
|
||||
++keyring->nkeys;
|
||||
EXPAND_ARRAY(keyring,keys);
|
||||
|
||||
if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY)
|
||||
pkey=&content->public_key;
|
||||
else
|
||||
pkey=&content->secret_key.public_key;
|
||||
|
||||
memset(&keyring->keys[keyring->nkeys],'\0',
|
||||
sizeof keyring->keys[keyring->nkeys]);
|
||||
|
||||
ops_keyid(keyring->keys[keyring->nkeys].key_id,pkey);
|
||||
ops_fingerprint(&keyring->keys[keyring->nkeys].fingerprint,pkey);
|
||||
|
||||
keyring->keys[keyring->nkeys].type=content_->tag;
|
||||
|
||||
if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY)
|
||||
keyring->keys[keyring->nkeys].key.pkey=*pkey;
|
||||
else
|
||||
keyring->keys[keyring->nkeys].key.skey=content->secret_key;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PTAG_CT_USER_ID:
|
||||
// printf("User ID: %s\n",content->user_id.user_id);
|
||||
if (!cur)
|
||||
{
|
||||
OPS_ERROR(cbinfo->errors,OPS_E_P_NO_USERID, "No user id found");
|
||||
return OPS_KEEP_MEMORY;
|
||||
}
|
||||
// assert(cur);
|
||||
ops_add_userid_to_keydata(cur, &content->user_id);
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PARSER_PACKET_END:
|
||||
if(!cur)
|
||||
return OPS_RELEASE_MEMORY;
|
||||
ops_add_packet_to_keydata(cur, &content->packet);
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PARSER_ERROR:
|
||||
fprintf(stderr,"Error: %s\n",content->error.error);
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case OPS_PARSER_ERRCODE:
|
||||
switch(content->errcode.errcode)
|
||||
{
|
||||
default:
|
||||
fprintf(stderr,"parse error: %s\n",
|
||||
ops_errcode(content->errcode.errcode));
|
||||
//assert(0);
|
||||
}
|
||||
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 ops_parse_stacked_cb(content_,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_info Options to use when parsing
|
||||
*/
|
||||
|
||||
int ops_parse_and_accumulate(ops_keyring_t *keyring,
|
||||
ops_parse_info_t *parse_info)
|
||||
{
|
||||
int rtn;
|
||||
|
||||
accumulate_arg_t arg;
|
||||
|
||||
assert(!parse_info->rinfo.accumulate);
|
||||
|
||||
memset(&arg,'\0',sizeof arg);
|
||||
|
||||
arg.keyring=keyring;
|
||||
/* Kinda weird, but to do with counting, and we put it back after */
|
||||
--keyring->nkeys;
|
||||
|
||||
ops_parse_cb_push(parse_info,accumulate_cb,&arg);
|
||||
|
||||
parse_info->rinfo.accumulate=ops_true;
|
||||
|
||||
rtn=ops_parse(parse_info);
|
||||
++keyring->nkeys;
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void dump_one_keydata(const ops_keydata_t *key)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
printf("Key ID: ");
|
||||
hexdump(key->key_id,8);
|
||||
|
||||
printf("\nFingerpint: ");
|
||||
hexdump(key->fingerprint.fingerprint,key->fingerprint.length);
|
||||
|
||||
printf("\n\nUIDs\n====\n\n");
|
||||
for(n=0 ; n < key->nuids ; ++n)
|
||||
printf("%s\n",key->uids[n].user_id);
|
||||
|
||||
printf("\nPackets\n=======\n");
|
||||
for(n=0 ; n < key->npackets ; ++n)
|
||||
{
|
||||
printf("\n%03d: ",n);
|
||||
hexdump(key->packets[n].raw,key->packets[n].length);
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
// XXX: not a maintained part of the API - use ops_keyring_list()
|
||||
/** ops_dump_keyring
|
||||
*/
|
||||
void ops_dump_keyring(const ops_keyring_t *keyring)
|
||||
{
|
||||
int n;
|
||||
|
||||
for(n=0 ; n < keyring->nkeys ; ++n)
|
||||
dump_one_keydata(&keyring->keys[n]);
|
||||
}
|
405
openpgpsdk/src/compress.c
Normal file
405
openpgpsdk/src/compress.c
Normal file
@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <zlib.h>
|
||||
#include <bzlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/compress.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include "parse_local.h"
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
#define DECOMPRESS_BUFFER 1024
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_compression_type_t type;
|
||||
ops_region_t *region;
|
||||
unsigned char in[DECOMPRESS_BUFFER];
|
||||
unsigned char out[DECOMPRESS_BUFFER];
|
||||
z_stream zstream; // ZIP and ZLIB
|
||||
size_t offset;
|
||||
int inflate_ret;
|
||||
} z_decompress_arg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_compression_type_t type;
|
||||
ops_region_t *region;
|
||||
char in[DECOMPRESS_BUFFER];
|
||||
char out[DECOMPRESS_BUFFER];
|
||||
bz_stream bzstream; // BZIP2
|
||||
size_t offset;
|
||||
int inflate_ret;
|
||||
} bz_decompress_arg_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
z_stream stream;
|
||||
unsigned char *src;
|
||||
unsigned char *dst;
|
||||
} compress_arg_t;
|
||||
|
||||
// \todo remove code duplication between this and bzip2_compressed_data_reader
|
||||
static int zlib_compressed_data_reader(void *dest,size_t length,
|
||||
ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
z_decompress_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
assert(arg->type==OPS_C_ZIP || arg->type==OPS_C_ZLIB);
|
||||
|
||||
//ops_parser_content_t content;
|
||||
int saved=length;
|
||||
|
||||
if(/*arg->region->indeterminate && */ arg->inflate_ret == Z_STREAM_END
|
||||
&& arg->zstream.next_out == &arg->out[arg->offset])
|
||||
return 0;
|
||||
|
||||
if(arg->region->length_read == arg->region->length)
|
||||
{
|
||||
if(arg->inflate_ret != Z_STREAM_END)
|
||||
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,"Compressed data didn't end when region ended.");
|
||||
/*
|
||||
else
|
||||
return 0;
|
||||
www.zlib.org
|
||||
*/
|
||||
}
|
||||
|
||||
while(length > 0)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if(&arg->out[arg->offset] == arg->zstream.next_out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
arg->zstream.next_out=arg->out;
|
||||
arg->zstream.avail_out=sizeof arg->out;
|
||||
arg->offset=0;
|
||||
if(arg->zstream.avail_in == 0)
|
||||
{
|
||||
unsigned n=arg->region->length;
|
||||
|
||||
if(!arg->region->indeterminate)
|
||||
{
|
||||
n-=arg->region->length_read;
|
||||
if(n > sizeof arg->in)
|
||||
n=sizeof arg->in;
|
||||
}
|
||||
else
|
||||
n=sizeof arg->in;
|
||||
|
||||
if(!ops_stacked_limited_read(arg->in,n,arg->region,
|
||||
errors,rinfo,cbinfo))
|
||||
return -1;
|
||||
|
||||
arg->zstream.next_in=arg->in;
|
||||
arg->zstream.avail_in=arg->region->indeterminate
|
||||
? arg->region->last_read : n;
|
||||
}
|
||||
|
||||
ret=inflate(&arg->zstream,Z_SYNC_FLUSH);
|
||||
if(ret == Z_STREAM_END)
|
||||
{
|
||||
if(!arg->region->indeterminate
|
||||
&& arg->region->length_read != arg->region->length)
|
||||
OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR,"Compressed stream ended before packet end.");
|
||||
}
|
||||
else if(ret != Z_OK)
|
||||
{
|
||||
fprintf(stderr,"ret=%d\n",ret);
|
||||
OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR, arg->zstream.msg);
|
||||
}
|
||||
arg->inflate_ret=ret;
|
||||
}
|
||||
assert(arg->zstream.next_out > &arg->out[arg->offset]);
|
||||
len=arg->zstream.next_out-&arg->out[arg->offset];
|
||||
if(len > length)
|
||||
len=length;
|
||||
memcpy(dest,&arg->out[arg->offset],len);
|
||||
arg->offset+=len;
|
||||
length-=len;
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
// \todo remove code duplication between this and zlib_compressed_data_reader
|
||||
static int bzip2_compressed_data_reader(void *dest,size_t length,
|
||||
ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
bz_decompress_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
assert(arg->type==OPS_C_BZIP2);
|
||||
|
||||
//ops_parser_content_t content;
|
||||
int saved=length;
|
||||
|
||||
if(arg->inflate_ret == BZ_STREAM_END
|
||||
&& arg->bzstream.next_out == &arg->out[arg->offset])
|
||||
return 0;
|
||||
|
||||
if(arg->region->length_read == arg->region->length)
|
||||
{
|
||||
if(arg->inflate_ret != BZ_STREAM_END)
|
||||
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,"Compressed data didn't end when region ended.");
|
||||
}
|
||||
|
||||
while(length > 0)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if(&arg->out[arg->offset] == arg->bzstream.next_out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
arg->bzstream.next_out=(char *) arg->out;
|
||||
arg->bzstream.avail_out=sizeof arg->out;
|
||||
arg->offset=0;
|
||||
if(arg->bzstream.avail_in == 0)
|
||||
{
|
||||
unsigned n=arg->region->length;
|
||||
|
||||
if(!arg->region->indeterminate)
|
||||
{
|
||||
n-=arg->region->length_read;
|
||||
if(n > sizeof arg->in)
|
||||
n=sizeof arg->in;
|
||||
}
|
||||
else
|
||||
n=sizeof arg->in;
|
||||
|
||||
if(!ops_stacked_limited_read((unsigned char *)arg->in,n,arg->region,
|
||||
errors,rinfo,cbinfo))
|
||||
return -1;
|
||||
|
||||
arg->bzstream.next_in=arg->in;
|
||||
arg->bzstream.avail_in=arg->region->indeterminate
|
||||
? arg->region->last_read : n;
|
||||
}
|
||||
|
||||
ret=BZ2_bzDecompress(&arg->bzstream);
|
||||
if(ret == BZ_STREAM_END)
|
||||
{
|
||||
if(!arg->region->indeterminate
|
||||
&& arg->region->length_read != arg->region->length)
|
||||
OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR,"Compressed stream ended before packet end.");
|
||||
}
|
||||
else if(ret != BZ_OK)
|
||||
{
|
||||
OPS_ERROR_1(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR,"Invalid return %d from BZ2_bzDecompress", ret);
|
||||
}
|
||||
arg->inflate_ret=ret;
|
||||
}
|
||||
assert(arg->bzstream.next_out > &arg->out[arg->offset]);
|
||||
len=arg->bzstream.next_out-&arg->out[arg->offset];
|
||||
if(len > length)
|
||||
len=length;
|
||||
memcpy(dest,&arg->out[arg->offset],len);
|
||||
arg->offset+=len;
|
||||
length-=len;
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Compress
|
||||
*
|
||||
* \param *region Pointer to a region
|
||||
* \param *parse_info How to parse
|
||||
* \param type Which compression type to expect
|
||||
*/
|
||||
|
||||
int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
|
||||
ops_compression_type_t type)
|
||||
{
|
||||
z_decompress_arg_t z_arg;
|
||||
bz_decompress_arg_t bz_arg;
|
||||
int ret;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OPS_C_ZIP:
|
||||
case OPS_C_ZLIB:
|
||||
memset(&z_arg,'\0',sizeof z_arg);
|
||||
|
||||
z_arg.region=region;
|
||||
z_arg.offset=0;
|
||||
z_arg.type=type;
|
||||
|
||||
z_arg.zstream.next_in=Z_NULL;
|
||||
z_arg.zstream.avail_in=0;
|
||||
z_arg.zstream.next_out=z_arg.out;
|
||||
z_arg.zstream.zalloc=Z_NULL;
|
||||
z_arg.zstream.zfree=Z_NULL;
|
||||
z_arg.zstream.opaque=Z_NULL;
|
||||
break;
|
||||
|
||||
case OPS_C_BZIP2:
|
||||
memset(&bz_arg,'\0',sizeof bz_arg);
|
||||
|
||||
bz_arg.region=region;
|
||||
bz_arg.offset=0;
|
||||
bz_arg.type=type;
|
||||
|
||||
bz_arg.bzstream.next_in=NULL;
|
||||
bz_arg.bzstream.avail_in=0;
|
||||
bz_arg.bzstream.next_out=bz_arg.out;
|
||||
bz_arg.bzstream.bzalloc=NULL;
|
||||
bz_arg.bzstream.bzfree=NULL;
|
||||
bz_arg.bzstream.opaque=NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case OPS_C_ZIP:
|
||||
ret=inflateInit2(&z_arg.zstream,-15);
|
||||
break;
|
||||
|
||||
case OPS_C_ZLIB:
|
||||
ret=inflateInit(&z_arg.zstream);
|
||||
break;
|
||||
|
||||
case OPS_C_BZIP2:
|
||||
/*
|
||||
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %s is not yet supported", "BZIP2");
|
||||
return 0;
|
||||
*/
|
||||
ret=BZ2_bzDecompressInit(&bz_arg.bzstream, 1, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OPS_C_ZIP:
|
||||
case OPS_C_ZLIB:
|
||||
if(ret != Z_OK)
|
||||
{
|
||||
OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR, "Cannot initialise ZIP or ZLIB stream for decompression: error=%d", ret);
|
||||
return 0;
|
||||
}
|
||||
ops_reader_push(parse_info,zlib_compressed_data_reader,NULL,&z_arg);
|
||||
break;
|
||||
|
||||
case OPS_C_BZIP2:
|
||||
if (ret != BZ_OK)
|
||||
{
|
||||
OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR, "Cannot initialise BZIP2 stream for decompression: error=%d", ret);
|
||||
return 0;
|
||||
}
|
||||
ops_reader_push(parse_info,bzip2_compressed_data_reader,NULL,&bz_arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret=ops_parse(parse_info);
|
||||
|
||||
ops_reader_pop(parse_info);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_WritePackets
|
||||
\brief Writes Compressed packet
|
||||
\param data Data to write out
|
||||
\param len Length of data
|
||||
\param cinfo Write settings
|
||||
\return ops_true if OK; else ops_false
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_write_compressed(const unsigned char *data,
|
||||
const unsigned int len,
|
||||
ops_create_info_t *cinfo)
|
||||
{
|
||||
int r=0;
|
||||
int sz_in=0;
|
||||
int sz_out=0;
|
||||
compress_arg_t* compress=ops_mallocz(sizeof *compress);
|
||||
|
||||
// compress the data
|
||||
const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels
|
||||
compress->stream.zalloc=Z_NULL;
|
||||
compress->stream.zfree=Z_NULL;
|
||||
compress->stream.opaque=NULL;
|
||||
|
||||
// all other fields set to zero by use of ops_mallocz
|
||||
|
||||
if (deflateInit(&compress->stream,level) != Z_OK)
|
||||
{
|
||||
// can't initialise
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// do necessary transformation
|
||||
// copy input to maintain const'ness of src
|
||||
assert(compress->src==NULL);
|
||||
assert(compress->dst==NULL);
|
||||
|
||||
sz_in=len * sizeof (unsigned char);
|
||||
sz_out= (sz_in * 1.01) + 12; // from zlib webpage
|
||||
compress->src=ops_mallocz(sz_in);
|
||||
compress->dst=ops_mallocz(sz_out);
|
||||
memcpy(compress->src,data,len);
|
||||
|
||||
// setup stream
|
||||
compress->stream.next_in=compress->src;
|
||||
compress->stream.avail_in=sz_in;
|
||||
compress->stream.total_in=0;
|
||||
|
||||
compress->stream.next_out=compress->dst;
|
||||
compress->stream.avail_out=sz_out;
|
||||
compress->stream.total_out=0;
|
||||
|
||||
r=deflate(&compress->stream, Z_FINISH);
|
||||
assert(r==Z_STREAM_END); // need to loop if not
|
||||
|
||||
// write it out
|
||||
return (ops_write_ptag(OPS_PTAG_CT_COMPRESSED, cinfo)
|
||||
&& ops_write_length(1+compress->stream.total_out, cinfo)
|
||||
&& ops_write_scalar(OPS_C_ZLIB,1,cinfo)
|
||||
&& ops_write(compress->dst, compress->stream.total_out,cinfo));
|
||||
}
|
||||
|
||||
// EOF
|
1258
openpgpsdk/src/create.c
Normal file
1258
openpgpsdk/src/create.c
Normal file
File diff suppressed because it is too large
Load Diff
400
openpgpsdk/src/crypto.c
Normal file
400
openpgpsdk/src/crypto.c
Normal file
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/random.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include <openpgpsdk/writer_armoured.h>
|
||||
#include "parse_local.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
/**
|
||||
\ingroup Core_MPI
|
||||
\brief Decrypt and unencode MPI
|
||||
\param buf Buffer in which to write decrypted unencoded MPI
|
||||
\param buflen Length of buffer
|
||||
\param encmpi
|
||||
\param skey
|
||||
\return length of MPI
|
||||
\note only RSA at present
|
||||
*/
|
||||
int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM *encmpi,
|
||||
const ops_secret_key_t *skey)
|
||||
{
|
||||
unsigned char encmpibuf[8192];
|
||||
unsigned char mpibuf[8192];
|
||||
unsigned mpisize;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
mpisize=BN_num_bytes(encmpi);
|
||||
/* MPI can't be more than 65,536 */
|
||||
assert(mpisize <= sizeof encmpibuf);
|
||||
BN_bn2bin(encmpi,encmpibuf);
|
||||
|
||||
assert(skey->public_key.algorithm == OPS_PKA_RSA);
|
||||
|
||||
/*
|
||||
fprintf(stderr,"\nDECRYPTING\n");
|
||||
fprintf(stderr,"encrypted data : ");
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", encmpibuf[i]);
|
||||
fprintf(stderr,"\n");
|
||||
*/
|
||||
|
||||
n=ops_rsa_private_decrypt(mpibuf,encmpibuf,(BN_num_bits(encmpi)+7)/8,
|
||||
&skey->key.rsa,&skey->public_key.key.rsa);
|
||||
assert(n!=-1);
|
||||
|
||||
/*
|
||||
fprintf(stderr,"decrypted encoded m buf : ");
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", mpibuf[i]);
|
||||
fprintf(stderr,"\n");
|
||||
*/
|
||||
|
||||
if(n <= 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
printf(" decrypted=%d ",n);
|
||||
hexdump(mpibuf,n);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
// Decode EME-PKCS1_V1_5 (RFC 2437).
|
||||
|
||||
if(mpibuf[0] != 0 || mpibuf[1] != 2)
|
||||
return ops_false;
|
||||
|
||||
// Skip the random bytes.
|
||||
for(i=2 ; i < n && mpibuf[i] ; ++i)
|
||||
;
|
||||
|
||||
if(i == n || i < 10)
|
||||
return ops_false;
|
||||
|
||||
// Skip the zero
|
||||
++i;
|
||||
|
||||
// this is the unencoded m buf
|
||||
if((unsigned)(n-i) <= buflen)
|
||||
memcpy(buf,mpibuf+i,n-i);
|
||||
|
||||
/*
|
||||
printf("decoded m buf:\n");
|
||||
int j;
|
||||
for (j=0; j<n-i; j++)
|
||||
printf("%2x ",buf[j]);
|
||||
printf("\n");
|
||||
*/
|
||||
|
||||
return n-i;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_MPI
|
||||
\brief RSA-encrypt an MPI
|
||||
*/
|
||||
ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *encoded_m_buf,
|
||||
const size_t sz_encoded_m_buf,
|
||||
const ops_public_key_t *pkey,
|
||||
ops_pk_session_key_parameters_t *skp)
|
||||
{
|
||||
assert(sz_encoded_m_buf==(size_t) BN_num_bytes(pkey->key.rsa.n));
|
||||
|
||||
unsigned char encmpibuf[8192];
|
||||
int n=0;
|
||||
|
||||
n=ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, sz_encoded_m_buf, &pkey->key.rsa);
|
||||
assert(n!=-1);
|
||||
|
||||
if(n <= 0)
|
||||
return ops_false;
|
||||
|
||||
skp->rsa.encrypted_m=BN_bin2bn(encmpibuf, n, NULL);
|
||||
|
||||
/*
|
||||
fprintf(stderr,"encrypted mpi buf : ");
|
||||
int i;
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", encmpibuf[i]);
|
||||
fprintf(stderr,"\n");
|
||||
*/
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
#define MAXBUF 1024
|
||||
|
||||
static ops_parse_cb_return_t
|
||||
callback_write_parsed(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Crypto
|
||||
Encrypt a file
|
||||
\param input_filename Name of file to be encrypted
|
||||
\param output_filename Name of file to write to. If NULL, name is constructed from input_filename
|
||||
\param pub_key Public Key to encrypt file for
|
||||
\param use_armour Write armoured text, if set
|
||||
\param allow_overwrite Allow output file to be overwrwritten if it exists
|
||||
\return ops_true if OK; else ops_false
|
||||
*/
|
||||
ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_filename, const ops_keydata_t *pub_key, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite)
|
||||
{
|
||||
int fd_in=0;
|
||||
int fd_out=0;
|
||||
|
||||
ops_create_info_t *cinfo;
|
||||
|
||||
#ifdef WIN32
|
||||
fd_in=open(input_filename,O_RDONLY | O_BINARY);
|
||||
#else
|
||||
fd_in=open(input_filename,O_RDONLY);
|
||||
#endif
|
||||
if(fd_in < 0)
|
||||
{
|
||||
perror(input_filename);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
fd_out=ops_setup_file_write(&cinfo, output_filename, allow_overwrite);
|
||||
if (fd_out < 0)
|
||||
return ops_false;
|
||||
|
||||
// set armoured/not armoured here
|
||||
if (use_armour)
|
||||
ops_writer_push_armoured_message(cinfo);
|
||||
|
||||
// Push the encrypted writer
|
||||
ops_writer_push_encrypt_se_ip(cinfo,pub_key);
|
||||
|
||||
// Do the writing
|
||||
|
||||
unsigned char* buf=NULL;
|
||||
size_t bufsz=16;
|
||||
int done=0;
|
||||
for (;;)
|
||||
{
|
||||
buf=realloc(buf,done+bufsz);
|
||||
|
||||
int n=0;
|
||||
|
||||
n=read(fd_in,buf+done,bufsz);
|
||||
if (!n)
|
||||
break;
|
||||
assert(n>=0);
|
||||
done+=n;
|
||||
}
|
||||
|
||||
// This does the writing
|
||||
ops_write(buf,done,cinfo);
|
||||
|
||||
// tidy up
|
||||
close(fd_in);
|
||||
free(buf);
|
||||
ops_teardown_file_write(cinfo,fd_out);
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Crypto
|
||||
\brief Decrypt a file.
|
||||
\param input_filename Name of file to be decrypted
|
||||
\param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions.
|
||||
\param keyring Keyring to use
|
||||
\param use_armour Expect armoured text, if set
|
||||
\param allow_overwrite Allow output file to overwritten, if set.
|
||||
\param cb_get_passphrase Callback to use to get passphrase
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_filename, ops_keyring_t* keyring, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite, ops_parse_cb_t* cb_get_passphrase)
|
||||
{
|
||||
int fd_in=0;
|
||||
int fd_out=0;
|
||||
char* myfilename=NULL;
|
||||
|
||||
//
|
||||
ops_parse_info_t *pinfo=NULL;
|
||||
|
||||
// setup for reading from given input file
|
||||
fd_in=ops_setup_file_read(&pinfo, input_filename,
|
||||
NULL,
|
||||
callback_write_parsed,
|
||||
ops_false);
|
||||
if (fd_in < 0)
|
||||
{
|
||||
perror(input_filename);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
// setup output filename
|
||||
|
||||
if (output_filename)
|
||||
{
|
||||
fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, output_filename, allow_overwrite);
|
||||
|
||||
if (fd_out < 0)
|
||||
{
|
||||
perror(output_filename);
|
||||
ops_teardown_file_read(pinfo,fd_in);
|
||||
return ops_false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int suffixlen=4;
|
||||
char *defaultsuffix=".decrypted";
|
||||
const char *suffix=input_filename+strlen((char *)input_filename)-suffixlen;
|
||||
if (!strcmp(suffix,".gpg") || !strcmp(suffix,".asc"))
|
||||
{
|
||||
myfilename=ops_mallocz(strlen(input_filename)-suffixlen+1);
|
||||
strncpy(myfilename,input_filename,strlen(input_filename)-suffixlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned filenamelen=strlen(input_filename)+strlen(defaultsuffix)+1;
|
||||
myfilename=ops_mallocz(filenamelen);
|
||||
snprintf(myfilename,filenamelen,"%s%s",input_filename,defaultsuffix);
|
||||
}
|
||||
|
||||
fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, myfilename, allow_overwrite);
|
||||
|
||||
if (fd_out < 0)
|
||||
{
|
||||
perror(myfilename);
|
||||
free(myfilename);
|
||||
ops_teardown_file_read(pinfo,fd_in);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
free (myfilename);
|
||||
}
|
||||
|
||||
// \todo check for suffix matching armour param
|
||||
|
||||
// setup for writing decrypted contents to given output file
|
||||
|
||||
// setup keyring and passphrase callback
|
||||
pinfo->cbinfo.cryptinfo.keyring=keyring;
|
||||
pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase;
|
||||
|
||||
// Set up armour/passphrase options
|
||||
|
||||
if (use_armour)
|
||||
ops_reader_push_dearmour(pinfo);
|
||||
|
||||
// Do it
|
||||
|
||||
ops_parse_and_print_errors(pinfo);
|
||||
|
||||
// Unsetup
|
||||
|
||||
if (use_armour)
|
||||
ops_reader_pop_dearmour(pinfo);
|
||||
|
||||
ops_teardown_file_write(pinfo->cbinfo.cinfo, fd_out);
|
||||
ops_teardown_file_read(pinfo, fd_in);
|
||||
// \todo cleardown crypt
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static ops_parse_cb_return_t
|
||||
callback_write_parsed(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
|
||||
static ops_boolean_t skipping;
|
||||
// ops_boolean_t write=ops_true;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
// ops_print_packet(content_);
|
||||
|
||||
if(content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping)
|
||||
{
|
||||
puts("...end of skip");
|
||||
skipping=ops_false;
|
||||
}
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PTAG_CT_UNARMOURED_TEXT:
|
||||
printf("OPS_PTAG_CT_UNARMOURED_TEXT\n");
|
||||
if(!skipping)
|
||||
{
|
||||
puts("Skipping...");
|
||||
skipping=ops_true;
|
||||
}
|
||||
fwrite(content->unarmoured_text.data,1,
|
||||
content->unarmoured_text.length,stdout);
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_PK_SESSION_KEY:
|
||||
return callback_pk_session_key(content_,cbinfo);
|
||||
break;
|
||||
|
||||
case OPS_PARSER_CMD_GET_SECRET_KEY:
|
||||
return callback_cmd_get_secret_key(content_,cbinfo);
|
||||
break;
|
||||
|
||||
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
|
||||
// return callback_cmd_get_secret_key_passphrase(content_,cbinfo);
|
||||
return cbinfo->cryptinfo.cb_get_passphrase(content_,cbinfo);
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_LITERAL_DATA_BODY:
|
||||
return callback_literal_data(content_,cbinfo);
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_ARMOUR_HEADER:
|
||||
case OPS_PTAG_CT_ARMOUR_TRAILER:
|
||||
case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
|
||||
case OPS_PTAG_CT_COMPRESSED:
|
||||
case OPS_PTAG_CT_LITERAL_DATA_HEADER:
|
||||
case OPS_PTAG_CT_SE_IP_DATA_BODY:
|
||||
case OPS_PTAG_CT_SE_IP_DATA_HEADER:
|
||||
case OPS_PTAG_CT_SE_DATA_BODY:
|
||||
case OPS_PTAG_CT_SE_DATA_HEADER:
|
||||
|
||||
// Ignore these packets
|
||||
// They're handled in ops_parse_one_packet()
|
||||
// and nothing else needs to be done
|
||||
break;
|
||||
|
||||
default:
|
||||
// return callback_general(content_,cbinfo);
|
||||
break;
|
||||
// fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag,
|
||||
// content_->tag);
|
||||
// assert(0);
|
||||
}
|
||||
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
// EOF
|
211
openpgpsdk/src/errors.c
Normal file
211
openpgpsdk/src/errors.c
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Error Handling
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include <openpgpsdk/util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#include <openpgpsdk/packet-show.h>
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
#define ERRNAME(code) { code, #code }
|
||||
|
||||
static ops_errcode_name_map_t errcode_name_map[] =
|
||||
{
|
||||
ERRNAME(OPS_E_OK),
|
||||
ERRNAME(OPS_E_FAIL),
|
||||
ERRNAME(OPS_E_SYSTEM_ERROR),
|
||||
ERRNAME(OPS_E_UNIMPLEMENTED),
|
||||
|
||||
ERRNAME(OPS_E_R),
|
||||
ERRNAME(OPS_E_R_READ_FAILED),
|
||||
ERRNAME(OPS_E_R_EARLY_EOF),
|
||||
ERRNAME(OPS_E_R_BAD_FORMAT),
|
||||
ERRNAME(OPS_E_R_UNCONSUMED_DATA),
|
||||
|
||||
ERRNAME(OPS_E_W),
|
||||
ERRNAME(OPS_E_W_WRITE_FAILED),
|
||||
ERRNAME(OPS_E_W_WRITE_TOO_SHORT),
|
||||
|
||||
ERRNAME(OPS_E_P),
|
||||
ERRNAME(OPS_E_P_NOT_ENOUGH_DATA),
|
||||
ERRNAME(OPS_E_P_UNKNOWN_TAG),
|
||||
ERRNAME(OPS_E_P_PACKET_CONSUMED),
|
||||
ERRNAME(OPS_E_P_MPI_FORMAT_ERROR),
|
||||
|
||||
ERRNAME(OPS_E_C),
|
||||
|
||||
ERRNAME(OPS_E_V),
|
||||
ERRNAME(OPS_E_V_BAD_SIGNATURE),
|
||||
ERRNAME(OPS_E_V_NO_SIGNATURE),
|
||||
ERRNAME(OPS_E_V_UNKNOWN_SIGNER),
|
||||
|
||||
ERRNAME(OPS_E_ALG),
|
||||
ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
|
||||
ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
|
||||
ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
|
||||
ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG),
|
||||
|
||||
ERRNAME(OPS_E_PROTO),
|
||||
ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT),
|
||||
ERRNAME(OPS_E_PROTO_UNKNOWN_SS),
|
||||
ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED),
|
||||
ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN),
|
||||
ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN),
|
||||
ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
|
||||
ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN),
|
||||
ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
|
||||
ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM),
|
||||
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
|
||||
/**
|
||||
* \ingroup Core_Errors
|
||||
* \brief returns error code name
|
||||
* \param errcode
|
||||
* \return error code name or "Unknown"
|
||||
*/
|
||||
char *ops_errcode(const ops_errcode_t errcode)
|
||||
{
|
||||
return(ops_str_from_map((int) errcode, (ops_map_t *) errcode_name_map));
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Errors
|
||||
* \brief Pushes the given error on the given errorstack
|
||||
* \param errstack Error stack to use
|
||||
* \param errcode Code of error to push
|
||||
* \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR)
|
||||
* \param file Source filename where error occurred
|
||||
* \param line Line in source file where error occurred
|
||||
* \param fmt Comment
|
||||
*
|
||||
*/
|
||||
|
||||
void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
|
||||
const char *file,int line,const char *fmt,...)
|
||||
{
|
||||
// first get the varargs and generate the comment
|
||||
char *comment;
|
||||
int maxbuf=128;
|
||||
va_list args;
|
||||
ops_error_t *err;
|
||||
|
||||
comment=malloc(maxbuf+1);
|
||||
assert(comment);
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(comment,maxbuf+1,fmt,args);
|
||||
va_end(args);
|
||||
|
||||
// alloc a new error and add it to the top of the stack
|
||||
|
||||
err=malloc(sizeof(ops_error_t));
|
||||
assert(err);
|
||||
|
||||
err->next=*errstack;
|
||||
*errstack=err;
|
||||
|
||||
// fill in the details
|
||||
err->errcode=errcode;
|
||||
err->sys_errno=sys_errno;
|
||||
err->file=file;
|
||||
err->line=line;
|
||||
|
||||
err->comment=comment;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Errors
|
||||
\brief print this error
|
||||
\param err Error to print
|
||||
*/
|
||||
void ops_print_error(ops_error_t *err)
|
||||
{
|
||||
printf("%s:%d: ",err->file,err->line);
|
||||
if(err->errcode==OPS_E_SYSTEM_ERROR)
|
||||
printf("system error %d returned from %s()\n",err->sys_errno,
|
||||
err->comment);
|
||||
else
|
||||
printf("%s, %s\n",ops_errcode(err->errcode),err->comment);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Errors
|
||||
\brief Print all errors on stack
|
||||
\param errstack Error stack to print
|
||||
*/
|
||||
void ops_print_errors(ops_error_t *errstack)
|
||||
{
|
||||
ops_error_t *err;
|
||||
|
||||
for(err=errstack ; err!=NULL ; err=err->next)
|
||||
ops_print_error(err);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Errors
|
||||
\brief Return true if given error is present anywhere on stack
|
||||
\param errstack Error stack to check
|
||||
\param errcode Error code to look for
|
||||
\return 1 if found; else 0
|
||||
*/
|
||||
int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode)
|
||||
{
|
||||
ops_error_t *err;
|
||||
for (err=errstack; err!=NULL; err=err->next)
|
||||
{
|
||||
if (err->errcode==errcode)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Errors
|
||||
\brief Frees all errors on stack
|
||||
\param errstack Error stack to free
|
||||
*/
|
||||
void ops_free_errors(ops_error_t *errstack)
|
||||
{
|
||||
ops_error_t *next;
|
||||
while(errstack!=NULL) {
|
||||
next=errstack->next;
|
||||
free(errstack->comment);
|
||||
free(errstack);
|
||||
errstack=next;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
139
openpgpsdk/src/fingerprint.c
Normal file
139
openpgpsdk/src/fingerprint.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/packet.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/configure.h>
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define alloca _alloca
|
||||
#endif
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
/**
|
||||
* \ingroup Core_Keys
|
||||
* \brief Calculate a public key fingerprint.
|
||||
* \param fp Where to put the calculated fingerprint
|
||||
* \param key The key for which the fingerprint is calculated
|
||||
*/
|
||||
|
||||
void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key)
|
||||
{
|
||||
if(key->version == 2 || key->version == 3)
|
||||
{
|
||||
unsigned char *bn;
|
||||
int n;
|
||||
ops_hash_t md5;
|
||||
|
||||
assert(key->algorithm == OPS_PKA_RSA
|
||||
|| key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY
|
||||
|| key->algorithm == OPS_PKA_RSA_SIGN_ONLY );
|
||||
|
||||
ops_hash_md5(&md5);
|
||||
md5.init(&md5);
|
||||
|
||||
n=BN_num_bytes(key->key.rsa.n);
|
||||
bn=alloca(n);
|
||||
BN_bn2bin(key->key.rsa.n,bn);
|
||||
md5.add(&md5,bn,n);
|
||||
|
||||
n=BN_num_bytes(key->key.rsa.e);
|
||||
bn=alloca(n);
|
||||
BN_bn2bin(key->key.rsa.e,bn);
|
||||
md5.add(&md5,bn,n);
|
||||
|
||||
md5.finish(&md5,fp->fingerprint);
|
||||
fp->length=16;
|
||||
}
|
||||
else
|
||||
{
|
||||
ops_memory_t *mem=ops_memory_new();
|
||||
ops_hash_t sha1;
|
||||
size_t l;
|
||||
|
||||
ops_build_public_key(mem,key,ops_false);
|
||||
|
||||
if (debug)
|
||||
{ fprintf(stderr,"--- creating key fingerprint\n"); }
|
||||
|
||||
ops_hash_sha1(&sha1);
|
||||
sha1.init(&sha1);
|
||||
|
||||
l=ops_memory_get_length(mem);
|
||||
|
||||
ops_hash_add_int(&sha1,0x99,1);
|
||||
ops_hash_add_int(&sha1,l,2);
|
||||
sha1.add(&sha1,ops_memory_get_data(mem),l);
|
||||
sha1.finish(&sha1,fp->fingerprint);
|
||||
|
||||
if (debug)
|
||||
{ fprintf(stderr,"--- finished creating key fingerprint\n"); }
|
||||
|
||||
fp->length=20;
|
||||
|
||||
ops_memory_free(mem);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Keys
|
||||
* \brief Calculate the Key ID from the public key.
|
||||
* \param keyid Space for the calculated ID to be stored
|
||||
* \param key The key for which the ID is calculated
|
||||
*/
|
||||
|
||||
void ops_keyid(unsigned char keyid[8],const ops_public_key_t *key)
|
||||
{
|
||||
if(key->version == 2 || key->version == 3)
|
||||
{
|
||||
unsigned char bn[8192];
|
||||
unsigned n=BN_num_bytes(key->key.rsa.n);
|
||||
|
||||
assert(n <= sizeof bn);
|
||||
assert(key->algorithm == OPS_PKA_RSA
|
||||
|| key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY
|
||||
|| key->algorithm == OPS_PKA_RSA_SIGN_ONLY );
|
||||
BN_bn2bin(key->key.rsa.n,bn);
|
||||
memcpy(keyid,bn+n-8,8);
|
||||
}
|
||||
else
|
||||
{
|
||||
ops_fingerprint_t fingerprint;
|
||||
|
||||
ops_fingerprint(&fingerprint,key);
|
||||
memcpy(keyid,fingerprint.fingerprint+fingerprint.length-8,8);
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
249
openpgpsdk/src/hash.c
Normal file
249
openpgpsdk/src/hash.c
Normal file
@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Add to the hash
|
||||
\param hash Hash to add to
|
||||
\param n Int to add
|
||||
\param length Length of int in bytes
|
||||
*/
|
||||
void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length)
|
||||
{
|
||||
while(length--)
|
||||
{
|
||||
unsigned char c[1];
|
||||
|
||||
c[0]=n >> (length*8);
|
||||
hash->add(hash,c,1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Setup hash for given hash algorithm
|
||||
\param hash Hash to set up
|
||||
\param alg Hash algorithm to use
|
||||
*/
|
||||
void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg)
|
||||
{
|
||||
switch(alg)
|
||||
{
|
||||
case OPS_HASH_MD5:
|
||||
ops_hash_md5(hash);
|
||||
break;
|
||||
|
||||
case OPS_HASH_SHA1:
|
||||
ops_hash_sha1(hash);
|
||||
break;
|
||||
|
||||
case OPS_HASH_SHA256:
|
||||
ops_hash_sha256(hash);
|
||||
break;
|
||||
|
||||
case OPS_HASH_SHA384:
|
||||
ops_hash_sha384(hash);
|
||||
break;
|
||||
|
||||
case OPS_HASH_SHA512:
|
||||
ops_hash_sha512(hash);
|
||||
break;
|
||||
|
||||
case OPS_HASH_SHA224:
|
||||
ops_hash_sha224(hash);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Returns size of hash for given hash algorithm
|
||||
\param alg Hash algorithm to use
|
||||
\return Size of hash algorithm in bytes
|
||||
*/
|
||||
unsigned ops_hash_size(ops_hash_algorithm_t alg)
|
||||
{
|
||||
switch(alg)
|
||||
{
|
||||
case OPS_HASH_MD5:
|
||||
return 16;
|
||||
|
||||
case OPS_HASH_SHA1:
|
||||
return 20;
|
||||
|
||||
case OPS_HASH_SHA256:
|
||||
return 32;
|
||||
|
||||
case OPS_HASH_SHA224:
|
||||
return 28;
|
||||
|
||||
case OPS_HASH_SHA512:
|
||||
return 64;
|
||||
|
||||
case OPS_HASH_SHA384:
|
||||
return 48;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Returns hash enum corresponding to given string
|
||||
\param hash Text name of hash algorithm i.e. "SHA1"
|
||||
\returns Corresponding enum i.e. OPS_HASH_SHA1
|
||||
*/
|
||||
ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash)
|
||||
{
|
||||
if(!strcmp(hash,"SHA1"))
|
||||
return OPS_HASH_SHA1;
|
||||
else if(!strcmp(hash,"MD5"))
|
||||
return OPS_HASH_MD5;
|
||||
else if (!strcmp(hash,"SHA256"))
|
||||
return OPS_HASH_SHA256;
|
||||
/*
|
||||
else if (!strcmp(hash,"SHA224"))
|
||||
return OPS_HASH_SHA224;
|
||||
*/
|
||||
else if (!strcmp(hash,"SHA512"))
|
||||
return OPS_HASH_SHA512;
|
||||
else if (!strcmp(hash,"SHA384"))
|
||||
return OPS_HASH_SHA384;
|
||||
|
||||
return OPS_HASH_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Hash given data
|
||||
\param out Where to write the hash
|
||||
\param alg Hash algorithm to use
|
||||
\param in Data to hash
|
||||
\param length Length of data
|
||||
\return Size of hash created
|
||||
*/
|
||||
unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in,
|
||||
size_t length)
|
||||
{
|
||||
ops_hash_t hash;
|
||||
|
||||
ops_hash_any(&hash,alg);
|
||||
hash.init(&hash);
|
||||
hash.add(&hash,in,length);
|
||||
return hash.finish(&hash,out);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Calculate hash for MDC packet
|
||||
\param preamble Preamble to hash
|
||||
\param sz_preamble Size of preamble
|
||||
\param plaintext Plaintext to hash
|
||||
\param sz_plaintext Size of plaintext
|
||||
\param hashed Resulting hash
|
||||
*/
|
||||
void ops_calc_mdc_hash(const unsigned char* preamble, const size_t sz_preamble, const unsigned char* plaintext, const unsigned int sz_plaintext, unsigned char *hashed)
|
||||
{
|
||||
ops_hash_t hash;
|
||||
unsigned char c[1];
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"ops_calc_mdc_hash():\n");
|
||||
|
||||
fprintf(stderr,"\npreamble: ");
|
||||
for (i=0; i<sz_preamble;i++)
|
||||
fprintf(stderr," 0x%02x", preamble[i]);
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
fprintf(stderr,"\nplaintext (len=%d): ",sz_plaintext);
|
||||
for (i=0; i<sz_plaintext;i++)
|
||||
fprintf(stderr," 0x%02x", plaintext[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
// init
|
||||
ops_hash_any(&hash, OPS_HASH_SHA1);
|
||||
hash.init(&hash);
|
||||
|
||||
// preamble
|
||||
hash.add(&hash,preamble,sz_preamble);
|
||||
// plaintext
|
||||
hash.add(&hash,plaintext,sz_plaintext);
|
||||
// MDC packet tag
|
||||
c[0]=0xD3;
|
||||
hash.add(&hash,&c[0],1);
|
||||
// MDC packet len
|
||||
c[0]=0x14;
|
||||
hash.add(&hash,&c[0],1);
|
||||
|
||||
//finish
|
||||
hash.finish(&hash,hashed);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"\nhashed (len=%d): ",OPS_SHA1_HASH_SIZE);
|
||||
for (i=0; i<OPS_SHA1_HASH_SIZE;i++)
|
||||
fprintf(stderr," 0x%02x", hashed[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Supported
|
||||
\brief Is this Hash Algorithm supported?
|
||||
\param hash_alg Hash Algorithm to check
|
||||
\return ops_true if supported; else ops_false
|
||||
*/
|
||||
ops_boolean_t ops_is_hash_alg_supported(const ops_hash_algorithm_t *hash_alg)
|
||||
{
|
||||
switch (*hash_alg)
|
||||
{
|
||||
case OPS_HASH_MD5:
|
||||
case OPS_HASH_SHA1:
|
||||
case OPS_HASH_SHA256:
|
||||
return ops_true;
|
||||
|
||||
default:
|
||||
return ops_false;
|
||||
}
|
||||
}
|
||||
|
||||
// EOF
|
906
openpgpsdk/src/keyring.c
Normal file
906
openpgpsdk/src/keyring.c
Normal file
@ -0,0 +1,906 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/armour.h>
|
||||
#include <openpgpsdk/std_print.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/accumulate.h>
|
||||
#include <openpgpsdk/validate.h>
|
||||
#include <openpgpsdk/signature.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include <openpgpsdk/defs.h>
|
||||
|
||||
#include "keyring_local.h"
|
||||
#include "parse_local.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Keyring
|
||||
|
||||
\brief Creates a new ops_keydata_t struct
|
||||
|
||||
\return A new ops_keydata_t struct, initialised to zero.
|
||||
|
||||
\note The returned ops_keydata_t struct must be freed after use with ops_keydata_free.
|
||||
*/
|
||||
|
||||
ops_keydata_t *ops_keydata_new(void)
|
||||
{ return ops_mallocz(sizeof(ops_keydata_t)); }
|
||||
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Keyring
|
||||
|
||||
\brief Frees keydata and its memory
|
||||
|
||||
\param keydata Key to be freed.
|
||||
|
||||
\note This frees the keydata itself, as well as any other memory alloc-ed by it.
|
||||
*/
|
||||
void ops_keydata_free(ops_keydata_t *keydata)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
for(n=0 ; n < keydata->nuids ; ++n)
|
||||
ops_user_id_free(&keydata->uids[n]);
|
||||
free(keydata->uids);
|
||||
keydata->uids=NULL;
|
||||
keydata->nuids=0;
|
||||
|
||||
for(n=0 ; n < keydata->npackets ; ++n)
|
||||
ops_packet_free(&keydata->packets[n]);
|
||||
free(keydata->packets);
|
||||
keydata->packets=NULL;
|
||||
keydata->npackets=0;
|
||||
|
||||
if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY)
|
||||
ops_public_key_free(&keydata->key.pkey);
|
||||
else
|
||||
ops_secret_key_free(&keydata->key.skey);
|
||||
|
||||
free(keydata);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyGeneral
|
||||
|
||||
\brief Returns the public key in the given keydata.
|
||||
\param keydata
|
||||
|
||||
\return Pointer to public key
|
||||
|
||||
\note This is not a copy, do not free it after use.
|
||||
*/
|
||||
|
||||
const ops_public_key_t *
|
||||
ops_get_public_key_from_data(const ops_keydata_t *keydata)
|
||||
{
|
||||
if(keydata->type == OPS_PTAG_CT_PUBLIC_KEY)
|
||||
return &keydata->key.pkey;
|
||||
return &keydata->key.skey.public_key;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyGeneral
|
||||
|
||||
\brief Check whether this is a secret key or not.
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_is_key_secret(const ops_keydata_t *data)
|
||||
{ return data->type != OPS_PTAG_CT_PUBLIC_KEY; }
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyGeneral
|
||||
|
||||
\brief Returns the secret key in the given keydata.
|
||||
|
||||
\note This is not a copy, do not free it after use.
|
||||
|
||||
\note This returns a const. If you need to be able to write to this pointer, use ops_get_writable_secret_key_from_data
|
||||
*/
|
||||
|
||||
const ops_secret_key_t *
|
||||
ops_get_secret_key_from_data(const ops_keydata_t *data)
|
||||
{
|
||||
if(data->type != OPS_PTAG_CT_SECRET_KEY)
|
||||
return NULL;
|
||||
|
||||
return &data->key.skey;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyGeneral
|
||||
|
||||
\brief Returns the secret key in the given keydata.
|
||||
|
||||
\note This is not a copy, do not free it after use.
|
||||
|
||||
\note If you do not need to be able to modify this key, there is an equivalent read-only function ops_get_secret_key_from_data.
|
||||
*/
|
||||
|
||||
ops_secret_key_t *
|
||||
ops_get_writable_secret_key_from_data(ops_keydata_t *data)
|
||||
{
|
||||
if (data->type != OPS_PTAG_CT_SECRET_KEY)
|
||||
return NULL;
|
||||
|
||||
return &data->key.skey;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ops_keydata_t *key;
|
||||
char *pphrase;
|
||||
ops_secret_key_t *skey;
|
||||
} decrypt_arg_t;
|
||||
|
||||
static ops_parse_cb_return_t decrypt_cb(const ops_parser_content_t *content_,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
const ops_parser_content_union_t *content=&content_->content;
|
||||
decrypt_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PARSER_PTAG:
|
||||
case OPS_PTAG_CT_USER_ID:
|
||||
case OPS_PTAG_CT_SIGNATURE:
|
||||
case OPS_PTAG_CT_SIGNATURE_HEADER:
|
||||
case OPS_PTAG_CT_SIGNATURE_FOOTER:
|
||||
case OPS_PTAG_CT_TRUST:
|
||||
break;
|
||||
|
||||
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
|
||||
*content->secret_key_passphrase.passphrase=arg->pphrase;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PARSER_ERRCODE:
|
||||
switch(content->errcode.errcode)
|
||||
{
|
||||
case OPS_E_P_MPI_FORMAT_ERROR:
|
||||
/* Generally this means a bad passphrase */
|
||||
fprintf(stderr,"Bad passphrase!\n");
|
||||
goto done;
|
||||
|
||||
case OPS_E_P_PACKET_CONSUMED:
|
||||
/* And this is because of an error we've accepted */
|
||||
goto done;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"parse error: %s\n",
|
||||
ops_errcode(content->errcode.errcode));
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OPS_PARSER_ERROR:
|
||||
printf("parse error: %s\n",content->error.error);
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_SECRET_KEY:
|
||||
arg->skey=malloc(sizeof *arg->skey);
|
||||
*arg->skey=content->secret_key;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PARSER_PACKET_END:
|
||||
// nothing to do
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"Unexpected tag %d (0x%x)\n",content_->tag,
|
||||
content_->tag);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
done:
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Decrypts secret key from given keydata with given passphrase
|
||||
\param key Key from which to get secret key
|
||||
\param pphrase Passphrase to use to decrypt secret key
|
||||
\return secret key
|
||||
*/
|
||||
ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key,
|
||||
const char *pphrase)
|
||||
{
|
||||
ops_parse_info_t *pinfo;
|
||||
decrypt_arg_t arg;
|
||||
|
||||
memset(&arg,'\0',sizeof arg);
|
||||
arg.key=key;
|
||||
arg.pphrase=strdup(pphrase);
|
||||
|
||||
pinfo=ops_parse_info_new();
|
||||
|
||||
ops_keydata_reader_set(pinfo,key);
|
||||
ops_parse_cb_set(pinfo,decrypt_cb,&arg);
|
||||
pinfo->rinfo.accumulate=ops_true;
|
||||
|
||||
ops_parse(pinfo);
|
||||
|
||||
return arg.skey;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Set secret key in content
|
||||
\param content Content to be set
|
||||
\param key Keydata to get secret key from
|
||||
*/
|
||||
void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key)
|
||||
{
|
||||
*content->get_secret_key.secret_key=&key->key.skey;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Get Key ID from keydata
|
||||
\param key Keydata to get Key ID from
|
||||
\return Pointer to Key ID inside keydata
|
||||
*/
|
||||
const unsigned char* ops_get_key_id(const ops_keydata_t *key)
|
||||
{
|
||||
return key->key_id;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief How many User IDs in this key?
|
||||
\param key Keydata to check
|
||||
\return Num of user ids
|
||||
*/
|
||||
unsigned ops_get_user_id_count(const ops_keydata_t *key)
|
||||
{
|
||||
return key->nuids;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Get indexed user id from key
|
||||
\param key Key to get user id from
|
||||
\param index Which key to get
|
||||
\return Pointer to requested user id
|
||||
*/
|
||||
const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index)
|
||||
{
|
||||
return key->uids[index].user_id;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Supported
|
||||
\brief Checks whether key's algorithm and type are supported by OpenPGP::SDK
|
||||
\param keydata Key to be checked
|
||||
\return ops_true if key algorithm and type are supported by OpenPGP::SDK; ops_false if not
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_is_key_supported(const ops_keydata_t *keydata)
|
||||
{
|
||||
if ( keydata->type == OPS_PTAG_CT_PUBLIC_KEY ) {
|
||||
if ( keydata->key.pkey.algorithm == OPS_PKA_RSA ) {
|
||||
return ops_true;
|
||||
}
|
||||
} else if ( keydata->type == OPS_PTAG_CT_PUBLIC_KEY ) {
|
||||
if ( keydata->key.skey.algorithm == (ops_symmetric_algorithm_t)OPS_PKA_RSA ) {
|
||||
return ops_true;
|
||||
}
|
||||
}
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringFind
|
||||
|
||||
\brief Returns key inside a keyring, chosen by index
|
||||
|
||||
\param keyring Pointer to existing keyring
|
||||
\param index Index of required key
|
||||
|
||||
\note Index starts at 0
|
||||
|
||||
\note This returns a pointer to the original key, not a copy. You do not need to free the key after use.
|
||||
|
||||
\return Pointer to the required key; or NULL if index too large.
|
||||
|
||||
Example code:
|
||||
\code
|
||||
void example(const ops_keyring_t* keyring)
|
||||
{
|
||||
ops_keydata_t* keydata=NULL;
|
||||
keydata=ops_keyring_get_key_by_index(keyring, 0);
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index)
|
||||
{
|
||||
if (index >= keyring->nkeys)
|
||||
return NULL;
|
||||
return &keyring->keys[index];
|
||||
}
|
||||
|
||||
// \todo check where userid pointers are copied
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Copy user id, including contents
|
||||
\param dst Destination User ID
|
||||
\param src Source User ID
|
||||
\note If dst already has a user_id, it will be freed.
|
||||
*/
|
||||
void ops_copy_userid(ops_user_id_t* dst, const ops_user_id_t* src)
|
||||
{
|
||||
int len=strlen((char *)src->user_id);
|
||||
if (dst->user_id)
|
||||
free(dst->user_id);
|
||||
dst->user_id=ops_mallocz(len+1);
|
||||
|
||||
memcpy(dst->user_id, src->user_id, len);
|
||||
}
|
||||
|
||||
// \todo check where pkt pointers are copied
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Copy packet, including contents
|
||||
\param dst Destination packet
|
||||
\param src Source packet
|
||||
\note If dst already has a packet, it will be freed.
|
||||
*/
|
||||
void ops_copy_packet(ops_packet_t* dst, const ops_packet_t* src)
|
||||
{
|
||||
if (dst->raw)
|
||||
free(dst->raw);
|
||||
dst->raw=ops_mallocz(src->length);
|
||||
|
||||
dst->length=src->length;
|
||||
memcpy(dst->raw, src->raw, src->length);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Add User ID to keydata
|
||||
\param keydata Key to which to add User ID
|
||||
\param userid User ID to add
|
||||
\return Pointer to new User ID
|
||||
*/
|
||||
ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid)
|
||||
{
|
||||
ops_user_id_t* new_uid=NULL;
|
||||
|
||||
EXPAND_ARRAY(keydata, uids);
|
||||
|
||||
// initialise new entry in array
|
||||
new_uid=&keydata->uids[keydata->nuids];
|
||||
|
||||
new_uid->user_id=NULL;
|
||||
|
||||
// now copy it
|
||||
ops_copy_userid(new_uid,userid);
|
||||
keydata->nuids++;
|
||||
|
||||
return new_uid;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Add packet to key
|
||||
\param keydata Key to which to add packet
|
||||
\param packet Packet to add
|
||||
\return Pointer to new packet
|
||||
*/
|
||||
ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet)
|
||||
{
|
||||
ops_packet_t* new_pkt=NULL;
|
||||
|
||||
EXPAND_ARRAY(keydata, packets);
|
||||
|
||||
// initialise new entry in array
|
||||
new_pkt=&keydata->packets[keydata->npackets];
|
||||
new_pkt->length=0;
|
||||
new_pkt->raw=NULL;
|
||||
|
||||
// now copy it
|
||||
ops_copy_packet(new_pkt, packet);
|
||||
keydata->npackets++;
|
||||
|
||||
return new_pkt;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Add signed User ID to key
|
||||
\param keydata Key to which to add signed User ID
|
||||
\param user_id User ID to add
|
||||
\param sigpacket Packet to add
|
||||
*/
|
||||
void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* user_id, const ops_packet_t* sigpacket)
|
||||
{
|
||||
//int i=0;
|
||||
ops_user_id_t * uid=NULL;
|
||||
ops_packet_t * pkt=NULL;
|
||||
|
||||
uid=ops_add_userid_to_keydata(keydata, user_id);
|
||||
pkt=ops_add_packet_to_keydata(keydata, sigpacket);
|
||||
|
||||
/*
|
||||
* add entry in sigs array to link the userid and sigpacket
|
||||
*/
|
||||
|
||||
// and add ptr to it from the sigs array
|
||||
EXPAND_ARRAY(keydata, sigs);
|
||||
|
||||
// setup new entry in array
|
||||
|
||||
keydata->sigs[keydata->nsigs].userid=uid;
|
||||
keydata->sigs[keydata->nsigs].packet=pkt;
|
||||
|
||||
keydata->nsigs++;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Add selfsigned User ID to key
|
||||
\param keydata Key to which to add user ID
|
||||
\param userid Self-signed User ID to add
|
||||
\return ops_true if OK; else ops_false
|
||||
*/
|
||||
ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid)
|
||||
{
|
||||
ops_packet_t sigpacket;
|
||||
|
||||
ops_memory_t* mem_userid=NULL;
|
||||
ops_create_info_t* cinfo_userid=NULL;
|
||||
|
||||
ops_memory_t* mem_sig=NULL;
|
||||
ops_create_info_t* cinfo_sig=NULL;
|
||||
|
||||
ops_create_signature_t *sig=NULL;
|
||||
|
||||
/*
|
||||
* create signature packet for this userid
|
||||
*/
|
||||
|
||||
// create userid pkt
|
||||
ops_setup_memory_write(&cinfo_userid, &mem_userid, 128);
|
||||
ops_write_struct_user_id(userid, cinfo_userid);
|
||||
|
||||
// create sig for this pkt
|
||||
|
||||
sig=ops_create_signature_new();
|
||||
ops_signature_start_key_signature(sig, &keydata->key.skey.public_key, userid, OPS_CERT_POSITIVE);
|
||||
ops_signature_add_creation_time(sig,time(NULL));
|
||||
ops_signature_add_issuer_key_id(sig,keydata->key_id);
|
||||
ops_signature_add_primary_user_id(sig, ops_true);
|
||||
ops_signature_hashed_subpackets_end(sig);
|
||||
|
||||
ops_setup_memory_write(&cinfo_sig, &mem_sig, 128);
|
||||
ops_write_signature(sig,&keydata->key.skey.public_key,&keydata->key.skey, cinfo_sig);
|
||||
|
||||
// add this packet to keydata
|
||||
|
||||
sigpacket.length=ops_memory_get_length(mem_sig);
|
||||
sigpacket.raw=ops_memory_get_data(mem_sig);
|
||||
|
||||
// add userid to keydata
|
||||
ops_add_signed_userid_to_keydata(keydata, userid, &sigpacket);
|
||||
|
||||
// cleanup
|
||||
ops_create_signature_delete(sig);
|
||||
ops_create_info_delete(cinfo_userid);
|
||||
ops_create_info_delete(cinfo_sig);
|
||||
ops_memory_free(mem_userid);
|
||||
ops_memory_free(mem_sig);
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Keys
|
||||
\brief Initialise ops_keydata_t
|
||||
\param keydata Keydata to initialise
|
||||
\param type OPS_PTAG_CT_PUBLIC_KEY or OPS_PTAG_CT_SECRET_KEY
|
||||
*/
|
||||
void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type)
|
||||
{
|
||||
assert(keydata->type==OPS_PTAG_CT_RESERVED);
|
||||
assert(type==OPS_PTAG_CT_PUBLIC_KEY || type==OPS_PTAG_CT_SECRET_KEY);
|
||||
|
||||
keydata->type=type;
|
||||
}
|
||||
|
||||
/**
|
||||
Example Usage:
|
||||
\code
|
||||
|
||||
// definition of variables
|
||||
ops_keyring_t keyring;
|
||||
char* filename="~/.gnupg/pubring.gpg";
|
||||
|
||||
// Read keyring from file
|
||||
ops_keyring_read_from_file(&keyring,filename);
|
||||
|
||||
// do actions using keyring
|
||||
...
|
||||
|
||||
// Free memory alloc-ed in ops_keyring_read_from_file()
|
||||
ops_keyring_free(keyring);
|
||||
\endcode
|
||||
*/
|
||||
|
||||
static ops_parse_cb_return_t
|
||||
cb_keyring_read(const ops_parser_content_t *content_,
|
||||
ops_parse_cb_info_t *cbinfo);
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringRead
|
||||
|
||||
\brief Reads a keyring from a file
|
||||
|
||||
\param keyring Pointer to an existing ops_keyring_t struct
|
||||
\param armour ops_true if file is armoured; else ops_false
|
||||
\param filename Filename of keyring to be read
|
||||
|
||||
\return ops true if OK; ops_false on error
|
||||
|
||||
\note Keyring struct must already exist.
|
||||
|
||||
\note Can be used with either a public or secret keyring.
|
||||
|
||||
\note You must call ops_keyring_free() after usage to free alloc-ed memory.
|
||||
|
||||
\note If you call this twice on the same keyring struct, without calling
|
||||
ops_keyring_free() between these calls, you will introduce a memory leak.
|
||||
|
||||
\sa ops_keyring_read_from_mem()
|
||||
\sa ops_keyring_free()
|
||||
|
||||
Example code:
|
||||
\code
|
||||
ops_keyring_t* keyring=ops_mallocz(sizeof *keyring);
|
||||
ops_boolean_t armoured=ops_false;
|
||||
ops_keyring_read_from_file(keyring, armoured, "~/.gnupg/pubring.gpg");
|
||||
...
|
||||
ops_keyring_free(keyring);
|
||||
free (keyring);
|
||||
|
||||
\endcode
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename)
|
||||
{
|
||||
ops_parse_info_t *pinfo;
|
||||
int fd;
|
||||
ops_boolean_t res = ops_true;
|
||||
|
||||
pinfo=ops_parse_info_new();
|
||||
|
||||
// add this for the moment,
|
||||
// \todo need to fix the problems with reading signature subpackets later
|
||||
|
||||
// ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_RAW);
|
||||
ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED);
|
||||
|
||||
#ifdef WIN32
|
||||
fd=open(filename,O_RDONLY|O_BINARY);
|
||||
#else
|
||||
fd=open(filename,O_RDONLY);
|
||||
#endif
|
||||
if(fd < 0)
|
||||
{
|
||||
ops_parse_info_delete(pinfo);
|
||||
perror(filename);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
ops_reader_set_fd(pinfo,fd);
|
||||
|
||||
ops_parse_cb_set(pinfo,cb_keyring_read,NULL);
|
||||
|
||||
if (armour)
|
||||
{ ops_reader_push_dearmour(pinfo); }
|
||||
|
||||
if ( ops_parse_and_accumulate(keyring,pinfo) == 0 ) {
|
||||
res = ops_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ops_true;
|
||||
}
|
||||
ops_print_errors(ops_parse_info_get_errors(pinfo));
|
||||
|
||||
if (armour)
|
||||
ops_reader_pop_dearmour(pinfo);
|
||||
|
||||
close(fd);
|
||||
|
||||
ops_parse_info_delete(pinfo);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringRead
|
||||
|
||||
\brief Reads a keyring from memory
|
||||
|
||||
\param keyring Pointer to existing ops_keyring_t struct
|
||||
\param armour ops_true if file is armoured; else ops_false
|
||||
\param mem Pointer to a ops_memory_t struct containing keyring to be read
|
||||
|
||||
\return ops true if OK; ops_false on error
|
||||
|
||||
\note Keyring struct must already exist.
|
||||
|
||||
\note Can be used with either a public or secret keyring.
|
||||
|
||||
\note You must call ops_keyring_free() after usage to free alloc-ed memory.
|
||||
|
||||
\note If you call this twice on the same keyring struct, without calling
|
||||
ops_keyring_free() between these calls, you will introduce a memory leak.
|
||||
|
||||
\sa ops_keyring_read_from_file
|
||||
\sa ops_keyring_free
|
||||
|
||||
Example code:
|
||||
\code
|
||||
ops_memory_t* mem; // Filled with keyring packets
|
||||
ops_keyring_t* keyring=ops_mallocz(sizeof *keyring);
|
||||
ops_boolean_t armoured=ops_false;
|
||||
ops_keyring_read_from_mem(keyring, armoured, mem);
|
||||
...
|
||||
ops_keyring_free(keyring);
|
||||
free (keyring);
|
||||
\endcode
|
||||
*/
|
||||
ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t* mem)
|
||||
{
|
||||
ops_parse_info_t *pinfo=NULL;
|
||||
ops_boolean_t res = ops_true;
|
||||
|
||||
pinfo=ops_parse_info_new();
|
||||
ops_parse_options(pinfo,OPS_PTAG_SS_ALL,OPS_PARSE_PARSED);
|
||||
|
||||
ops_setup_memory_read(&pinfo, mem, NULL, cb_keyring_read, OPS_ACCUMULATE_NO);
|
||||
|
||||
if (armour)
|
||||
{ ops_reader_push_dearmour(pinfo); }
|
||||
|
||||
if ( ops_parse_and_accumulate(keyring,pinfo) == 0 )
|
||||
{
|
||||
res = ops_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ops_true;
|
||||
}
|
||||
ops_print_errors(ops_parse_info_get_errors(pinfo));
|
||||
|
||||
if (armour)
|
||||
ops_reader_pop_dearmour(pinfo);
|
||||
|
||||
// don't call teardown_memory_read because memory was passed in
|
||||
ops_parse_info_delete(pinfo);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringRead
|
||||
|
||||
\brief Frees keyring's contents (but not keyring itself)
|
||||
|
||||
\param keyring Keyring whose data is to be freed
|
||||
|
||||
\note This does not free keyring itself, just the memory alloc-ed in it.
|
||||
*/
|
||||
void ops_keyring_free(ops_keyring_t *keyring)
|
||||
{
|
||||
free(keyring->keys);
|
||||
keyring->keys=NULL;
|
||||
keyring->nkeys=0;
|
||||
keyring->nkeys_allocated=0;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringFind
|
||||
|
||||
\brief Finds key in keyring from its Key ID
|
||||
|
||||
\param keyring Keyring to be searched
|
||||
\param keyid ID of required key
|
||||
|
||||
\return Pointer to key, if found; NULL, if not found
|
||||
|
||||
\note This returns a pointer to the key inside the given keyring, not a copy. Do not free it after use.
|
||||
|
||||
Example code:
|
||||
\code
|
||||
void example(ops_keyring_t* keyring)
|
||||
{
|
||||
ops_keydata_t* keydata=NULL;
|
||||
unsigned char keyid[OPS_KEY_ID_SIZE]; // value set elsewhere
|
||||
keydata=ops_keyring_find_key_by_id(keyring,keyid);
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
const ops_keydata_t *
|
||||
ops_keyring_find_key_by_id(const ops_keyring_t *keyring,
|
||||
const unsigned char keyid[OPS_KEY_ID_SIZE])
|
||||
{
|
||||
int n;
|
||||
|
||||
if (!keyring)
|
||||
return NULL;
|
||||
|
||||
for(n=0 ; n < keyring->nkeys ; ++n)
|
||||
{
|
||||
if(!memcmp(keyring->keys[n].key_id,keyid,OPS_KEY_ID_SIZE))
|
||||
return &keyring->keys[n];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringFind
|
||||
|
||||
\brief Finds key from its User ID
|
||||
|
||||
\param keyring Keyring to be searched
|
||||
\param userid User ID of required key
|
||||
|
||||
\return Pointer to Key, if found; NULL, if not found
|
||||
|
||||
\note This returns a pointer to the key inside the keyring, not a copy. Do not free it.
|
||||
|
||||
Example code:
|
||||
\code
|
||||
void example(ops_keyring_t* keyring)
|
||||
{
|
||||
ops_keydata_t* keydata=NULL;
|
||||
keydata=ops_keyring_find_key_by_userid(keyring,"user@domain.com");
|
||||
...
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
const ops_keydata_t *
|
||||
ops_keyring_find_key_by_userid(const ops_keyring_t *keyring,
|
||||
const char *userid)
|
||||
{
|
||||
int n=0;
|
||||
unsigned int i=0;
|
||||
|
||||
if (!keyring)
|
||||
return NULL;
|
||||
|
||||
for(n=0 ; n < keyring->nkeys ; ++n)
|
||||
{
|
||||
for(i=0; i<keyring->keys[n].nuids; i++)
|
||||
{
|
||||
//printf("[%d][%d] userid %s\n",n,i,keyring->keys[n].uids[i].user_id);
|
||||
if(!strncmp((char *)keyring->keys[n].uids[i].user_id,userid,strlen(userid)))
|
||||
return &keyring->keys[n];
|
||||
}
|
||||
}
|
||||
|
||||
//printf("end: n=%d,i=%d\n",n,i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyringList
|
||||
|
||||
\brief Prints all keys in keyring to stdout.
|
||||
|
||||
\param keyring Keyring to use
|
||||
|
||||
\return none
|
||||
|
||||
Example code:
|
||||
\code
|
||||
void example()
|
||||
{
|
||||
ops_keyring_t* keyring=ops_mallocz(sizeof *keyring);
|
||||
ops_boolean_t armoured=ops_false;
|
||||
ops_keyring_read_from_file(keyring, armoured, "~/.gnupg/pubring.gpg");
|
||||
|
||||
ops_keyring_list(keyring);
|
||||
|
||||
ops_keyring_free(keyring);
|
||||
free (keyring);
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
void
|
||||
ops_keyring_list(const ops_keyring_t* keyring)
|
||||
{
|
||||
int n;
|
||||
unsigned int i;
|
||||
ops_keydata_t* key;
|
||||
|
||||
printf ("%d keys\n", keyring->nkeys);
|
||||
for(n=0,key=&keyring->keys[n] ; n < keyring->nkeys ; ++n,++key)
|
||||
{
|
||||
for(i=0; i<key->nuids; i++)
|
||||
{
|
||||
if (ops_is_key_secret(key))
|
||||
ops_print_secret_keydata(key);
|
||||
else
|
||||
ops_print_public_keydata(key);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Static functions */
|
||||
|
||||
static ops_parse_cb_return_t
|
||||
cb_keyring_read(const ops_parser_content_t *content_,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PARSER_PTAG:
|
||||
case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY: // we get these because we didn't prompt
|
||||
case OPS_PTAG_CT_SIGNATURE_HEADER:
|
||||
case OPS_PTAG_CT_SIGNATURE_FOOTER:
|
||||
case OPS_PTAG_CT_SIGNATURE:
|
||||
case OPS_PTAG_CT_TRUST:
|
||||
case OPS_PARSER_ERRCODE:
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
/*\@}*/
|
||||
|
||||
// eof
|
63
openpgpsdk/src/keyring_local.h
Normal file
63
openpgpsdk/src/keyring_local.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/packet.h>
|
||||
|
||||
#define DECLARE_ARRAY(type,arr) unsigned n##arr; unsigned n##arr##_allocated; type *arr
|
||||
#define EXPAND_ARRAY(str,arr) do if(str->n##arr == str->n##arr##_allocated) \
|
||||
{ \
|
||||
str->n##arr##_allocated=str->n##arr##_allocated*2+10; \
|
||||
str->arr=realloc(str->arr,str->n##arr##_allocated*sizeof *str->arr); \
|
||||
} while(0)
|
||||
|
||||
/** ops_keydata_key_t
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
ops_public_key_t pkey;
|
||||
ops_secret_key_t skey;
|
||||
} ops_keydata_key_t;
|
||||
|
||||
|
||||
/** sigpacket_t */
|
||||
typedef struct
|
||||
{
|
||||
ops_user_id_t* userid;
|
||||
ops_packet_t* packet;
|
||||
} sigpacket_t;
|
||||
|
||||
// XXX: gonna have to expand this to hold onto subkeys, too...
|
||||
/** \struct ops_keydata
|
||||
* \todo expand to hold onto subkeys
|
||||
*/
|
||||
struct ops_keydata
|
||||
{
|
||||
DECLARE_ARRAY(ops_user_id_t,uids);
|
||||
DECLARE_ARRAY(ops_packet_t,packets);
|
||||
DECLARE_ARRAY(sigpacket_t, sigs);
|
||||
unsigned char key_id[8];
|
||||
ops_fingerprint_t fingerprint;
|
||||
ops_content_tag_t type;
|
||||
ops_keydata_key_t key;
|
||||
};
|
107
openpgpsdk/src/lists.c
Normal file
107
openpgpsdk/src/lists.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* Set of functions to manage a dynamic list
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/lists.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
/**
|
||||
* \ingroup Core_Lists
|
||||
* \brief Initialises ulong list
|
||||
* \param *list Pointer to existing list structure
|
||||
*/
|
||||
void ops_ulong_list_init(ops_ulong_list_t *list)
|
||||
{
|
||||
list->size=0;
|
||||
list->used=0;
|
||||
list->ulongs=NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Lists
|
||||
* \brief Frees allocated memory in ulong list. Does not free *list itself.
|
||||
* \param *list
|
||||
*/
|
||||
void ops_ulong_list_free(ops_ulong_list_t *list)
|
||||
{
|
||||
if (list->ulongs)
|
||||
free(list->ulongs);
|
||||
ops_ulong_list_init(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Lists
|
||||
* \brief Resizes ulong list.
|
||||
*
|
||||
* We only resize in one direction - upwards.
|
||||
* Algorithm used : double the current size then add 1
|
||||
*
|
||||
* \param *list Pointer to list
|
||||
* \return 1 if success, else 0
|
||||
*/
|
||||
|
||||
static unsigned int ops_ulong_list_resize(ops_ulong_list_t *list)
|
||||
{
|
||||
|
||||
int newsize=0;
|
||||
|
||||
newsize=list->size*2 + 1;
|
||||
list->ulongs=realloc(list->ulongs,newsize*sizeof *list->ulongs);
|
||||
if (list->ulongs)
|
||||
{
|
||||
list->size=newsize;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* xxx - realloc failed. error message? - rachel */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Lists
|
||||
* Adds entry to ulong list
|
||||
*
|
||||
* \param *list
|
||||
* \param *ulong
|
||||
*
|
||||
* \return 1 if success, else 0
|
||||
*/
|
||||
unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong)
|
||||
{
|
||||
if (list->size==list->used)
|
||||
if (!ops_ulong_list_resize(list))
|
||||
return 0;
|
||||
|
||||
list->ulongs[list->used]=*ulong;
|
||||
list->used++;
|
||||
return 1;
|
||||
}
|
||||
|
204
openpgpsdk/src/memory.c
Normal file
204
openpgpsdk/src/memory.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
struct ops_memory
|
||||
{
|
||||
unsigned char *buf;
|
||||
size_t length;
|
||||
size_t allocated;
|
||||
};
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Memory to initialise
|
||||
\param mem memory to initialise
|
||||
\param initial_size Size to initialise to
|
||||
*/
|
||||
void ops_memory_init(ops_memory_t *mem,size_t initial_size)
|
||||
{
|
||||
mem->length=0;
|
||||
if(mem->buf)
|
||||
{
|
||||
if(mem->allocated < initial_size)
|
||||
{
|
||||
mem->buf=realloc(mem->buf,initial_size);
|
||||
mem->allocated=initial_size;
|
||||
}
|
||||
return;
|
||||
}
|
||||
mem->buf=malloc(initial_size);
|
||||
mem->allocated=initial_size;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Pad memory to required length
|
||||
\param mem Memory to use
|
||||
\param length New size
|
||||
*/
|
||||
void ops_memory_pad(ops_memory_t *mem,size_t length)
|
||||
{
|
||||
assert(mem->allocated >= mem->length);
|
||||
if(mem->allocated < mem->length+length)
|
||||
{
|
||||
mem->allocated=mem->allocated*2+length;
|
||||
mem->buf=realloc(mem->buf,mem->allocated);
|
||||
}
|
||||
assert(mem->allocated >= mem->length+length);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Add data to memory
|
||||
\param mem Memory to which to add
|
||||
\param src Data to add
|
||||
\param length Length of data to add
|
||||
*/
|
||||
void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length)
|
||||
{
|
||||
ops_memory_pad(mem,length);
|
||||
memcpy(mem->buf+mem->length,src,length);
|
||||
mem->length+=length;
|
||||
}
|
||||
|
||||
// XXX: this could be refactored via the writer, but an awful lot of
|
||||
// hoops to jump through for 2 lines of code!
|
||||
void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n,
|
||||
size_t length)
|
||||
{
|
||||
assert(mem->allocated >= offset+length);
|
||||
|
||||
while(length--)
|
||||
mem->buf[offset++]=n >> (length*8);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup HighLevel_Memory
|
||||
* \brief Retains allocated memory and set length of stored data to zero.
|
||||
* \param mem Memory to clear
|
||||
* \sa ops_memory_release()
|
||||
* \sa ops_memory_free()
|
||||
*/
|
||||
void ops_memory_clear(ops_memory_t *mem)
|
||||
{ mem->length=0; }
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Free memory and associated data
|
||||
\param mem Memory to free
|
||||
\note This does not free mem itself
|
||||
\sa ops_memory_clear()
|
||||
\sa ops_memory_free()
|
||||
*/
|
||||
void ops_memory_release(ops_memory_t *mem)
|
||||
{
|
||||
free(mem->buf);
|
||||
mem->buf=NULL;
|
||||
mem->length=0;
|
||||
}
|
||||
|
||||
void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag)
|
||||
{
|
||||
size_t extra;
|
||||
|
||||
if(out->length < 192)
|
||||
extra=1;
|
||||
else if(out->length < 8384)
|
||||
extra=2;
|
||||
else
|
||||
extra=5;
|
||||
|
||||
ops_memory_pad(out,extra+1);
|
||||
memmove(out->buf+extra+1,out->buf,out->length);
|
||||
|
||||
out->buf[0]=OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT|tag;
|
||||
|
||||
if(out->length < 192)
|
||||
out->buf[1]=out->length;
|
||||
else if(out->length < 8384)
|
||||
{
|
||||
out->buf[1]=((out->length-192) >> 8)+192;
|
||||
out->buf[2]=out->length-192;
|
||||
}
|
||||
else
|
||||
{
|
||||
out->buf[1]=0xff;
|
||||
out->buf[2]=out->length >> 24;
|
||||
out->buf[3]=out->length >> 16;
|
||||
out->buf[4]=out->length >> 8;
|
||||
out->buf[5]=out->length;
|
||||
}
|
||||
|
||||
out->length+=extra+1;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Create a new zeroed ops_memory_t
|
||||
\return Pointer to new ops_memory_t
|
||||
\note Free using ops_memory_free() after use.
|
||||
\sa ops_memory_free()
|
||||
*/
|
||||
|
||||
ops_memory_t *ops_memory_new()
|
||||
{ return ops_mallocz(sizeof(ops_memory_t)); }
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Free memory ptr and associated memory
|
||||
\param mem Memory to be freed
|
||||
\sa ops_memory_release()
|
||||
\sa ops_memory_clear()
|
||||
*/
|
||||
|
||||
void ops_memory_free(ops_memory_t *mem)
|
||||
{
|
||||
ops_memory_release(mem);
|
||||
free(mem);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Get length of data stored in ops_memory_t struct
|
||||
\return Number of bytes in data
|
||||
*/
|
||||
size_t ops_memory_get_length(const ops_memory_t *mem)
|
||||
{ return mem->length; }
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Memory
|
||||
\brief Get data stored in ops_memory_t struct
|
||||
\return Pointer to data
|
||||
*/
|
||||
void *ops_memory_get_data(ops_memory_t *mem)
|
||||
{ return mem->buf; }
|
||||
|
||||
// EOF
|
792
openpgpsdk/src/openssl_crypto.c
Normal file
792
openpgpsdk/src/openssl_crypto.c
Normal file
@ -0,0 +1,792 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <openpgpsdk/configure.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include "keyring_local.h"
|
||||
#include <openpgpsdk/std_print.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
void test_secret_key(const ops_secret_key_t *skey)
|
||||
{
|
||||
RSA* test=RSA_new();
|
||||
|
||||
test->n=BN_dup(skey->public_key.key.rsa.n);
|
||||
test->e=BN_dup(skey->public_key.key.rsa.e);
|
||||
|
||||
test->d=BN_dup(skey->key.rsa.d);
|
||||
test->p=BN_dup(skey->key.rsa.p);
|
||||
test->q=BN_dup(skey->key.rsa.q);
|
||||
|
||||
assert(RSA_check_key(test)==1);
|
||||
RSA_free(test);
|
||||
}
|
||||
|
||||
static void md5_init(ops_hash_t *hash)
|
||||
{
|
||||
assert(!hash->data);
|
||||
hash->data=malloc(sizeof(MD5_CTX));
|
||||
MD5_Init(hash->data);
|
||||
}
|
||||
|
||||
static void md5_add(ops_hash_t *hash,const unsigned char *data,unsigned length)
|
||||
{
|
||||
MD5_Update(hash->data,data,length);
|
||||
}
|
||||
|
||||
static unsigned md5_finish(ops_hash_t *hash,unsigned char *out)
|
||||
{
|
||||
MD5_Final(out,hash->data);
|
||||
free(hash->data);
|
||||
hash->data=NULL;
|
||||
return 16;
|
||||
}
|
||||
|
||||
static ops_hash_t md5={OPS_HASH_MD5,MD5_DIGEST_LENGTH,"MD5",md5_init,md5_add,
|
||||
md5_finish,NULL};
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief Initialise to MD5
|
||||
\param hash Hash to initialise
|
||||
*/
|
||||
void ops_hash_md5(ops_hash_t *hash)
|
||||
{
|
||||
*hash=md5;
|
||||
}
|
||||
|
||||
static void sha1_init(ops_hash_t *hash)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"***\n***\nsha1_init\n***\n");
|
||||
}
|
||||
assert(!hash->data);
|
||||
hash->data=malloc(sizeof(SHA_CTX));
|
||||
SHA1_Init(hash->data);
|
||||
}
|
||||
|
||||
static void sha1_add(ops_hash_t *hash,const unsigned char *data,
|
||||
unsigned length)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"adding %d to hash:\n ", length);
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", data[i]);
|
||||
if (!((i+1) % 16))
|
||||
fprintf(stderr,"\n");
|
||||
else if (!((i+1) % 8))
|
||||
fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
SHA1_Update(hash->data,data,length);
|
||||
}
|
||||
|
||||
static unsigned sha1_finish(ops_hash_t *hash,unsigned char *out)
|
||||
{
|
||||
SHA1_Final(out,hash->data);
|
||||
if (debug)
|
||||
{
|
||||
unsigned i=0;
|
||||
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
|
||||
for (i=0; i<SHA_DIGEST_LENGTH; i++)
|
||||
fprintf(stderr,"0x%02x ",out[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
free(hash->data);
|
||||
hash->data=NULL;
|
||||
return SHA_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
static ops_hash_t sha1={OPS_HASH_SHA1,SHA_DIGEST_LENGTH,"SHA1",sha1_init,
|
||||
sha1_add,sha1_finish,NULL};
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief Initialise to SHA1
|
||||
\param hash Hash to initialise
|
||||
*/
|
||||
void ops_hash_sha1(ops_hash_t *hash)
|
||||
{
|
||||
*hash=sha1;
|
||||
}
|
||||
|
||||
static void sha256_init(ops_hash_t *hash)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"***\n***\nsha256_init\n***\n");
|
||||
}
|
||||
assert(!hash->data);
|
||||
hash->data=malloc(sizeof(SHA256_CTX));
|
||||
SHA256_Init(hash->data);
|
||||
}
|
||||
|
||||
static void sha256_add(ops_hash_t *hash,const unsigned char *data,
|
||||
unsigned length)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"adding %d to hash:\n ", length);
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", data[i]);
|
||||
if (!((i+1) % 16))
|
||||
fprintf(stderr,"\n");
|
||||
else if (!((i+1) % 8))
|
||||
fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
SHA256_Update(hash->data,data,length);
|
||||
}
|
||||
|
||||
static unsigned sha256_finish(ops_hash_t *hash,unsigned char *out)
|
||||
{
|
||||
SHA256_Final(out,hash->data);
|
||||
if (debug)
|
||||
{
|
||||
unsigned i=0;
|
||||
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
|
||||
for (i=0; i<SHA256_DIGEST_LENGTH; i++)
|
||||
fprintf(stderr,"0x%02x ",out[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
free(hash->data);
|
||||
hash->data=NULL;
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
static ops_hash_t sha256={OPS_HASH_SHA256,SHA256_DIGEST_LENGTH,"SHA256",sha256_init,
|
||||
sha256_add,sha256_finish,NULL};
|
||||
|
||||
void ops_hash_sha256(ops_hash_t *hash)
|
||||
{
|
||||
*hash=sha256;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA384
|
||||
*/
|
||||
|
||||
static void sha384_init(ops_hash_t *hash)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"***\n***\nsha384_init\n***\n");
|
||||
}
|
||||
assert(!hash->data);
|
||||
hash->data=malloc(sizeof(SHA512_CTX));
|
||||
SHA384_Init(hash->data);
|
||||
}
|
||||
|
||||
static void sha384_add(ops_hash_t *hash,const unsigned char *data,
|
||||
unsigned length)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"adding %d to hash:\n ", length);
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", data[i]);
|
||||
if (!((i+1) % 16))
|
||||
fprintf(stderr,"\n");
|
||||
else if (!((i+1) % 8))
|
||||
fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
SHA384_Update(hash->data,data,length);
|
||||
}
|
||||
|
||||
static unsigned sha384_finish(ops_hash_t *hash,unsigned char *out)
|
||||
{
|
||||
SHA384_Final(out,hash->data);
|
||||
if (debug)
|
||||
{
|
||||
unsigned i=0;
|
||||
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
|
||||
for (i=0; i<SHA384_DIGEST_LENGTH; i++)
|
||||
fprintf(stderr,"0x%02x ",out[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
free(hash->data);
|
||||
hash->data=NULL;
|
||||
return SHA384_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
static ops_hash_t sha384={OPS_HASH_SHA384,SHA384_DIGEST_LENGTH,"SHA384",sha384_init,
|
||||
sha384_add,sha384_finish,NULL};
|
||||
|
||||
void ops_hash_sha384(ops_hash_t *hash)
|
||||
{
|
||||
*hash=sha384;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA512
|
||||
*/
|
||||
|
||||
static void sha512_init(ops_hash_t *hash)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"***\n***\nsha512_init\n***\n");
|
||||
}
|
||||
assert(!hash->data);
|
||||
hash->data=malloc(sizeof(SHA512_CTX));
|
||||
SHA512_Init(hash->data);
|
||||
}
|
||||
|
||||
static void sha512_add(ops_hash_t *hash,const unsigned char *data,
|
||||
unsigned length)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"adding %d to hash:\n ", length);
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", data[i]);
|
||||
if (!((i+1) % 16))
|
||||
fprintf(stderr,"\n");
|
||||
else if (!((i+1) % 8))
|
||||
fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
SHA512_Update(hash->data,data,length);
|
||||
}
|
||||
|
||||
static unsigned sha512_finish(ops_hash_t *hash,unsigned char *out)
|
||||
{
|
||||
SHA512_Final(out,hash->data);
|
||||
if (debug)
|
||||
{
|
||||
unsigned i=0;
|
||||
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
|
||||
for (i=0; i<SHA512_DIGEST_LENGTH; i++)
|
||||
fprintf(stderr,"0x%02x ",out[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
free(hash->data);
|
||||
hash->data=NULL;
|
||||
return SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
static ops_hash_t sha512={OPS_HASH_SHA512,SHA512_DIGEST_LENGTH,"SHA512",sha512_init,
|
||||
sha512_add,sha512_finish,NULL};
|
||||
|
||||
void ops_hash_sha512(ops_hash_t *hash)
|
||||
{
|
||||
*hash=sha512;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA224
|
||||
*/
|
||||
|
||||
static void sha224_init(ops_hash_t *hash)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"***\n***\nsha1_init\n***\n");
|
||||
}
|
||||
assert(!hash->data);
|
||||
hash->data=malloc(sizeof(SHA256_CTX));
|
||||
SHA224_Init(hash->data);
|
||||
}
|
||||
|
||||
static void sha224_add(ops_hash_t *hash,const unsigned char *data,
|
||||
unsigned length)
|
||||
{
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"adding %d to hash:\n ", length);
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", data[i]);
|
||||
if (!((i+1) % 16))
|
||||
fprintf(stderr,"\n");
|
||||
else if (!((i+1) % 8))
|
||||
fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
SHA224_Update(hash->data,data,length);
|
||||
}
|
||||
|
||||
static unsigned sha224_finish(ops_hash_t *hash,unsigned char *out)
|
||||
{
|
||||
SHA224_Final(out,hash->data);
|
||||
if (debug)
|
||||
{
|
||||
unsigned i=0;
|
||||
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
|
||||
for (i=0; i<SHA224_DIGEST_LENGTH; i++)
|
||||
fprintf(stderr,"0x%02x ",out[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
free(hash->data);
|
||||
hash->data=NULL;
|
||||
return SHA224_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
static ops_hash_t sha224={OPS_HASH_SHA224,SHA224_DIGEST_LENGTH,"SHA224",sha224_init,
|
||||
sha224_add,sha224_finish,NULL};
|
||||
|
||||
void ops_hash_sha224(ops_hash_t *hash)
|
||||
{
|
||||
*hash=sha224;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
|
||||
const ops_dsa_signature_t *sig,
|
||||
const ops_dsa_public_key_t *dsa)
|
||||
{
|
||||
DSA_SIG *osig;
|
||||
DSA *odsa;
|
||||
int ret;
|
||||
|
||||
osig=DSA_SIG_new();
|
||||
osig->r=sig->r;
|
||||
osig->s=sig->s;
|
||||
|
||||
odsa=DSA_new();
|
||||
odsa->p=dsa->p;
|
||||
odsa->q=dsa->q;
|
||||
odsa->g=dsa->g;
|
||||
odsa->pub_key=dsa->y;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"hash passed in:\n");
|
||||
unsigned i;
|
||||
for (i=0; i<hash_length; i++)
|
||||
{
|
||||
fprintf(stderr,"%02x ", hash[i]);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
//printf("hash_length=%ld\n", hash_length);
|
||||
//printf("Q=%d\n", BN_num_bytes(odsa->q));
|
||||
unsigned int qlen=BN_num_bytes(odsa->q);
|
||||
if (qlen < hash_length)
|
||||
hash_length=qlen;
|
||||
// ret=DSA_do_verify(hash,hash_length,osig,odsa);
|
||||
ret=DSA_do_verify(hash,hash_length,osig,odsa);
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"ret=%d\n",ret);
|
||||
}
|
||||
assert(ret >= 0);
|
||||
|
||||
odsa->p=odsa->q=odsa->g=odsa->pub_key=NULL;
|
||||
DSA_free(odsa);
|
||||
|
||||
osig->r=osig->s=NULL;
|
||||
DSA_SIG_free(osig);
|
||||
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief Recovers message digest from the signature
|
||||
\param out Where to write decrypted data to
|
||||
\param in Encrypted data
|
||||
\param length Length of encrypted data
|
||||
\param rsa RSA public key
|
||||
\return size of recovered message digest
|
||||
*/
|
||||
int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_public_key_t *rsa)
|
||||
{
|
||||
RSA *orsa;
|
||||
int n;
|
||||
|
||||
orsa=RSA_new();
|
||||
orsa->n=rsa->n;
|
||||
orsa->e=rsa->e;
|
||||
|
||||
n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING);
|
||||
|
||||
orsa->n=orsa->e=NULL;
|
||||
RSA_free(orsa);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief Signs data with RSA
|
||||
\param out Where to write signature
|
||||
\param in Data to sign
|
||||
\param length Length of data
|
||||
\param srsa RSA secret key
|
||||
\param rsa RSA public key
|
||||
\return number of bytes decrypted
|
||||
*/
|
||||
int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_secret_key_t *srsa,
|
||||
const ops_rsa_public_key_t *rsa)
|
||||
{
|
||||
RSA *orsa;
|
||||
int n;
|
||||
|
||||
orsa=RSA_new();
|
||||
orsa->n=rsa->n; // XXX: do we need n?
|
||||
orsa->d=srsa->d;
|
||||
orsa->p=srsa->q;
|
||||
orsa->q=srsa->p;
|
||||
|
||||
/* debug */
|
||||
orsa->e=rsa->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 ops_decrypt_secret_key_from_data() to do that.
|
||||
assert(orsa->d);
|
||||
assert(RSA_check_key(orsa) == 1);
|
||||
orsa->e=NULL;
|
||||
/* end debug */
|
||||
|
||||
n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING);
|
||||
|
||||
orsa->n=orsa->d=orsa->p=orsa->q=NULL;
|
||||
RSA_free(orsa);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief Decrypts RSA-encrypted data
|
||||
\param out Where to write the plaintext
|
||||
\param in Encrypted data
|
||||
\param length Length of encrypted data
|
||||
\param srsa RSA secret key
|
||||
\param rsa RSA public key
|
||||
\return size of recovered plaintext
|
||||
*/
|
||||
int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_secret_key_t *srsa,
|
||||
const ops_rsa_public_key_t *rsa)
|
||||
{
|
||||
RSA *orsa;
|
||||
int n;
|
||||
char errbuf[1024];
|
||||
|
||||
orsa=RSA_new();
|
||||
orsa->n=rsa->n; // XXX: do we need n?
|
||||
orsa->d=srsa->d;
|
||||
orsa->p=srsa->q;
|
||||
orsa->q=srsa->p;
|
||||
|
||||
/* debug */
|
||||
orsa->e=rsa->e;
|
||||
assert(RSA_check_key(orsa) == 1);
|
||||
orsa->e=NULL;
|
||||
/* end debug */
|
||||
|
||||
n=RSA_private_decrypt(length,in,out,orsa,RSA_NO_PADDING);
|
||||
|
||||
// printf("ops_rsa_private_decrypt: n=%d\n",n);
|
||||
|
||||
errbuf[0]='\0';
|
||||
if (n==-1)
|
||||
{
|
||||
unsigned long err=ERR_get_error();
|
||||
ERR_error_string(err,&errbuf[0]);
|
||||
fprintf(stderr,"openssl error : %s\n",errbuf);
|
||||
}
|
||||
orsa->n=orsa->d=orsa->p=orsa->q=NULL;
|
||||
RSA_free(orsa);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief RSA-encrypts data
|
||||
\param out Where to write the encrypted data
|
||||
\param in Plaintext
|
||||
\param length Size of plaintext
|
||||
\param rsa RSA Public Key
|
||||
*/
|
||||
int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
|
||||
size_t length,const ops_rsa_public_key_t *rsa)
|
||||
{
|
||||
RSA *orsa;
|
||||
int n;
|
||||
|
||||
// printf("ops_rsa_public_encrypt: length=%ld\n", length);
|
||||
|
||||
orsa=RSA_new();
|
||||
orsa->n=rsa->n;
|
||||
orsa->e=rsa->e;
|
||||
|
||||
// printf("len: %ld\n", length);
|
||||
// ops_print_bn("n: ", orsa->n);
|
||||
// ops_print_bn("e: ", orsa->e);
|
||||
n=RSA_public_encrypt(length,in,out,orsa,RSA_NO_PADDING);
|
||||
|
||||
if (n==-1)
|
||||
{
|
||||
BIO *fd_out;
|
||||
fd_out=BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
|
||||
ERR_print_errors(fd_out);
|
||||
}
|
||||
|
||||
orsa->n=orsa->e=NULL;
|
||||
RSA_free(orsa);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief initialises openssl
|
||||
\note Would usually call ops_init() instead
|
||||
\sa ops_init()
|
||||
*/
|
||||
void ops_crypto_init()
|
||||
{
|
||||
#ifdef DMALLOC
|
||||
CRYPTO_malloc_debug_init();
|
||||
CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
|
||||
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Crypto
|
||||
\brief Finalise openssl
|
||||
\note Would usually call ops_finish() instead
|
||||
\sa ops_finish()
|
||||
*/
|
||||
void ops_crypto_finish()
|
||||
{
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
ERR_remove_state(0);
|
||||
#ifdef DMALLOC
|
||||
CRYPTO_mem_leaks_fp(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Hashes
|
||||
\brief Get Hash name
|
||||
\param hash Hash struct
|
||||
\return Hash name
|
||||
*/
|
||||
const char *ops_text_from_hash(ops_hash_t *hash)
|
||||
{ return hash->name; }
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyGenerate
|
||||
\brief Generates an RSA keypair
|
||||
\param numbits Modulus size
|
||||
\param e Public Exponent
|
||||
\param keydata Pointer to keydata struct to hold new key
|
||||
\return ops_true if key generated successfully; otherwise ops_false
|
||||
\note It is the caller's responsibility to call ops_keydata_free(keydata)
|
||||
*/
|
||||
ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata)
|
||||
{
|
||||
ops_secret_key_t *skey=NULL;
|
||||
RSA *rsa=NULL;
|
||||
BN_CTX *ctx=BN_CTX_new();
|
||||
|
||||
ops_keydata_init(keydata,OPS_PTAG_CT_SECRET_KEY);
|
||||
skey=ops_get_writable_secret_key_from_data(keydata);
|
||||
|
||||
// generate the key pair
|
||||
|
||||
rsa=RSA_generate_key(numbits,e,NULL,NULL);
|
||||
|
||||
// populate ops key from ssl key
|
||||
|
||||
skey->public_key.version=4;
|
||||
skey->public_key.creation_time=time(NULL);
|
||||
skey->public_key.days_valid=0;
|
||||
skey->public_key.algorithm= OPS_PKA_RSA;
|
||||
|
||||
skey->public_key.key.rsa.n=BN_dup(rsa->n);
|
||||
skey->public_key.key.rsa.e=BN_dup(rsa->e);
|
||||
|
||||
skey->s2k_usage=OPS_S2KU_ENCRYPTED_AND_HASHED;
|
||||
skey->s2k_specifier=OPS_S2KS_SALTED;
|
||||
//skey->s2k_specifier=OPS_S2KS_SIMPLE;
|
||||
skey->algorithm=OPS_SA_CAST5; // \todo make param
|
||||
skey->hash_algorithm=OPS_HASH_SHA1; // \todo make param
|
||||
skey->octet_count=0;
|
||||
skey->checksum=0;
|
||||
|
||||
skey->key.rsa.d=BN_dup(rsa->d);
|
||||
skey->key.rsa.p=BN_dup(rsa->p);
|
||||
skey->key.rsa.q=BN_dup(rsa->q);
|
||||
skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx);
|
||||
assert(skey->key.rsa.u);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
RSA_free(rsa);
|
||||
|
||||
ops_keyid(keydata->key_id, &keydata->key.skey.public_key);
|
||||
ops_fingerprint(&keydata->fingerprint, &keydata->key.skey.public_key);
|
||||
|
||||
// Generate checksum
|
||||
|
||||
ops_create_info_t *cinfo=NULL;
|
||||
ops_memory_t *mem=NULL;
|
||||
|
||||
ops_setup_memory_write(&cinfo, &mem, 128);
|
||||
|
||||
ops_push_skey_checksum_writer(cinfo, skey);
|
||||
|
||||
switch(skey->public_key.algorithm)
|
||||
{
|
||||
// case OPS_PKA_DSA:
|
||||
// return ops_write_mpi(key->key.dsa.x,info);
|
||||
|
||||
case OPS_PKA_RSA:
|
||||
case OPS_PKA_RSA_ENCRYPT_ONLY:
|
||||
case OPS_PKA_RSA_SIGN_ONLY:
|
||||
if(!ops_write_mpi(skey->key.rsa.d,cinfo)
|
||||
|| !ops_write_mpi(skey->key.rsa.p,cinfo)
|
||||
|| !ops_write_mpi(skey->key.rsa.q,cinfo)
|
||||
|| !ops_write_mpi(skey->key.rsa.u,cinfo))
|
||||
return ops_false;
|
||||
break;
|
||||
|
||||
// case OPS_PKA_ELGAMAL:
|
||||
// return ops_write_mpi(key->key.elgamal.x,info);
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// close rather than pop, since its the only one on the stack
|
||||
ops_writer_close(cinfo);
|
||||
ops_teardown_memory_write(cinfo, mem);
|
||||
|
||||
// should now have checksum in skey struct
|
||||
|
||||
// test
|
||||
if (debug)
|
||||
test_secret_key(skey);
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_KeyGenerate
|
||||
\brief Creates a self-signed RSA keypair
|
||||
\param numbits Modulus size
|
||||
\param e Public Exponent
|
||||
\param userid User ID
|
||||
\return The new keypair or NULL
|
||||
|
||||
\note It is the caller's responsibility to call ops_keydata_free(keydata)
|
||||
\sa ops_rsa_generate_keypair()
|
||||
\sa ops_keydata_free()
|
||||
*/
|
||||
ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid)
|
||||
{
|
||||
ops_keydata_t *keydata=NULL;
|
||||
|
||||
keydata=ops_keydata_new();
|
||||
|
||||
if (ops_rsa_generate_keypair(numbits, e, keydata) != ops_true
|
||||
|| ops_add_selfsigned_userid_to_keydata(keydata, userid) != ops_true)
|
||||
{
|
||||
ops_keydata_free(keydata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return keydata;
|
||||
}
|
||||
|
||||
/*
|
||||
int ops_dsa_size(const ops_dsa_public_key_t *dsa)
|
||||
{
|
||||
int size;
|
||||
DSA *odsa;
|
||||
odsa=DSA_new();
|
||||
odsa->p=dsa->p;
|
||||
odsa->q=dsa->q;
|
||||
odsa->g=dsa->g;
|
||||
odsa->pub_key=dsa->y;
|
||||
|
||||
DSAparams_print_fp(stderr, odsa);
|
||||
size=DSA_size(odsa);
|
||||
|
||||
odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL;
|
||||
DSA_free(odsa);
|
||||
|
||||
return size;
|
||||
}
|
||||
*/
|
||||
|
||||
DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa)
|
||||
{
|
||||
DSA *odsa;
|
||||
DSA_SIG *dsasig;
|
||||
|
||||
odsa=DSA_new();
|
||||
odsa->p=dsa->p;
|
||||
odsa->q=dsa->q;
|
||||
odsa->g=dsa->g;
|
||||
odsa->pub_key=dsa->y;
|
||||
odsa->priv_key=sdsa->x;
|
||||
|
||||
dsasig=DSA_do_sign(hashbuf,hashsize,odsa);
|
||||
|
||||
odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL;
|
||||
DSA_free(odsa);
|
||||
|
||||
return dsasig;
|
||||
}
|
||||
|
||||
// eof
|
3261
openpgpsdk/src/packet-parse.c
Normal file
3261
openpgpsdk/src/packet-parse.c
Normal file
File diff suppressed because it is too large
Load Diff
1839
openpgpsdk/src/packet-print.c
Normal file
1839
openpgpsdk/src/packet-print.c
Normal file
File diff suppressed because it is too large
Load Diff
854
openpgpsdk/src/packet-show.c
Normal file
854
openpgpsdk/src/packet-show.c
Normal file
@ -0,0 +1,854 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* Creates printable text strings from packet contents
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/configure.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/packet-show.h>
|
||||
#include <openpgpsdk/util.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
/*
|
||||
* Arrays of value->text maps
|
||||
*/
|
||||
|
||||
static ops_map_t packet_tag_map[] =
|
||||
{
|
||||
{ OPS_PTAG_CT_RESERVED, "Reserved" },
|
||||
{ OPS_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key" },
|
||||
{ OPS_PTAG_CT_SIGNATURE, "Signature" },
|
||||
{ OPS_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key" },
|
||||
{ OPS_PTAG_CT_ONE_PASS_SIGNATURE, "One-Pass Signature" },
|
||||
{ OPS_PTAG_CT_SECRET_KEY, "Secret Key" },
|
||||
{ OPS_PTAG_CT_PUBLIC_KEY, "Public Key" },
|
||||
{ OPS_PTAG_CT_SECRET_SUBKEY, "Secret Subkey" },
|
||||
{ OPS_PTAG_CT_COMPRESSED, "Compressed Data" },
|
||||
{ OPS_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data" },
|
||||
{ OPS_PTAG_CT_MARKER, "Marker" },
|
||||
{ OPS_PTAG_CT_LITERAL_DATA, "Literal Data" },
|
||||
{ OPS_PTAG_CT_TRUST, "Trust" },
|
||||
{ OPS_PTAG_CT_USER_ID, "User ID" },
|
||||
{ OPS_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey" },
|
||||
{ OPS_PTAG_CT_RESERVED2, "reserved" },
|
||||
{ OPS_PTAG_CT_RESERVED3, "reserved" },
|
||||
{ OPS_PTAG_CT_USER_ATTRIBUTE, "User Attribute" },
|
||||
{ OPS_PTAG_CT_SE_IP_DATA, "Sym. Encrypted and Integrity Protected Data" },
|
||||
{ OPS_PTAG_CT_MDC, "Modification Detection Code" },
|
||||
{ OPS_PARSER_PTAG, "OPS_PARSER_PTAG" },
|
||||
{ OPS_PTAG_RAW_SS, "OPS_PTAG_RAW_SS" },
|
||||
{ OPS_PTAG_SS_ALL, "OPS_PTAG_SS_ALL" },
|
||||
{ OPS_PARSER_PACKET_END, "OPS_PARSER_PACKET_END" },
|
||||
{ OPS_PTAG_SIGNATURE_SUBPACKET_BASE, "OPS_PTAG_SIGNATURE_SUBPACKET_BASE" },
|
||||
|
||||
{ OPS_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time" },
|
||||
{ OPS_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time" },
|
||||
{ OPS_PTAG_SS_EXPORTABLE_CERTIFICATION, "SS: Exportable Certification" },
|
||||
{ OPS_PTAG_SS_TRUST, "SS: Trust Signature" },
|
||||
{ OPS_PTAG_SS_REGEXP, "SS: Regular Expression" },
|
||||
{ OPS_PTAG_SS_REVOCABLE, "SS: Revocable" },
|
||||
{ OPS_PTAG_SS_KEY_EXPIRATION_TIME, "SS: Key Expiration Time" },
|
||||
{ OPS_PTAG_SS_RESERVED, "SS: Reserved" },
|
||||
{ OPS_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm" },
|
||||
{ OPS_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key" },
|
||||
{ OPS_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id" },
|
||||
{ OPS_PTAG_SS_NOTATION_DATA, "SS: Notation Data" },
|
||||
{ OPS_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm" },
|
||||
{ OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Compression Algorithm" },
|
||||
{ OPS_PTAG_SS_KEY_SERVER_PREFS, "SS: Key Server Preferences" },
|
||||
{ OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Key Server" },
|
||||
{ OPS_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID" },
|
||||
{ OPS_PTAG_SS_POLICY_URI, "SS: Policy URI" },
|
||||
{ OPS_PTAG_SS_KEY_FLAGS, "SS: Key Flags" },
|
||||
{ OPS_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID" },
|
||||
{ OPS_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation" },
|
||||
{ OPS_PTAG_SS_FEATURES, "SS: Features" },
|
||||
{ OPS_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target" },
|
||||
{ OPS_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature" },
|
||||
|
||||
{ OPS_PTAG_CT_LITERAL_DATA_HEADER, "CT: Literal Data Header" },
|
||||
{ OPS_PTAG_CT_LITERAL_DATA_BODY, "CT: Literal Data Body" },
|
||||
{ OPS_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header" },
|
||||
{ OPS_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer" },
|
||||
{ OPS_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header" },
|
||||
{ OPS_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer" },
|
||||
{ OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header" },
|
||||
{ OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body" },
|
||||
{ OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer" },
|
||||
{ OPS_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text" },
|
||||
{ OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key" },
|
||||
{ OPS_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header" },
|
||||
{ OPS_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body" },
|
||||
{ OPS_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header" },
|
||||
{ OPS_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body" },
|
||||
{ OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key" },
|
||||
{ OPS_PARSER_CMD_GET_SK_PASSPHRASE, "CMD: Get Secret Key Passphrase" },
|
||||
{ OPS_PARSER_CMD_GET_SECRET_KEY, "CMD: Get Secret Key" },
|
||||
{ OPS_PARSER_ERROR, "OPS_PARSER_ERROR" },
|
||||
{ OPS_PARSER_ERRCODE, "OPS_PARSER_ERRCODE" },
|
||||
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
typedef ops_map_t packet_tag_map_t;
|
||||
|
||||
static ops_map_t ss_type_map[] =
|
||||
{
|
||||
{ OPS_PTAG_SS_CREATION_TIME, "Signature Creation Time" },
|
||||
{ OPS_PTAG_SS_EXPIRATION_TIME, "Signature Expiration Time" },
|
||||
{ OPS_PTAG_SS_TRUST, "Trust Signature" },
|
||||
{ OPS_PTAG_SS_REGEXP, "Regular Expression" },
|
||||
{ OPS_PTAG_SS_REVOCABLE, "Revocable" },
|
||||
{ OPS_PTAG_SS_KEY_EXPIRATION_TIME, "Key Expiration Time" },
|
||||
{ OPS_PTAG_SS_PREFERRED_SKA, "Preferred Symmetric Algorithms" },
|
||||
{ OPS_PTAG_SS_REVOCATION_KEY, "Revocation Key" },
|
||||
{ OPS_PTAG_SS_ISSUER_KEY_ID, "Issuer key ID" },
|
||||
{ OPS_PTAG_SS_NOTATION_DATA, "Notation Data" },
|
||||
{ OPS_PTAG_SS_PREFERRED_HASH, "Preferred Hash Algorithms" },
|
||||
{ OPS_PTAG_SS_PREFERRED_COMPRESSION,"Preferred Compression Algorithms" },
|
||||
{ OPS_PTAG_SS_KEY_SERVER_PREFS, "Key Server Preferences" },
|
||||
{ OPS_PTAG_SS_PREFERRED_KEY_SERVER, "Preferred Key Server" },
|
||||
{ OPS_PTAG_SS_PRIMARY_USER_ID, "Primary User ID" },
|
||||
{ OPS_PTAG_SS_POLICY_URI, "Policy URI" },
|
||||
{ OPS_PTAG_SS_KEY_FLAGS, "Key Flags" },
|
||||
{ OPS_PTAG_SS_REVOCATION_REASON, "Reason for Revocation" },
|
||||
{ OPS_PTAG_SS_FEATURES, "Features" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
typedef ops_map_t ss_type_map_t;
|
||||
|
||||
|
||||
static ops_map_t ss_rr_code_map[] =
|
||||
{
|
||||
{ 0x00, "No reason specified" },
|
||||
{ 0x01, "Key is superseded" },
|
||||
{ 0x02, "Key material has been compromised" },
|
||||
{ 0x03, "Key is retired and no longer used" },
|
||||
{ 0x20, "User ID information is no longer valid" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
typedef ops_map_t ss_rr_code_map_t;
|
||||
|
||||
static ops_map_t sig_type_map[] =
|
||||
{
|
||||
{ OPS_SIG_BINARY, "Signature of a binary document" },
|
||||
{ OPS_SIG_TEXT, "Signature of a canonical text document" },
|
||||
{ OPS_SIG_STANDALONE, "Standalone signature" },
|
||||
{ OPS_CERT_GENERIC, "Generic certification of a User ID and Public Key packet" },
|
||||
{ OPS_CERT_PERSONA, "Persona certification of a User ID and Public Key packet" },
|
||||
{ OPS_CERT_CASUAL, "Casual certification of a User ID and Public Key packet" },
|
||||
{ OPS_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet" },
|
||||
{ OPS_SIG_SUBKEY, "Subkey Binding Signature" },
|
||||
{ OPS_SIG_PRIMARY, "Primary Key Binding Signature" },
|
||||
{ OPS_SIG_DIRECT, "Signature directly on a key" },
|
||||
{ OPS_SIG_REV_KEY, "Key revocation signature" },
|
||||
{ OPS_SIG_REV_SUBKEY, "Subkey revocation signature" },
|
||||
{ OPS_SIG_REV_CERT, "Certification revocation signature" },
|
||||
{ OPS_SIG_TIMESTAMP, "Timestamp signature" },
|
||||
{ OPS_SIG_3RD_PARTY, "Third-Party Confirmation signature" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
typedef ops_map_t sig_type_map_t;
|
||||
|
||||
static ops_map_t public_key_algorithm_map[] =
|
||||
{
|
||||
{ OPS_PKA_RSA, "RSA (Encrypt or Sign)" },
|
||||
{ OPS_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only" },
|
||||
{ OPS_PKA_RSA_SIGN_ONLY, "RSA Sign-Only" },
|
||||
{ OPS_PKA_ELGAMAL, "Elgamal (Encrypt-Only)" },
|
||||
{ OPS_PKA_DSA, "DSA" },
|
||||
{ OPS_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve" },
|
||||
{ OPS_PKA_RESERVED_ECDSA, "Reserved for ECDSA" },
|
||||
{ OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign" },
|
||||
{ OPS_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)" },
|
||||
{ OPS_PKA_PRIVATE00, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE01, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE02, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE03, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE04, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE05, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE06, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE07, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE08, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE09, "Private/Experimental" },
|
||||
{ OPS_PKA_PRIVATE10, "Private/Experimental" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
typedef ops_map_t public_key_algorithm_map_t;
|
||||
|
||||
static ops_map_t symmetric_algorithm_map[] =
|
||||
{
|
||||
{ OPS_SA_PLAINTEXT, "Plaintext or unencrypted data" },
|
||||
{ OPS_SA_IDEA, "IDEA" },
|
||||
{ OPS_SA_TRIPLEDES, "TripleDES" },
|
||||
{ OPS_SA_CAST5, "CAST5" },
|
||||
{ OPS_SA_BLOWFISH, "Blowfish" },
|
||||
{ OPS_SA_AES_128, "AES (128-bit key)" },
|
||||
{ OPS_SA_AES_192, "AES (192-bit key)" },
|
||||
{ OPS_SA_AES_256, "AES (256-bit key)" },
|
||||
{ OPS_SA_TWOFISH, "Twofish(256-bit key)" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
|
||||
static ops_map_t hash_algorithm_map[] =
|
||||
{
|
||||
{ OPS_HASH_MD5, "MD5" },
|
||||
{ OPS_HASH_SHA1, "SHA1" },
|
||||
{ OPS_HASH_RIPEMD, "RIPEMD160" },
|
||||
{ OPS_HASH_SHA256, "SHA256" },
|
||||
{ OPS_HASH_SHA384, "SHA384" },
|
||||
{ OPS_HASH_SHA512, "SHA512" },
|
||||
{ OPS_HASH_SHA224, "SHA224" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
|
||||
static ops_map_t compression_algorithm_map[] =
|
||||
{
|
||||
{ OPS_C_NONE, "Uncompressed" },
|
||||
{ OPS_C_ZIP, "ZIP(RFC1951)" },
|
||||
{ OPS_C_ZLIB, "ZLIB(RFC1950)" },
|
||||
{ OPS_C_BZIP2, "Bzip2(BZ2)" },
|
||||
{ 0x00, NULL }, /* this is the end-of-array marker */
|
||||
};
|
||||
|
||||
static ops_bit_map_t ss_notation_data_map_byte0[] =
|
||||
{
|
||||
{ 0x80, "Human-readable" },
|
||||
{ 0x00, NULL },
|
||||
};
|
||||
|
||||
static ops_bit_map_t *ss_notation_data_map[] =
|
||||
{
|
||||
ss_notation_data_map_byte0,
|
||||
};
|
||||
|
||||
static ops_bit_map_t ss_feature_map_byte0[] =
|
||||
{
|
||||
{ 0x01, "Modification Detection" },
|
||||
{ 0x00, NULL },
|
||||
};
|
||||
|
||||
static ops_bit_map_t *ss_feature_map[] =
|
||||
{
|
||||
ss_feature_map_byte0,
|
||||
};
|
||||
|
||||
static ops_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 ops_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 },
|
||||
};
|
||||
|
||||
#include <openpgpsdk/packet-show-cast.h>
|
||||
|
||||
/*
|
||||
* Private functions
|
||||
*/
|
||||
|
||||
static void list_init(ops_list_t *list)
|
||||
{
|
||||
list->size=0;
|
||||
list->used=0;
|
||||
list->strings=NULL;
|
||||
}
|
||||
|
||||
static void list_free_strings(ops_list_t *list)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for(i=0; i < list->used ; i++)
|
||||
{
|
||||
free(list->strings[i]);
|
||||
list->strings[i]=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void list_free(ops_list_t *list)
|
||||
{
|
||||
if (list->strings)
|
||||
free(list->strings);
|
||||
list_init(list);
|
||||
}
|
||||
|
||||
static unsigned int list_resize(ops_list_t *list)
|
||||
{
|
||||
/* We only resize in one direction - upwards.
|
||||
Algorithm used : double the current size then add 1
|
||||
*/
|
||||
|
||||
int newsize=0;
|
||||
|
||||
newsize=list->size*2 + 1;
|
||||
list->strings=realloc(list->strings,newsize*sizeof(char *));
|
||||
if (list->strings)
|
||||
{
|
||||
list->size=newsize;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* xxx - realloc failed. error message? - rachel */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int add_str(ops_list_t *list,char *str)
|
||||
{
|
||||
if (list->size==list->used)
|
||||
if (!list_resize(list))
|
||||
return 0;
|
||||
|
||||
list->strings[list->used]=str;
|
||||
list->used++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *str_from_bitfield_or_null(unsigned char octet, ops_bit_map_t *map)
|
||||
{
|
||||
ops_bit_map_t *row;
|
||||
|
||||
for ( row=map; row->string != NULL; row++ )
|
||||
if (row->mask == octet)
|
||||
return row->string;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *str_from_bitfield(unsigned char octet, ops_bit_map_t *map)
|
||||
{
|
||||
char *str;
|
||||
str=str_from_bitfield_or_null(octet,map);
|
||||
if (str)
|
||||
return str;
|
||||
else
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/*! generic function to initialise ops_text_t structure */
|
||||
void ops_text_init(ops_text_t *text)
|
||||
{
|
||||
list_init(&text->known);
|
||||
list_init(&text->unknown);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* ops_text_free() frees the memory used by an ops_text_t structure
|
||||
*
|
||||
* \param text Pointer to a previously allocated structure. This structure and its contents will be freed.
|
||||
*/
|
||||
void ops_text_free(ops_text_t *text)
|
||||
{
|
||||
/* Strings in "known" array will be constants, so don't free them */
|
||||
list_free(&text->known);
|
||||
|
||||
/* Strings in "unknown" array will be dynamically allocated, so do free them */
|
||||
list_free_strings(&text->unknown);
|
||||
list_free(&text->unknown);
|
||||
|
||||
/* finally, free the text structure itself */
|
||||
free(text);
|
||||
}
|
||||
|
||||
// XXX: should this (and many others) be ops_boolean_t?
|
||||
/*! generic function which adds text derived from single octet map to text */
|
||||
static unsigned int add_str_from_octet_map(ops_text_t *text,char *str,
|
||||
unsigned char octet)
|
||||
{
|
||||
if (str && !add_str(&text->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 NULL */
|
||||
str=malloc(len);
|
||||
snprintf(str,len,"0x%x",octet);
|
||||
if (!add_str(&text->unknown,str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*! generic function which adds text derived from single bit map to text */
|
||||
static unsigned int add_str_from_bit_map(ops_text_t *text, char *str, unsigned char bit)
|
||||
{
|
||||
char *fmt_unknown="Unknown bit(0x%x)";
|
||||
|
||||
if (str && !add_str(&text->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 */
|
||||
unsigned len=strlen(fmt_unknown)+1;
|
||||
str=malloc(len);
|
||||
|
||||
snprintf(str,len,fmt_unknown,bit);
|
||||
if (!add_str(&text->unknown,str))
|
||||
return 0;
|
||||
}
|
||||
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 ops_text_t *text_from_bytemapped_octets(ops_data_t *data,
|
||||
const char *(*text_fn)(unsigned char octet))
|
||||
{
|
||||
|
||||
ops_text_t *text=NULL;
|
||||
const char *str;
|
||||
unsigned i;
|
||||
|
||||
/*! allocate and initialise ops_text_t structure to store derived strings */
|
||||
text=malloc(sizeof(ops_text_t));
|
||||
if (!text)
|
||||
return NULL;
|
||||
|
||||
ops_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,strdup(str),data->contents[i]))
|
||||
{
|
||||
ops_text_free(text);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
/*! All values have been added to either the known or the unknown list */
|
||||
/*! Return text */
|
||||
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 ops_text_t *showall_octets_bits(ops_data_t *data,ops_bit_map_t **map,
|
||||
size_t nmap)
|
||||
{
|
||||
ops_text_t *text=NULL;
|
||||
char *str;
|
||||
unsigned i;
|
||||
int j=0;
|
||||
unsigned char mask, bit;
|
||||
|
||||
/*! allocate and initialise ops_text_t structure to store derived strings */
|
||||
text=malloc(sizeof(ops_text_t));
|
||||
if (!text)
|
||||
return NULL;
|
||||
|
||||
ops_text_init(text);
|
||||
|
||||
/*! for each octet in field ... */
|
||||
for(i=0 ; i < data->len ; i++)
|
||||
{
|
||||
/*! for each bit in octet ... */
|
||||
for (j=0, mask=0x80; j<8; j++, mask = mask>>1 )
|
||||
{
|
||||
bit = data->contents[i]&mask;
|
||||
if (bit)
|
||||
{
|
||||
if(i >= nmap)
|
||||
str="Unknown";
|
||||
else
|
||||
str=str_from_bitfield ( bit, map[i] );
|
||||
if (!add_str_from_bit_map( text, str, bit))
|
||||
{
|
||||
ops_text_free(text);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/*
|
||||
* Public Functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
* returns description of the Packet Tag
|
||||
* \param packet_tag
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_packet_tag(ops_packet_tag_t packet_tag)
|
||||
{
|
||||
char *rtn=NULL;
|
||||
rtn=show_packet_tag(packet_tag,packet_tag_map);
|
||||
|
||||
if (!rtn)
|
||||
rtn="Unknown Tag";
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns description of the Signature Sub-Packet type
|
||||
* \param ss_type Signature Sub-Packet type
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_ss_type(ops_ss_type_t ss_type)
|
||||
{
|
||||
return show_ss_type(ss_type,ss_type_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns description of the Revocation Reason code
|
||||
* \param ss_rr_code Revocation Reason code
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code)
|
||||
{
|
||||
return show_ss_rr_code(ss_rr_code,ss_rr_code_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns description of the given Signature type
|
||||
* \param sig_type Signature type
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_sig_type(ops_sig_type_t sig_type)
|
||||
{
|
||||
return show_sig_type(sig_type, sig_type_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns description of the given Public Key Algorithm
|
||||
* \param pka Public Key Algorithm type
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_pka(ops_public_key_algorithm_t pka)
|
||||
{
|
||||
return show_pka(pka, public_key_algorithm_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
* returns description of the Preferred Compression
|
||||
* \param octet Preferred Compression
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_ss_preferred_compression(unsigned char octet)
|
||||
{
|
||||
return ops_str_from_map(octet,compression_algorithm_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns set of descriptions of the given Preferred Compression Algorithms
|
||||
* \param ss_preferred_compression Array of Preferred Compression Algorithms
|
||||
* \return NULL if cannot allocate memory or other error
|
||||
* \return pointer to structure, if no error
|
||||
*/
|
||||
ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression)
|
||||
{
|
||||
return text_from_bytemapped_octets(&ss_preferred_compression.data,
|
||||
&ops_show_ss_preferred_compression);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns description of the Hash Algorithm type
|
||||
* \param hash Hash Algorithm type
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_hash_algorithm(unsigned char hash)
|
||||
{
|
||||
return show_hash_algorithm(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns set of descriptions of the given Preferred Hash Algorithms
|
||||
* \param ss_preferred_hash Array of Preferred Hash Algorithms
|
||||
* \return NULL if cannot allocate memory or other error
|
||||
* \return pointer to structure, if no error
|
||||
*/
|
||||
ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash)
|
||||
{
|
||||
return text_from_bytemapped_octets(&ss_preferred_hash.data,
|
||||
&ops_show_hash_algorithm);
|
||||
}
|
||||
|
||||
const char *ops_show_symmetric_algorithm(unsigned char hash)
|
||||
{
|
||||
return show_symmetric_algorithm(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
* returns description of the given Preferred Symmetric Key Algorithm
|
||||
* \param octet
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_ss_preferred_ska(unsigned char octet)
|
||||
{
|
||||
return ops_str_from_map(octet,symmetric_algorithm_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* returns set of descriptions of the given Preferred Symmetric Key Algorithms
|
||||
* \param ss_preferred_ska Array of Preferred Symmetric Key Algorithms
|
||||
* \return NULL if cannot allocate memory or other error
|
||||
* \return pointer to structure, if no error
|
||||
*/
|
||||
ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska)
|
||||
{
|
||||
return text_from_bytemapped_octets(&ss_preferred_ska.data,
|
||||
&ops_show_ss_preferred_ska);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
* returns description of one SS Feature
|
||||
* \param octet
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
static char *ops_show_ss_feature(unsigned char octet,unsigned offset)
|
||||
{
|
||||
if(offset >= OPS_ARRAY_SIZE(ss_feature_map))
|
||||
return "Unknown";
|
||||
return str_from_bitfield(octet,ss_feature_map[offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* \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? */
|
||||
ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features)
|
||||
{
|
||||
ops_text_t *text=NULL;
|
||||
char *str;
|
||||
unsigned i;
|
||||
int j=0;
|
||||
unsigned char mask, bit;
|
||||
|
||||
text=malloc(sizeof(ops_text_t));
|
||||
if (!text)
|
||||
return NULL;
|
||||
|
||||
ops_text_init(text);
|
||||
|
||||
for(i=0 ; i < ss_features.data.len ; i++)
|
||||
{
|
||||
for (j=0, mask=0x80; j<8; j++, mask = mask>>1 )
|
||||
{
|
||||
bit = ss_features.data.contents[i]&mask;
|
||||
if (bit)
|
||||
{
|
||||
str=ops_show_ss_feature ( bit, i );
|
||||
if (!add_str_from_bit_map( text, str, bit))
|
||||
{
|
||||
ops_text_free(text);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
* returns description of SS Key Flag
|
||||
* \param octet
|
||||
* \param map
|
||||
* \return
|
||||
*/
|
||||
const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map)
|
||||
{
|
||||
return str_from_bitfield(octet,map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \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
|
||||
*/
|
||||
ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags)
|
||||
{
|
||||
ops_text_t *text=NULL;
|
||||
const char *str;
|
||||
int i=0;
|
||||
unsigned char mask, bit;
|
||||
|
||||
text=malloc(sizeof(ops_text_t));
|
||||
if (!text)
|
||||
return NULL;
|
||||
|
||||
ops_text_init(text);
|
||||
|
||||
/* xxx - TBD: extend to handle multiple octets of bits - rachel */
|
||||
|
||||
for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1)
|
||||
{
|
||||
bit=ss_key_flags.data.contents[0]&mask;
|
||||
if(bit)
|
||||
{
|
||||
str=ops_show_ss_key_flag(bit,&ss_key_flags_map[0]);
|
||||
if(!add_str_from_bit_map(text,strdup(str),bit))
|
||||
{
|
||||
ops_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 description of one given Key Server Preference
|
||||
*
|
||||
* \param prefs Byte containing bitfield of preferences
|
||||
* \param map
|
||||
* \return string or "Unknown"
|
||||
*/
|
||||
const char *ops_show_ss_key_server_prefs(unsigned char prefs,
|
||||
ops_bit_map_t *map)
|
||||
{
|
||||
return str_from_bitfield(prefs,map);
|
||||
}
|
||||
|
||||
/**
|
||||
* \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
|
||||
*
|
||||
*/
|
||||
ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs)
|
||||
{
|
||||
ops_text_t *text=NULL;
|
||||
const char *str;
|
||||
int i=0;
|
||||
unsigned char mask, bit;
|
||||
|
||||
text=malloc(sizeof(ops_text_t));
|
||||
if (!text)
|
||||
return NULL;
|
||||
|
||||
ops_text_init(text);
|
||||
|
||||
/* xxx - TBD: extend to handle multiple octets of bits - rachel */
|
||||
|
||||
for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1)
|
||||
{
|
||||
bit=ss_key_server_prefs.data.contents[0]&mask;
|
||||
if (bit)
|
||||
{
|
||||
str=ops_show_ss_key_server_prefs(bit,
|
||||
&ss_key_server_prefs_map[0]);
|
||||
if(!add_str_from_bit_map( text, strdup(str), bit))
|
||||
{
|
||||
ops_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_data Signature Sub-Packet Notation Data
|
||||
* \return NULL if cannot allocate memory or other error
|
||||
* \return pointer to structure, if no error
|
||||
*/
|
||||
ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data)
|
||||
{
|
||||
return showall_octets_bits(&ss_notation_data.flags,ss_notation_data_map,
|
||||
OPS_ARRAY_SIZE(ss_notation_data_map));
|
||||
}
|
118
openpgpsdk/src/parse_local.h
Normal file
118
openpgpsdk/src/parse_local.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
#include <openpgpsdk/types.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
|
||||
/** ops_reader_info */
|
||||
struct ops_reader_info
|
||||
{
|
||||
ops_reader_t *reader; /*!< the reader function to use to get the
|
||||
data to be parsed */
|
||||
ops_reader_destroyer_t *destroyer;
|
||||
void *arg; /*!< the args to pass to the reader function */
|
||||
|
||||
ops_boolean_t accumulate:1; /*!< set to accumulate packet data */
|
||||
unsigned char *accumulated; /*!< the accumulated data */
|
||||
unsigned asize; /*!< size of the buffer */
|
||||
unsigned alength; /*!< used buffer */
|
||||
/* XXX: what do we do about offsets into compressed packets? */
|
||||
unsigned position; /*!< the offset from the beginning (with this reader) */
|
||||
|
||||
ops_reader_info_t *next;
|
||||
ops_parse_info_t *pinfo; /*!< A pointer back to the parent parse_info structure */
|
||||
};
|
||||
|
||||
|
||||
/** ops_crypt_info
|
||||
Encrypt/decrypt settings
|
||||
*/
|
||||
struct ops_crypt_info
|
||||
{
|
||||
char *passphrase; /*<! passphrase to use, this is set by cb_get_passphrase */
|
||||
ops_keyring_t *keyring; /*<! keyring to use */
|
||||
const ops_keydata_t *keydata; /*<! keydata to use */
|
||||
ops_parse_cb_t *cb_get_passphrase; /*<! callback to use to get the passphrase */
|
||||
};
|
||||
|
||||
/** ops_parse_cb_info */
|
||||
struct ops_parse_cb_info
|
||||
{
|
||||
ops_parse_cb_t *cb; /*!< the callback function to use when parsing */
|
||||
void *arg; /*!< the args to pass to the callback function */
|
||||
ops_error_t** errors; /*!< the address of the error stack to use */
|
||||
|
||||
ops_parse_cb_info_t *next;
|
||||
|
||||
ops_create_info_t *cinfo; /*!< used if writing out parsed info */
|
||||
ops_crypt_info_t cryptinfo; /*!< used when decrypting */
|
||||
};
|
||||
|
||||
/** ops_parse_hash_info_t */
|
||||
typedef struct
|
||||
{
|
||||
ops_hash_t hash; /*!< hashes we should hash data with */
|
||||
unsigned char keyid[OPS_KEY_ID_SIZE];
|
||||
} ops_parse_hash_info_t;
|
||||
|
||||
#define NTAGS 0x100
|
||||
/** \brief Structure to hold information about a packet parse.
|
||||
*
|
||||
* This information includes options about the parse:
|
||||
* - whether the packet contents should be accumulated or not
|
||||
* - whether signature subpackets should be parsed or left raw
|
||||
*
|
||||
* It contains options specific to the parsing of armoured data:
|
||||
* - whether headers are allowed in armoured data without a gap
|
||||
* - whether a blank line is allowed at the start of the armoured data
|
||||
*
|
||||
* It also specifies :
|
||||
* - the callback function to use and its arguments
|
||||
* - the reader function to use and its arguments
|
||||
*
|
||||
* It also contains information about the current state of the parse:
|
||||
* - offset from the beginning
|
||||
* - the accumulated data, if any
|
||||
* - the size of the buffer, and how much has been used
|
||||
*
|
||||
* It has a linked list of errors.
|
||||
*/
|
||||
|
||||
struct ops_parse_info
|
||||
{
|
||||
unsigned char ss_raw[NTAGS/8]; /*!< one bit per signature-subpacket type;
|
||||
set to get raw data */
|
||||
unsigned char ss_parsed[NTAGS/8]; /*!< one bit per signature-subpacket type;
|
||||
set to get parsed data */
|
||||
|
||||
ops_reader_info_t rinfo;
|
||||
ops_parse_cb_info_t cbinfo;
|
||||
ops_error_t *errors;
|
||||
ops_crypt_t decrypt;
|
||||
ops_crypt_info_t cryptinfo;
|
||||
size_t nhashes;
|
||||
ops_parse_hash_info_t *hashes;
|
||||
ops_boolean_t reading_v3_secret:1;
|
||||
ops_boolean_t reading_mpi_length:1;
|
||||
ops_boolean_t exact_read:1;
|
||||
};
|
29
openpgpsdk/src/random.c
Normal file
29
openpgpsdk/src/random.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/random.h>
|
||||
|
||||
#include <openssl/rand.h>
|
||||
|
||||
void ops_random(void *dest,size_t length)
|
||||
{
|
||||
RAND_bytes(dest,length);
|
||||
}
|
107
openpgpsdk/src/reader.c
Normal file
107
openpgpsdk/src/reader.c
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include <openpgpsdk/callback.h>
|
||||
|
||||
#include "parse_local.h"
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup Internal_Readers_Generic
|
||||
* \brief Starts reader stack
|
||||
* \param pinfo Parse settings
|
||||
* \param reader Reader to use
|
||||
* \param destroyer Destroyer to use
|
||||
* \param arg Reader-specific arg
|
||||
*/
|
||||
void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg)
|
||||
{
|
||||
pinfo->rinfo.reader=reader;
|
||||
pinfo->rinfo.destroyer=destroyer;
|
||||
pinfo->rinfo.arg=arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Internal_Readers_Generic
|
||||
* \brief Adds to reader stack
|
||||
* \param pinfo Parse settings
|
||||
* \param reader Reader to use
|
||||
* \param destroyer Reader's destroyer
|
||||
* \param arg Reader-specific arg
|
||||
*/
|
||||
void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg)
|
||||
{
|
||||
ops_reader_info_t *rinfo=malloc(sizeof *rinfo);
|
||||
|
||||
*rinfo=pinfo->rinfo;
|
||||
memset(&pinfo->rinfo,'\0',sizeof pinfo->rinfo);
|
||||
pinfo->rinfo.next=rinfo;
|
||||
pinfo->rinfo.pinfo=pinfo;
|
||||
|
||||
// should copy accumulate flags from other reader? RW
|
||||
pinfo->rinfo.accumulate=rinfo->accumulate;
|
||||
|
||||
ops_reader_set(pinfo,reader,destroyer,arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Internal_Readers_Generic
|
||||
* \brief Removes from reader stack
|
||||
* \param pinfo Parse settings
|
||||
*/
|
||||
void ops_reader_pop(ops_parse_info_t *pinfo)
|
||||
{
|
||||
ops_reader_info_t *next=pinfo->rinfo.next;
|
||||
|
||||
pinfo->rinfo=*next;
|
||||
free(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Internal_Readers_Generic
|
||||
* \brief Gets arg from reader
|
||||
* \param rinfo Reader info
|
||||
* \return Pointer to reader info's arg
|
||||
*/
|
||||
void *ops_reader_get_arg(ops_reader_info_t *rinfo)
|
||||
{ return rinfo->arg; }
|
||||
|
||||
/**
|
||||
* \ingroup Internal_Readers_Generic
|
||||
* \brief Gets reader's arg from parse_info
|
||||
* \param pinfo
|
||||
* \return Pointer to parse_info's reader_info's arg
|
||||
*/
|
||||
void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo)
|
||||
{ return pinfo->rinfo.arg; }
|
||||
|
||||
// EOF
|
1046
openpgpsdk/src/reader_armoured.c
Normal file
1046
openpgpsdk/src/reader_armoured.c
Normal file
File diff suppressed because it is too large
Load Diff
217
openpgpsdk/src/reader_encrypted_se.c
Normal file
217
openpgpsdk/src/reader_encrypted_se.c
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/cast.h>
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
#include <openssl/idea.h>
|
||||
#endif
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/des.h>
|
||||
#include "parse_local.h"
|
||||
|
||||
#include <openpgpsdk/packet-show.h>
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
|
||||
#ifndef WIN32
|
||||
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||
#else
|
||||
#define ATTRIBUTE_UNUSED
|
||||
#endif // #ifndef WIN32
|
||||
|
||||
#endif /* ATTRIBUTE_UNUSED */
|
||||
|
||||
|
||||
// \todo there's also a encrypted_arg_t in adv_create.c
|
||||
// which is used for *encrypting* whereas this is used
|
||||
// for *decrypting*
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char decrypted[1024];
|
||||
size_t decrypted_count;
|
||||
size_t decrypted_offset;
|
||||
ops_crypt_t *decrypt;
|
||||
ops_region_t *region;
|
||||
ops_boolean_t prev_read_was_plain:1;
|
||||
} encrypted_arg_t;
|
||||
|
||||
static int encrypted_data_reader(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
encrypted_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
int saved=length;
|
||||
|
||||
// V3 MPIs have the count plain and the cipher is reset after each count
|
||||
if(arg->prev_read_was_plain && !rinfo->pinfo->reading_mpi_length)
|
||||
{
|
||||
assert(rinfo->pinfo->reading_v3_secret);
|
||||
arg->decrypt->decrypt_resync(arg->decrypt);
|
||||
arg->prev_read_was_plain=ops_false;
|
||||
}
|
||||
else if(rinfo->pinfo->reading_v3_secret
|
||||
&& rinfo->pinfo->reading_mpi_length)
|
||||
{
|
||||
arg->prev_read_was_plain=ops_true;
|
||||
}
|
||||
|
||||
while(length > 0)
|
||||
{
|
||||
if(arg->decrypted_count)
|
||||
{
|
||||
|
||||
unsigned n;
|
||||
|
||||
// if we are reading v3 we should never read more than
|
||||
// we're asked for
|
||||
assert(length >= arg->decrypted_count
|
||||
|| (!rinfo->pinfo->reading_v3_secret
|
||||
&& !rinfo->pinfo->exact_read));
|
||||
|
||||
if(length > arg->decrypted_count)
|
||||
n=arg->decrypted_count;
|
||||
else
|
||||
n=length;
|
||||
|
||||
memcpy(dest,arg->decrypted+arg->decrypted_offset,n);
|
||||
arg->decrypted_count-=n;
|
||||
arg->decrypted_offset+=n;
|
||||
length-=n;
|
||||
#ifdef WIN32
|
||||
(char*)dest+=n;
|
||||
#else
|
||||
dest+=n;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned n=arg->region->length;
|
||||
unsigned char buffer[1024];
|
||||
|
||||
if(!n)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!arg->region->indeterminate)
|
||||
{
|
||||
n-=arg->region->length_read;
|
||||
if(n == 0)
|
||||
return saved-length;
|
||||
if(n > sizeof buffer)
|
||||
n=sizeof buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
n=sizeof buffer;
|
||||
}
|
||||
|
||||
// we can only read as much as we're asked for in v3 keys
|
||||
// because they're partially unencrypted!
|
||||
if((rinfo->pinfo->reading_v3_secret || rinfo->pinfo->exact_read)
|
||||
&& n > length)
|
||||
n=length;
|
||||
|
||||
if(!ops_stacked_limited_read(buffer,n,arg->region,errors,rinfo,
|
||||
cbinfo))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!rinfo->pinfo->reading_v3_secret
|
||||
|| !rinfo->pinfo->reading_mpi_length)
|
||||
{
|
||||
arg->decrypted_count=ops_decrypt_se_ip(arg->decrypt,
|
||||
arg->decrypted,
|
||||
buffer,n);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"READING:\nencrypted: ");
|
||||
int i=0;
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", buffer[i]);
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"decrypted: ");
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", arg->decrypted[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(arg->decrypted,buffer,n);
|
||||
arg->decrypted_count=n;
|
||||
}
|
||||
|
||||
assert(arg->decrypted_count > 0);
|
||||
|
||||
arg->decrypted_offset=0;
|
||||
}
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static void encrypted_data_destroyer(ops_reader_info_t *rinfo)
|
||||
{ free(ops_reader_get_arg(rinfo)); }
|
||||
|
||||
/**
|
||||
* \ingroup Core_Readers_SE
|
||||
* \brief Pushes decryption reader onto stack
|
||||
* \sa ops_reader_pop_decrypt()
|
||||
*/
|
||||
void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt,
|
||||
ops_region_t *region)
|
||||
{
|
||||
encrypted_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
arg->decrypt=decrypt;
|
||||
arg->region=region;
|
||||
|
||||
ops_decrypt_init(arg->decrypt);
|
||||
|
||||
ops_reader_push(pinfo,encrypted_data_reader,encrypted_data_destroyer,arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Readers_Encrypted
|
||||
* \brief Pops decryption reader from stack
|
||||
* \sa ops_reader_push_decrypt()
|
||||
*/
|
||||
void ops_reader_pop_decrypt(ops_parse_info_t *pinfo)
|
||||
{
|
||||
encrypted_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
|
||||
|
||||
arg->decrypt->decrypt_finish(arg->decrypt);
|
||||
free(arg);
|
||||
|
||||
ops_reader_pop(pinfo);
|
||||
}
|
||||
|
||||
// eof
|
248
openpgpsdk/src/reader_encrypted_seip.c
Normal file
248
openpgpsdk/src/reader_encrypted_seip.c
Normal file
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Parser for OpenPGP packets
|
||||
*/
|
||||
|
||||
#include <openssl/cast.h>
|
||||
|
||||
#include <openpgpsdk/callback.h>
|
||||
#include <openpgpsdk/packet.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/compress.h>
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include <openpgpsdk/packet-show.h>
|
||||
#include <openpgpsdk/std_print.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/hash.h>
|
||||
|
||||
#include "parse_local.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// boolean: false once we've done the preamble/MDC checks
|
||||
// and are reading from the plaintext
|
||||
int passed_checks;
|
||||
unsigned char *plaintext;
|
||||
size_t plaintext_available;
|
||||
size_t plaintext_offset;
|
||||
ops_region_t *region;
|
||||
ops_crypt_t *decrypt;
|
||||
} decrypt_se_ip_arg_t;
|
||||
|
||||
static int se_ip_data_reader(void *dest_, size_t len, ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
|
||||
/*
|
||||
Gets entire SE_IP data packet.
|
||||
Verifies leading preamble
|
||||
Verifies trailing MDC packet
|
||||
Then passes up plaintext as requested
|
||||
*/
|
||||
|
||||
unsigned int n=0;
|
||||
|
||||
ops_region_t decrypted_region;
|
||||
|
||||
decrypt_se_ip_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
|
||||
if (!arg->passed_checks)
|
||||
{
|
||||
unsigned char*buf=NULL;
|
||||
|
||||
ops_hash_t hash;
|
||||
unsigned char hashed[SHA_DIGEST_LENGTH];
|
||||
|
||||
size_t b;
|
||||
size_t sz_preamble;
|
||||
size_t sz_mdc_hash;
|
||||
size_t sz_mdc;
|
||||
size_t sz_plaintext;
|
||||
|
||||
unsigned char* preamble;
|
||||
unsigned char* plaintext;
|
||||
unsigned char* mdc;
|
||||
unsigned char* mdc_hash;
|
||||
|
||||
ops_hash_any(&hash,OPS_HASH_SHA1);
|
||||
hash.init(&hash);
|
||||
|
||||
ops_init_subregion(&decrypted_region,NULL);
|
||||
decrypted_region.length = arg->region->length - arg->region->length_read;
|
||||
buf=ops_mallocz(decrypted_region.length);
|
||||
|
||||
// read entire SE IP packet
|
||||
|
||||
if (!ops_stacked_limited_read(buf,decrypted_region.length, &decrypted_region,errors,rinfo,cbinfo))
|
||||
{
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"\n\nentire SE IP packet (len=%d):\n",decrypted_region.length);
|
||||
for (i=0; i<decrypted_region.length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", buf[i]);
|
||||
if (!((i+1)%8))
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
// verify leading preamble
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"\npreamble: ");
|
||||
for (i=0; i<arg->decrypt->blocksize+2;i++)
|
||||
fprintf(stderr," 0x%02x", buf[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
b=arg->decrypt->blocksize;
|
||||
if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1])
|
||||
{
|
||||
fprintf(stderr,"Bad symmetric decrypt (%02x%02x vs %02x%02x)\n",
|
||||
buf[b-2],buf[b-1],buf[b],buf[b+1]);
|
||||
OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT,"Bad symmetric decrypt when parsing SE IP packet");
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Verify trailing MDC hash
|
||||
|
||||
sz_preamble=arg->decrypt->blocksize+2;
|
||||
sz_mdc_hash=OPS_SHA1_HASH_SIZE;
|
||||
sz_mdc=1+1+sz_mdc_hash;
|
||||
sz_plaintext=decrypted_region.length-sz_preamble-sz_mdc;
|
||||
|
||||
preamble=buf;
|
||||
plaintext=buf+sz_preamble;
|
||||
mdc=plaintext+sz_plaintext;
|
||||
mdc_hash=mdc+2;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
|
||||
fprintf(stderr,"\nplaintext (len=%ld): ",sz_plaintext);
|
||||
for (i=0; i<sz_plaintext;i++)
|
||||
fprintf(stderr," 0x%02x", plaintext[i]);
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
fprintf(stderr,"\nmdc (len=%ld): ",sz_mdc);
|
||||
for (i=0; i<sz_mdc;i++)
|
||||
fprintf(stderr," 0x%02x", mdc[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
#endif /*DEBUG*/
|
||||
|
||||
ops_calc_mdc_hash(preamble,sz_preamble,plaintext,sz_plaintext,&hashed[0]);
|
||||
|
||||
if (memcmp(mdc_hash,hashed,OPS_SHA1_HASH_SIZE))
|
||||
{
|
||||
OPS_ERROR(errors, OPS_E_V_BAD_HASH, "Bad hash in MDC packet");
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// all done with the checks
|
||||
// now can start reading from the plaintext
|
||||
assert(!arg->plaintext);
|
||||
arg->plaintext=ops_mallocz(sz_plaintext);
|
||||
memcpy(arg->plaintext, plaintext, sz_plaintext);
|
||||
arg->plaintext_available=sz_plaintext;
|
||||
|
||||
arg->passed_checks=1;
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
n=len;
|
||||
if (n > arg->plaintext_available)
|
||||
n=arg->plaintext_available;
|
||||
|
||||
memcpy(dest_, arg->plaintext+arg->plaintext_offset, n);
|
||||
arg->plaintext_available-=n;
|
||||
arg->plaintext_offset+=n;
|
||||
len-=n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void se_ip_data_destroyer(ops_reader_info_t *rinfo)
|
||||
{
|
||||
decrypt_se_ip_arg_t* arg=ops_reader_get_arg(rinfo);
|
||||
free (arg->plaintext);
|
||||
free (arg);
|
||||
// free(ops_reader_get_arg(rinfo));
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Internal_Readers_SEIP
|
||||
*/
|
||||
void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt,
|
||||
ops_region_t *region)
|
||||
{
|
||||
decrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
arg->region=region;
|
||||
arg->decrypt=decrypt;
|
||||
|
||||
ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer,arg);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Internal_Readers_SEIP
|
||||
*/
|
||||
void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo)
|
||||
{
|
||||
// decrypt_se_ip_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
|
||||
// free(arg);
|
||||
ops_reader_pop(pinfo);
|
||||
}
|
||||
|
||||
// eof
|
109
openpgpsdk/src/reader_fd.c
Normal file
109
openpgpsdk/src/reader_fd.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
/** Arguments for reader_fd
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int fd; /*!< file descriptor */
|
||||
} reader_fd_arg_t;
|
||||
|
||||
/**
|
||||
* \ingroup Core_Readers
|
||||
*
|
||||
* ops_reader_fd() attempts to read up to "plength" bytes from the file
|
||||
* descriptor in "parse_info" into the buffer starting at "dest" using the
|
||||
* rules contained in "flags"
|
||||
*
|
||||
* \param dest Pointer to previously allocated buffer
|
||||
* \param plength Number of bytes to try to read
|
||||
* \param flags Rules about reading to use
|
||||
* \param parse_info Gets cast to ops_reader_fd_arg_t
|
||||
*
|
||||
* \return OPS_R_EOF if no bytes were read
|
||||
* \return OPS_R_PARTIAL_READ if not enough bytes were read, and OPS_RETURN_LENGTH is set in "flags"
|
||||
* \return OPS_R_EARLY_EOF if not enough bytes were read, and OPS_RETURN_LENGTH was not set in "flags"
|
||||
* \return OPS_R_OK if expected length was read
|
||||
* \return OPS_R_ERROR if cannot read
|
||||
*
|
||||
* OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack
|
||||
*
|
||||
* \sa enum opt_reader_ret_t
|
||||
*
|
||||
* \todo change arg_ to typesafe?
|
||||
*/
|
||||
static int fd_reader(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
reader_fd_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
int n=read(arg->fd,dest,length);
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
if(n == 0)
|
||||
return 0;
|
||||
|
||||
if(n < 0)
|
||||
{
|
||||
OPS_SYSTEM_ERROR_1(errors,OPS_E_R_READ_FAILED,"read",
|
||||
"file descriptor %d",arg->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void fd_destroyer(ops_reader_info_t *rinfo)
|
||||
{ free(ops_reader_get_arg(rinfo)); }
|
||||
|
||||
/**
|
||||
\ingroup Core_Readers_First
|
||||
\brief Starts stack with file reader
|
||||
*/
|
||||
|
||||
void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd)
|
||||
{
|
||||
reader_fd_arg_t *arg=malloc(sizeof *arg);
|
||||
|
||||
arg->fd=fd;
|
||||
ops_reader_set(pinfo,fd_reader,fd_destroyer,arg);
|
||||
}
|
||||
|
||||
// eof
|
62
openpgpsdk/src/reader_hashed.c
Normal file
62
openpgpsdk/src/reader_hashed.c
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int hash_reader(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
ops_hash_t *hash=ops_reader_get_arg(rinfo);
|
||||
int r=ops_stacked_read(dest,length,errors,rinfo,cbinfo);
|
||||
|
||||
if(r <= 0)
|
||||
return r;
|
||||
|
||||
hash->add(hash,dest,r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Internal_Readers_Hash
|
||||
\brief Push hashed data reader on stack
|
||||
*/
|
||||
void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash)
|
||||
{
|
||||
hash->init(hash);
|
||||
ops_reader_push(pinfo,hash_reader,NULL,hash);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Internal_Readers_Hash
|
||||
\brief Pop hashed data reader from stack
|
||||
*/
|
||||
void ops_reader_pop_hash(ops_parse_info_t *pinfo)
|
||||
{ ops_reader_pop(pinfo); }
|
||||
|
||||
// EOF
|
90
openpgpsdk/src/reader_mem.c
Normal file
90
openpgpsdk/src/reader_mem.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t offset;
|
||||
} reader_mem_arg_t;
|
||||
|
||||
static int mem_reader(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
reader_mem_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
unsigned n;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
OPS_USED(errors);
|
||||
|
||||
if(arg->offset+length > arg->length)
|
||||
n=arg->length-arg->offset;
|
||||
else
|
||||
n=length;
|
||||
|
||||
if(n == 0)
|
||||
return 0;
|
||||
|
||||
memcpy(dest,arg->buffer+arg->offset,n);
|
||||
arg->offset+=n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void mem_destroyer(ops_reader_info_t *rinfo)
|
||||
{ free(ops_reader_get_arg(rinfo)); }
|
||||
|
||||
/**
|
||||
\ingroup Core_Readers_First
|
||||
\brief Starts stack with memory reader
|
||||
*/
|
||||
|
||||
void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer,
|
||||
size_t length)
|
||||
{
|
||||
reader_mem_arg_t *arg=malloc(sizeof *arg);
|
||||
|
||||
arg->buffer=buffer;
|
||||
arg->length=length;
|
||||
arg->offset=0;
|
||||
ops_reader_set(pinfo,mem_reader,mem_destroyer,arg);
|
||||
}
|
||||
|
||||
/* eof */
|
451
openpgpsdk/src/readerwriter.c
Normal file
451
openpgpsdk/src/readerwriter.c
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <direct.h>
|
||||
#endif
|
||||
#include <termios.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include <openpgpsdk/callback.h>
|
||||
|
||||
#include "parse_local.h"
|
||||
|
||||
/**
|
||||
\ingroup Core_Writers
|
||||
\brief Create and initialise cinfo and mem; Set for writing to mem
|
||||
\param cinfo Address where new cinfo pointer will be set
|
||||
\param mem Address when new mem pointer will be set
|
||||
\param bufsz Initial buffer size (will automatically be increased when necessary)
|
||||
\note It is the caller's responsiblity to free cinfo and mem.
|
||||
\sa ops_teardown_memory_write()
|
||||
*/
|
||||
void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz)
|
||||
{
|
||||
/*
|
||||
* initialise needed structures for writing to memory
|
||||
*/
|
||||
|
||||
*cinfo=ops_create_info_new();
|
||||
*mem=ops_memory_new();
|
||||
|
||||
ops_memory_init(*mem,bufsz);
|
||||
|
||||
ops_writer_set_memory(*cinfo,*mem);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Writers
|
||||
\brief Closes writer and frees cinfo and mem
|
||||
\param cinfo
|
||||
\param mem
|
||||
\sa ops_setup_memory_write()
|
||||
*/
|
||||
void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem)
|
||||
{
|
||||
ops_writer_close(cinfo); // new
|
||||
ops_create_info_delete(cinfo);
|
||||
ops_memory_free(mem);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Readers
|
||||
\brief Create parse_info and sets to read from memory
|
||||
\param pinfo Address where new parse_info will be set
|
||||
\param mem Memory to read from
|
||||
\param arg Reader-specific arg
|
||||
\param callback Callback to use with reader
|
||||
\param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification)
|
||||
\note It is the caller's responsiblity to free parse_info
|
||||
\sa ops_teardown_memory_read()
|
||||
*/
|
||||
void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem,
|
||||
void* arg,
|
||||
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),
|
||||
ops_boolean_t accumulate)
|
||||
{
|
||||
/*
|
||||
* initialise needed uctures for reading
|
||||
*/
|
||||
|
||||
*pinfo=ops_parse_info_new();
|
||||
ops_parse_cb_set(*pinfo,callback,arg);
|
||||
ops_reader_set_memory(*pinfo,
|
||||
ops_memory_get_data(mem),
|
||||
ops_memory_get_length(mem));
|
||||
|
||||
if (accumulate)
|
||||
(*pinfo)->rinfo.accumulate=ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Readers
|
||||
\brief Frees pinfo and mem
|
||||
\param pinfo
|
||||
\param mem
|
||||
\sa ops_setup_memory_read()
|
||||
*/
|
||||
void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem)
|
||||
{
|
||||
ops_parse_info_delete(pinfo);
|
||||
ops_memory_free(mem);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Writers
|
||||
\brief Create and initialise cinfo and mem; Set for writing to file
|
||||
\param cinfo Address where new cinfo pointer will be set
|
||||
\param filename File to write to
|
||||
\param allow_overwrite Allows file to be overwritten, if set.
|
||||
\return Newly-opened file descriptor
|
||||
\note It is the caller's responsiblity to free cinfo and to close fd.
|
||||
\sa ops_teardown_file_write()
|
||||
*/
|
||||
int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite)
|
||||
{
|
||||
int fd=0;
|
||||
int flags=0;
|
||||
|
||||
/*
|
||||
* initialise needed structures for writing to file
|
||||
*/
|
||||
|
||||
flags=O_WRONLY | O_CREAT;
|
||||
if (allow_overwrite==ops_true)
|
||||
flags |= O_TRUNC;
|
||||
else
|
||||
flags |= O_EXCL;
|
||||
|
||||
#ifdef WIN32
|
||||
flags |= O_BINARY;
|
||||
#endif
|
||||
|
||||
fd=open(filename, flags, 0600);
|
||||
if(fd < 0)
|
||||
{
|
||||
perror(filename);
|
||||
return fd;
|
||||
}
|
||||
|
||||
*cinfo=ops_create_info_new();
|
||||
|
||||
ops_writer_set_fd(*cinfo,fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Writers
|
||||
\brief Closes writer, frees info, closes fd
|
||||
\param cinfo
|
||||
\param fd
|
||||
*/
|
||||
void ops_teardown_file_write(ops_create_info_t *cinfo, int fd)
|
||||
{
|
||||
ops_writer_close(cinfo);
|
||||
close(fd);
|
||||
ops_create_info_delete(cinfo);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Writers
|
||||
\brief As ops_setup_file_write, but appends to file
|
||||
*/
|
||||
int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename)
|
||||
{
|
||||
int fd;
|
||||
/*
|
||||
* initialise needed structures for writing to file
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
fd=open(filename,O_WRONLY | O_APPEND | O_BINARY, 0600);
|
||||
#else
|
||||
fd=open(filename,O_WRONLY | O_APPEND, 0600);
|
||||
#endif
|
||||
if(fd < 0)
|
||||
{
|
||||
perror(filename);
|
||||
return fd;
|
||||
}
|
||||
|
||||
*cinfo=ops_create_info_new();
|
||||
|
||||
ops_writer_set_fd(*cinfo,fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Writers
|
||||
\brief As ops_teardown_file_write()
|
||||
*/
|
||||
void ops_teardown_file_append(ops_create_info_t *cinfo, int fd)
|
||||
{
|
||||
ops_teardown_file_write(cinfo,fd);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Readers
|
||||
\brief Creates parse_info, opens file, and sets to read from file
|
||||
\param pinfo Address where new parse_info will be set
|
||||
\param filename Name of file to read
|
||||
\param arg Reader-specific arg
|
||||
\param callback Callback to use when reading
|
||||
\param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification)
|
||||
\note It is the caller's responsiblity to free parse_info and to close fd
|
||||
\sa ops_teardown_file_read()
|
||||
*/
|
||||
|
||||
int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename,
|
||||
void* arg,
|
||||
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),
|
||||
ops_boolean_t accumulate)
|
||||
{
|
||||
int fd=0;
|
||||
/*
|
||||
* initialise needed structures for reading
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
fd=open(filename,O_RDONLY | O_BINARY);
|
||||
#else
|
||||
fd=open(filename,O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
{
|
||||
perror(filename);
|
||||
return fd;
|
||||
}
|
||||
|
||||
*pinfo=ops_parse_info_new();
|
||||
ops_parse_cb_set(*pinfo,callback,arg);
|
||||
ops_reader_set_fd(*pinfo,fd);
|
||||
|
||||
if (accumulate)
|
||||
(*pinfo)->rinfo.accumulate=ops_true;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Readers
|
||||
\brief Frees pinfo and closes fd
|
||||
\param pinfo
|
||||
\param fd
|
||||
\sa ops_setup_file_read()
|
||||
*/
|
||||
void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd)
|
||||
{
|
||||
close(fd);
|
||||
ops_parse_info_delete(pinfo);
|
||||
}
|
||||
|
||||
ops_parse_cb_return_t
|
||||
callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
// ops_print_packet(content_);
|
||||
|
||||
// Read data from packet into static buffer
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PTAG_CT_LITERAL_DATA_BODY:
|
||||
// if writer enabled, use it
|
||||
if (cbinfo->cinfo)
|
||||
{
|
||||
ops_write(content->literal_data_body.data,
|
||||
content->literal_data_body.length,
|
||||
cbinfo->cinfo);
|
||||
}
|
||||
/*
|
||||
ops_memory_add(mem_literal_data,
|
||||
content->literal_data_body.data,
|
||||
content->literal_data_body.length);
|
||||
*/
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_LITERAL_DATA_HEADER:
|
||||
// ignore
|
||||
break;
|
||||
|
||||
default:
|
||||
// return callback_general(content_,cbinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
ops_parse_cb_return_t
|
||||
callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
// ops_print_packet(content_);
|
||||
|
||||
// Read data from packet into static buffer
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PTAG_CT_PK_SESSION_KEY:
|
||||
// printf ("OPS_PTAG_CT_PK_SESSION_KEY\n");
|
||||
assert(cbinfo->cryptinfo.keyring);
|
||||
cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,
|
||||
content->pk_session_key.key_id);
|
||||
if(!cbinfo->cryptinfo.keydata)
|
||||
break;
|
||||
break;
|
||||
|
||||
default:
|
||||
// return callback_general(content_,cbinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_Callbacks
|
||||
|
||||
\brief Callback to get secret key, decrypting if necessary.
|
||||
|
||||
@verbatim
|
||||
This callback does the following:
|
||||
* finds the session key in the keyring
|
||||
* gets a passphrase if required
|
||||
* decrypts the secret key, if necessary
|
||||
* sets the secret_key in the content struct
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
ops_parse_cb_return_t
|
||||
callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
|
||||
const ops_secret_key_t *secret;
|
||||
ops_parser_content_t pc;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
// ops_print_packet(content_);
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PARSER_CMD_GET_SECRET_KEY:
|
||||
cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,content->get_secret_key.pk_session_key->key_id);
|
||||
if (!cbinfo->cryptinfo.keydata || !ops_is_key_secret(cbinfo->cryptinfo.keydata))
|
||||
return 0;
|
||||
|
||||
/* now get the key from the data */
|
||||
secret=ops_get_secret_key_from_data(cbinfo->cryptinfo.keydata);
|
||||
while(!secret)
|
||||
{
|
||||
if (!cbinfo->cryptinfo.passphrase)
|
||||
{
|
||||
memset(&pc,'\0',sizeof pc);
|
||||
pc.content.secret_key_passphrase.passphrase=&cbinfo->cryptinfo.passphrase;
|
||||
CB(cbinfo,OPS_PARSER_CMD_GET_SK_PASSPHRASE,&pc);
|
||||
if (!cbinfo->cryptinfo.passphrase)
|
||||
{
|
||||
fprintf(stderr,"can't get passphrase\n");
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
/* then it must be encrypted */
|
||||
secret=ops_decrypt_secret_key_from_data(cbinfo->cryptinfo.keydata,cbinfo->cryptinfo.passphrase);
|
||||
}
|
||||
|
||||
*content->get_secret_key.secret_key=secret;
|
||||
break;
|
||||
|
||||
default:
|
||||
// return callback_general(content_,cbinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
char *ops_get_passphrase(void)
|
||||
{
|
||||
return ops_malloc_passphrase(getpass("Passphrase: "));
|
||||
}
|
||||
|
||||
char *ops_malloc_passphrase(char *pp)
|
||||
{
|
||||
char *passphrase;
|
||||
size_t n;
|
||||
|
||||
n=strlen(pp);
|
||||
passphrase=malloc(n+1);
|
||||
strncpy(passphrase,pp,n+1);
|
||||
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Callbacks
|
||||
\brief Callback to use when you need to prompt user for passphrase
|
||||
\param content_
|
||||
\param cbinfo
|
||||
*/
|
||||
ops_parse_cb_return_t
|
||||
callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
|
||||
// ops_print_packet(content_);
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
|
||||
*(content->secret_key_passphrase.passphrase)=ops_get_passphrase();
|
||||
return OPS_KEEP_MEMORY;
|
||||
break;
|
||||
|
||||
default:
|
||||
// return callback_general(content_,cbinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state)
|
||||
{
|
||||
pinfo->rinfo.accumulate=state;
|
||||
return state;
|
||||
}
|
||||
|
||||
// EOF
|
1322
openpgpsdk/src/signature.c
Normal file
1322
openpgpsdk/src/signature.c
Normal file
File diff suppressed because it is too large
Load Diff
49
openpgpsdk/src/src.pro
Normal file
49
openpgpsdk/src/src.pro
Normal file
@ -0,0 +1,49 @@
|
||||
TEMPLATE = lib
|
||||
CONFIG = staticlib
|
||||
|
||||
DEFINES *= OPENSSL_NO_IDEA
|
||||
|
||||
QMAKE_CXXFLAGS *= -Wall -Werror -W
|
||||
|
||||
TARGET = ops
|
||||
DESTDIR = ../lib
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += . ../include
|
||||
|
||||
# Input
|
||||
HEADERS += keyring_local.h parse_local.h
|
||||
SOURCES += accumulate.c \
|
||||
compress.c \
|
||||
create.c \
|
||||
crypto.c \
|
||||
errors.c \
|
||||
fingerprint.c \
|
||||
hash.c \
|
||||
keyring.c \
|
||||
lists.c \
|
||||
memory.c \
|
||||
openssl_crypto.c \
|
||||
packet-parse.c \
|
||||
packet-print.c \
|
||||
packet-show.c \
|
||||
random.c \
|
||||
reader.c \
|
||||
reader_armoured.c \
|
||||
reader_encrypted_se.c \
|
||||
reader_encrypted_seip.c \
|
||||
reader_fd.c \
|
||||
reader_hashed.c \
|
||||
reader_mem.c \
|
||||
readerwriter.c \
|
||||
signature.c \
|
||||
symmetric.c \
|
||||
util.c \
|
||||
validate.c \
|
||||
writer.c \
|
||||
writer_armour.c \
|
||||
writer_encrypt.c \
|
||||
writer_encrypt_se_ip.c \
|
||||
writer_fd.c \
|
||||
writer_memory.c \
|
||||
writer_skey_checksum.c \
|
||||
writer_stream_encrypt_se_ip.c
|
525
openpgpsdk/src/symmetric.c
Normal file
525
openpgpsdk/src/symmetric.c
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <openssl/cast.h>
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
#include <openssl/idea.h>
|
||||
#endif
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/des.h>
|
||||
#include "parse_local.h"
|
||||
|
||||
#include <openpgpsdk/packet-show.h>
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
//static int debug=0;
|
||||
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
|
||||
#ifndef WIN32
|
||||
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||
#else
|
||||
#define ATTRIBUTE_UNUSED
|
||||
#endif // #ifndef WIN32
|
||||
|
||||
#endif /* ATTRIBUTE_UNUSED */
|
||||
|
||||
static void std_set_iv(ops_crypt_t *crypt,const unsigned char *iv)
|
||||
{
|
||||
memcpy(crypt->iv,iv,crypt->blocksize);
|
||||
crypt->num=0;
|
||||
}
|
||||
|
||||
static void std_set_key(ops_crypt_t *crypt,const unsigned char *key)
|
||||
{ memcpy(crypt->key,key,crypt->keysize); }
|
||||
|
||||
static void std_resync(ops_crypt_t *decrypt)
|
||||
{
|
||||
if(decrypt->num == decrypt->blocksize)
|
||||
return;
|
||||
|
||||
memmove(decrypt->civ+decrypt->blocksize-decrypt->num,decrypt->civ,
|
||||
decrypt->num);
|
||||
memcpy(decrypt->civ,decrypt->siv+decrypt->num,
|
||||
decrypt->blocksize-decrypt->num);
|
||||
decrypt->num=0;
|
||||
}
|
||||
|
||||
static void std_finish(ops_crypt_t *crypt)
|
||||
{
|
||||
if (crypt->encrypt_key)
|
||||
{
|
||||
free(crypt->encrypt_key);
|
||||
crypt->encrypt_key=NULL;
|
||||
}
|
||||
if (crypt->decrypt_key)
|
||||
{
|
||||
free(crypt->decrypt_key);
|
||||
crypt->decrypt_key=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void cast5_init(ops_crypt_t *crypt)
|
||||
{
|
||||
if (crypt->encrypt_key)
|
||||
free(crypt->encrypt_key);
|
||||
crypt->encrypt_key=malloc(sizeof(CAST_KEY));
|
||||
CAST_set_key(crypt->encrypt_key,crypt->keysize,crypt->key);
|
||||
crypt->decrypt_key=malloc(sizeof(CAST_KEY));
|
||||
CAST_set_key(crypt->decrypt_key,crypt->keysize,crypt->key);
|
||||
}
|
||||
|
||||
static void cast5_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
|
||||
{ CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_ENCRYPT); }
|
||||
|
||||
static void cast5_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
|
||||
{ CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_DECRYPT); }
|
||||
|
||||
static void cast5_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
|
||||
{
|
||||
CAST_cfb64_encrypt(in,out,count,
|
||||
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
|
||||
CAST_ENCRYPT);
|
||||
}
|
||||
|
||||
static void cast5_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
|
||||
{
|
||||
CAST_cfb64_encrypt(in,out,count,
|
||||
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
|
||||
CAST_DECRYPT);
|
||||
}
|
||||
|
||||
#define TRAILER "","","","",0,NULL,NULL
|
||||
|
||||
static ops_crypt_t cast5=
|
||||
{
|
||||
OPS_SA_CAST5,
|
||||
CAST_BLOCK,
|
||||
CAST_KEY_LENGTH,
|
||||
std_set_iv,
|
||||
std_set_key,
|
||||
cast5_init,
|
||||
std_resync,
|
||||
cast5_block_encrypt,
|
||||
cast5_block_decrypt,
|
||||
cast5_cfb_encrypt,
|
||||
cast5_cfb_decrypt,
|
||||
std_finish,
|
||||
TRAILER
|
||||
};
|
||||
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
static void idea_init(ops_crypt_t *crypt)
|
||||
{
|
||||
assert(crypt->keysize == IDEA_KEY_LENGTH);
|
||||
|
||||
if (crypt->encrypt_key)
|
||||
free(crypt->encrypt_key);
|
||||
crypt->encrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE));
|
||||
|
||||
// note that we don't invert the key when decrypting for CFB mode
|
||||
idea_set_encrypt_key(crypt->key,crypt->encrypt_key);
|
||||
|
||||
if (crypt->decrypt_key)
|
||||
free(crypt->decrypt_key);
|
||||
crypt->decrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE));
|
||||
|
||||
idea_set_decrypt_key(crypt->encrypt_key,crypt->decrypt_key);
|
||||
}
|
||||
|
||||
static void idea_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
|
||||
{ idea_ecb_encrypt(in,out,crypt->encrypt_key); }
|
||||
|
||||
static void idea_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
|
||||
{ idea_ecb_encrypt(in,out,crypt->decrypt_key); }
|
||||
|
||||
static void idea_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
|
||||
{
|
||||
idea_cfb64_encrypt(in,out,count,
|
||||
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
|
||||
CAST_ENCRYPT);
|
||||
}
|
||||
|
||||
static void idea_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
|
||||
{
|
||||
idea_cfb64_encrypt(in,out,count,
|
||||
crypt->decrypt_key, crypt->iv, (int *)&crypt->num,
|
||||
CAST_DECRYPT);
|
||||
}
|
||||
|
||||
static const ops_crypt_t idea=
|
||||
{
|
||||
OPS_SA_IDEA,
|
||||
IDEA_BLOCK,
|
||||
IDEA_KEY_LENGTH,
|
||||
std_set_iv,
|
||||
std_set_key,
|
||||
idea_init,
|
||||
std_resync,
|
||||
idea_block_encrypt,
|
||||
idea_block_decrypt,
|
||||
idea_cfb_encrypt,
|
||||
idea_cfb_decrypt,
|
||||
std_finish,
|
||||
TRAILER
|
||||
};
|
||||
#endif /* OPENSSL_NO_IDEA */
|
||||
|
||||
// AES with 128-bit key (AES)
|
||||
|
||||
#define KEYBITS_AES128 128
|
||||
|
||||
static void aes128_init(ops_crypt_t *crypt)
|
||||
{
|
||||
if (crypt->encrypt_key)
|
||||
free(crypt->encrypt_key);
|
||||
crypt->encrypt_key=malloc(sizeof(AES_KEY));
|
||||
if (AES_set_encrypt_key(crypt->key,KEYBITS_AES128,crypt->encrypt_key))
|
||||
fprintf(stderr,"aes128_init: Error setting encrypt_key\n");
|
||||
|
||||
if (crypt->decrypt_key)
|
||||
free(crypt->decrypt_key);
|
||||
crypt->decrypt_key=malloc(sizeof(AES_KEY));
|
||||
if (AES_set_decrypt_key(crypt->key,KEYBITS_AES128,crypt->decrypt_key))
|
||||
fprintf(stderr,"aes128_init: Error setting decrypt_key\n");
|
||||
}
|
||||
|
||||
static void aes_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
|
||||
{ AES_encrypt(in,out,crypt->encrypt_key); }
|
||||
|
||||
static void aes_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
|
||||
{ AES_decrypt(in,out,crypt->decrypt_key); }
|
||||
|
||||
static void aes_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
|
||||
{
|
||||
AES_cfb128_encrypt(in,out,count,
|
||||
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
|
||||
AES_ENCRYPT);
|
||||
}
|
||||
|
||||
static void aes_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
|
||||
{
|
||||
AES_cfb128_encrypt(in,out,count,
|
||||
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
|
||||
AES_DECRYPT);
|
||||
}
|
||||
|
||||
static const ops_crypt_t aes128=
|
||||
{
|
||||
OPS_SA_AES_128,
|
||||
AES_BLOCK_SIZE,
|
||||
KEYBITS_AES128/8,
|
||||
std_set_iv,
|
||||
std_set_key,
|
||||
aes128_init,
|
||||
std_resync,
|
||||
aes_block_encrypt,
|
||||
aes_block_decrypt,
|
||||
aes_cfb_encrypt,
|
||||
aes_cfb_decrypt,
|
||||
std_finish,
|
||||
TRAILER
|
||||
};
|
||||
|
||||
// AES with 256-bit key
|
||||
|
||||
#define KEYBITS_AES256 256
|
||||
|
||||
static void aes256_init(ops_crypt_t *crypt)
|
||||
{
|
||||
if (crypt->encrypt_key)
|
||||
free(crypt->encrypt_key);
|
||||
crypt->encrypt_key=malloc(sizeof(AES_KEY));
|
||||
if (AES_set_encrypt_key(crypt->key,KEYBITS_AES256,crypt->encrypt_key))
|
||||
fprintf(stderr,"aes256_init: Error setting encrypt_key\n");
|
||||
|
||||
if (crypt->decrypt_key)
|
||||
free(crypt->decrypt_key);
|
||||
crypt->decrypt_key=malloc(sizeof(AES_KEY));
|
||||
if (AES_set_decrypt_key(crypt->key,KEYBITS_AES256,crypt->decrypt_key))
|
||||
fprintf(stderr,"aes256_init: Error setting decrypt_key\n");
|
||||
}
|
||||
|
||||
static const ops_crypt_t aes256=
|
||||
{
|
||||
OPS_SA_AES_256,
|
||||
AES_BLOCK_SIZE,
|
||||
KEYBITS_AES256/8,
|
||||
std_set_iv,
|
||||
std_set_key,
|
||||
aes256_init,
|
||||
std_resync,
|
||||
aes_block_encrypt,
|
||||
aes_block_decrypt,
|
||||
aes_cfb_encrypt,
|
||||
aes_cfb_decrypt,
|
||||
std_finish,
|
||||
TRAILER
|
||||
};
|
||||
|
||||
// Triple DES
|
||||
|
||||
static void tripledes_init(ops_crypt_t *crypt)
|
||||
{
|
||||
DES_key_schedule *keys;
|
||||
int n;
|
||||
|
||||
if (crypt->encrypt_key)
|
||||
free(crypt->encrypt_key);
|
||||
keys=crypt->encrypt_key=malloc(3*sizeof(DES_key_schedule));
|
||||
|
||||
for(n=0 ; n < 3 ; ++n)
|
||||
DES_set_key((DES_cblock *)(crypt->key+n*8),&keys[n]);
|
||||
}
|
||||
|
||||
static void tripledes_block_encrypt(ops_crypt_t *crypt,void *out,
|
||||
const void *in)
|
||||
{
|
||||
DES_key_schedule *keys=crypt->encrypt_key;
|
||||
|
||||
DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_ENCRYPT);
|
||||
}
|
||||
|
||||
static void tripledes_block_decrypt(ops_crypt_t *crypt,void *out,
|
||||
const void *in)
|
||||
{
|
||||
DES_key_schedule *keys=crypt->encrypt_key;
|
||||
|
||||
DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_DECRYPT);
|
||||
}
|
||||
|
||||
static void tripledes_cfb_encrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED,void *out ATTRIBUTE_UNUSED,const void *in ATTRIBUTE_UNUSED, size_t count ATTRIBUTE_UNUSED)
|
||||
{
|
||||
DES_key_schedule *keys=crypt->encrypt_key;
|
||||
DES_ede3_cfb64_encrypt(in,out,count,
|
||||
&keys[0],&keys[1],&keys[2], (DES_cblock *)crypt->iv, (int *)&crypt->num,
|
||||
DES_ENCRYPT);
|
||||
}
|
||||
|
||||
static void tripledes_cfb_decrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED,void *out ATTRIBUTE_UNUSED,const void *in ATTRIBUTE_UNUSED, size_t count ATTRIBUTE_UNUSED)
|
||||
{
|
||||
DES_key_schedule *keys=crypt->encrypt_key;
|
||||
DES_ede3_cfb64_encrypt(in,out,count,
|
||||
&keys[0],&keys[1],&keys[2], (DES_cblock *)crypt->iv, (int *)&crypt->num,
|
||||
DES_DECRYPT);
|
||||
}
|
||||
|
||||
static const ops_crypt_t tripledes=
|
||||
{
|
||||
OPS_SA_TRIPLEDES,
|
||||
8,
|
||||
24,
|
||||
std_set_iv,
|
||||
std_set_key,
|
||||
tripledes_init,
|
||||
std_resync,
|
||||
tripledes_block_encrypt,
|
||||
tripledes_block_decrypt,
|
||||
tripledes_cfb_encrypt,
|
||||
tripledes_cfb_decrypt,
|
||||
std_finish,
|
||||
TRAILER
|
||||
};
|
||||
|
||||
static const ops_crypt_t *get_proto(ops_symmetric_algorithm_t alg)
|
||||
{
|
||||
switch(alg)
|
||||
{
|
||||
case OPS_SA_CAST5:
|
||||
return &cast5;
|
||||
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
case OPS_SA_IDEA:
|
||||
return &idea;
|
||||
#endif /* OPENSSL_NO_IDEA */
|
||||
|
||||
case OPS_SA_AES_128:
|
||||
return &aes128;
|
||||
|
||||
case OPS_SA_AES_256:
|
||||
return &aes256;
|
||||
|
||||
case OPS_SA_TRIPLEDES:
|
||||
return &tripledes;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"Unknown algorithm: %d (%s)\n",alg,ops_show_symmetric_algorithm(alg));
|
||||
// assert(0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ops_crypt_any(ops_crypt_t *crypt,ops_symmetric_algorithm_t alg)
|
||||
{
|
||||
const ops_crypt_t *ptr=get_proto(alg);
|
||||
if (ptr)
|
||||
{
|
||||
*crypt=*ptr;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(crypt,'\0',sizeof *crypt);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ops_block_size(ops_symmetric_algorithm_t alg)
|
||||
{
|
||||
const ops_crypt_t *p=get_proto(alg);
|
||||
|
||||
if(!p)
|
||||
return 0;
|
||||
|
||||
return p->blocksize;
|
||||
}
|
||||
|
||||
unsigned ops_key_size(ops_symmetric_algorithm_t alg)
|
||||
{
|
||||
const ops_crypt_t *p=get_proto(alg);
|
||||
|
||||
if(!p)
|
||||
return 0;
|
||||
|
||||
return p->keysize;
|
||||
}
|
||||
|
||||
void ops_encrypt_init(ops_crypt_t * encrypt)
|
||||
{
|
||||
// \todo should there be a separate ops_encrypt_init?
|
||||
ops_decrypt_init(encrypt);
|
||||
}
|
||||
|
||||
void ops_decrypt_init(ops_crypt_t *decrypt)
|
||||
{
|
||||
decrypt->base_init(decrypt);
|
||||
decrypt->block_encrypt(decrypt,decrypt->siv,decrypt->iv);
|
||||
memcpy(decrypt->civ,decrypt->siv,decrypt->blocksize);
|
||||
decrypt->num=0;
|
||||
}
|
||||
|
||||
size_t ops_decrypt_se
|
||||
(ops_crypt_t *decrypt,void *out_,const void *in_,
|
||||
size_t count)
|
||||
{
|
||||
unsigned char *out=out_;
|
||||
const unsigned char *in=in_;
|
||||
int saved=count;
|
||||
|
||||
/* in order to support v3's weird resyncing we have to implement CFB mode
|
||||
ourselves */
|
||||
while(count-- > 0)
|
||||
{
|
||||
unsigned char t;
|
||||
|
||||
if(decrypt->num == decrypt->blocksize)
|
||||
{
|
||||
memcpy(decrypt->siv,decrypt->civ,decrypt->blocksize);
|
||||
decrypt->block_decrypt(decrypt,decrypt->civ,decrypt->civ);
|
||||
decrypt->num=0;
|
||||
}
|
||||
t=decrypt->civ[decrypt->num];
|
||||
*out++=t^(decrypt->civ[decrypt->num++]=*in++);
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out_,const void *in_,
|
||||
size_t count)
|
||||
{
|
||||
unsigned char *out=out_;
|
||||
const unsigned char *in=in_;
|
||||
int saved=count;
|
||||
|
||||
/* in order to support v3's weird resyncing we have to implement CFB mode
|
||||
ourselves */
|
||||
while(count-- > 0)
|
||||
{
|
||||
if(encrypt->num == encrypt->blocksize)
|
||||
{
|
||||
memcpy(encrypt->siv,encrypt->civ,encrypt->blocksize);
|
||||
encrypt->block_encrypt(encrypt,encrypt->civ,encrypt->civ);
|
||||
encrypt->num=0;
|
||||
}
|
||||
encrypt->civ[encrypt->num]=*out++=encrypt->civ[encrypt->num]^*in++;
|
||||
++encrypt->num;
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Supported
|
||||
\brief Is this Symmetric Algorithm supported?
|
||||
\param alg Symmetric Algorithm to check
|
||||
\return ops_true if supported; else ops_false
|
||||
*/
|
||||
ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg)
|
||||
{
|
||||
switch (alg)
|
||||
{
|
||||
case OPS_SA_AES_128:
|
||||
case OPS_SA_AES_256:
|
||||
case OPS_SA_CAST5:
|
||||
case OPS_SA_TRIPLEDES:
|
||||
#ifndef OPENSSL_NO_IDEA
|
||||
case OPS_SA_IDEA:
|
||||
#endif
|
||||
return ops_true;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"\nWarning: %s not supported\n",
|
||||
ops_show_symmetric_algorithm(alg));
|
||||
return ops_false;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ops_encrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_,
|
||||
size_t count)
|
||||
{
|
||||
if (!ops_is_sa_supported(crypt->algorithm))
|
||||
return -1;
|
||||
|
||||
crypt->cfb_encrypt(crypt, out_, in_, count);
|
||||
|
||||
// \todo test this number was encrypted
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t ops_decrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_,
|
||||
size_t count)
|
||||
{
|
||||
if (!ops_is_sa_supported(crypt->algorithm))
|
||||
return -1;
|
||||
|
||||
crypt->cfb_decrypt(crypt, out_, in_, count);
|
||||
|
||||
// \todo check this number was in fact decrypted
|
||||
return count;
|
||||
}
|
||||
|
||||
// EOF
|
222
openpgpsdk/src/util.c
Normal file
222
openpgpsdk/src/util.c
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/crypto.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/errors.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
/**
|
||||
* Searches the given map for the given type.
|
||||
* Returns a human-readable descriptive string if found,
|
||||
* returns NULL if not found
|
||||
*
|
||||
* It is the responsibility of the calling function to handle the
|
||||
* error case sensibly (i.e. don't just print out the return string.
|
||||
*
|
||||
*/
|
||||
static char *str_from_map_or_null(int type, ops_map_t *map)
|
||||
{
|
||||
ops_map_t *row;
|
||||
|
||||
for ( row=map; row->string != NULL; row++ )
|
||||
if (row->type == type)
|
||||
return row->string;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Print
|
||||
*
|
||||
* Searches the given map for the given type.
|
||||
* Returns a readable string if found, "Unknown" if not.
|
||||
*/
|
||||
|
||||
char *ops_str_from_map(int type, ops_map_t *map)
|
||||
{
|
||||
char *str;
|
||||
str=str_from_map_or_null(type,map);
|
||||
if (str)
|
||||
return(str);
|
||||
else
|
||||
return("Unknown");
|
||||
}
|
||||
|
||||
void hexdump(const unsigned char *src,size_t length)
|
||||
{
|
||||
while(length--)
|
||||
printf("%02X",*src++);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup HighLevel_Functions
|
||||
* \brief Initialises OpenPGP::SDK. To be called before any other OPS function.
|
||||
*
|
||||
* Initialises OpenPGP::SDK and the underlying openssl library.
|
||||
*/
|
||||
|
||||
void ops_init(void)
|
||||
{
|
||||
ops_crypto_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup HighLevel_Functions
|
||||
* \brief Closes down OpenPGP::SDK.
|
||||
*
|
||||
* Close down OpenPGP:SDK, release any resources under the control of
|
||||
* the library. No OpenPGP:SDK function other than ops_init() should
|
||||
* be called after this function.
|
||||
*/
|
||||
|
||||
void ops_finish(void)
|
||||
{
|
||||
ops_crypto_finish();
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
size_t length;
|
||||
size_t offset;
|
||||
} reader_mem_arg_t;
|
||||
|
||||
static int mem_reader(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
reader_mem_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
unsigned n;
|
||||
|
||||
OPS_USED(cbinfo);
|
||||
OPS_USED(errors);
|
||||
|
||||
if(arg->offset+length > arg->length)
|
||||
n=arg->length-arg->offset;
|
||||
else
|
||||
n=length;
|
||||
|
||||
if(n == 0)
|
||||
return 0;
|
||||
|
||||
memcpy(dest,arg->buffer+arg->offset,n);
|
||||
arg->offset+=n;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void mem_destroyer(ops_reader_info_t *rinfo)
|
||||
{ free(ops_reader_get_arg(rinfo)); }
|
||||
|
||||
// Note that its the caller's responsibility to ensure buffer continues to
|
||||
// exist
|
||||
void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer,
|
||||
size_t length)
|
||||
{
|
||||
reader_mem_arg_t *arg=malloc(sizeof *arg);
|
||||
|
||||
arg->buffer=buffer;
|
||||
arg->length=length;
|
||||
arg->offset=0;
|
||||
ops_reader_set(pinfo,mem_reader,mem_destroyer,arg);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Misc
|
||||
\brief mallocs and zeros memory
|
||||
\param n Number of bytes to be alloc-ed.
|
||||
\return Pointer to new memory.
|
||||
\note Should be freed after use with free().
|
||||
*/
|
||||
void *ops_mallocz(size_t n)
|
||||
{
|
||||
void *m=malloc(n);
|
||||
|
||||
memset(m,'\0',n);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned short sum;
|
||||
} sum16_arg_t;
|
||||
|
||||
static int sum16_reader(void *dest_,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
const unsigned char *dest=dest_;
|
||||
sum16_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
int r=ops_stacked_read(dest_,length,errors,rinfo,cbinfo);
|
||||
int n;
|
||||
|
||||
if(r < 0)
|
||||
return r;
|
||||
|
||||
for(n=0 ; n < r ; ++n)
|
||||
arg->sum=(arg->sum+dest[n])&0xffff;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sum16_destroyer(ops_reader_info_t *rinfo)
|
||||
{ free(ops_reader_get_arg(rinfo)); }
|
||||
|
||||
/**
|
||||
\ingroup Internal_Readers_Sum16
|
||||
\param pinfo Parse settings
|
||||
*/
|
||||
|
||||
void ops_reader_push_sum16(ops_parse_info_t *pinfo)
|
||||
{
|
||||
sum16_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
ops_reader_push(pinfo,sum16_reader,sum16_destroyer,arg);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Internal_Readers_Sum16
|
||||
\param pinfo Parse settings
|
||||
\return sum
|
||||
*/
|
||||
unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo)
|
||||
{
|
||||
sum16_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
|
||||
unsigned short sum=arg->sum;
|
||||
|
||||
ops_reader_pop(pinfo);
|
||||
free(arg);
|
||||
|
||||
return sum;
|
||||
}
|
746
openpgpsdk/src/validate.c
Normal file
746
openpgpsdk/src/validate.c
Normal file
@ -0,0 +1,746 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/packet-parse.h>
|
||||
#include <openpgpsdk/packet-show.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include "keyring_local.h"
|
||||
#include "parse_local.h"
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/armour.h>
|
||||
#include <openpgpsdk/signature.h>
|
||||
#include <openpgpsdk/memory.h>
|
||||
#include <openpgpsdk/validate.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
static ops_boolean_t check_binary_signature(const unsigned len,
|
||||
const unsigned char *data,
|
||||
const ops_signature_t *sig,
|
||||
const ops_public_key_t *signer __attribute__((unused)))
|
||||
{
|
||||
// Does the signed hash match the given hash?
|
||||
|
||||
int n=0;
|
||||
ops_hash_t hash;
|
||||
unsigned char hashout[OPS_MAX_HASH_SIZE];
|
||||
unsigned char trailer[6];
|
||||
unsigned int hashedlen;
|
||||
|
||||
//common_init_signature(&hash,sig);
|
||||
ops_hash_any(&hash,sig->info.hash_algorithm);
|
||||
hash.init(&hash);
|
||||
hash.add(&hash,data,len);
|
||||
switch (sig->info.version)
|
||||
{
|
||||
case OPS_V3:
|
||||
trailer[0]=sig->info.type;
|
||||
trailer[1]=sig->info.creation_time >> 24;
|
||||
trailer[2]=sig->info.creation_time >> 16;
|
||||
trailer[3]=sig->info.creation_time >> 8;
|
||||
trailer[4]=sig->info.creation_time;
|
||||
hash.add(&hash,&trailer[0],5);
|
||||
break;
|
||||
|
||||
case OPS_V4:
|
||||
hash.add(&hash,sig->info.v4_hashed_data,sig->info.v4_hashed_data_length);
|
||||
|
||||
trailer[0]=0x04; // version
|
||||
trailer[1]=0xFF;
|
||||
hashedlen=sig->info.v4_hashed_data_length;
|
||||
trailer[2]=hashedlen >> 24;
|
||||
trailer[3]=hashedlen >> 16;
|
||||
trailer[4]=hashedlen >> 8;
|
||||
trailer[5]=hashedlen;
|
||||
hash.add(&hash,&trailer[0],6);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"Invalid signature version %d\n", sig->info.version);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
n=hash.finish(&hash,hashout);
|
||||
|
||||
// return ops_false;
|
||||
return ops_check_signature(hashout,n,sig,signer);
|
||||
}
|
||||
|
||||
static int keydata_reader(void *dest,size_t length,ops_error_t **errors,
|
||||
ops_reader_info_t *rinfo,
|
||||
ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
validate_reader_arg_t *arg=ops_reader_get_arg(rinfo);
|
||||
|
||||
OPS_USED(errors);
|
||||
OPS_USED(cbinfo);
|
||||
if(arg->offset == arg->key->packets[arg->packet].length)
|
||||
{
|
||||
++arg->packet;
|
||||
arg->offset=0;
|
||||
}
|
||||
|
||||
if(arg->packet == arg->key->npackets)
|
||||
return 0;
|
||||
|
||||
// we should never be asked to cross a packet boundary in a single read
|
||||
assert(arg->key->packets[arg->packet].length >= arg->offset+length);
|
||||
|
||||
memcpy(dest,&arg->key->packets[arg->packet].raw[arg->offset],length);
|
||||
arg->offset+=length;
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static void free_signature_info(ops_signature_info_t *sig)
|
||||
{
|
||||
free (sig->v4_hashed_data);
|
||||
free (sig);
|
||||
}
|
||||
|
||||
static void copy_signature_info(ops_signature_info_t* dst, const ops_signature_info_t* src)
|
||||
{
|
||||
memcpy(dst,src,sizeof *src);
|
||||
dst->v4_hashed_data=ops_mallocz(src->v4_hashed_data_length);
|
||||
memcpy(dst->v4_hashed_data,src->v4_hashed_data,src->v4_hashed_data_length);
|
||||
}
|
||||
|
||||
static void add_sig_to_valid_list(ops_validate_result_t * result, const ops_signature_info_t* sig)
|
||||
{
|
||||
size_t newsize;
|
||||
size_t start;
|
||||
|
||||
// increment count
|
||||
++result->valid_count;
|
||||
|
||||
// increase size of array
|
||||
newsize=(sizeof *sig) * result->valid_count;
|
||||
if (!result->valid_sigs)
|
||||
result->valid_sigs=malloc(newsize);
|
||||
else
|
||||
result->valid_sigs=realloc(result->valid_sigs, newsize);
|
||||
|
||||
// copy key ptr to array
|
||||
start=(sizeof *sig) * (result->valid_count-1);
|
||||
copy_signature_info(result->valid_sigs+start,sig);
|
||||
}
|
||||
|
||||
static void add_sig_to_invalid_list(ops_validate_result_t * result, const ops_signature_info_t *sig)
|
||||
{
|
||||
size_t newsize;
|
||||
size_t start;
|
||||
|
||||
// increment count
|
||||
++result->invalid_count;
|
||||
|
||||
// increase size of array
|
||||
newsize=(sizeof *sig) * result->invalid_count;
|
||||
if (!result->invalid_sigs)
|
||||
result->invalid_sigs=malloc(newsize);
|
||||
else
|
||||
result->invalid_sigs=realloc(result->invalid_sigs, newsize);
|
||||
|
||||
// copy key ptr to array
|
||||
start=(sizeof *sig) * (result->invalid_count-1);
|
||||
copy_signature_info(result->invalid_sigs+start, sig);
|
||||
}
|
||||
|
||||
static void add_sig_to_unknown_list(ops_validate_result_t * result, const ops_signature_info_t *sig)
|
||||
{
|
||||
size_t newsize;
|
||||
size_t start;
|
||||
|
||||
// increment count
|
||||
++result->unknown_signer_count;
|
||||
|
||||
// increase size of array
|
||||
newsize=(sizeof *sig) * result->unknown_signer_count;
|
||||
if (!result->unknown_sigs)
|
||||
result->unknown_sigs=malloc(newsize);
|
||||
else
|
||||
result->unknown_sigs=realloc(result->unknown_sigs, newsize);
|
||||
|
||||
// copy key id to array
|
||||
start=OPS_KEY_ID_SIZE * (result->unknown_signer_count-1);
|
||||
copy_signature_info(result->unknown_sigs+start, sig);
|
||||
}
|
||||
|
||||
ops_parse_cb_return_t
|
||||
ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
const ops_parser_content_union_t *content=&content_->content;
|
||||
validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
|
||||
ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
|
||||
const ops_keydata_t *signer;
|
||||
ops_boolean_t valid=ops_false;
|
||||
|
||||
if (debug)
|
||||
printf("%s\n",ops_show_packet_tag(content_->tag));
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PTAG_CT_PUBLIC_KEY:
|
||||
assert(arg->pkey.version == 0);
|
||||
arg->pkey=content->public_key;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PTAG_CT_PUBLIC_SUBKEY:
|
||||
if(arg->subkey.version)
|
||||
ops_public_key_free(&arg->subkey);
|
||||
arg->subkey=content->public_key;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PTAG_CT_SECRET_KEY:
|
||||
arg->skey=content->secret_key;
|
||||
arg->pkey=arg->skey.public_key;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PTAG_CT_USER_ID:
|
||||
if(arg->user_id.user_id)
|
||||
ops_user_id_free(&arg->user_id);
|
||||
arg->user_id=content->user_id;
|
||||
arg->last_seen=ID;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PTAG_CT_USER_ATTRIBUTE:
|
||||
assert(content->user_attribute.data.len);
|
||||
printf("user attribute, length=%d\n",(int)content->user_attribute.data.len);
|
||||
if(arg->user_attribute.data.len)
|
||||
ops_user_attribute_free(&arg->user_attribute);
|
||||
arg->user_attribute=content->user_attribute;
|
||||
arg->last_seen=ATTRIBUTE;
|
||||
return OPS_KEEP_MEMORY;
|
||||
|
||||
case OPS_PTAG_CT_SIGNATURE: // V3 sigs
|
||||
case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs
|
||||
/*
|
||||
printf(" type=%02x signer_id=",content->signature.type);
|
||||
hexdump(content->signature.signer_id,
|
||||
sizeof content->signature.signer_id);
|
||||
*/
|
||||
|
||||
signer=ops_keyring_find_key_by_id(arg->keyring,
|
||||
content->signature.info.signer_id);
|
||||
if(!signer)
|
||||
{
|
||||
add_sig_to_unknown_list(arg->result, &content->signature.info);
|
||||
break;
|
||||
}
|
||||
|
||||
switch(content->signature.info.type)
|
||||
{
|
||||
case OPS_CERT_GENERIC:
|
||||
case OPS_CERT_PERSONA:
|
||||
case OPS_CERT_CASUAL:
|
||||
case OPS_CERT_POSITIVE:
|
||||
case OPS_SIG_REV_CERT:
|
||||
if(arg->last_seen == ID)
|
||||
valid=ops_check_user_id_certification_signature(&arg->pkey,
|
||||
&arg->user_id,
|
||||
&content->signature,
|
||||
ops_get_public_key_from_data(signer),
|
||||
arg->rarg->key->packets[arg->rarg->packet].raw);
|
||||
else
|
||||
valid=ops_check_user_attribute_certification_signature(&arg->pkey,
|
||||
&arg->user_attribute,
|
||||
&content->signature,
|
||||
ops_get_public_key_from_data(signer),
|
||||
arg->rarg->key->packets[arg->rarg->packet].raw);
|
||||
|
||||
break;
|
||||
|
||||
case OPS_SIG_SUBKEY:
|
||||
// XXX: we should also check that the signer is the key we are validating, I think.
|
||||
valid=ops_check_subkey_signature(&arg->pkey,&arg->subkey,
|
||||
&content->signature,
|
||||
ops_get_public_key_from_data(signer),
|
||||
arg->rarg->key->packets[arg->rarg->packet].raw);
|
||||
break;
|
||||
|
||||
case OPS_SIG_DIRECT:
|
||||
valid=ops_check_direct_signature(&arg->pkey,&content->signature,
|
||||
ops_get_public_key_from_data(signer),
|
||||
arg->rarg->key->packets[arg->rarg->packet].raw);
|
||||
break;
|
||||
|
||||
case OPS_SIG_STANDALONE:
|
||||
case OPS_SIG_PRIMARY:
|
||||
case OPS_SIG_REV_KEY:
|
||||
case OPS_SIG_REV_SUBKEY:
|
||||
case OPS_SIG_TIMESTAMP:
|
||||
case OPS_SIG_3RD_PARTY:
|
||||
OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
|
||||
"Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type);
|
||||
break;
|
||||
|
||||
default:
|
||||
OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
|
||||
"Unexpected signature type 0x%02x\n", content->signature.info.type);
|
||||
}
|
||||
|
||||
if(valid)
|
||||
{
|
||||
// printf(" validated\n");
|
||||
//++arg->result->valid_count;
|
||||
add_sig_to_valid_list(arg->result, &content->signature.info);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature");
|
||||
// printf(" BAD SIGNATURE\n");
|
||||
// ++arg->result->invalid_count;
|
||||
add_sig_to_invalid_list(arg->result, &content->signature.info);
|
||||
}
|
||||
break;
|
||||
|
||||
// ignore these
|
||||
case OPS_PARSER_PTAG:
|
||||
case OPS_PTAG_CT_SIGNATURE_HEADER:
|
||||
case OPS_PARSER_PACKET_END:
|
||||
break;
|
||||
|
||||
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
|
||||
if (arg->cb_get_passphrase)
|
||||
{
|
||||
return arg->cb_get_passphrase(content_,cbinfo);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"unexpected tag=0x%x\n",content_->tag);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
ops_parse_cb_return_t
|
||||
validate_data_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
|
||||
{
|
||||
const ops_parser_content_union_t *content=&content_->content;
|
||||
validate_data_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
|
||||
ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
|
||||
const ops_keydata_t *signer;
|
||||
ops_boolean_t valid=ops_false;
|
||||
ops_memory_t* mem=NULL;
|
||||
|
||||
if (debug)
|
||||
printf("%s\n",ops_show_packet_tag(content_->tag));
|
||||
|
||||
switch(content_->tag)
|
||||
{
|
||||
case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
|
||||
// ignore - this gives us the "Armor Header" line "Hash: SHA1" or similar
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_LITERAL_DATA_HEADER:
|
||||
// ignore
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_LITERAL_DATA_BODY:
|
||||
arg->data.literal_data_body=content->literal_data_body;
|
||||
arg->use=LITERAL_DATA;
|
||||
return OPS_KEEP_MEMORY;
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
|
||||
arg->data.signed_cleartext_body=content->signed_cleartext_body;
|
||||
arg->use=SIGNED_CLEARTEXT;
|
||||
return OPS_KEEP_MEMORY;
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
|
||||
// this gives us an ops_hash_t struct
|
||||
break;
|
||||
|
||||
case OPS_PTAG_CT_SIGNATURE: // V3 sigs
|
||||
case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs
|
||||
|
||||
if (debug)
|
||||
{
|
||||
printf("\n*** hashed data:\n");
|
||||
unsigned int zzz=0;
|
||||
for (zzz=0; zzz<content->signature.info.v4_hashed_data_length; zzz++)
|
||||
printf("0x%02x ", content->signature.info.v4_hashed_data[zzz]);
|
||||
printf("\n");
|
||||
printf(" type=%02x signer_id=",content->signature.info.type);
|
||||
hexdump(content->signature.info.signer_id,
|
||||
sizeof content->signature.info.signer_id);
|
||||
}
|
||||
|
||||
signer=ops_keyring_find_key_by_id(arg->keyring,
|
||||
content->signature.info.signer_id);
|
||||
if(!signer)
|
||||
{
|
||||
OPS_ERROR(errors,OPS_E_V_UNKNOWN_SIGNER,"Unknown Signer");
|
||||
add_sig_to_unknown_list(arg->result, &content->signature.info);
|
||||
break;
|
||||
}
|
||||
|
||||
mem=ops_memory_new();
|
||||
ops_memory_init(mem,128);
|
||||
|
||||
switch(content->signature.info.type)
|
||||
{
|
||||
case OPS_SIG_BINARY:
|
||||
case OPS_SIG_TEXT:
|
||||
switch(arg->use)
|
||||
{
|
||||
case LITERAL_DATA:
|
||||
ops_memory_add(mem,
|
||||
arg->data.literal_data_body.data,
|
||||
arg->data.literal_data_body.length);
|
||||
break;
|
||||
|
||||
case SIGNED_CLEARTEXT:
|
||||
ops_memory_add(mem,
|
||||
arg->data.signed_cleartext_body.data,
|
||||
arg->data.signed_cleartext_body.length);
|
||||
break;
|
||||
|
||||
default:
|
||||
OPS_ERROR_1(errors,OPS_E_UNIMPLEMENTED,"Unimplemented Sig Use %d", arg->use);
|
||||
printf(" Unimplemented Sig Use %d\n", arg->use);
|
||||
break;
|
||||
}
|
||||
|
||||
valid=check_binary_signature(ops_memory_get_length(mem),
|
||||
ops_memory_get_data(mem),
|
||||
&content->signature,
|
||||
ops_get_public_key_from_data(signer));
|
||||
break;
|
||||
|
||||
default:
|
||||
OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
|
||||
"Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type);
|
||||
break;
|
||||
|
||||
}
|
||||
ops_memory_free(mem);
|
||||
|
||||
if(valid)
|
||||
{
|
||||
add_sig_to_valid_list(arg->result, &content->signature.info);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature");
|
||||
add_sig_to_invalid_list(arg->result, &content->signature.info);
|
||||
}
|
||||
break;
|
||||
|
||||
// ignore these
|
||||
case OPS_PARSER_PTAG:
|
||||
case OPS_PTAG_CT_SIGNATURE_HEADER:
|
||||
case OPS_PTAG_CT_ARMOUR_HEADER:
|
||||
case OPS_PTAG_CT_ARMOUR_TRAILER:
|
||||
case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
|
||||
case OPS_PARSER_PACKET_END:
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr,"unexpected tag=0x%x\n",content_->tag);
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return OPS_RELEASE_MEMORY;
|
||||
}
|
||||
|
||||
static void keydata_destroyer(ops_reader_info_t *rinfo)
|
||||
{ free(ops_reader_get_arg(rinfo)); }
|
||||
|
||||
void ops_keydata_reader_set(ops_parse_info_t *pinfo,const ops_keydata_t *key)
|
||||
{
|
||||
validate_reader_arg_t *arg=malloc(sizeof *arg);
|
||||
|
||||
memset(arg,'\0',sizeof *arg);
|
||||
|
||||
arg->key=key;
|
||||
arg->packet=0;
|
||||
arg->offset=0;
|
||||
|
||||
ops_reader_set(pinfo,keydata_reader,keydata_destroyer,arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup HighLevel_Verify
|
||||
* \brief Indicicates whether any errors were found
|
||||
* \param result Validation result to check
|
||||
* \return ops_false if any invalid signatures or unknown signers or no valid signatures; else ops_true
|
||||
*/
|
||||
ops_boolean_t validate_result_status(ops_validate_result_t* result)
|
||||
{
|
||||
if (result->invalid_count || result->unknown_signer_count || !result->valid_count)
|
||||
return ops_false;
|
||||
else
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup HighLevel_Verify
|
||||
* \brief Validate all signatures on a single key against the given keyring
|
||||
* \param result Where to put the result
|
||||
* \param key Key to validate
|
||||
* \param keyring Keyring to use for validation
|
||||
* \param cb_get_passphrase Callback to use to get passphrase
|
||||
* \return ops_true if all signatures OK; else ops_false
|
||||
* \note It is the caller's responsiblity to free result after use.
|
||||
* \sa ops_validate_result_free()
|
||||
|
||||
Example Code:
|
||||
\code
|
||||
void example(const ops_keydata_t* key, const ops_keyring_t *keyring)
|
||||
{
|
||||
ops_validate_result_t *result=NULL;
|
||||
if (ops_validate_key_signatures(result, key, keyring, callback_cmd_get_passphrase_from_cmdline)==ops_true)
|
||||
printf("OK");
|
||||
else
|
||||
printf("ERR");
|
||||
printf("valid=%d, invalid=%d, unknown=%d\n",
|
||||
result->valid_count,
|
||||
result->invalid_count,
|
||||
result->unknown_signer_count);
|
||||
ops_validate_result_free(result);
|
||||
}
|
||||
|
||||
\endcode
|
||||
*/
|
||||
ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,const ops_keydata_t *key,
|
||||
const ops_keyring_t *keyring,
|
||||
ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *)
|
||||
)
|
||||
{
|
||||
ops_parse_info_t *pinfo;
|
||||
validate_key_cb_arg_t carg;
|
||||
|
||||
memset(&carg,'\0',sizeof carg);
|
||||
carg.result=result;
|
||||
carg.cb_get_passphrase=cb_get_passphrase;
|
||||
|
||||
pinfo=ops_parse_info_new();
|
||||
// ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED);
|
||||
|
||||
carg.keyring=keyring;
|
||||
|
||||
ops_parse_cb_set(pinfo,ops_validate_key_cb,&carg);
|
||||
pinfo->rinfo.accumulate=ops_true;
|
||||
ops_keydata_reader_set(pinfo,key);
|
||||
|
||||
// Note: Coverity incorrectly reports an error that carg.rarg
|
||||
// is never used.
|
||||
carg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
|
||||
|
||||
ops_parse(pinfo);
|
||||
|
||||
ops_public_key_free(&carg.pkey);
|
||||
if(carg.subkey.version)
|
||||
ops_public_key_free(&carg.subkey);
|
||||
ops_user_id_free(&carg.user_id);
|
||||
ops_user_attribute_free(&carg.user_attribute);
|
||||
|
||||
ops_parse_info_delete(pinfo);
|
||||
|
||||
if (result->invalid_count || result->unknown_signer_count || !result->valid_count)
|
||||
return ops_false;
|
||||
else
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
\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 ops_validate_result_free()
|
||||
*/
|
||||
ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result,
|
||||
const ops_keyring_t *ring,
|
||||
ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *)
|
||||
)
|
||||
{
|
||||
int n;
|
||||
|
||||
memset(result,'\0',sizeof *result);
|
||||
for(n=0 ; n < ring->nkeys ; ++n)
|
||||
ops_validate_key_signatures(result,&ring->keys[n],ring, cb_get_passphrase);
|
||||
return validate_result_status(result);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Verify
|
||||
\brief Frees validation result and associated memory
|
||||
\param result Struct to be freed
|
||||
\note Must be called after validation functions
|
||||
*/
|
||||
void ops_validate_result_free(ops_validate_result_t *result)
|
||||
{
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
if (result->valid_sigs)
|
||||
free_signature_info(result->valid_sigs);
|
||||
if (result->invalid_sigs)
|
||||
free_signature_info(result->invalid_sigs);
|
||||
if (result->unknown_sigs)
|
||||
free_signature_info(result->unknown_sigs);
|
||||
|
||||
free(result);
|
||||
result=NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Verify
|
||||
\brief Verifies the signatures in a signed file
|
||||
\param result Where to put the result
|
||||
\param filename Name of file to be validated
|
||||
\param armoured Treat file as armoured, if set
|
||||
\param keyring Keyring to use
|
||||
\return ops_true if signatures validate successfully; ops_false if signatures fail or there are no signatures
|
||||
\note After verification, result holds the details of all keys which
|
||||
have passed, failed and not been recognised.
|
||||
\note It is the caller's responsiblity to call ops_validate_result_free(result) after use.
|
||||
|
||||
Example code:
|
||||
\code
|
||||
void example(const char* filename, const int armoured, const ops_keyring_t* keyring)
|
||||
{
|
||||
ops_validate_result_t* result=ops_mallocz(sizeof *result);
|
||||
|
||||
if (ops_validate_file(result, filename, armoured, keyring)==ops_true)
|
||||
{
|
||||
printf("OK");
|
||||
// look at result for details of keys with good signatures
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("ERR");
|
||||
// look at result for details of failed signatures or unknown signers
|
||||
}
|
||||
|
||||
ops_validate_result_free(result);
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
ops_boolean_t ops_validate_file(ops_validate_result_t *result, const char* filename, const int armoured, const ops_keyring_t* keyring)
|
||||
{
|
||||
ops_parse_info_t *pinfo=NULL;
|
||||
validate_data_cb_arg_t validate_arg;
|
||||
|
||||
int fd=0;
|
||||
|
||||
//
|
||||
fd=ops_setup_file_read(&pinfo, filename, &validate_arg, validate_data_cb, ops_true);
|
||||
if (fd < 0)
|
||||
return ops_false;
|
||||
|
||||
// Set verification reader and handling options
|
||||
|
||||
memset(&validate_arg,'\0',sizeof validate_arg);
|
||||
validate_arg.result=result;
|
||||
validate_arg.keyring=keyring;
|
||||
// Note: Coverity incorrectly reports an error that carg.rarg
|
||||
// is never used.
|
||||
validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
|
||||
|
||||
if (armoured)
|
||||
ops_reader_push_dearmour(pinfo);
|
||||
|
||||
// Do the verification
|
||||
|
||||
ops_parse(pinfo);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
printf("valid=%d, invalid=%d, unknown=%d\n",
|
||||
result->valid_count,
|
||||
result->invalid_count,
|
||||
result->unknown_signer_count);
|
||||
}
|
||||
|
||||
// Tidy up
|
||||
if (armoured)
|
||||
ops_reader_pop_dearmour(pinfo);
|
||||
ops_teardown_file_read(pinfo, fd);
|
||||
|
||||
return validate_result_status(result);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup HighLevel_Verify
|
||||
\brief Verifies the signatures in a ops_memory_t struct
|
||||
\param result Where to put the result
|
||||
\param mem Memory to be validated
|
||||
\param armoured Treat data as armoured, if set
|
||||
\param keyring Keyring to use
|
||||
\return ops_true if signature validates successfully; ops_false if not
|
||||
\note After verification, result holds the details of all keys which
|
||||
have passed, failed and not been recognised.
|
||||
\note It is the caller's responsiblity to call ops_validate_result_free(result) after use.
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring)
|
||||
{
|
||||
ops_parse_info_t *pinfo=NULL;
|
||||
validate_data_cb_arg_t validate_arg;
|
||||
|
||||
//
|
||||
ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true);
|
||||
|
||||
// Set verification reader and handling options
|
||||
|
||||
memset(&validate_arg,'\0',sizeof validate_arg);
|
||||
validate_arg.result=result;
|
||||
validate_arg.keyring=keyring;
|
||||
// Note: Coverity incorrectly reports an error that carg.rarg
|
||||
// is never used.
|
||||
validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
|
||||
|
||||
if (armoured)
|
||||
ops_reader_push_dearmour(pinfo);
|
||||
|
||||
// Do the verification
|
||||
|
||||
ops_parse(pinfo);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
printf("valid=%d, invalid=%d, unknown=%d\n",
|
||||
result->valid_count,
|
||||
result->invalid_count,
|
||||
result->unknown_signer_count);
|
||||
}
|
||||
|
||||
// Tidy up
|
||||
if (armoured)
|
||||
ops_reader_pop_dearmour(pinfo);
|
||||
ops_teardown_memory_read(pinfo, mem);
|
||||
|
||||
return validate_result_status(result);
|
||||
}
|
||||
|
||||
// eof
|
331
openpgpsdk/src/writer.c
Normal file
331
openpgpsdk/src/writer.c
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* 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
|
||||
* This file contains the base functions used by the writers.
|
||||
*/
|
||||
|
||||
#include <openssl/cast.h>
|
||||
|
||||
#include <openpgpsdk/armour.h>
|
||||
#include <openpgpsdk/writer.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/memory.h>
|
||||
#include <openpgpsdk/random.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
#include "keyring_local.h"
|
||||
#include <openpgpsdk/packet.h>
|
||||
#include <openpgpsdk/util.h>
|
||||
#include <openpgpsdk/std_print.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
//static int debug=0;
|
||||
|
||||
/*
|
||||
* return true if OK, otherwise false
|
||||
*/
|
||||
static ops_boolean_t base_write(const void *src,unsigned length,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
return info->winfo.writer(src,length,&info->errors,&info->winfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritePackets
|
||||
*
|
||||
* \param src
|
||||
* \param length
|
||||
* \param info
|
||||
* \return 1 if OK, otherwise 0
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_write(const void *src,unsigned length,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
return base_write(src,length,info);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritePackets
|
||||
* \param n
|
||||
* \param length
|
||||
* \param info
|
||||
* \return ops_true if OK, otherwise ops_false
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_write_scalar(unsigned n,unsigned length,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
while(length-- > 0)
|
||||
{
|
||||
unsigned char c[1];
|
||||
|
||||
c[0]=n >> (length*8);
|
||||
if(!base_write(c,1,info))
|
||||
return ops_false;
|
||||
}
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritePackets
|
||||
* \param bn
|
||||
* \param info
|
||||
* \return 1 if OK, otherwise 0
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *info)
|
||||
{
|
||||
unsigned char buf[8192];
|
||||
int bits=BN_num_bits(bn);
|
||||
|
||||
assert(bits <= 65535);
|
||||
BN_bn2bin(bn,buf);
|
||||
return ops_write_scalar(bits,2,info)
|
||||
&& ops_write(buf,(bits+7)/8,info);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritePackets
|
||||
* \param tag
|
||||
* \param info
|
||||
* \return 1 if OK, otherwise 0
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *info)
|
||||
{
|
||||
unsigned char c[1];
|
||||
|
||||
c[0]=tag|OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT;
|
||||
|
||||
return base_write(c,1,info);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritePackets
|
||||
* \param length
|
||||
* \param info
|
||||
* \return 1 if OK, otherwise 0
|
||||
*/
|
||||
|
||||
ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *info)
|
||||
{
|
||||
unsigned char c[2];
|
||||
|
||||
if(length < 192)
|
||||
{
|
||||
c[0]=length;
|
||||
return base_write(c,1,info);
|
||||
}
|
||||
else if(length < 8384)
|
||||
{
|
||||
c[0]=((length-192) >> 8)+192;
|
||||
c[1]=(length-192)%256;
|
||||
return base_write(c,2,info);
|
||||
}
|
||||
return ops_write_scalar(0xff,1,info) && ops_write_scalar(length,4,info);
|
||||
}
|
||||
|
||||
/* Note that we finalise from the top down, so we don't use writers below
|
||||
* that have already been finalised
|
||||
*/
|
||||
ops_boolean_t writer_info_finalise(ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
ops_boolean_t ret=ops_true;
|
||||
|
||||
if(winfo->finaliser)
|
||||
{
|
||||
ret=winfo->finaliser(errors,winfo);
|
||||
winfo->finaliser=NULL;
|
||||
}
|
||||
if(winfo->next && !writer_info_finalise(errors,winfo->next))
|
||||
{
|
||||
winfo->finaliser=NULL;
|
||||
return ops_false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void writer_info_delete(ops_writer_info_t *winfo)
|
||||
{
|
||||
// we should have finalised before deleting
|
||||
assert(!winfo->finaliser);
|
||||
if(winfo->next)
|
||||
{
|
||||
writer_info_delete(winfo->next);
|
||||
free(winfo->next);
|
||||
winfo->next=NULL;
|
||||
}
|
||||
if(winfo->destroyer)
|
||||
{
|
||||
winfo->destroyer(winfo);
|
||||
winfo->destroyer=NULL;
|
||||
}
|
||||
winfo->writer=NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* Set a writer in info. There should not be another writer set.
|
||||
*
|
||||
* \param info The info structure
|
||||
* \param writer
|
||||
* \param finaliser
|
||||
* \param destroyer
|
||||
* \param arg The argument for the writer and destroyer
|
||||
*/
|
||||
void ops_writer_set(ops_create_info_t *info,
|
||||
ops_writer_t *writer,
|
||||
ops_writer_finaliser_t *finaliser,
|
||||
ops_writer_destroyer_t *destroyer,
|
||||
void *arg)
|
||||
{
|
||||
assert(!info->winfo.writer);
|
||||
info->winfo.writer=writer;
|
||||
info->winfo.finaliser=finaliser;
|
||||
info->winfo.destroyer=destroyer;
|
||||
info->winfo.arg=arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* Push a writer in info. There must already be another writer set.
|
||||
*
|
||||
* \param info The info structure
|
||||
* \param writer
|
||||
* \param finaliser
|
||||
* \param destroyer
|
||||
* \param arg The argument for the writer and destroyer
|
||||
*/
|
||||
void ops_writer_push(ops_create_info_t *info,
|
||||
ops_writer_t *writer,
|
||||
ops_writer_finaliser_t *finaliser,
|
||||
ops_writer_destroyer_t *destroyer,
|
||||
void *arg)
|
||||
{
|
||||
ops_writer_info_t *copy=ops_mallocz(sizeof *copy);
|
||||
|
||||
assert(info->winfo.writer);
|
||||
*copy=info->winfo;
|
||||
info->winfo.next=copy;
|
||||
|
||||
info->winfo.writer=writer;
|
||||
info->winfo.finaliser=finaliser;
|
||||
info->winfo.destroyer=destroyer;
|
||||
info->winfo.arg=arg;
|
||||
}
|
||||
|
||||
void ops_writer_pop(ops_create_info_t *info)
|
||||
{
|
||||
ops_writer_info_t *next;
|
||||
|
||||
// Make sure the finaliser has been called.
|
||||
assert(!info->winfo.finaliser);
|
||||
// Make sure this is a stacked writer
|
||||
assert(info->winfo.next);
|
||||
if(info->winfo.destroyer)
|
||||
info->winfo.destroyer(&info->winfo);
|
||||
|
||||
next=info->winfo.next;
|
||||
info->winfo=*next;
|
||||
|
||||
free(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* Close the writer currently set in info.
|
||||
*
|
||||
* \param info The info structure
|
||||
*/
|
||||
ops_boolean_t ops_writer_close(ops_create_info_t *info)
|
||||
{
|
||||
ops_boolean_t ret=writer_info_finalise(&info->errors,&info->winfo);
|
||||
|
||||
writer_info_delete(&info->winfo);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* Get the arg supplied to ops_create_info_set_writer().
|
||||
*
|
||||
* \param winfo The writer_info structure
|
||||
* \return The arg
|
||||
*/
|
||||
void *ops_writer_get_arg(ops_writer_info_t *winfo)
|
||||
{ return winfo->arg; }
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* Write to the next writer down in the stack.
|
||||
*
|
||||
* \param src The data to write.
|
||||
* \param length The length of src.
|
||||
* \param errors A place to store errors.
|
||||
* \param winfo The writer_info structure.
|
||||
* \return Success - if ops_false, then errors should contain the error.
|
||||
*/
|
||||
ops_boolean_t ops_stacked_write(const void *src,unsigned length,
|
||||
ops_error_t **errors,ops_writer_info_t *winfo)
|
||||
{
|
||||
return winfo->next->writer(src,length,errors,winfo->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* Free the arg. Many writers just have a malloc()ed lump of storage, this
|
||||
* function releases it.
|
||||
*
|
||||
* \param winfo the info structure.
|
||||
*/
|
||||
void ops_writer_generic_destroyer(ops_writer_info_t *winfo)
|
||||
{ free(ops_writer_get_arg(winfo)); }
|
||||
|
||||
/**
|
||||
* \ingroup Core_Writers
|
||||
*
|
||||
* A writer that just writes to the next one down. Useful for when you
|
||||
* want to insert just a finaliser into the stack.
|
||||
*/
|
||||
ops_boolean_t ops_writer_passthrough(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{ return ops_stacked_write(src,length,errors,winfo); }
|
||||
|
||||
|
||||
// EOF
|
488
openpgpsdk/src/writer_armour.c
Normal file
488
openpgpsdk/src/writer_armour.c
Normal file
@ -0,0 +1,488 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openpgpsdk/armour.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/signature.h>
|
||||
#include <openpgpsdk/version.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
/**
|
||||
* \struct dash_escaped_arg_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ops_boolean_t seen_nl:1;
|
||||
ops_boolean_t seen_cr:1;
|
||||
ops_create_signature_t *sig;
|
||||
ops_memory_t *trailing;
|
||||
} dash_escaped_arg_t;
|
||||
|
||||
static ops_boolean_t dash_escaped_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
dash_escaped_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
unsigned n;
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"dash_escaped_writer writing %d:\n", length);
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
fprintf(stderr,"0x%02x ", src[i]);
|
||||
if (!((i+1) % 16))
|
||||
fprintf(stderr,"\n");
|
||||
else if (!((i+1) % 8))
|
||||
fprintf(stderr," ");
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
// XXX: make this efficient
|
||||
for(n=0 ; n < length ; ++n)
|
||||
{
|
||||
unsigned l;
|
||||
|
||||
if(arg->seen_nl)
|
||||
{
|
||||
if(src[n] == '-' && !ops_stacked_write("- ",2,errors,winfo))
|
||||
return ops_false;
|
||||
arg->seen_nl=ops_false;
|
||||
}
|
||||
|
||||
arg->seen_nl=src[n] == '\n';
|
||||
|
||||
if(arg->seen_nl && !arg->seen_cr)
|
||||
{
|
||||
if(!ops_stacked_write("\r",1,errors,winfo))
|
||||
return ops_false;
|
||||
ops_signature_add_data(arg->sig,"\r",1);
|
||||
}
|
||||
|
||||
arg->seen_cr=src[n] == '\r';
|
||||
|
||||
if(!ops_stacked_write(&src[n],1,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
/* trailing whitespace isn't included in the signature */
|
||||
if(src[n] == ' ' || src[n] == '\t')
|
||||
ops_memory_add(arg->trailing,&src[n],1);
|
||||
else
|
||||
{
|
||||
if((l=ops_memory_get_length(arg->trailing)))
|
||||
{
|
||||
if(!arg->seen_nl && !arg->seen_cr)
|
||||
ops_signature_add_data(arg->sig,
|
||||
ops_memory_get_data(arg->trailing),
|
||||
l);
|
||||
ops_memory_clear(arg->trailing);
|
||||
}
|
||||
ops_signature_add_data(arg->sig,&src[n],1);
|
||||
}
|
||||
}
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \param winfo
|
||||
*/
|
||||
static void dash_escaped_destroyer(ops_writer_info_t *winfo)
|
||||
{
|
||||
dash_escaped_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
|
||||
ops_memory_free(arg->trailing);
|
||||
free(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritersNext
|
||||
* \brief Push Clearsigned Writer onto stack
|
||||
* \param info
|
||||
* \param sig
|
||||
*/
|
||||
ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
|
||||
ops_create_signature_t *sig)
|
||||
{
|
||||
static char header[]="-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: ";
|
||||
const char *hash=ops_text_from_hash(ops_signature_get_hash(sig));
|
||||
dash_escaped_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
ops_boolean_t rtn;
|
||||
|
||||
rtn= ( ops_write(header,sizeof header-1,info)
|
||||
&& ops_write(hash,strlen(hash),info)
|
||||
&& ops_write("\r\n\r\n",4,info));
|
||||
|
||||
if (rtn==ops_false)
|
||||
{
|
||||
OPS_ERROR(&info->errors, OPS_E_W, "Error pushing clearsigned header");
|
||||
free(arg);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
arg->seen_nl=ops_true;
|
||||
arg->sig=sig;
|
||||
arg->trailing=ops_memory_new();
|
||||
ops_writer_push(info,dash_escaped_writer,NULL,dash_escaped_destroyer,arg);
|
||||
return rtn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \struct base64_arg_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned pos;
|
||||
unsigned char t;
|
||||
unsigned checksum;
|
||||
} base64_arg_t;
|
||||
|
||||
static char b64map[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static ops_boolean_t base64_writer(const unsigned char *src,
|
||||
unsigned length,ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
base64_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
unsigned n;
|
||||
|
||||
for(n=0 ; n < length ; )
|
||||
{
|
||||
arg->checksum=ops_crc24(arg->checksum,src[n]);
|
||||
if(arg->pos == 0)
|
||||
{
|
||||
/* XXXXXX00 00000000 00000000 */
|
||||
if(!ops_stacked_write(&b64map[src[n] >> 2],1,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
/* 000000XX xxxx0000 00000000 */
|
||||
arg->t=(src[n++]&3) << 4;
|
||||
arg->pos=1;
|
||||
}
|
||||
else if(arg->pos == 1)
|
||||
{
|
||||
/* 000000xx XXXX0000 00000000 */
|
||||
arg->t+=src[n] >> 4;
|
||||
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
/* 00000000 0000XXXX xx000000 */
|
||||
arg->t=(src[n++]&0xf) << 2;
|
||||
arg->pos=2;
|
||||
}
|
||||
else if(arg->pos == 2)
|
||||
{
|
||||
/* 00000000 0000xxxx XX000000 */
|
||||
arg->t+=src[n] >> 6;
|
||||
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
/* 00000000 00000000 00XXXXXX */
|
||||
if(!ops_stacked_write(&b64map[src[n++]&0x3f],1,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
arg->pos=0;
|
||||
}
|
||||
}
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static ops_boolean_t signature_finaliser(ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
base64_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
static char trailer[]="\r\n-----END PGP SIGNATURE-----\r\n";
|
||||
unsigned char c[3];
|
||||
|
||||
if(arg->pos)
|
||||
{
|
||||
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
|
||||
return ops_false;
|
||||
if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo))
|
||||
return ops_false;
|
||||
if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo))
|
||||
return ops_false;
|
||||
}
|
||||
/* Ready for the checksum */
|
||||
if(!ops_stacked_write("\r\n=",3,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
arg->pos=0; /* get ready to write the checksum */
|
||||
|
||||
c[0]=arg->checksum >> 16;
|
||||
c[1]=arg->checksum >> 8;
|
||||
c[2]=arg->checksum;
|
||||
/* push the checksum through our own writer */
|
||||
if(!base64_writer(c,3,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* \struct linebreak_arg_t
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned pos;
|
||||
} linebreak_arg_t;
|
||||
|
||||
#define BREAKPOS 76
|
||||
|
||||
static ops_boolean_t linebreak_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
linebreak_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
unsigned n;
|
||||
|
||||
for(n=0 ; n < length ; ++n,++arg->pos)
|
||||
{
|
||||
if(src[n] == '\r' || src[n] == '\n')
|
||||
arg->pos=0;
|
||||
|
||||
if(arg->pos == BREAKPOS)
|
||||
{
|
||||
if(!ops_stacked_write("\r\n",2,errors,winfo))
|
||||
return ops_false;
|
||||
arg->pos=0;
|
||||
}
|
||||
if(!ops_stacked_write(&src[n],1,errors,winfo))
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritersNext
|
||||
* \brief Push armoured signature on stack
|
||||
* \param info
|
||||
*/
|
||||
ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info)
|
||||
{
|
||||
static char header[]="\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: "
|
||||
OPS_VERSION_STRING "\r\n\r\n";
|
||||
base64_arg_t *base64;
|
||||
|
||||
ops_writer_pop(info);
|
||||
if (ops_write(header,sizeof header-1,info)==ops_false)
|
||||
{
|
||||
OPS_ERROR(&info->errors, OPS_E_W, "Error switching to armoured signature");
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer,
|
||||
ops_mallocz(sizeof(linebreak_arg_t)));
|
||||
|
||||
base64=ops_mallocz(sizeof *base64);
|
||||
if (!base64)
|
||||
{
|
||||
OPS_MEMORY_ERROR(&info->errors);
|
||||
return ops_false;
|
||||
}
|
||||
base64->checksum=CRC24_INIT;
|
||||
ops_writer_push(info,base64_writer,signature_finaliser,
|
||||
ops_writer_generic_destroyer,base64);
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static ops_boolean_t armoured_message_finaliser(ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
// TODO: This is same as signature_finaliser apart from trailer.
|
||||
base64_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
static char trailer[]="\r\n-----END PGP MESSAGE-----\r\n";
|
||||
unsigned char c[3];
|
||||
|
||||
if(arg->pos)
|
||||
{
|
||||
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
|
||||
return ops_false;
|
||||
if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo))
|
||||
return ops_false;
|
||||
if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo))
|
||||
return ops_false;
|
||||
}
|
||||
/* Ready for the checksum */
|
||||
if(!ops_stacked_write("\r\n=",3,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
arg->pos=0; /* get ready to write the checksum */
|
||||
|
||||
c[0]=arg->checksum >> 16;
|
||||
c[1]=arg->checksum >> 8;
|
||||
c[2]=arg->checksum;
|
||||
/* push the checksum through our own writer */
|
||||
if(!base64_writer(c,3,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_WritersNext
|
||||
\brief Write a PGP MESSAGE
|
||||
\todo replace with generic function
|
||||
*/
|
||||
void ops_writer_push_armoured_message(ops_create_info_t *info)
|
||||
// ops_create_signature_t *sig)
|
||||
{
|
||||
static char header[]="-----BEGIN PGP MESSAGE-----\r\n";
|
||||
|
||||
base64_arg_t *base64;
|
||||
|
||||
ops_write(header,sizeof header-1,info);
|
||||
ops_write("\r\n",2,info);
|
||||
base64=ops_mallocz(sizeof *base64);
|
||||
base64->checksum=CRC24_INIT;
|
||||
ops_writer_push(info,base64_writer,armoured_message_finaliser,ops_writer_generic_destroyer,base64);
|
||||
}
|
||||
|
||||
static ops_boolean_t armoured_finaliser(ops_armor_type_t type, ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
static char tail_public_key[]="\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n";
|
||||
static char tail_private_key[]="\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n";
|
||||
|
||||
char* tail=NULL;
|
||||
unsigned int sz_tail=0;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case OPS_PGP_PUBLIC_KEY_BLOCK:
|
||||
tail=tail_public_key;
|
||||
sz_tail=sizeof tail_public_key-1;
|
||||
break;
|
||||
|
||||
case OPS_PGP_PRIVATE_KEY_BLOCK:
|
||||
tail=tail_private_key;
|
||||
sz_tail=sizeof tail_private_key-1;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
base64_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
unsigned char c[3];
|
||||
|
||||
if(arg->pos)
|
||||
{
|
||||
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
|
||||
return ops_false;
|
||||
if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo))
|
||||
return ops_false;
|
||||
if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo))
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
/* Ready for the checksum */
|
||||
if(!ops_stacked_write("\r\n=",3,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
arg->pos=0; /* get ready to write the checksum */
|
||||
|
||||
c[0]=arg->checksum >> 16;
|
||||
c[1]=arg->checksum >> 8;
|
||||
c[2]=arg->checksum;
|
||||
/* push the checksum through our own writer */
|
||||
if(!base64_writer(c,3,errors,winfo))
|
||||
return ops_false;
|
||||
|
||||
return ops_stacked_write(tail,sz_tail,errors,winfo);
|
||||
}
|
||||
|
||||
static ops_boolean_t armoured_public_key_finaliser(ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK,errors,winfo);
|
||||
}
|
||||
|
||||
static ops_boolean_t armoured_private_key_finaliser(ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK,errors,winfo);
|
||||
}
|
||||
|
||||
// \todo use this for other armoured types
|
||||
/**
|
||||
\ingroup Core_WritersNext
|
||||
\brief Push Armoured Writer on stack (generic)
|
||||
*/
|
||||
void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type)
|
||||
{
|
||||
static char hdr_public_key[]="-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: "
|
||||
OPS_VERSION_STRING "\r\n\r\n";
|
||||
static char hdr_private_key[]="-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: "
|
||||
OPS_VERSION_STRING "\r\n\r\n";
|
||||
|
||||
char* header=NULL;
|
||||
unsigned int sz_hdr=0;
|
||||
ops_boolean_t (* finaliser)(ops_error_t **errors, ops_writer_info_t *winfo);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case OPS_PGP_PUBLIC_KEY_BLOCK:
|
||||
header=hdr_public_key;
|
||||
sz_hdr=sizeof hdr_public_key-1;
|
||||
finaliser=armoured_public_key_finaliser;
|
||||
break;
|
||||
|
||||
case OPS_PGP_PRIVATE_KEY_BLOCK:
|
||||
header=hdr_private_key;
|
||||
sz_hdr=sizeof hdr_private_key-1;
|
||||
finaliser=armoured_private_key_finaliser;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
ops_write(header,sz_hdr,info);
|
||||
|
||||
ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer,
|
||||
ops_mallocz(sizeof(linebreak_arg_t)));
|
||||
|
||||
base64_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
arg->checksum=CRC24_INIT;
|
||||
ops_writer_push(info,base64_writer,finaliser,ops_writer_generic_destroyer,arg);
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
122
openpgpsdk/src/writer_encrypt.c
Normal file
122
openpgpsdk/src/writer_encrypt.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_crypt_t* crypt;
|
||||
int free_crypt;
|
||||
} crypt_arg_t;
|
||||
|
||||
/*
|
||||
* This writer simply takes plaintext as input,
|
||||
* encrypts it with the given key
|
||||
* and outputs the resulting encrypted text
|
||||
*/
|
||||
static ops_boolean_t encrypt_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
|
||||
#define BUFSZ 1024 // arbitrary number
|
||||
unsigned char encbuf[BUFSZ];
|
||||
unsigned remaining=length;
|
||||
unsigned done=0;
|
||||
|
||||
crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo);
|
||||
|
||||
if (!ops_is_sa_supported(arg->crypt->algorithm))
|
||||
assert(0); // \todo proper error handling
|
||||
|
||||
while (remaining)
|
||||
{
|
||||
unsigned len = remaining < BUFSZ ? remaining : BUFSZ;
|
||||
// memcpy(buf,src,len); // \todo copy needed here?
|
||||
|
||||
arg->crypt->cfb_encrypt(arg->crypt, encbuf, src+done, len);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
int i=0;
|
||||
fprintf(stderr,"WRITING:\nunencrypted: ");
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", src[done+i]);
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr,"encrypted: ");
|
||||
for (i=0; i<16; i++)
|
||||
fprintf(stderr,"%2x ", encbuf[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
if (!ops_stacked_write(encbuf,len,errors,winfo))
|
||||
{
|
||||
if (debug)
|
||||
{ fprintf(stderr, "encrypted_writer got error from stacked write, returning\n"); }
|
||||
return ops_false;
|
||||
}
|
||||
remaining-=len;
|
||||
done+=len;
|
||||
}
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static void encrypt_destroyer (ops_writer_info_t *winfo)
|
||||
|
||||
{
|
||||
crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo);
|
||||
if (arg->free_crypt)
|
||||
free(arg->crypt);
|
||||
free (arg);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_WritersNext
|
||||
\brief Push Encrypted Writer onto stack (create SE packets)
|
||||
*/
|
||||
void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo,
|
||||
ops_crypt_t *crypt)
|
||||
{
|
||||
// Create arg to be used with this writer
|
||||
// Remember to free this in the destroyer
|
||||
|
||||
crypt_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
// Setup the arg
|
||||
|
||||
arg->crypt=crypt;
|
||||
arg->free_crypt=0;
|
||||
|
||||
// And push writer on stack
|
||||
ops_writer_push(cinfo,encrypt_writer,NULL,encrypt_destroyer,arg);
|
||||
|
||||
}
|
||||
|
||||
// EOF
|
242
openpgpsdk/src/writer_encrypt_se_ip.c
Normal file
242
openpgpsdk/src/writer_encrypt_se_ip.c
Normal file
@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/cast.h>
|
||||
|
||||
#include "keyring_local.h"
|
||||
#include <openpgpsdk/compress.h>
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/hash.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/random.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
|
||||
static int debug=0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_crypt_t* crypt;
|
||||
} encrypt_se_ip_arg_t;
|
||||
|
||||
static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo);
|
||||
static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo);
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
\ingroup Core_WritersNext
|
||||
\brief Push Encrypted SE IP Writer onto stack
|
||||
*/
|
||||
void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo,
|
||||
const ops_keydata_t *pub_key)
|
||||
{
|
||||
ops_crypt_t* encrypt;
|
||||
unsigned char *iv=NULL;
|
||||
|
||||
// Create arg to be used with this writer
|
||||
// Remember to free this in the destroyer
|
||||
encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
// Create and write encrypted PK session key
|
||||
ops_pk_session_key_t* encrypted_pk_session_key;
|
||||
encrypted_pk_session_key=ops_create_pk_session_key(pub_key);
|
||||
ops_write_pk_session_key(cinfo,encrypted_pk_session_key);
|
||||
|
||||
// Setup the arg
|
||||
encrypt=ops_mallocz(sizeof *encrypt);
|
||||
ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm);
|
||||
iv=ops_mallocz(encrypt->blocksize);
|
||||
encrypt->set_iv(encrypt, iv);
|
||||
encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]);
|
||||
ops_encrypt_init(encrypt);
|
||||
|
||||
arg->crypt=encrypt;
|
||||
|
||||
// And push writer on stack
|
||||
ops_writer_push(cinfo,encrypt_se_ip_writer,NULL,encrypt_se_ip_destroyer,arg);
|
||||
// tidy up
|
||||
free(encrypted_pk_session_key);
|
||||
free(iv);
|
||||
}
|
||||
|
||||
static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
|
||||
ops_boolean_t rtn=ops_true;
|
||||
|
||||
ops_memory_t *mem_literal;
|
||||
ops_create_info_t *cinfo_literal;
|
||||
|
||||
ops_memory_t *mem_compressed;
|
||||
ops_create_info_t *cinfo_compressed;
|
||||
|
||||
ops_memory_t *my_mem;
|
||||
ops_create_info_t *my_cinfo;
|
||||
|
||||
const unsigned int bufsz=128; // initial value; gets expanded as necessary
|
||||
ops_setup_memory_write(&cinfo_literal,&mem_literal,bufsz);
|
||||
ops_setup_memory_write(&cinfo_compressed,&mem_compressed,bufsz);
|
||||
ops_setup_memory_write(&my_cinfo,&my_mem,bufsz);
|
||||
|
||||
// create literal data packet from source data
|
||||
ops_write_literal_data_from_buf(src, length, OPS_LDT_BINARY, cinfo_literal);
|
||||
assert(ops_memory_get_length(mem_literal)>length);
|
||||
|
||||
// create compressed packet from literal data packet
|
||||
ops_write_compressed(ops_memory_get_data(mem_literal),
|
||||
ops_memory_get_length(mem_literal),
|
||||
cinfo_compressed);
|
||||
|
||||
// create SE IP packet set from this compressed literal data
|
||||
ops_write_se_ip_pktset(ops_memory_get_data(mem_compressed),
|
||||
ops_memory_get_length(mem_compressed),
|
||||
arg->crypt, my_cinfo);
|
||||
assert(ops_memory_get_length(my_mem)>ops_memory_get_length(mem_compressed));
|
||||
|
||||
// now write memory to next writer
|
||||
rtn=ops_stacked_write(ops_memory_get_data(my_mem),
|
||||
ops_memory_get_length(my_mem),
|
||||
errors, winfo);
|
||||
|
||||
ops_memory_free(my_mem);
|
||||
ops_memory_free(mem_compressed);
|
||||
ops_memory_free(mem_literal);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo)
|
||||
|
||||
{
|
||||
encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
|
||||
free(arg->crypt);
|
||||
free(arg);
|
||||
}
|
||||
|
||||
ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
|
||||
const unsigned int len,
|
||||
ops_crypt_t *crypt,
|
||||
ops_create_info_t *cinfo)
|
||||
{
|
||||
unsigned char hashed[SHA_DIGEST_LENGTH];
|
||||
const size_t sz_mdc=1+1+SHA_DIGEST_LENGTH;
|
||||
|
||||
size_t sz_preamble=crypt->blocksize+2;
|
||||
unsigned char* preamble=ops_mallocz(sz_preamble);
|
||||
|
||||
size_t sz_buf=sz_preamble+len+sz_mdc;
|
||||
|
||||
ops_memory_t *mem_mdc;
|
||||
ops_create_info_t *cinfo_mdc;
|
||||
|
||||
if (!ops_write_ptag(OPS_PTAG_CT_SE_IP_DATA,cinfo)
|
||||
|| !ops_write_length(1+sz_buf,cinfo)
|
||||
|| !ops_write_scalar(SE_IP_DATA_VERSION,1,cinfo))
|
||||
{
|
||||
free (preamble);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ops_random(preamble, crypt->blocksize);
|
||||
preamble[crypt->blocksize]=preamble[crypt->blocksize-2];
|
||||
preamble[crypt->blocksize+1]=preamble[crypt->blocksize-1];
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
fprintf(stderr,"\npreamble: ");
|
||||
for (i=0; i<sz_preamble;i++)
|
||||
fprintf(stderr," 0x%02x", preamble[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
// now construct MDC packet and add to the end of the buffer
|
||||
|
||||
ops_setup_memory_write(&cinfo_mdc, &mem_mdc,sz_mdc);
|
||||
|
||||
ops_calc_mdc_hash(preamble,sz_preamble,data,len,&hashed[0]);
|
||||
|
||||
ops_write_mdc(hashed, cinfo_mdc);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
unsigned int i=0;
|
||||
size_t sz_plaintext=len;
|
||||
size_t sz_mdc=1+1+OPS_SHA1_HASH_SIZE;
|
||||
unsigned char* mdc=NULL;
|
||||
|
||||
fprintf(stderr,"\nplaintext: ");
|
||||
for (i=0; i<sz_plaintext;i++)
|
||||
fprintf(stderr," 0x%02x", data[i]);
|
||||
fprintf(stderr,"\n");
|
||||
|
||||
fprintf(stderr,"\nmdc: ");
|
||||
mdc=ops_memory_get_data(mem_mdc);
|
||||
for (i=0; i<sz_mdc;i++)
|
||||
fprintf(stderr," 0x%02x", mdc[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
// and write it out
|
||||
|
||||
ops_writer_push_encrypt_crypt(cinfo, crypt);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (debug)
|
||||
{
|
||||
fprintf(stderr,"writing %ld + %d + %ld\n", sz_preamble, len, ops_memory_get_length(mem_mdc));
|
||||
}
|
||||
#endif /*DEBUG*/
|
||||
|
||||
if (!ops_write(preamble, sz_preamble,cinfo)
|
||||
|| !ops_write(data, len, cinfo)
|
||||
|| !ops_write(ops_memory_get_data(mem_mdc), ops_memory_get_length(mem_mdc), cinfo))
|
||||
// \todo fix cleanup here and in old code functions
|
||||
return 0;
|
||||
|
||||
ops_writer_pop(cinfo);
|
||||
|
||||
// cleanup
|
||||
ops_teardown_memory_write(cinfo_mdc, mem_mdc);
|
||||
free (preamble);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// EOF
|
88
openpgpsdk/src/writer_fd.c
Normal file
88
openpgpsdk/src/writer_fd.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openpgpsdk/create.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
} writer_fd_arg_t;
|
||||
|
||||
static ops_boolean_t fd_writer(const unsigned char *src,unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
writer_fd_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
int n=write(arg->fd,src,length);
|
||||
|
||||
if(n == -1)
|
||||
{
|
||||
OPS_SYSTEM_ERROR_1(errors,OPS_E_W_WRITE_FAILED,"write",
|
||||
"file descriptor %d",arg->fd);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
if((unsigned)n != length)
|
||||
{
|
||||
OPS_ERROR_1(errors,OPS_E_W_WRITE_TOO_SHORT,
|
||||
"file descriptor %d",arg->fd);
|
||||
return ops_false;
|
||||
}
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static void fd_destroyer(ops_writer_info_t *winfo)
|
||||
{
|
||||
free(ops_writer_get_arg(winfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritersFirst
|
||||
* \brief Write to a File
|
||||
*
|
||||
* Set the writer in info to be a stock writer that writes to a file
|
||||
* descriptor. If another writer has already been set, then that is
|
||||
* first destroyed.
|
||||
*
|
||||
* \param info The info structure
|
||||
* \param fd The file descriptor
|
||||
*
|
||||
*/
|
||||
|
||||
void ops_writer_set_fd(ops_create_info_t *info,int fd)
|
||||
{
|
||||
writer_fd_arg_t *arg=malloc(sizeof *arg);
|
||||
|
||||
arg->fd=fd;
|
||||
ops_writer_set(info,fd_writer,NULL,fd_destroyer,arg);
|
||||
}
|
||||
|
||||
// EOF
|
61
openpgpsdk/src/writer_memory.c
Normal file
61
openpgpsdk/src/writer_memory.c
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
static ops_boolean_t memory_writer(const unsigned char *src,unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
ops_memory_t *mem=ops_writer_get_arg(winfo);
|
||||
|
||||
OPS_USED(errors);
|
||||
ops_memory_add(mem,src,length);
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup Core_WritersFirst
|
||||
* \brief Write to memory
|
||||
*
|
||||
* Set a memory writer.
|
||||
*
|
||||
* \param info The info structure
|
||||
* \param mem The memory structure
|
||||
* \note It is the caller's responsiblity to call ops_memory_free(mem)
|
||||
* \sa ops_memory_free()
|
||||
*/
|
||||
|
||||
void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem)
|
||||
{
|
||||
ops_writer_set(info,memory_writer,NULL,NULL,mem);
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
88
openpgpsdk/src/writer_skey_checksum.c
Normal file
88
openpgpsdk/src/writer_skey_checksum.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/create.h>
|
||||
|
||||
#include <openpgpsdk/final.h>
|
||||
|
||||
//static int debug=0;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_hash_algorithm_t hash_algorithm;
|
||||
ops_hash_t hash;
|
||||
unsigned char *hashed;
|
||||
} skey_checksum_arg_t;
|
||||
|
||||
static ops_boolean_t skey_checksum_writer(const unsigned char *src, const unsigned length, ops_error_t **errors, ops_writer_info_t *winfo)
|
||||
{
|
||||
skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
ops_boolean_t rtn=ops_true;
|
||||
|
||||
// add contents to hash
|
||||
arg->hash.add(&arg->hash, src, length);
|
||||
|
||||
// write to next stacked writer
|
||||
rtn=ops_stacked_write(src,length,errors,winfo);
|
||||
|
||||
// tidy up and return
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static ops_boolean_t skey_checksum_finaliser(ops_error_t **errors __attribute__((unused)), ops_writer_info_t *winfo)
|
||||
{
|
||||
skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
arg->hash.finish(&arg->hash, arg->hashed);
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static void skey_checksum_destroyer(ops_writer_info_t* winfo)
|
||||
{
|
||||
skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
free(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
\ingroup Core_WritersNext
|
||||
\param cinfo
|
||||
\param skey
|
||||
*/
|
||||
void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey)
|
||||
{
|
||||
// OPS_USED(info);
|
||||
// XXX: push a SHA-1 checksum writer (and change s2k to 254).
|
||||
skey_checksum_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
// configure the arg
|
||||
arg->hash_algorithm=skey->hash_algorithm;
|
||||
arg->hashed=&skey->checkhash[0];
|
||||
|
||||
// init the hash
|
||||
ops_hash_any(&arg->hash, arg->hash_algorithm);
|
||||
arg->hash.init(&arg->hash);
|
||||
|
||||
ops_writer_push(cinfo, skey_checksum_writer, skey_checksum_finaliser, skey_checksum_destroyer, arg);
|
||||
}
|
||||
|
||||
// EOF
|
412
openpgpsdk/src/writer_stream_encrypt_se_ip.c
Normal file
412
openpgpsdk/src/writer_stream_encrypt_se_ip.c
Normal file
@ -0,0 +1,412 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/cast.h>
|
||||
|
||||
#include "keyring_local.h"
|
||||
#include <openpgpsdk/create.h>
|
||||
#include <openpgpsdk/keyring.h>
|
||||
#include <openpgpsdk/random.h>
|
||||
#include <openpgpsdk/readerwriter.h>
|
||||
|
||||
#define MAX_PARTIAL_DATA_LENGTH 1073741824
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ops_crypt_t*crypt;
|
||||
ops_memory_t *mem_data;
|
||||
ops_memory_t *mem_literal;
|
||||
ops_create_info_t *cinfo_literal;
|
||||
ops_memory_t *mem_se_ip;
|
||||
ops_create_info_t *cinfo_se_ip;
|
||||
ops_hash_t hash;
|
||||
} stream_encrypt_se_ip_arg_t;
|
||||
|
||||
|
||||
static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo);
|
||||
|
||||
static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t** errors,
|
||||
ops_writer_info_t* winfo);
|
||||
|
||||
static void stream_encrypt_se_ip_destroyer (ops_writer_info_t *winfo);
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
\ingroup Core_WritersNext
|
||||
\param cinfo
|
||||
\param pub_key
|
||||
*/
|
||||
void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
|
||||
const ops_keydata_t *pub_key)
|
||||
{
|
||||
ops_crypt_t* encrypt;
|
||||
unsigned char *iv=NULL;
|
||||
|
||||
const unsigned int bufsz=1024; // initial value; gets expanded as necessary
|
||||
|
||||
// Create arg to be used with this writer
|
||||
// Remember to free this in the destroyer
|
||||
stream_encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
|
||||
|
||||
// Create and write encrypted PK session key
|
||||
ops_pk_session_key_t* encrypted_pk_session_key;
|
||||
encrypted_pk_session_key=ops_create_pk_session_key(pub_key);
|
||||
ops_write_pk_session_key(cinfo,encrypted_pk_session_key);
|
||||
|
||||
// Setup the arg
|
||||
encrypt=ops_mallocz(sizeof *encrypt);
|
||||
ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm);
|
||||
iv=ops_mallocz(encrypt->blocksize);
|
||||
encrypt->set_iv(encrypt, iv);
|
||||
encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]);
|
||||
ops_encrypt_init(encrypt);
|
||||
|
||||
arg->crypt=encrypt;
|
||||
|
||||
arg->mem_data=ops_memory_new();
|
||||
ops_memory_init(arg->mem_data,bufsz);
|
||||
|
||||
arg->mem_literal = NULL;
|
||||
arg->cinfo_literal = NULL;
|
||||
|
||||
ops_setup_memory_write(&arg->cinfo_se_ip, &arg->mem_se_ip, bufsz);
|
||||
|
||||
// And push writer on stack
|
||||
ops_writer_push(cinfo,
|
||||
stream_encrypt_se_ip_writer,
|
||||
stream_encrypt_se_ip_finaliser,
|
||||
stream_encrypt_se_ip_destroyer,arg);
|
||||
// tidy up
|
||||
free(encrypted_pk_session_key);
|
||||
free(iv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int ops_calc_partial_data_length(unsigned int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int mask = MAX_PARTIAL_DATA_LENGTH;
|
||||
assert( len > 0 );
|
||||
|
||||
if ( len > MAX_PARTIAL_DATA_LENGTH ) {
|
||||
return MAX_PARTIAL_DATA_LENGTH;
|
||||
}
|
||||
|
||||
for ( i = 0; i <= 30; i++ ) {
|
||||
if ( mask & len) break;
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_write_partial_data_length(unsigned int len,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
// len must be a power of 2 from 0 to 30
|
||||
int i;
|
||||
unsigned char c[1];
|
||||
|
||||
for ( i = 0; i <= 30; i++ ) {
|
||||
if ( (len >> i) & 1) break;
|
||||
}
|
||||
|
||||
c[0] = 224 + i;
|
||||
return ops_write(c,1,info);
|
||||
}
|
||||
|
||||
ops_boolean_t ops_stream_write_literal_data(const unsigned char *data,
|
||||
unsigned int len,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
while (len > 0) {
|
||||
size_t pdlen = ops_calc_partial_data_length(len);
|
||||
ops_write_partial_data_length(pdlen, info);
|
||||
ops_write(data, pdlen, info);
|
||||
data += pdlen;
|
||||
len -= pdlen;
|
||||
}
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_stream_write_literal_data_first(const unsigned char *data,
|
||||
unsigned int len,
|
||||
const ops_literal_data_type_t type,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
// \todo add filename
|
||||
// \todo add date
|
||||
// \todo do we need to check text data for <cr><lf> line endings ?
|
||||
|
||||
size_t sz_towrite = 1 + 1 + 4 + len;
|
||||
size_t sz_pd = ops_calc_partial_data_length(sz_towrite);
|
||||
assert(sz_pd >= 512);
|
||||
|
||||
ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, info);
|
||||
ops_write_partial_data_length(sz_pd, info);
|
||||
ops_write_scalar(type, 1, info);
|
||||
ops_write_scalar(0, 1, info);
|
||||
ops_write_scalar(0, 4, info);
|
||||
ops_write(data, sz_pd - 6, info);
|
||||
|
||||
data += (sz_pd - 6);
|
||||
sz_towrite -= sz_pd;
|
||||
|
||||
ops_stream_write_literal_data(data, sz_towrite, info);
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_stream_write_literal_data_last(const unsigned char *data,
|
||||
unsigned int len,
|
||||
ops_create_info_t *info)
|
||||
{
|
||||
ops_write_length(len, info);
|
||||
ops_write(data, len, info);
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_stream_write_se_ip(const unsigned char *data,
|
||||
unsigned int len,
|
||||
stream_encrypt_se_ip_arg_t *arg,
|
||||
ops_create_info_t *cinfo)
|
||||
{
|
||||
while (len > 0) {
|
||||
size_t pdlen = ops_calc_partial_data_length(len);
|
||||
ops_write_partial_data_length(pdlen, cinfo);
|
||||
|
||||
ops_writer_push_encrypt_crypt(cinfo, arg->crypt);
|
||||
ops_write(data, pdlen, cinfo);
|
||||
ops_writer_pop(cinfo);
|
||||
|
||||
arg->hash.add(&arg->hash, data, pdlen);
|
||||
|
||||
data += pdlen;
|
||||
len -= pdlen;
|
||||
}
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_stream_write_se_ip_first(const unsigned char *data,
|
||||
unsigned int len,
|
||||
stream_encrypt_se_ip_arg_t *arg,
|
||||
ops_create_info_t *cinfo)
|
||||
{
|
||||
size_t sz_preamble = arg->crypt->blocksize + 2;
|
||||
size_t sz_towrite = sz_preamble + 1 + len;
|
||||
unsigned char* preamble = ops_mallocz(sz_preamble);
|
||||
|
||||
size_t sz_pd = ops_calc_partial_data_length(sz_towrite);
|
||||
assert(sz_pd >= 512);
|
||||
|
||||
ops_write_ptag(OPS_PTAG_CT_SE_IP_DATA, cinfo);
|
||||
ops_write_partial_data_length(sz_pd, cinfo);
|
||||
ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo);
|
||||
|
||||
ops_writer_push_encrypt_crypt(cinfo, arg->crypt);
|
||||
|
||||
ops_random(preamble, arg->crypt->blocksize);
|
||||
preamble[arg->crypt->blocksize]=preamble[arg->crypt->blocksize-2];
|
||||
preamble[arg->crypt->blocksize+1]=preamble[arg->crypt->blocksize-1];
|
||||
|
||||
ops_hash_any(&arg->hash, OPS_HASH_SHA1);
|
||||
arg->hash.init(&arg->hash);
|
||||
|
||||
ops_write(preamble, sz_preamble, cinfo);
|
||||
arg->hash.add(&arg->hash, preamble, sz_preamble);
|
||||
|
||||
ops_write(data, sz_pd - sz_preamble - 1, cinfo);
|
||||
arg->hash.add(&arg->hash, data, sz_pd - sz_preamble - 1);
|
||||
|
||||
data += (sz_pd - sz_preamble -1);
|
||||
sz_towrite -= sz_pd;
|
||||
|
||||
ops_writer_pop(cinfo);
|
||||
|
||||
ops_stream_write_se_ip(data, sz_towrite, arg, cinfo);
|
||||
|
||||
free(preamble);
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
ops_boolean_t ops_stream_write_se_ip_last(const unsigned char *data,
|
||||
unsigned int len,
|
||||
stream_encrypt_se_ip_arg_t *arg,
|
||||
ops_create_info_t *cinfo)
|
||||
{
|
||||
unsigned char c[1];
|
||||
unsigned char hashed[SHA_DIGEST_LENGTH];
|
||||
const size_t sz_mdc = 1 + 1 + SHA_DIGEST_LENGTH;
|
||||
size_t sz_buf = len + sz_mdc;
|
||||
|
||||
ops_memory_t *mem_mdc;
|
||||
ops_create_info_t *cinfo_mdc;
|
||||
|
||||
arg->hash.add(&arg->hash, data, len);
|
||||
|
||||
// MDC packet tag
|
||||
c[0]=0xD3;
|
||||
arg->hash.add(&arg->hash, &c[0], 1);
|
||||
|
||||
// MDC packet len
|
||||
c[0]=0x14;
|
||||
arg->hash.add(&arg->hash, &c[0], 1);
|
||||
|
||||
//finish
|
||||
arg->hash.finish(&arg->hash, hashed);
|
||||
|
||||
ops_setup_memory_write(&cinfo_mdc, &mem_mdc, sz_mdc);
|
||||
ops_write_mdc(hashed, cinfo_mdc);
|
||||
|
||||
// write length of last se_ip chunk
|
||||
ops_write_length(sz_buf, cinfo);
|
||||
|
||||
// encode everting
|
||||
ops_writer_push_encrypt_crypt(cinfo, arg->crypt);
|
||||
|
||||
ops_write(data, len, cinfo);
|
||||
ops_write(ops_memory_get_data(mem_mdc), ops_memory_get_length(mem_mdc), cinfo);
|
||||
|
||||
ops_writer_pop(cinfo);
|
||||
|
||||
ops_teardown_memory_write(cinfo_mdc, mem_mdc);
|
||||
|
||||
return ops_true;
|
||||
}
|
||||
|
||||
static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src,
|
||||
unsigned length,
|
||||
ops_error_t **errors,
|
||||
ops_writer_info_t *winfo)
|
||||
{
|
||||
stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
|
||||
ops_boolean_t rtn=ops_true;
|
||||
|
||||
if ( arg->cinfo_literal == NULL ) { // first literal data chunk is not yet written
|
||||
size_t datalength;
|
||||
|
||||
ops_memory_add(arg->mem_data,src,length);
|
||||
datalength = ops_memory_get_length(arg->mem_data);
|
||||
|
||||
// 4.2.2.4. Partial Body Lengths
|
||||
// The first partial length MUST be at least 512 octets long.
|
||||
if ( datalength < 512 ) {
|
||||
return ops_true; // will wait for more data or end of stream
|
||||
}
|
||||
|
||||
ops_setup_memory_write(&arg->cinfo_literal,&arg->mem_literal,datalength+32);
|
||||
ops_stream_write_literal_data_first(ops_memory_get_data(arg->mem_data),
|
||||
datalength,
|
||||
OPS_LDT_BINARY,
|
||||
arg->cinfo_literal);
|
||||
|
||||
ops_stream_write_se_ip_first(ops_memory_get_data(arg->mem_literal),
|
||||
ops_memory_get_length(arg->mem_literal),
|
||||
arg, arg->cinfo_se_ip);
|
||||
} else {
|
||||
ops_stream_write_literal_data(src, length, arg->cinfo_literal);
|
||||
ops_stream_write_se_ip(ops_memory_get_data(arg->mem_literal),
|
||||
ops_memory_get_length(arg->mem_literal),
|
||||
arg, arg->cinfo_se_ip);
|
||||
}
|
||||
|
||||
// now write memory to next writer
|
||||
rtn=ops_stacked_write(ops_memory_get_data(arg->mem_se_ip),
|
||||
ops_memory_get_length(arg->mem_se_ip),
|
||||
errors, winfo);
|
||||
|
||||
ops_memory_clear(arg->mem_literal);
|
||||
ops_memory_clear(arg->mem_se_ip);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t** errors,
|
||||
ops_writer_info_t* winfo)
|
||||
{
|
||||
stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
// write last chunk of data
|
||||
|
||||
if ( arg->cinfo_literal == NULL ) {
|
||||
// first literal data chunk was not written
|
||||
// so we know the total length of data, write a simple packet
|
||||
|
||||
// create literal data packet from buffered data
|
||||
ops_setup_memory_write(&arg->cinfo_literal,
|
||||
&arg->mem_literal,
|
||||
ops_memory_get_length(arg->mem_data)+32);
|
||||
|
||||
ops_write_literal_data_from_buf(ops_memory_get_data(arg->mem_data),
|
||||
ops_memory_get_length(arg->mem_data),
|
||||
OPS_LDT_BINARY, arg->cinfo_literal);
|
||||
|
||||
// create SE IP packet set from this literal data
|
||||
ops_write_se_ip_pktset(ops_memory_get_data(arg->mem_literal),
|
||||
ops_memory_get_length(arg->mem_literal),
|
||||
arg->crypt, arg->cinfo_se_ip);
|
||||
|
||||
} else {
|
||||
// finish writing
|
||||
ops_stream_write_literal_data_last(NULL, 0, arg->cinfo_literal);
|
||||
ops_stream_write_se_ip_last(ops_memory_get_data(arg->mem_literal),
|
||||
ops_memory_get_length(arg->mem_literal),
|
||||
arg, arg->cinfo_se_ip);
|
||||
}
|
||||
|
||||
// now write memory to next writer
|
||||
return ops_stacked_write(ops_memory_get_data(arg->mem_se_ip),
|
||||
ops_memory_get_length(arg->mem_se_ip),
|
||||
errors, winfo);
|
||||
}
|
||||
|
||||
static void stream_encrypt_se_ip_destroyer (ops_writer_info_t *winfo)
|
||||
|
||||
{
|
||||
stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
|
||||
|
||||
ops_memory_free(arg->mem_data);
|
||||
ops_teardown_memory_write(arg->cinfo_literal, arg->mem_literal);
|
||||
ops_teardown_memory_write(arg->cinfo_se_ip, arg->mem_se_ip);
|
||||
|
||||
arg->crypt->decrypt_finish(arg->crypt);
|
||||
|
||||
free(arg->crypt);
|
||||
free(arg);
|
||||
}
|
||||
|
||||
|
||||
// EOF
|
Loading…
Reference in New Issue
Block a user