updated to trunk of openpgp-sdk

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-OpenPGP@5078 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2012-04-04 19:27:07 +00:00
parent eb448cbaaf
commit c27f695a37
39 changed files with 1956 additions and 747 deletions

View File

@ -29,37 +29,116 @@ std::string PGPIdType::toStdString() const
return res ;
}
std::string PGPFingerprintType::toStdString() const
{
static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
PGPIdType::PGPIdType(const std::string& s)
std::string res ;
for(int j = 0; j < KEY_FINGERPRINT_SIZE; j++)
{
res += out[ (bytes[j]>>4) ] ;
res += out[ bytes[j] & 0xf ] ;
}
return res ;
}
PGPIdType PGPIdType::fromUserId_hex(const std::string& s)
{
int n=0;
if(s.length() != KEY_ID_SIZE*2)
throw std::runtime_error("PGPIdType::PGPIdType: can only init from 16 chars hexadecimal string") ;
PGPIdType res ;
for(int i = 0; i < KEY_ID_SIZE; ++i)
{
bytes[i] = 0 ;
res.bytes[i] = 0 ;
for(int k=0;k<2;++k)
{
char b = s[n++] ;
if(b >= 'A' && b <= 'F')
bytes[i] += (b-'A'+10) << 4*(1-k) ;
res.bytes[i] += (b-'A'+10) << 4*(1-k) ;
else if(b >= 'a' && b <= 'f')
bytes[i] += (b-'a'+10) << 4*(1-k) ;
res.bytes[i] += (b-'a'+10) << 4*(1-k) ;
else if(b >= '0' && b <= '9')
bytes[i] += (b-'0') << 4*(1-k) ;
res.bytes[i] += (b-'0') << 4*(1-k) ;
else
throw std::runtime_error("PGPIdType::Sha1CheckSum: can't init from non pure hexadecimal string") ;
}
}
return res ;
}
PGPIdType PGPIdType::fromFingerprint_hex(const std::string& s)
{
if(s.length() != PGPFingerprintType::KEY_FINGERPRINT_SIZE*2)
throw std::runtime_error("PGPIdType::PGPIdType: can only init from 40 chars hexadecimal string") ;
PGPIdType res ;
int n=PGPFingerprintType::KEY_FINGERPRINT_SIZE - PGPIdType::KEY_ID_SIZE -1;
for(int i = 0; i < PGPIdType::KEY_ID_SIZE; ++i)
{
res.bytes[i] = 0 ;
for(int k=0;k<2;++k)
{
char b = s[n++] ;
if(b >= 'A' && b <= 'F')
res.bytes[i] += (b-'A'+10) << 4*(1-k) ;
else if(b >= 'a' && b <= 'f')
res.bytes[i] += (b-'a'+10) << 4*(1-k) ;
else if(b >= '0' && b <= '9')
res.bytes[i] += (b-'0') << 4*(1-k) ;
else
throw std::runtime_error("PGPIdType::Sha1CheckSum: can't init from non pure hexadecimal string") ;
}
}
return res ;
}
PGPFingerprintType PGPFingerprintType::fromFingerprint_hex(const std::string& s)
{
int n=0;
if(s.length() != PGPFingerprintType::KEY_FINGERPRINT_SIZE*2)
throw std::runtime_error("PGPIdType::PGPIdType: can only init from 40 chars hexadecimal string") ;
PGPFingerprintType res ;
for(int i = 0; i < PGPFingerprintType::KEY_FINGERPRINT_SIZE; ++i)
{
res.bytes[i] = 0 ;
for(int k=0;k<2;++k)
{
char b = s[n++] ;
if(b >= 'A' && b <= 'F')
res.bytes[i] += (b-'A'+10) << 4*(1-k) ;
else if(b >= 'a' && b <= 'f')
res.bytes[i] += (b-'a'+10) << 4*(1-k) ;
else if(b >= '0' && b <= '9')
res.bytes[i] += (b-'0') << 4*(1-k) ;
else
throw std::runtime_error("PGPIdType::Sha1CheckSum: can't init from non pure hexadecimal string") ;
}
}
return res ;
}
PGPIdType::PGPIdType(const unsigned char b[])
{
memcpy(bytes,b,8) ;
memcpy(bytes,b,KEY_ID_SIZE) ;
}
PGPFingerprintType::PGPFingerprintType(const unsigned char b[])
{
memcpy(bytes,b,KEY_FINGERPRINT_SIZE) ;
}
uint64_t PGPIdType::toUInt64() const
{
@ -210,7 +289,6 @@ bool PGPHandler::GeneratePGPCertificate(const std::string& name, const std::stri
ops_write_transferable_secret_key(key,(unsigned char *)passphrase.c_str(),passphrase.length(),ops_false,cinfo);
ops_keydata_free(key) ;
free(key) ;
// 3 - read the file into a keyring
@ -388,18 +466,48 @@ bool PGPHandler::SignDataBin(const PGPIdType& id,const void *data, const uint32_
return true ;
}
bool PGPHandler::VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const std::string &withfingerprint)
bool PGPHandler::getKeyFingerprint(const PGPIdType& id,PGPFingerprintType& fp) const
{
ops_memory_t *mem = ops_memory_new() ;
ops_memory_add(mem,(unsigned char *)sign,sign_len) ;
const ops_keydata_t *key = getPublicKey(id) ;
ops_validate_result_t *result = (ops_validate_result_t*)ops_mallocz(sizeof(ops_validate_result_t)) ;
ops_boolean_t res = ops_validate_mem(result, mem, ops_false, _pubring);
if(key == NULL)
return false ;
ops_validate_result_free(result) ;
ops_fingerprint_t f ;
ops_fingerprint(&f,&key->key.pkey) ;
// no need to clear mem. It's already deleted by ops_validate_mem (weird but true).
fp = PGPFingerprintType(f.fingerprint) ;
return res ;
return true ;
}
bool PGPHandler::VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& key_fingerprint)
{
PGPIdType id = PGPIdType::fromFingerprint_hex(key_fingerprint.toStdString()) ;
const ops_keydata_t *key = getPublicKey(id) ;
if(key == NULL)
{
std::cerr << "No key returned by fingerprint " << key_fingerprint.toStdString() << ", and ID " << id.toStdString() << ", signature verification failed!" << std::endl;
return false ;
}
// Check that fingerprint is the same.
const ops_public_key_t *pkey = &key->key.pkey ;
ops_fingerprint_t fp ;
ops_fingerprint(&fp,pkey) ;
if(key_fingerprint != PGPFingerprintType(fp.fingerprint))
{
std::cerr << "Key fingerprint does not match " << key_fingerprint.toStdString() << ", for ID " << id.toStdString() << ", signature verification failed!" << std::endl;
return false ;
}
ops_signature_t signature ;
// ops_signature_add_data(&signature,sign,sign_len) ;
// ops_boolean_t valid=check_binary_signature(data_len,data,signature,pkey) ;
return false ;
}

View File

@ -18,10 +18,12 @@ class PGPIdType
{
public:
static const int KEY_ID_SIZE = 8 ;
PGPIdType() {}
PGPIdType(const std::string& hex_string) ;
PGPIdType(const unsigned char bytes[]) ;
static PGPIdType fromUserId_hex(const std::string& hex_string) ;
static PGPIdType fromFingerprint_hex(const std::string& hex_string) ;
explicit PGPIdType(const unsigned char bytes[]) ;
std::string toStdString() const ;
uint64_t toUInt64() const ;
@ -30,6 +32,33 @@ class PGPIdType
private:
unsigned char bytes[KEY_ID_SIZE] ;
};
class PGPFingerprintType
{
public:
static const int KEY_FINGERPRINT_SIZE = 20 ;
static PGPFingerprintType fromFingerprint_hex(const std::string& hex_string) ;
explicit PGPFingerprintType(const unsigned char bytes[]) ;
std::string toStdString() const ;
const unsigned char *toByteArray() const { return &bytes[0] ; }
bool operator==(const PGPFingerprintType& fp) const
{
for(int i=0;i<KEY_FINGERPRINT_SIZE;++i)
if(fp.bytes[i] != bytes[i])
return false ;
return true ;
}
bool operator!=(const PGPFingerprintType& fp) const
{
return !operator==(fp) ;
}
PGPFingerprintType() {}
private:
unsigned char bytes[KEY_FINGERPRINT_SIZE] ;
};
class PGPHandler
{
@ -51,7 +80,9 @@ class PGPHandler
bool TrustCertificate(const PGPIdType& id, int trustlvl);
bool SignDataBin(const PGPIdType& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) ;
bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const std::string &withfingerprint) ;
bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) ;
bool getKeyFingerprint(const PGPIdType& id,PGPFingerprintType& fp) const ;
// Debug stuff.
virtual void printKeys() const ;

View File

@ -12,7 +12,7 @@ int main(int argc,char *argv[])
{
// test pgp ids.
//
PGPIdType id("3e5b22140ef56abb") ;
PGPIdType id = PGPIdType::fromUserId_hex("3e5b22140ef56abb") ;
std::cerr << "Id is : " << std::hex << id.toUInt64() << std::endl;
std::cerr << "Id st : " << id.toStdString() << std::endl;
@ -55,7 +55,7 @@ int main(int argc,char *argv[])
else
std::cerr << "Certificate generation success. New id = " << newid.toStdString() << std::endl;
PGPIdType id2(std::string("618E54CF7670FF5E")) ;
PGPIdType id2 = PGPIdType::fromUserId_hex("618E54CF7670FF5E") ;
std::cerr << "Now extracting key " << id2.toStdString() << " from keyring:" << std::endl ;
std::string cert = pgph.SaveCertificateToString(id2,false) ;
@ -87,7 +87,11 @@ int main(int argc,char *argv[])
std::cerr << "Now verifying signature..." << std::endl;
if(!pgph.VerifySignBin(test_bin,13,sign,signlen,""))
PGPFingerprintType fingerprint ;
if(!pgph.getKeyFingerprint(newid,fingerprint) )
std::cerr << "Cannot find fingerprint of key id " << newid.toStdString() << std::endl;
if(!pgph.VerifySignBin(test_bin,13,sign,signlen,fingerprint))
std::cerr << "Signature verification failed." << std::endl;
else
std::cerr << "Signature verification worked!" << std::endl;

View File

@ -1123,11 +1123,11 @@ bool AuthGPGimpl::VerifySignature(const void *data, int datalen, const void *sig
fprintf(stderr, "AuthGPGimpl::VerifySignature() OK\n");
#endif
if (withfingerprint.empty() == false && withfingerprint == sg->fpr) {
#ifdef GPG_DEBUG
//#ifdef GPG_DEBUG
fprintf(stderr, "AuthGPGimpl::VerifySignature() for the fingerprint key : ");
std::cerr << withfingerprint;
fprintf(stderr, "\n");
#endif
//#endif
valid = true;
break;
}

View File

@ -30,3 +30,5 @@ int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
ops_boolean_t ops_write_compressed(const unsigned char* data,
const unsigned int len,
ops_create_info_t *cinfo);
void ops_writer_push_compressed(ops_create_info_t *cinfo);

View File

@ -43,6 +43,8 @@ struct ops_create_info
ops_error_t *errors; /*!< an error stack */
};
void ops_prepare_parent_info(ops_create_info_t *parent_info,
ops_writer_info_t *winfo);
ops_create_info_t *ops_create_info_new(void);
void ops_create_info_delete(ops_create_info_t *info);

View File

@ -30,6 +30,12 @@
#include "packet.h"
#include "packet-parse.h"
#include <openssl/dsa.h>
#include <openssl/opensslv.h>
#include <openssl/opensslconf.h>
#if OPENSSL_VERSION_NUMBER < 0x00908030L
# define OPENSSL_NO_CAMELLIA
#endif
#define OPS_MIN_HASH_SIZE 16
@ -166,6 +172,7 @@ void ops_writer_push_encrypt(ops_create_info_t *info,
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);
extern void ops_encrypt_stream(ops_create_info_t* cinfo, const ops_keydata_t* public_key, const ops_secret_key_t* secret_key, const ops_boolean_t compress, const ops_boolean_t use_armour);
// Keys
ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata);

View File

@ -113,6 +113,7 @@ 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);
void ops_move_errors(ops_create_info_t *source, ops_error_t **errstack);
#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

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2005-2009 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_LITERAL_H__
#define __OPS_LITERAL_H__
ops_boolean_t write_literal_header(ops_create_info_t *info,
void *header_data);
void ops_writer_push_literal(ops_create_info_t *info);
void ops_writer_push_literal_with_opts(ops_create_info_t *info,
unsigned int buf_size);
#endif /* __OPS_LITERAL_H__ */
// EOF

View File

@ -132,7 +132,6 @@ 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);
void ops_parse_options(ops_parse_info_t *pinfo,ops_content_tag_t tag,
ops_parse_type_t type);
@ -140,7 +139,7 @@ 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_boolean_t ops_stacked_limited_read(void *dest,unsigned length,
ops_region_t *region,
ops_error_t **errors,
ops_reader_info_t *rinfo,

View File

@ -127,7 +127,6 @@ typedef enum
#define OPS_PTAG_NF_CONTENT_TAG_SHIFT 0
/** Structure to hold one parse error string. */
typedef struct
{
@ -310,6 +309,9 @@ typedef enum
OPS_SA_AES_192 =8, /*!< AES with 192-bit key */
OPS_SA_AES_256 =9, /*!< AES with 256-bit key */
OPS_SA_TWOFISH =10, /*!< Twofish with 256-bit key (TWOFISH) */
OPS_SA_CAMELLIA_128 =11, /*!< Camellia with 128-bit key */
OPS_SA_CAMELLIA_192 =12, /*!< Camellia with 192-bit key */
OPS_SA_CAMELLIA_256 =13, /*!< Camellia with 256-bit key */
} ops_symmetric_algorithm_t;
/** Hashing Algorithm Numbers.
@ -358,7 +360,8 @@ typedef struct
ops_public_key_t public_key;
ops_s2k_usage_t s2k_usage;
ops_s2k_specifier_t s2k_specifier;
ops_symmetric_algorithm_t algorithm;
ops_symmetric_algorithm_t algorithm; // the algorithm used to encrypt
// the key
ops_hash_algorithm_t hash_algorithm;
unsigned char salt[OPS_SALT_SIZE];
unsigned octet_count;
@ -658,8 +661,8 @@ typedef struct
/** Signature Subpacket : Revocation Key */
typedef struct
{
unsigned char cclass;
unsigned char algid;
unsigned char clss; /* class - name changed for C++ */
unsigned char algid;
unsigned char fingerprint[20];
} ops_ss_revocation_key_t;

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2005-2009 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* 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_PARTIAL_H__
#define __OPS_PARTIAL_H__
#include "types.h"
#include "writer.h"
/**
* Function that writes out a packet header. See
* ops_writer_push_partial
*/
typedef ops_boolean_t ops_write_partial_header_t(ops_create_info_t *info,
void *data);
typedef ops_boolean_t ops_write_partial_trailer_t(ops_create_info_t *info,
void *data);
void ops_writer_push_partial(size_t packet_size,
ops_create_info_t *info,
ops_content_tag_t tag,
ops_write_partial_header_t *header_writer,
void *header_data);
void ops_writer_push_partial_with_trailer(
size_t packet_size,
ops_create_info_t *cinfo,
ops_content_tag_t tag,
ops_write_partial_header_t *header_writer,
void *header_data,
ops_write_partial_trailer_t *trailer_writer,
void *trailer_data);
#endif /* __OPS_PARTIAL_H__ */

View File

@ -91,5 +91,6 @@ ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, const char*
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);
ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, const ops_sig_type_t sig_type, const ops_secret_key_t *skey);
#endif

View File

@ -25,6 +25,6 @@
#include <openpgpsdk/readerwriter.h>
void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
const ops_key_data_t *pub_key);
const ops_keydata_t *pub_key);
#endif /*__OPS_STREAMWRITER_H__*/

View File

@ -189,6 +189,10 @@ typedef enum ops_content_tag_t ops_ss_type_t;
typedef unsigned char ops_ss_rr_code_t;
/** ops_parse_type_t */
/** Used to specify whether subpackets should be returned raw, parsed or ignored.
*/
typedef enum ops_parse_type_t ops_parse_type_t;
/** ops_parser_content_t */
@ -208,8 +212,6 @@ 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

View File

@ -71,7 +71,7 @@ typedef struct
} validate_key_cb_arg_t;
/** Struct use with the validate_data_cb callback */
typedef struct
typedef struct validate_data_cb_arg
{
enum
{

View File

@ -91,13 +91,15 @@ accumulate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
return OPS_KEEP_MEMORY;
}
// assert(cur);
ops_add_userid_to_keydata(cur, &content->user_id);
ops_add_userid_to_keydata(cur, &content->user_id);
free(content->user_id.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);
ops_add_packet_to_keydata(cur, &content->packet);
free(content->packet.raw);
return OPS_KEEP_MEMORY;
case OPS_PARSER_ERROR:

View File

@ -1,8 +1,9 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* Copyright (c) 2005-2009 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
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* 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
@ -21,7 +22,7 @@
/** \file
*/
#include <zlib.h>
#include <bzlib.h>
#include <assert.h>
@ -33,8 +34,12 @@
#include <openpgpsdk/errors.h>
#include "parse_local.h"
#include <openpgpsdk/final.h>
#include <openpgpsdk/partial.h>
static const int debug = 0;
#define DECOMPRESS_BUFFER 1024
#define COMPRESS_BUFFER 32768
typedef struct
{
@ -63,13 +68,15 @@ typedef struct
z_stream stream;
unsigned char *src;
unsigned char *dst;
size_t bytes_in;
size_t bytes_out;
} 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)
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);
@ -84,7 +91,8 @@ static int zlib_compressed_data_reader(void *dest,size_t length,
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.");
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Compressed data didn't end when region ended.");
/*
else
return 0;
@ -130,7 +138,8 @@ static int zlib_compressed_data_reader(void *dest,size_t length,
{
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.");
OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR,
"Compressed stream ended before packet end.");
}
else if(ret != Z_OK)
{
@ -153,9 +162,9 @@ static int zlib_compressed_data_reader(void *dest,size_t length,
// \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)
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);
@ -170,7 +179,8 @@ static int bzip2_compressed_data_reader(void *dest,size_t length,
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.");
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Compressed data didn't end when region ended.");
}
while(length > 0)
@ -197,8 +207,8 @@ static int bzip2_compressed_data_reader(void *dest,size_t length,
else
n=sizeof arg->in;
if(!ops_stacked_limited_read((unsigned char *)arg->in,n,arg->region,
errors,rinfo,cbinfo))
if(!ops_stacked_limited_read(arg->in, n, arg->region, errors,
rinfo, cbinfo))
return -1;
arg->bzstream.next_in=arg->in;
@ -211,11 +221,13 @@ static int bzip2_compressed_data_reader(void *dest,size_t length,
{
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.");
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);
OPS_ERROR_1(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Invalid return %d from BZ2_bzDecompress", ret);
}
arg->inflate_ret=ret;
}
@ -280,7 +292,8 @@ int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
break;
default:
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type);
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG,
"Compression algorithm %d is not yet supported", type);
return 0;
}
@ -303,7 +316,8 @@ int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
break;
default:
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type);
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG,
"Compression algorithm %d is not yet supported", type);
return 0;
}
@ -313,7 +327,9 @@ int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
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);
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);
@ -322,14 +338,17 @@ int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
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);
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);
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG,
"Compression algorithm %d is not yet supported", type);
return 0;
}
@ -402,4 +421,158 @@ ops_boolean_t ops_write_compressed(const unsigned char *data,
&& ops_write(compress->dst, compress->stream.total_out,cinfo));
}
// Writes out the header for the compressed packet. Invoked by the
// partial stream writer. Note that writing the packet tag and the
// packet length is handled by the partial stream writer.
static ops_boolean_t write_compressed_header(ops_create_info_t *info,
void *header_data)
{
OPS_USED(header_data);
// Write the compression type. Currently we just use ZLIB
ops_write_scalar(OPS_C_ZLIB, 1, info);
return ops_true;
}
static void zlib_error(ops_error_t **errors, z_stream *stream, int error)
{
OPS_ERROR_2(errors,OPS_E_FAIL,
"Error from compression stream %d (%s)", error,
stream->msg == NULL ? "Unknown" : stream->msg);
}
static ops_boolean_t stream_compress_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
// ZLib doesn't like being asked to compress nothing, so return if
// we are given no input.
if (length == 0)
return ops_true;
if (debug)
fprintf(stderr, "Compressing %u bytes\n", length);
compress_arg_t* compress = ops_writer_get_arg(winfo);
compress->bytes_in += length;
compress->stream.next_in = (void*) src;
compress->stream.avail_in = length;
ops_boolean_t result = ops_true;
do
{
compress->stream.next_out = compress->dst;
compress->stream.avail_out = COMPRESS_BUFFER;
int retcode = deflate(&compress->stream, Z_NO_FLUSH);
if (retcode != Z_OK)
{
zlib_error(errors, &compress->stream, retcode);
deflateEnd(&compress->stream);
return ops_false;
}
unsigned bytes_to_write = COMPRESS_BUFFER - compress->stream.avail_out;
if (debug)
fprintf(stderr, "bytes_to_write = %u\n", bytes_to_write);
compress->bytes_out += bytes_to_write;
result = ops_stacked_write(compress->dst, bytes_to_write, errors,
winfo);
}
while (result && compress->stream.avail_out == 0);
return result;
}
static ops_boolean_t stream_compress_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
compress_arg_t* compress = ops_writer_get_arg(winfo);
compress->stream.next_in = NULL;
compress->stream.avail_in = 0;
int retcode = Z_OK;
int output_size = COMPRESS_BUFFER;
ops_boolean_t result = ops_true;
do
{
compress->stream.next_out = compress->dst;
compress->stream.avail_out = output_size;
retcode = deflate(&compress->stream, Z_FINISH);
if (retcode != Z_STREAM_END && retcode != Z_OK)
{
zlib_error(errors, &compress->stream, retcode);
deflateEnd(&compress->stream);
return ops_false;
}
int bytes_to_write = output_size - compress->stream.avail_out;
if (debug)
fprintf(stderr, "At end, bytes_to_write = %u\n", bytes_to_write);
compress->bytes_out += bytes_to_write;
result = ops_stacked_write(compress->dst, bytes_to_write, errors,
winfo);
// If deflate returns Z_OK after we have asked to flush, it means
// that there was not enough space in the output buffer. Increase
// the buffer size and try again.
if (retcode != Z_STREAM_END)
{
if (debug)
fprintf(stderr, "Reallocating %u\n", output_size * 2);
output_size *= 2;
compress->dst = realloc(compress->dst, output_size);
}
}
while (result && retcode != Z_STREAM_END);
int error = deflateEnd(&compress->stream);
if (error != Z_OK)
{
zlib_error(errors, &compress->stream, error);
return ops_false;
}
return result;
}
static void stream_compress_destroyer(ops_writer_info_t *winfo)
{
compress_arg_t* compress = ops_writer_get_arg(winfo);
if (debug)
fprintf(stderr, "Compressed %zu to %zu\n", compress->bytes_in,
compress->bytes_out);
free(compress->dst);
free(compress);
}
/**
\ingroup Core_WritePackets
\brief Pushes a compressed writer onto the stack. Data written
will be encoded as a compressed packet.
\param cinfo Write settings
*/
void ops_writer_push_compressed(ops_create_info_t *cinfo)
{
// This is a streaming writer, so we don't know the length in
// advance. Use a partial writer to handle the partial body
// packet lengths.
ops_writer_push_partial(COMPRESS_BUFFER,
cinfo, OPS_PTAG_CT_COMPRESSED,
write_compressed_header, NULL);
// Create arg to be used with this writer
// Remember to free this in the destroyer
compress_arg_t *compress = ops_mallocz(sizeof *compress);
compress->dst = malloc(COMPRESS_BUFFER);
const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels
compress->stream.zalloc=Z_NULL;
compress->stream.zfree=Z_NULL;
compress->stream.opaque=NULL;
compress->stream.avail_out = COMPRESS_BUFFER;
// all other fields set to zero by use of ops_mallocz
if (deflateInit(&compress->stream, level) != Z_OK)
// can't initialise. Is there a better way to handle this?
assert(0);
// And push writer on stack
ops_writer_push(cinfo, stream_compress_writer, stream_compress_finaliser,
stream_compress_destroyer, compress);
}
// EOF

View File

@ -103,7 +103,8 @@ ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id,
*
* \return return value from ops_write_struct_user_id()
*/
ops_boolean_t ops_write_user_id(const unsigned char *user_id,ops_create_info_t *info)
ops_boolean_t ops_write_user_id(const unsigned char *user_id,
ops_create_info_t *info)
{
ops_user_id_t id;
@ -204,6 +205,7 @@ static ops_boolean_t write_public_key_body(const ops_public_key_t *key,
&& ops_write_mpi(key->key.elgamal.y,info);
default:
fprintf(stderr, "Unknown algorithm %d\n", key->algorithm);
assert(0);
break;
}
@ -239,7 +241,8 @@ static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key,
if (!ops_write_scalar(key->algorithm,1,info))
return ops_false;
assert(key->s2k_specifier==OPS_S2KS_SIMPLE || key->s2k_specifier==OPS_S2KS_SALTED); // = 1 \todo could also be iterated-and-salted
assert(key->s2k_specifier==OPS_S2KS_SIMPLE
|| key->s2k_specifier==OPS_S2KS_SALTED); // = 1 \todo could also be iterated-and-salted
if (!ops_write_scalar(key->s2k_specifier,1,info))
return ops_false;
@ -268,7 +271,8 @@ static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key,
*/
default:
fprintf(stderr,"invalid/unsupported s2k specifier %d\n", key->s2k_specifier);
fprintf(stderr,"invalid/unsupported s2k specifier %d\n",
key->s2k_specifier);
assert(0);
}
@ -313,7 +317,8 @@ static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key,
hash.add(&hash, passphrase, pplen);
hash.finish(&hash, hashed);
// if more in hash than is needed by session key, use the leftmost octets
// if more in hash than is needed by session key, use the
// leftmost octets
memcpy(session_key+(i*SHA_DIGEST_LENGTH), hashed, use);
done += use;
assert(done<=CAST_KEY_LENGTH);
@ -329,7 +334,8 @@ static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key,
*/
default:
fprintf(stderr,"invalid/unsupported s2k specifier %d\n", key->s2k_specifier);
fprintf(stderr,"invalid/unsupported s2k specifier %d\n",
key->s2k_specifier);
assert(0);
}
@ -432,7 +438,9 @@ static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key,
\endcode
*/
ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info)
ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *keydata,
ops_boolean_t armoured,
ops_create_info_t *info)
{
ops_boolean_t rtn;
unsigned int i=0,j=0;
@ -757,6 +765,47 @@ ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key,
&& write_secret_key_body(key,passphrase,pplen,info);
}
/**
* \ingroup InternalAPI
*
* \brief Initialise a temporary info structure that can be used for
* writing to a writer's parent.
*
* This is used by writers who want to use the various ops_write functions
* in order to write to the parent writer.
* Example code:
* \code
* ops_boolean_t writer(const unsigned char *src,
* unsigned length,
* ops_error_t **errors,
* ops_writer_info_t *winfo) {
* ops_create_info_t parent;
* ops_prepare_parent_info(&parent, winfo, errors);
*
* // The ptag will be written to the parent writer
* ops_write_ptag(OPS_PTAG_CT_LITERAL_DATA, &parent);
*
* // The data is written to the parent. This line is
// equivalent to:
* // ops_stacked_write(src, length, errors, winfo);
* ops_boolean_t result = ops_write(src, length, info);
* ops_move_errors(&parent_info, errors);
* return result;
* \endcode
*
* \note It is the responsiblity of the caller to assign space for the parent
* structure, typically on the stack. IOn order to report errors correctly,
* use ops_move_errors() after the write operation.
*
* \see ops_move_errors
*/
void ops_prepare_parent_info(ops_create_info_t *parent_info,
ops_writer_info_t *winfo)
{
parent_info->winfo = *winfo->next;
parent_info->errors = NULL;
}
/**
* \ingroup Core_Create
*
@ -791,7 +840,8 @@ void ops_create_info_delete(ops_create_info_t *info)
\param cs Checksum to be written
\return ops_true if OK; else ops_false
*/
ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, unsigned char cs[2])
ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key,
unsigned char cs[2])
{
unsigned int i=0;
unsigned long checksum=0;
@ -814,7 +864,8 @@ ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, u
// fprintf(stderr," %2x\n",cs[1]);
}
static ops_boolean_t create_unencoded_m_buf(ops_pk_session_key_t *session_key, unsigned char *m_buf)
static ops_boolean_t create_unencoded_m_buf(ops_pk_session_key_t *session_key,
unsigned char *m_buf)
{
int i=0;
// unsigned long checksum=0;
@ -826,7 +877,7 @@ static ops_boolean_t create_unencoded_m_buf(ops_pk_session_key_t *session_key, u
m_buf[0]=session_key->symmetric_algorithm;
assert(session_key->symmetric_algorithm==OPS_SA_CAST5);
assert(session_key->symmetric_algorithm == OPS_SA_CAST5);
for (i=0; i<CAST_KEY_LENGTH; i++)
{
m_buf[1+i]=session_key->key[i];
@ -898,7 +949,8 @@ ops_boolean_t encode_m_buf(const unsigned char *M, size_t mLen,
\brief Creates an ops_pk_session_key_t struct from keydata
\param key Keydata to use
\return ops_pk_session_key_t struct
\note It is the caller's responsiblity to free the returned pointer
\note It is the caller's responsiblity to free the returned pointer. Before freeing,
the key must be cleared by calling ops_pk_session_key_free()
\note Currently hard-coded to use CAST5
\note Currently hard-coded to use RSA
*/
@ -946,7 +998,8 @@ ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key)
if (debug)
{
unsigned int i=0;
fprintf(stderr,"CAST5 session key created (len=%d):\n ", CAST_KEY_LENGTH);
fprintf(stderr,"CAST5 session key created (len=%d):\n ",
CAST_KEY_LENGTH);
for (i=0; i<CAST_KEY_LENGTH; i++)
fprintf(stderr,"%2x ", session_key->key[i]);
fprintf(stderr,"\n");
@ -966,10 +1019,12 @@ ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key)
printf("%2x ", unencoded_m_buf[i]);
printf("\n");
}
encode_m_buf(&unencoded_m_buf[0], SZ_UNENCODED_M_BUF, pub_key, &encoded_m_buf[0]);
encode_m_buf(&unencoded_m_buf[0], SZ_UNENCODED_M_BUF, pub_key,
&encoded_m_buf[0]);
// and encrypt it
if(!ops_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pub_key, &session_key->parameters))
if(!ops_rsa_encrypt_mpi(encoded_m_buf, sz_encoded_m_buf, pub_key,
&session_key->parameters))
{
free (encoded_m_buf);
return NULL;
@ -993,7 +1048,9 @@ ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info,
assert(pksk->algorithm == OPS_PKA_RSA);
return ops_write_ptag(OPS_PTAG_CT_PK_SESSION_KEY, info)
&& ops_write_length(1 + 8 + 1 + BN_num_bytes(pksk->parameters.rsa.encrypted_m) + 2, info)
&& ops_write_length(1 + 8 + 1
+ BN_num_bytes(pksk->parameters.rsa.encrypted_m)
+ 2, info)
&& ops_write_scalar(pksk->version, 1, info)
&& ops_write(pksk->key_id, 8, info)
&& ops_write_scalar(pksk->algorithm, 1, info)
@ -1056,9 +1113,10 @@ ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data,
\return ops_true if OK; else ops_false
*/
ops_boolean_t ops_write_literal_data_from_file(const char *filename,
const ops_literal_data_type_t type,
ops_create_info_t *info)
ops_boolean_t
ops_write_literal_data_from_file(const char *filename,
const ops_literal_data_type_t type,
ops_create_info_t *info)
{
size_t initial_size=1024;
int fd=0;
@ -1066,8 +1124,7 @@ ops_boolean_t ops_write_literal_data_from_file(const char *filename,
unsigned char buf[1024];
ops_memory_t* mem=NULL;
size_t len=0;
#ifdef WIN32
#ifdef WINDOWS_SYS
fd=open(filename,O_RDONLY | O_BINARY);
#else
fd=open(filename,O_RDONLY);
@ -1109,7 +1166,8 @@ ops_boolean_t ops_write_literal_data_from_file(const char *filename,
\param errnum Pointer to error
\return new ops_memory_t pointer containing the contents of the file
\note If there was an error opening the file or reading from it, errnum is set to the cause
\note If there was an error opening the file or reading from it,
errnum is set to the cause
\note It is the caller's responsibility to call ops_memory_free(mem)
*/
@ -1122,8 +1180,7 @@ ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum)
ops_memory_t* mem=NULL;
*errnum=0;
#ifdef WIN32
#ifdef WINDOWS_SYS
fd=open(filename,O_RDONLY | O_BINARY);
#else
fd=open(filename,O_RDONLY);
@ -1165,7 +1222,8 @@ ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum)
\return 1 if OK; 0 if error
*/
int ops_write_file_from_buf(const char *filename, const char* buf, const size_t len, const ops_boolean_t overwrite)
int ops_write_file_from_buf(const char *filename, const char* buf,
const size_t len, const ops_boolean_t overwrite)
{
int fd=0;
size_t n=0;
@ -1176,9 +1234,10 @@ int ops_write_file_from_buf(const char *filename, const char* buf, const size_t
flags |= O_TRUNC;
else
flags |= O_EXCL;
#ifdef WIN32
#ifdef WINDOWS_SYS
flags |= O_BINARY;
#endif
fd=open(filename,flags, 0600);
if (fd < 0)
{
@ -1212,7 +1271,7 @@ ops_boolean_t ops_write_symmetrically_encrypted_data(const unsigned char *data,
int done=0;
ops_crypt_t crypt_info;
int encrypted_sz=0;// size of encrypted data
unsigned char *encrypted=(unsigned char *)NULL; // buffer to write encrypted data to
unsigned char *encrypted=NULL; // buffer to write encrypted data to
// \todo assume AES256 for now
ops_crypt_any(&crypt_info, OPS_SA_AES_256);
@ -1246,7 +1305,8 @@ ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey,
{
unsigned char keyid[OPS_KEY_ID_SIZE];
if (debug)
{ fprintf(stderr,"calling ops_keyid in write_one_pass_sig: this calls sha1_init\n"); }
fprintf(stderr, "calling ops_keyid in write_one_pass_sig: "
"this calls sha1_init\n");
ops_keyid(keyid,&skey->public_key);
return ops_write_ptag(OPS_PTAG_CT_ONE_PASS_SIGNATURE, info)

View File

@ -19,9 +19,12 @@
* limitations under the License.
*/
#include <openpgpsdk/compress.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/literal.h>
#include <openpgpsdk/random.h>
#include <openpgpsdk/readerwriter.h>
#include <openpgpsdk/streamwriter.h>
#include <openpgpsdk/writer_armoured.h>
#include "parse_local.h"
@ -41,8 +44,9 @@
\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)
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];
@ -53,7 +57,7 @@ int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM
mpisize=BN_num_bytes(encmpi);
/* MPI can't be more than 65,536 */
assert(mpisize <= sizeof encmpibuf);
BN_bn2bin(encmpi,encmpibuf);
BN_bn2bin(encmpi, encmpibuf);
assert(skey->public_key.algorithm == OPS_PKA_RSA);
@ -65,9 +69,9 @@ int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM
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);
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 : ");
@ -102,7 +106,7 @@ int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM
// this is the unencoded m buf
if((unsigned)(n-i) <= buflen)
memcpy(buf,mpibuf+i,n-i);
memcpy(buf, mpibuf+i, n-i);
/*
printf("decoded m buf:\n");
@ -120,16 +124,17 @@ int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM
\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)
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);
n=ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, sz_encoded_m_buf,
&pkey->key.rsa);
assert(n!=-1);
if(n <= 0)
@ -151,7 +156,8 @@ ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *encoded_m_buf,
#define MAXBUF 1024
static ops_parse_cb_return_t
callback_write_parsed(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
callback_write_parsed(const ops_parser_content_t *content_,
ops_parse_cb_info_t *cbinfo);
/**
\ingroup HighLevel_Crypto
@ -163,17 +169,20 @@ Encrypt a file
\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)
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);
#ifdef WINDOWS_SYS
fd_in=open(input_filename, O_RDONLY | O_BINARY);
#else
fd_in=open(input_filename,O_RDONLY);
fd_in=open(input_filename, O_RDONLY );
#endif
if(fd_in < 0)
{
@ -190,37 +199,76 @@ ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_fi
ops_writer_push_armoured_message(cinfo);
// Push the encrypted writer
ops_writer_push_encrypt_se_ip(cinfo,pub_key);
ops_writer_push_stream_encrypt_se_ip(cinfo, pub_key);
ops_writer_push_literal(cinfo);
// Do the writing
unsigned char* buf=NULL;
size_t bufsz=16;
int done=0;
unsigned buffer[10240];
for (;;)
{
buf=realloc(buf,done+bufsz);
int n=0;
int n=0;
n=read(fd_in,buf+done,bufsz);
if (!n)
break;
assert(n>=0);
done+=n;
n=read(fd_in, buffer, sizeof buffer);
if (!n)
break;
assert(n >= 0);
// FIXME: apparently writing can't fail.
ops_write(buffer, n, cinfo);
}
// This does the writing
ops_write(buf,done,cinfo);
// tidy up
close(fd_in);
free(buf);
ops_teardown_file_write(cinfo,fd_out);
ops_teardown_file_write(cinfo, fd_out);
return ops_true;
}
/**
\ingroup HighLevel_Crypto
Encrypt a compressed, signed stream.
\param cinfo the structure describing where the output will be written.
\param public_key the key used to encrypt the data
\param secret_key the key used to sign the data. If NULL, the data
will not be signed
\param compress If true, compress the stream before encrypting
\param use_armour Write armoured text, if set
\see ops_setup_file_write
Example Code:
\code
const char* filename = "armour_nocompress_sign.asc";
ops_create_info_t *info;
int fd = ops_setup_file_write(&info, filename, ops_true);
if (fd < 0) {
fprintf(stderr, "Cannot write to %s\n", filename);
return -1;
}
ops_encrypt_stream(info, public_key, secret_key, ops_false, ops_true);
ops_write(cleartext, strlen(cleartext), info);
ops_writer_close(info);
ops_create_info_delete(info);
\endcode
*/
extern void ops_encrypt_stream(ops_create_info_t* cinfo,
const ops_keydata_t* public_key,
const ops_secret_key_t* secret_key,
const ops_boolean_t compress,
const ops_boolean_t use_armour)
{
if (use_armour)
ops_writer_push_armoured_message(cinfo);
ops_writer_push_stream_encrypt_se_ip(cinfo, public_key);
if (compress)
ops_writer_push_compressed(cinfo);
if (secret_key != NULL)
ops_writer_push_signed(cinfo, OPS_SIG_BINARY, secret_key);
else
ops_writer_push_literal(cinfo);
}
/**
\ingroup HighLevel_Crypto
\brief Decrypt a file.
@ -232,7 +280,12 @@ ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_fi
\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)
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;
@ -243,9 +296,9 @@ ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_fi
// setup for reading from given input file
fd_in=ops_setup_file_read(&pinfo, input_filename,
NULL,
callback_write_parsed,
ops_false);
NULL,
callback_write_parsed,
ops_false);
if (fd_in < 0)
{
perror(input_filename);
@ -256,12 +309,13 @@ ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_fi
if (output_filename)
{
fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, output_filename, allow_overwrite);
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);
ops_teardown_file_read(pinfo, fd_in);
return ops_false;
}
}
@ -269,26 +323,29 @@ ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_fi
{
int suffixlen=4;
char *defaultsuffix=".decrypted";
const char *suffix=input_filename+strlen((char *)input_filename)-suffixlen;
if (!strcmp(suffix,".gpg") || !strcmp(suffix,".asc"))
const char *suffix=input_filename+strlen(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);
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);
snprintf(myfilename, filenamelen, "%s%s", input_filename,
defaultsuffix);
}
fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, myfilename, allow_overwrite);
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);
ops_teardown_file_read(pinfo, fd_in);
return ops_false;
}
@ -325,9 +382,11 @@ ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_fi
}
static ops_parse_cb_return_t
callback_write_parsed(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
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;
ops_parser_content_union_t* content
=(ops_parser_content_union_t *)&content_->content;
static ops_boolean_t skipping;
// ops_boolean_t write=ops_true;
@ -350,26 +409,26 @@ callback_write_parsed(const ops_parser_content_t *content_,ops_parse_cb_info_t *
puts("Skipping...");
skipping=ops_true;
}
fwrite(content->unarmoured_text.data,1,
content->unarmoured_text.length,stdout);
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);
return callback_pk_session_key(content_, cbinfo);
break;
case OPS_PARSER_CMD_GET_SECRET_KEY:
return callback_cmd_get_secret_key(content_,cbinfo);
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);
return cbinfo->cryptinfo.cb_get_passphrase(content_, cbinfo);
break;
case OPS_PTAG_CT_LITERAL_DATA_BODY:
return callback_literal_data(content_,cbinfo);
break;
return callback_literal_data(content_, cbinfo);
break;
case OPS_PTAG_CT_ARMOUR_HEADER:
case OPS_PTAG_CT_ARMOUR_TRAILER:

View File

@ -208,4 +208,26 @@ void ops_free_errors(ops_error_t *errstack)
}
}
/**
\ingroup InternalAPI
\brief Moves errors from a create info structure to another error stack.
The error stack wil be moved from the source structure to the destination
stack. If the destination already has errors defined, the errors will
be appended.
*/
void ops_move_errors(ops_create_info_t *source, ops_error_t **dest)
{
if (*dest == NULL)
*dest = source->errors;
else
{
ops_error_t *last = *dest;
while(last->next != NULL)
last = last->next;
last->next = source->errors;
}
source->errors = NULL;
}
// EOF

View File

@ -61,16 +61,8 @@ 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)
// Frees the content of a keydata structure, but not the keydata itself.
static void keydata_internal_free(ops_keydata_t *keydata)
{
unsigned n;
@ -98,7 +90,22 @@ void ops_keydata_free(ops_keydata_t *keydata)
else
ops_secret_key_free(&keydata->key.skey);
/* free(keydata); */
}
/**
\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)
{
keydata_internal_free(keydata);
free(keydata);
}
// \todo check where userid pointers are copied
@ -420,15 +427,11 @@ 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 *keydata)
{
if ( keydata->type == OPS_PTAG_CT_PUBLIC_KEY ) {
if ( keydata->key.pkey.algorithm == OPS_PKA_RSA ) {
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;
}
@ -688,9 +691,8 @@ ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boole
// 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);
#ifdef WINDOWS_SYS
fd=open(filename,O_RDONLY | O_BINARY);
#else
fd=open(filename,O_RDONLY);
#endif
@ -766,11 +768,10 @@ ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolea
ops_parse_info_t *pinfo=NULL;
ops_boolean_t res = ops_true;
pinfo=ops_parse_info_new();
ops_setup_memory_read(&pinfo, mem, NULL, cb_keyring_read,
OPS_ACCUMULATE_NO);
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); }
@ -787,7 +788,9 @@ ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolea
if (armour)
ops_reader_pop_dearmour(pinfo);
// don't call teardown_memory_read because memory was passed in
// don't call teardown_memory_read because memory was passed
// in. But we need to free the parse_info object allocated by
// ops_setup_memory_read().
ops_parse_info_delete(pinfo);
return res;
@ -804,9 +807,10 @@ ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolea
*/
void ops_keyring_free(ops_keyring_t *keyring)
{
int n;
for(n=0;n<keyring->nkeys;++n)
ops_keydata_free(&keyring->keys[n]) ;
int i;
for (i = 0; i < keyring->nkeys; i++)
keydata_internal_free(&keyring->keys[i]);
free(keyring->keys);
keyring->keys=NULL;

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

View File

@ -608,7 +608,8 @@ void ops_crypto_init()
void ops_crypto_finish()
{
CRYPTO_cleanup_all_ex_data();
ERR_remove_state(0);
// FIXME: what should we do instead (function is deprecated)?
// ERR_remove_state(0);
#ifdef DMALLOC
CRYPTO_mem_leaks_fp(stderr);
#endif
@ -632,18 +633,21 @@ const char *ops_text_from_hash(ops_hash_t *hash)
\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_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;
RSA *rsa=RSA_new();
BN_CTX *ctx=BN_CTX_new();
BIGNUM *ebn=BN_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);
BN_set_word(ebn,e);
RSA_generate_key_ex(rsa,numbits,ebn,NULL);
// populate ops key from ssl key

View File

@ -371,12 +371,14 @@ ops_boolean_t ops_limited_read(unsigned char *dest,size_t length,
\ingroup Core_ReadPackets
\brief Call ops_limited_read on next in stack
*/
ops_boolean_t ops_stacked_limited_read(unsigned char *dest,unsigned length,
ops_boolean_t ops_stacked_limited_read(void *dest, unsigned length,
ops_region_t *region,
ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo)
{ return ops_limited_read(dest,length,region,errors,rinfo->next,cbinfo); }
{
return ops_limited_read(dest, length, region, errors, rinfo->next, cbinfo);
}
static ops_boolean_t limited_read(unsigned char *dest,unsigned length,
ops_region_t *region,ops_parse_info_t *info)
@ -989,10 +991,6 @@ void ops_public_key_free(ops_public_key_t *p)
free_BN(&p->key.elgamal.g);
free_BN(&p->key.elgamal.y);
break;
//case 0:
// nothing to free
// break;
default:
assert(0);
@ -1251,8 +1249,6 @@ static int parse_user_id(ops_region_t *region,ops_parse_info_t *pinfo)
CBP(pinfo,OPS_PTAG_CT_USER_ID,&content);
free(C.user_id.user_id) ;
return 1;
}
@ -1307,6 +1303,7 @@ void ops_signature_free(ops_signature_t *sig)
default:
assert(0);
}
free(sig->info.v4_hashed_data);
}
/**
@ -1609,10 +1606,10 @@ static int parse_one_signature_subpacket(ops_signature_t *sig,
break;
case OPS_PTAG_SS_REVOCATION_KEY:
/* octet 0 = class. Bit 0x80 must be set */
if(!limited_read (&C.ss_revocation_key.cclass,1,&subregion,pinfo))
/* octet 0 = clss. Bit 0x80 must be set */
if(!limited_read (&C.ss_revocation_key.clss,1,&subregion,pinfo))
return 0;
if(!(C.ss_revocation_key.cclass&0x80))
if(!(C.ss_revocation_key.clss&0x80))
{
printf("Warning: OPS_PTAG_SS_REVOCATION_KEY class: "
"Bit 0x80 should be set\n");
@ -1906,8 +1903,6 @@ static int parse_v4_signature(ops_region_t *region,ops_parse_info_t *pinfo)
CBP(pinfo,OPS_PTAG_CT_SIGNATURE_FOOTER,&content);
free(C.signature.info.v4_hashed_data) ;
return 1;
}
@ -2227,7 +2222,6 @@ static int parse_secret_key(ops_region_t *region,ops_parse_info_t *pinfo)
int ret=1;
ops_region_t encregion;
ops_region_t *saved_region=NULL;
size_t checksum_length=2;
ops_hash_t checkhash;
int blocksize;
ops_boolean_t crypted;
@ -2252,8 +2246,6 @@ static int parse_secret_key(ops_region_t *region,ops_parse_info_t *pinfo)
if(!limited_read(c,1,region,pinfo))
return 0;
C.secret_key.s2k_usage=c[0];
if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
checksum_length=20;
if(C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED
|| C.secret_key.s2k_usage == OPS_S2KU_ENCRYPTED_AND_HASHED)
@ -2891,6 +2883,7 @@ static int ops_parse_one_packet(ops_parse_info_t *pinfo,
{
C.error.error="Format error (ptag bit not set)";
CBP(pinfo,OPS_PARSER_ERROR,&content);
OPS_ERROR(&pinfo->errors, OPS_E_P_UNKNOWN_TAG, C.error.error);
return 0;
}
C.ptag.new_format=!!(*ptag&OPS_PTAG_NEW_FORMAT);
@ -2904,7 +2897,7 @@ static int ops_parse_one_packet(ops_parse_info_t *pinfo,
}
else
{
ops_boolean_t rb;
ops_boolean_t rb = ops_false;
C.ptag.content_tag=(*ptag&OPS_PTAG_OF_CONTENT_TAG_MASK)
>> OPS_PTAG_OF_CONTENT_TAG_SHIFT;
@ -2930,8 +2923,11 @@ static int ops_parse_one_packet(ops_parse_info_t *pinfo,
break;
}
if(!rb)
return 0;
}
{
OPS_ERROR(&pinfo->errors, OPS_E_P, "Cannot read tag length");
return 0;
}
}
CBP(pinfo,OPS_PARSER_PTAG,&content);
@ -3028,17 +3024,17 @@ static int ops_parse_one_packet(ops_parse_info_t *pinfo,
{
C.packet.length=pinfo->rinfo.alength;
C.packet.raw=pinfo->rinfo.accumulated;
CBP(pinfo,OPS_PARSER_PACKET_END,&content);
//free(pinfo->rinfo.accumulated);
pinfo->rinfo.accumulated=NULL;
pinfo->rinfo.asize=0;
CBP(pinfo,OPS_PARSER_PACKET_END,&content);
}
else
C.packet.raw = NULL ;
pinfo->rinfo.alength=0;
free(C.packet.raw) ;
if(r < 0)
return -1;
@ -3099,11 +3095,13 @@ int ops_parse(ops_parse_info_t *pinfo)
unsigned long pktlen;
do
// Parse until we get a return code of 0 (error) or -1 (EOF)
{
r=ops_parse_one_packet(pinfo,&pktlen);
} while (r != -1);
} while (r > 0);
return pinfo->errors ? 0 : 1;
return r == -1 ? 0 : 1;
}
/**
@ -3117,8 +3115,7 @@ int ops_parse(ops_parse_info_t *pinfo)
int ops_parse_and_print_errors(ops_parse_info_t *pinfo)
{
int r;
r=ops_parse(pinfo);
ops_parse(pinfo);
ops_print_errors(pinfo->errors);
return pinfo->errors ? 0 : 1;
}

View File

@ -496,7 +496,7 @@ static void print_text_breakdown( ops_text_t *text)
for(i=0 ; i<text->known.used ; i++)
{
print_indent();
printf("%s",prefix);
fputs(prefix,stdout);
printf("%s\n",text->known.strings[i]);
}
@ -513,7 +513,7 @@ static void print_text_breakdown( ops_text_t *text)
for( i=0; i < text->unknown.used; i++)
{
print_indent();
printf("%s",prefix);
fputs(prefix,stdout);
printf("%s\n",text->unknown.strings[i]);
}
@ -849,11 +849,10 @@ int ops_print_packet(const ops_parser_content_t *content_)
start_subpacket(content_->tag);
/* not yet tested */
printf (" revocation key: class=0x%x",
content->ss_revocation_key.cclass);
if (content->ss_revocation_key.cclass&0x40)
content->ss_revocation_key.clss);
if (content->ss_revocation_key.clss&0x40)
printf (" (sensitive)");
printf (", algid=0x%x",
content->ss_revocation_key.algid);
printf (", algid=0x%x", content->ss_revocation_key.algid);
printf(", fingerprint=");
hexdump(content->ss_revocation_key.fingerprint,20);
printf("\n");
@ -862,8 +861,7 @@ int ops_print_packet(const ops_parser_content_t *content_)
case OPS_PTAG_SS_ISSUER_KEY_ID:
start_subpacket(content_->tag);
print_hexdump("Issuer Key Id",
&content->ss_issuer_key_id.key_id[0],
print_hexdump("Issuer Key Id", &content->ss_issuer_key_id.key_id[0],
sizeof content->ss_issuer_key_id.key_id);
end_subpacket();
break;
@ -1434,11 +1432,10 @@ static ops_parse_cb_return_t cb_list_packets(const ops_parser_content_t * conten
start_subpacket(content_->tag);
/* not yet tested */
printf (" revocation key: class=0x%x",
content->ss_revocation_key.class);
if (content->ss_revocation_key.class&0x40)
content->ss_revocation_key.clss);
if (content->ss_revocation_key.clss&0x40)
printf (" (sensitive)");
printf (", algid=0x%x",
content->ss_revocation_key.algid);
printf (", algid=0x%x", content->ss_revocation_key.algid);
printf(", fingerprint=");
hexdump(content->ss_revocation_key.fingerprint,20);
printf("\n");

View File

@ -212,6 +212,9 @@ static ops_map_t symmetric_algorithm_map[] =
{ OPS_SA_AES_192, "AES (192-bit key)" },
{ OPS_SA_AES_256, "AES (256-bit key)" },
{ OPS_SA_TWOFISH, "Twofish(256-bit key)" },
{ OPS_SA_CAMELLIA_128, "Camellia (128-bit key)" },
{ OPS_SA_CAMELLIA_192, "Camellia (192-bit key)" },
{ OPS_SA_CAMELLIA_256, "Camellia (256-bit key)" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};

View File

@ -81,7 +81,9 @@ void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_des
void ops_reader_pop(ops_parse_info_t *pinfo)
{
ops_reader_info_t *next=pinfo->rinfo.next;
// We are about to overwrite pinfo->rinfo, so free any data in the
// old rinfo structure first.
free(pinfo->rinfo.accumulated);
pinfo->rinfo=*next;
free(next);
}

View File

@ -139,8 +139,7 @@ int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_bo
flags |= O_TRUNC;
else
flags |= O_EXCL;
#ifdef WIN32
#ifdef WINDOWS_SYS
flags |= O_BINARY;
#endif
@ -182,10 +181,10 @@ int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename)
* initialise needed structures for writing to file
*/
#ifdef WIN32
#ifdef WINDOWS_SYS
fd=open(filename,O_WRONLY | O_APPEND | O_BINARY, 0600);
#else
fd=open(filename,O_WRONLY | O_APPEND, 0600);
fd=open(filename,O_WRONLY | O_APPEND , 0600);
#endif
if(fd < 0)
{
@ -231,10 +230,10 @@ int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename,
* initialise needed structures for reading
*/
#ifdef WIN32
#ifdef WINDOWS_SYS
fd=open(filename,O_RDONLY | O_BINARY);
#else
fd=open(filename,O_RDONLY);
fd=open(filename,O_RDONLY );
#endif
if (fd < 0)
{

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,8 @@ SOURCES += accumulate.c \
validate.c \
writer.c \
writer_armour.c \
writer_partial.c \
writer_literal.c \
writer_encrypt.c \
writer_encrypt_se_ip.c \
writer_fd.c \

View File

@ -24,9 +24,12 @@
#include <assert.h>
#include <openssl/cast.h>
#ifndef OPENSSL_NO_IDEA
#include <openssl/idea.h>
# include <openssl/idea.h>
#endif
#include <openssl/aes.h>
#ifndef OPENSSL_NO_CAMELLIA
# include <openssl/camellia.h>
#endif
#include <openssl/des.h>
#include "parse_local.h"
@ -278,6 +281,138 @@ static const ops_crypt_t aes256=
TRAILER
};
#ifndef OPENSSL_NO_CAMELLIA
// CAMELLIA with 128-bit key
#define KEYBITS_CAMELLIA128 128
static void camellia128_init(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY));
if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA128,crypt->encrypt_key))
fprintf(stderr,"camellia128_init: Error setting encrypt_key\n");
if (crypt->decrypt_key)
free(crypt->decrypt_key);
crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY));
if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA128,crypt->decrypt_key))
fprintf(stderr,"camellia128_init: Error setting decrypt_key\n");
}
static void camellia_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
{ Camellia_encrypt(in,out,crypt->encrypt_key); }
static void camellia_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
{ Camellia_decrypt(in,out,crypt->decrypt_key); }
static void camellia_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
Camellia_cfb128_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
CAMELLIA_ENCRYPT);
}
static void camellia_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
Camellia_cfb128_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
CAMELLIA_DECRYPT);
}
static const ops_crypt_t camellia128=
{
OPS_SA_CAMELLIA_128,
CAMELLIA_BLOCK_SIZE,
KEYBITS_CAMELLIA128/8,
std_set_iv,
std_set_key,
camellia128_init,
std_resync,
camellia_block_encrypt,
camellia_block_decrypt,
camellia_cfb_encrypt,
camellia_cfb_decrypt,
std_finish,
TRAILER
};
// CAMELLIA with 192-bit key
#define KEYBITS_CAMELLIA192 192
static void camellia192_init(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY));
if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA192,crypt->encrypt_key))
fprintf(stderr,"camellia192_init: Error setting encrypt_key\n");
if (crypt->decrypt_key)
free(crypt->decrypt_key);
crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY));
if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA192,crypt->decrypt_key))
fprintf(stderr,"camellia192_init: Error setting decrypt_key\n");
}
static const ops_crypt_t camellia192=
{
OPS_SA_CAMELLIA_192,
CAMELLIA_BLOCK_SIZE,
KEYBITS_CAMELLIA192/8,
std_set_iv,
std_set_key,
camellia192_init,
std_resync,
camellia_block_encrypt,
camellia_block_decrypt,
camellia_cfb_encrypt,
camellia_cfb_decrypt,
std_finish,
TRAILER
};
// CAMELLIA with 256-bit key
#define KEYBITS_CAMELLIA256 256
static void camellia256_init(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(CAMELLIA_KEY));
if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA256,crypt->encrypt_key))
fprintf(stderr,"camellia256_init: Error setting encrypt_key\n");
if (crypt->decrypt_key)
free(crypt->decrypt_key);
crypt->decrypt_key=malloc(sizeof(CAMELLIA_KEY));
if (Camellia_set_key(crypt->key,KEYBITS_CAMELLIA256,crypt->decrypt_key))
fprintf(stderr,"camellia256_init: Error setting decrypt_key\n");
}
static const ops_crypt_t camellia256=
{
OPS_SA_CAMELLIA_256,
CAMELLIA_BLOCK_SIZE,
KEYBITS_CAMELLIA256/8,
std_set_iv,
std_set_key,
camellia256_init,
std_resync,
camellia_block_encrypt,
camellia_block_decrypt,
camellia_cfb_encrypt,
camellia_cfb_decrypt,
std_finish,
TRAILER
};
#endif // ndef OPENSSL_NO_CAMELLIA
// Triple DES
static void tripledes_init(ops_crypt_t *crypt)
@ -309,20 +444,28 @@ static void tripledes_block_decrypt(ops_crypt_t *crypt,void *out,
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)
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);
&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)
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);
&keys[0],&keys[1],&keys[2],
(DES_cblock *)crypt->iv, (int *)&crypt->num,
DES_DECRYPT);
}
static const ops_crypt_t tripledes=
@ -360,11 +503,23 @@ static const ops_crypt_t *get_proto(ops_symmetric_algorithm_t alg)
case OPS_SA_AES_256:
return &aes256;
#ifndef OPENSSL_NO_CAMELLIA
case OPS_SA_CAMELLIA_128:
return &camellia128;
case OPS_SA_CAMELLIA_192:
return &camellia192;
case OPS_SA_CAMELLIA_256:
return &camellia256;
#endif // ndef OPENSSL_NO_CAMELLIA
case OPS_SA_TRIPLEDES:
return &tripledes;
default:
fprintf(stderr,"Unknown algorithm: %d (%s)\n",alg,ops_show_symmetric_algorithm(alg));
fprintf(stderr,"Unknown algorithm: %d (%s)\n",alg,
ops_show_symmetric_algorithm(alg));
// assert(0);
}
@ -483,6 +638,9 @@ ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg)
{
case OPS_SA_AES_128:
case OPS_SA_AES_256:
case OPS_SA_CAMELLIA_128:
case OPS_SA_CAMELLIA_192:
case OPS_SA_CAMELLIA_256:
case OPS_SA_CAST5:
case OPS_SA_TRIPLEDES:
#ifndef OPENSSL_NO_IDEA

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
@ -106,52 +106,6 @@ 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

View File

@ -321,6 +321,7 @@ ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cb
case OPS_PARSER_PTAG:
case OPS_PTAG_CT_SIGNATURE_HEADER:
case OPS_PARSER_PACKET_END:
case OPS_PTAG_CT_TRUST:
break;
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:

View File

@ -34,6 +34,10 @@
static int debug=0;
#define LINE_LENGTH 75
static const char newline[] = "\r\n";
/**
* \struct dash_escaped_arg_t
*/
@ -164,6 +168,8 @@ ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
*/
typedef struct
{
size_t chars_written;
ops_boolean_t writing_trailer;
unsigned pos;
unsigned char t;
unsigned checksum;
@ -172,6 +178,17 @@ typedef struct
static char b64map[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static ops_boolean_t check_newline(base64_arg_t* arg,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
arg->chars_written++;
if (!arg->writing_trailer && arg->chars_written % LINE_LENGTH == 0)
if (!ops_stacked_write(newline, strlen(newline), errors, winfo))
return ops_false;
return ops_true;
}
static ops_boolean_t base64_writer(const unsigned char *src,
unsigned length,ops_error_t **errors,
ops_writer_info_t *winfo)
@ -209,6 +226,8 @@ static ops_boolean_t base64_writer(const unsigned char *src,
arg->t+=src[n] >> 6;
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
return ops_false;
if(!check_newline(arg, errors, winfo))
return ops_false;
/* 00000000 00000000 00XXXXXX */
if(!ops_stacked_write(&b64map[src[n++]&0x3f],1,errors,winfo))
@ -216,8 +235,9 @@ static ops_boolean_t base64_writer(const unsigned char *src,
arg->pos=0;
}
}
if (!check_newline(arg, errors, winfo))
return ops_false;
}
return ops_true;
}
@ -246,7 +266,10 @@ static ops_boolean_t signature_finaliser(ops_error_t **errors,
c[0]=arg->checksum >> 16;
c[1]=arg->checksum >> 8;
c[2]=arg->checksum;
/* push the checksum through our own writer */
/* push the checksum through our own writer. Turn off the
writing_body flag so we don't put a newline in the trailer.
*/
arg->writing_trailer = ops_true;
if(!base64_writer(c,3,errors,winfo))
return ops_false;
@ -278,7 +301,7 @@ static ops_boolean_t linebreak_writer(const unsigned char *src,
if(arg->pos == BREAKPOS)
{
if(!ops_stacked_write("\r\n",2,errors,winfo))
if(!ops_stacked_write(newline,strlen(newline),errors,winfo))
return ops_false;
arg->pos=0;
}
@ -348,7 +371,10 @@ static ops_boolean_t armoured_message_finaliser(ops_error_t **errors,
c[0]=arg->checksum >> 16;
c[1]=arg->checksum >> 8;
c[2]=arg->checksum;
/* push the checksum through our own writer */
/* push the checksum through our own writer. Turn off the
writing_body flag so we don't put a newline in the trailer.
*/
arg->writing_trailer = ops_true;
if(!base64_writer(c,3,errors,winfo))
return ops_false;
@ -368,7 +394,7 @@ void ops_writer_push_armoured_message(ops_create_info_t *info)
base64_arg_t *base64;
ops_write(header,sizeof header-1,info);
ops_write("\r\n",2,info);
ops_write(newline,strlen(newline),info);
base64=ops_mallocz(sizeof *base64);
base64->checksum=CRC24_INIT;
ops_writer_push(info,base64_writer,armoured_message_finaliser,ops_writer_generic_destroyer,base64);
@ -421,7 +447,10 @@ static ops_boolean_t armoured_finaliser(ops_armor_type_t type, ops_error_t **err
c[0]=arg->checksum >> 16;
c[1]=arg->checksum >> 8;
c[2]=arg->checksum;
/* push the checksum through our own writer */
/* push the checksum through our own writer. Turn off the
writing_body flag so we don't put a newline in the trailer.
*/
arg->writing_trailer = ops_true;
if(!base64_writer(c,3,errors,winfo))
return ops_false;

View File

@ -50,7 +50,7 @@ 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);
static void encrypt_se_ip_destroyer(ops_writer_info_t *winfo);
//
@ -59,9 +59,9 @@ static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo);
\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)
const ops_keydata_t *pub_key)
{
ops_crypt_t* encrypt;
ops_crypt_t *encrypt;
unsigned char *iv=NULL;
// Create arg to be used with this writer
@ -69,9 +69,9 @@ void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo,
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;
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);
ops_write_pk_session_key(cinfo, encrypted_pk_session_key);
// Setup the arg
encrypt=ops_mallocz(sizeof *encrypt);
@ -84,8 +84,10 @@ void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo,
arg->crypt=encrypt;
// And push writer on stack
ops_writer_push(cinfo,encrypt_se_ip_writer,NULL,encrypt_se_ip_destroyer,arg);
ops_writer_push(cinfo, encrypt_se_ip_writer, NULL, encrypt_se_ip_destroyer,
arg);
// tidy up
ops_pk_session_key_free(encrypted_pk_session_key);
free(encrypted_pk_session_key);
free(iv);
}
@ -109,13 +111,13 @@ static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src,
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);
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);
assert(ops_memory_get_length(mem_literal) > length);
// create compressed packet from literal data packet
ops_write_compressed(ops_memory_get_data(mem_literal),
@ -126,7 +128,8 @@ static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src,
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));
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),
@ -150,9 +153,9 @@ static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo)
}
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)
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;
@ -165,9 +168,9 @@ ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
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))
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;
@ -190,7 +193,7 @@ ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
ops_setup_memory_write(&cinfo_mdc, &mem_mdc,sz_mdc);
ops_calc_mdc_hash(preamble,sz_preamble,data,len,&hashed[0]);
ops_calc_mdc_hash(preamble, sz_preamble, data, len, &hashed[0]);
ops_write_mdc(hashed, cinfo_mdc);
@ -203,13 +206,13 @@ ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
fprintf(stderr,"\nplaintext: ");
for (i=0; i<sz_plaintext;i++)
fprintf(stderr," 0x%02x", data[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, " 0x%02x", mdc[i]);
fprintf(stderr,"\n");
}
@ -220,13 +223,15 @@ ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
#ifdef DEBUG
if (debug)
{
fprintf(stderr,"writing %ld + %d + %ld\n", sz_preamble, len, ops_memory_get_length(mem_mdc));
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)
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))
|| !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;

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2005-2009 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* 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.
*/
/** Writes a literal data packet, using the partial data length encoding.
*/
#include <string.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <openpgpsdk/create.h>
#include <openpgpsdk/literal.h>
#include <openpgpsdk/partial.h>
#define MIN_PARTIAL_DATA_LENGTH 512
#define MAX_PARTIAL_DATA_LENGTH 1073741824
ops_boolean_t write_literal_header(ops_create_info_t *info,
void *header_data)
{
OPS_USED(header_data);
// \todo add the literal type as a header_data argument
// \todo add filename
// \todo add date
// \todo do we need to check text data for <cr><lf> line endings ?
ops_write_scalar(OPS_LDT_BINARY, 1, info); // data type
ops_write_scalar(0, 1, info); // Filename (length = 0)
ops_write_scalar(0, 4, info); // Date (unspecified)
return ops_true;
}
/**
* \ingroup InternalAPI
* \brief Pushes a literal writer onto the stack.
* \param cinfo the writer info
* \param buf_size the size of the internal buffer. For best
* throughput, write data in multiples of buf_size
*/
void ops_writer_push_literal_with_opts(ops_create_info_t *cinfo,
unsigned int buf_size)
{
// The literal writer doesn't need to transform the data, so we just
// push a partial packet writer onto the stack. This will handle
// the packet length encoding. All we need to provide is a function
// to write the header.
ops_writer_push_partial(buf_size, cinfo, OPS_PTAG_CT_LITERAL_DATA,
write_literal_header, NULL);
}
/**
* \ingroup InternalAPI
* \brief Pushes a literal writer onto the stack.
* \param cinfo the writer info
*/
void ops_writer_push_literal(ops_create_info_t *cinfo)
{
ops_writer_push_literal_with_opts(cinfo, 0);
}
// EOF

View File

@ -0,0 +1,381 @@
/*
* Copyright (c) 2005-2009 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* 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.
*/
/** Writes data using a series of partial body length headers.
* (See RFC 4880 4.2.2.4). This is normally used in conjunction
* with a streaming writer of some kind that needs to write out
* data packets of unknown length.
*/
#include <string.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <openpgpsdk/create.h>
#include <openpgpsdk/memory.h>
#include <openpgpsdk/partial.h>
#include <openpgpsdk/readerwriter.h>
static const int debug = 0;
#define PACKET_SIZE 2048
#define MIN_PARTIAL_DATA_LENGTH 512
#define MAX_PARTIAL_DATA_LENGTH 1073741824
typedef struct
{
size_t packet_size; // size of packets
ops_memory_t *buffer; // Data is buffered here until written
ops_content_tag_t tag; // Packet tag
ops_memory_t *header; // Header is written here
ops_boolean_t written_first; // Has the first packet been written?
ops_write_partial_trailer_t *trailer_fn; // Custom end-of-packet fn
void *trailer_data; // data for end-of-packet fn
} stream_partial_arg_t;
static 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;
}
static 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
unsigned i;
unsigned char c[1];
for (i = 0 ; i <= 30 ; i++)
if ((len >> i) & 1)
break;
assert((1u << i) == len);
c[0] = 224 + i;
return ops_write(c, 1, info);
}
static ops_boolean_t write_partial_data(const unsigned char *data,
size_t len,
ops_create_info_t *info)
{
if (debug)
fprintf(stderr, "Writing %zu bytes\n", len);
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;
}
static ops_boolean_t write_partial_data_first(stream_partial_arg_t *arg,
const unsigned char *data,
unsigned int len,
ops_create_info_t *info)
{
size_t header_len = ops_memory_get_length(arg->header);
size_t sz_towrite = len + header_len;
size_t sz_pd = ops_calc_partial_data_length(sz_towrite);
size_t first_data_len = (sz_pd - header_len);
assert(sz_pd >= MIN_PARTIAL_DATA_LENGTH);
if (debug)
fprintf(stderr, "Writing first packet of len %zu (%zu + %u)\n",
sz_towrite, header_len, len);
// Write the packet tag, the partial size and the header, followed
// by the first chunk of data and then the remainder of the data.
// (We have to do this in two chunks, as the partial length may not
// match the number of bytes to write.)
return ops_write_ptag(arg->tag, info) &&
ops_write_partial_data_length(sz_pd, info) &&
ops_write(ops_memory_get_data(arg->header), header_len, info) &&
ops_write(data, first_data_len, info) &&
write_partial_data(data + first_data_len, len - first_data_len, info);
}
/*
* Writes out the last packet. The length is encoded as a fixed-length
* packet. Note that even if there is no data accumulated in the
* buffer, we stil lneed to write out a packet, as the final packet in
* a partially-encoded stream must be a fixed-lngth packet.
*/
static ops_boolean_t write_partial_data_last(stream_partial_arg_t *arg,
ops_create_info_t *info)
{
size_t buffer_length = ops_memory_get_length(arg->buffer);
if (debug)
fprintf(stderr, "writing final packet of %zu bytes\n", buffer_length);
return ops_write_length(buffer_length, info) &&
ops_write(ops_memory_get_data(arg->buffer), buffer_length, info);
}
/*
* Writes out the data accumulated in the in-memory buffer.
*/
static ops_boolean_t flush_buffer(stream_partial_arg_t *arg,
ops_create_info_t *info)
{
ops_boolean_t result = ops_true;
size_t buffer_length = ops_memory_get_length(arg->buffer);
if (buffer_length > 0)
{
if (debug)
fprintf(stderr, "Flushing %zu bytes\n", buffer_length);
result = write_partial_data(ops_memory_get_data(arg->buffer),
buffer_length,
info);
ops_memory_clear(arg->buffer);
}
return result;
}
static ops_boolean_t stream_partial_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
stream_partial_arg_t *arg = ops_writer_get_arg(winfo);
// For the first write operation, we need to write out the header
// plus the data. The total size that we write out must be at least
// MIN_PARTIAL_DATA_LENGTH bytes. (See RFC 4880, sec 4.2.2.4,
// Partial Body Lengths.) If we are given less than this,
// then we need to store the data in the buffer until we have the
// minumum
if (!arg->written_first)
{
ops_memory_add(arg->buffer, src, length);
size_t buffer_length = ops_memory_get_length(arg->buffer);
size_t header_length = ops_memory_get_length(arg->header);
if (header_length + buffer_length < MIN_PARTIAL_DATA_LENGTH)
{
if (debug)
fprintf(stderr, "Storing %zu (%zu + %zu) bytes\n",
header_length + buffer_length, header_length,
buffer_length);
return ops_true; // will wait for more data or end of stream
}
arg->written_first = ops_true;
// Create a writer that will write to the parent stream. Allows
// useage of ops_write_ptag, etc.
ops_create_info_t parent_info;
ops_prepare_parent_info(&parent_info, winfo);
ops_boolean_t result =
write_partial_data_first(arg, ops_memory_get_data(arg->buffer),
buffer_length, &parent_info);
ops_memory_clear(arg->buffer);
ops_move_errors(&parent_info, errors);
return result;
}
else
{
size_t buffer_length = ops_memory_get_length(arg->buffer);
if (buffer_length + length < arg->packet_size)
{
ops_memory_add(arg->buffer, src, length);
if (debug)
fprintf(stderr, "Storing %u bytes (total %zu)\n",
length, buffer_length);
return ops_true;
}
else
{
ops_create_info_t parent_info;
parent_info.winfo = *winfo->next;
parent_info.errors = *errors;
return flush_buffer(arg, &parent_info) &&
write_partial_data(src, length, &parent_info);
}
}
return ops_true;
}
/*
* Invoked when the total packet size is less than
* MIN_PARTIAL_DATA_LENGTH. In that case, we write out the whole
* packet in a single operation, without using partial body length
* packets.
*/
static ops_boolean_t write_complete_packet(stream_partial_arg_t *arg,
ops_create_info_t *info)
{
size_t data_len = ops_memory_get_length(arg->buffer);
size_t header_len = ops_memory_get_length(arg->header);
// Write the header tag, the length of the packet, and the
// packet. Note that the packet includes the header
// bytes.
size_t total = data_len + header_len;
if (debug)
fprintf(stderr, "writing entire packet with length %zu (%zu + %zu)\n",
total, data_len, header_len);
return ops_write_ptag(arg->tag, info) &&
ops_write_length(total, info) &&
ops_write(ops_memory_get_data(arg->header), header_len, info) &&
ops_write(ops_memory_get_data(arg->buffer), data_len, info);
}
static ops_boolean_t stream_partial_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
stream_partial_arg_t *arg = ops_writer_get_arg(winfo);
// write last chunk of data
// Create a writer that will write to the parent stream. Allows
// useage of ops_write_ptag, etc.
ops_create_info_t parent_info;
ops_prepare_parent_info(&parent_info, winfo);
ops_boolean_t result;
if (!arg->written_first)
result = write_complete_packet(arg, &parent_info);
else
// finish writing
result = write_partial_data_last(arg, &parent_info);
if (result && arg->trailer_fn != NULL)
result = arg->trailer_fn(&parent_info, arg->trailer_data);
ops_move_errors(&parent_info, errors);
return result;
}
static void stream_partial_destroyer(ops_writer_info_t *winfo)
{
stream_partial_arg_t *arg = ops_writer_get_arg(winfo);
ops_memory_free(arg->buffer);
ops_memory_free(arg->header);
free(arg);
}
/**
* \ingroup InternalAPI
* \brief Pushes a partial packet writer onto the stack.
*
* This writer is used in conjunction with another writer that
* generates streaming data of unknown length. The partial writer
* handles the various partial body length packets. When writing the
* initial packet header, the partial writer will write out the given
* tag, write out an initial length, and then invoke the 'header'
* function to write the remainder of the header. Note that the header
* function should not write a packet tag or a length.
*
* \param packet_size the expected size of the incoming packets. Must
* be >= 512 bytes. Must be a power of 2. The partial writer
* will buffer incoming writes into packets of this size. Note
* that writes will be most efficient if done in chunks of
* packet_size. If the packet size is unknown, specify 0, and
* the default size will be used.
* \param cinfo the writer info
* \param tag the packet tag
* \param header_writer a function that writes the packet header.
* \param header_data passed into header_writer
*/
void ops_writer_push_partial(size_t packet_size,
ops_create_info_t *cinfo,
ops_content_tag_t tag,
ops_write_partial_header_t *header_writer,
void *header_data)
{
ops_writer_push_partial_with_trailer(packet_size, cinfo, tag, header_writer,
header_data, NULL, NULL);
}
/**
* \ingroup InternalAPI
* \brief Pushes a partial packet writer onto the stack. Adds a trailer
* function that will be invoked after writing out the partial
* packet.
*
* This writer is primarily used by the signature writer, which needs
* to append a signature packet after the literal data packet.
*
* \param trailer_writer a function that writes the trailer
* \param trailer_data passed into trailer_data
* \see ops_writer_push_partial
* \see ops_writer_push_signed
*/
void ops_writer_push_partial_with_trailer(
size_t packet_size,
ops_create_info_t *cinfo,
ops_content_tag_t tag,
ops_write_partial_header_t *header_writer,
void *header_data,
ops_write_partial_trailer_t *trailer_writer,
void *trailer_data)
{
if (packet_size == 0)
packet_size = PACKET_SIZE;
assert(packet_size >= MIN_PARTIAL_DATA_LENGTH);
// Verify that the packet size is a valid power of 2.
assert(ops_calc_partial_data_length(packet_size) == packet_size);
// Create arg to be used with this writer
// Remember to free this in the destroyer
stream_partial_arg_t *arg = ops_mallocz(sizeof *arg);
arg->tag = tag;
arg->written_first = ops_false;
arg->packet_size = packet_size;
arg->buffer = ops_memory_new();
ops_memory_init(arg->buffer, arg->packet_size);
arg->trailer_fn = trailer_writer;
arg->trailer_data = trailer_data;
// Write out the header into the memory buffer. Later we will write
// this buffer to the underlying output stream.
ops_create_info_t *header_info;
ops_setup_memory_write(&header_info, &arg->header, 128);
header_writer(header_info, header_data);
ops_writer_close(header_info);
ops_create_info_delete(header_info);
// And push writer on stack
ops_writer_push(cinfo, stream_partial_writer, stream_partial_finaliser,
stream_partial_destroyer, arg);
}
// EOF

View File

@ -1,8 +1,9 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* Copyright (c) 2005-2009 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
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* 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
@ -34,46 +35,60 @@
#include "keyring_local.h"
#include <openpgpsdk/create.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/partial.h>
#include <openpgpsdk/random.h>
#include <openpgpsdk/readerwriter.h>
#define MAX_PARTIAL_DATA_LENGTH 1073741824
#include <openpgpsdk/streamwriter.h>
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 write_encrypt_se_ip_header(ops_create_info_t *info,
void *header_data);
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 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
\brief Pushes a streaming encryption writer onto the stack.
Data written to the stream will be encoded in a Symmetrically
Encrypted Integrity Protected packet. Note that this writer must be
used in conjunction with a literal writer or a signed writer.
\param cinfo
\param pub_key
Example Code:
\code
ops_writer_push_stream_encrypt_se_ip(cinfo, public_key);
if (compress)
ops_writer_push_compressed(cinfo);
if (sign)
ops_writer_push_signed(cinfo, OPS_SIG_BINARY, secret_key);
else
ops_writer_push_literal(cinfo);
\endcode
*/
void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
const ops_keydata_t *pub_key)
{
ops_crypt_t* encrypt;
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
@ -81,9 +96,9 @@ void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
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;
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);
ops_write_pk_session_key(cinfo, encrypted_pk_session_key);
// Setup the arg
encrypt=ops_mallocz(sizeof *encrypt);
@ -95,144 +110,50 @@ void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
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_hash_any(&arg->hash, OPS_HASH_SHA1);
arg->hash.init(&arg->hash);
// This is a streaming writer, so we don't know the length in
// advance. Use a partial writer to handle the partial body
// packet lengths.
ops_writer_push_partial(2048, cinfo, OPS_PTAG_CT_SE_IP_DATA,
write_encrypt_se_ip_header, arg);
// And push encryption writer on stack
ops_writer_push(cinfo,
stream_encrypt_se_ip_writer,
stream_encrypt_se_ip_finaliser,
stream_encrypt_se_ip_destroyer,arg);
stream_encrypt_se_ip_writer,
stream_encrypt_se_ip_finaliser,
stream_encrypt_se_ip_destroyer, arg);
// tidy up
ops_pk_session_key_free(encrypted_pk_session_key);
free(encrypted_pk_session_key);
free(iv);
}
unsigned int ops_calc_partial_data_length(unsigned int len)
static 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)
{
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;
}
ops_writer_push_encrypt_crypt(cinfo, arg->crypt);
ops_write(data, len, cinfo);
ops_writer_pop(cinfo);
arg->hash.add(&arg->hash, data, len);
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)
// Writes out the header for the encrypted packet. Invoked by the
// partial stream writer. Note that writing the packet tag and the
// packet length is handled by the partial stream writer.
static ops_boolean_t write_encrypt_se_ip_header(ops_create_info_t *cinfo,
void *data)
{
stream_encrypt_se_ip_arg_t *arg = data;
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);
@ -241,42 +162,25 @@ ops_boolean_t ops_stream_write_se_ip_first(const unsigned char *data,
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)
static ops_boolean_t
ops_stream_write_se_ip_last(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);
@ -291,14 +195,11 @@ ops_boolean_t ops_stream_write_se_ip_last(const unsigned char *data,
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
// encode everthing
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_write(ops_memory_get_data(mem_mdc), ops_memory_get_length(mem_mdc),
cinfo);
ops_writer_pop(cinfo);
@ -316,97 +217,40 @@ static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src,
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);
}
ops_stream_write_se_ip(src, length,
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)
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);
}
// write trailer
ops_stream_write_se_ip_last(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)
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