mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-12 16:09:37 -05:00
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:
parent
eb448cbaaf
commit
c27f695a37
@ -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 ;
|
||||
}
|
||||
|
||||
|
@ -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 ;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
35
openpgpsdk/include/openpgpsdk/literal.h
Normal file
35
openpgpsdk/include/openpgpsdk/literal.h
Normal 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
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
54
openpgpsdk/include/openpgpsdk/partial.h
Normal file
54
openpgpsdk/include/openpgpsdk/partial.h
Normal 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__ */
|
@ -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
|
||||
|
@ -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__*/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
63
openpgpsdk/src/keyring_local.h
Normal file
63
openpgpsdk/src/keyring_local.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
|
||||
* All rights reserved.
|
||||
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
|
||||
* their moral rights under the UK Copyright Design and Patents Act 1988 to
|
||||
* be recorded as the authors of this copyright work.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include <openpgpsdk/packet.h>
|
||||
|
||||
#define DECLARE_ARRAY(type,arr) unsigned n##arr; unsigned n##arr##_allocated; type *arr
|
||||
#define EXPAND_ARRAY(str,arr) do if(str->n##arr == str->n##arr##_allocated) \
|
||||
{ \
|
||||
str->n##arr##_allocated=str->n##arr##_allocated*2+10; \
|
||||
str->arr=realloc(str->arr,str->n##arr##_allocated*sizeof *str->arr); \
|
||||
} while(0)
|
||||
|
||||
/** ops_keydata_key_t
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
ops_public_key_t pkey;
|
||||
ops_secret_key_t skey;
|
||||
} ops_keydata_key_t;
|
||||
|
||||
|
||||
/** sigpacket_t */
|
||||
typedef struct
|
||||
{
|
||||
ops_user_id_t* userid;
|
||||
ops_packet_t* packet;
|
||||
} sigpacket_t;
|
||||
|
||||
// XXX: gonna have to expand this to hold onto subkeys, too...
|
||||
/** \struct ops_keydata
|
||||
* \todo expand to hold onto subkeys
|
||||
*/
|
||||
struct ops_keydata
|
||||
{
|
||||
DECLARE_ARRAY(ops_user_id_t,uids);
|
||||
DECLARE_ARRAY(ops_packet_t,packets);
|
||||
DECLARE_ARRAY(sigpacket_t, sigs);
|
||||
unsigned char key_id[8];
|
||||
ops_fingerprint_t fingerprint;
|
||||
ops_content_tag_t type;
|
||||
ops_keydata_key_t key;
|
||||
};
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
85
openpgpsdk/src/writer_literal.c
Normal file
85
openpgpsdk/src/writer_literal.c
Normal 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
|
381
openpgpsdk/src/writer_partial.c
Normal file
381
openpgpsdk/src/writer_partial.c
Normal 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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user