Merged branch v0.5-OpenPGP into trunk:

User-level changes:
==================
- libgpgme is not used anymore; it is replaced by a built-in piece of code called OpenPGP-SDK 
  (http://openpgp.nominet.org.uk/cgi-bin/trac.cgi) that was improved to be used by RetroShare
  for handling PGP keys.

- the gnupg keyring is not used anymore. Now, RetroShare has it's own gpg keyring, shared by all instances.
  On linux it's located in ~/.retroshare/pgp/. A lock system prevents multiple locations to read/write keyrings
  simultaneously.

- the trust database from gnupg is not documented, so RetroShare cannot import it. This comes from the fact that
  the GPG standard (RFC4880) asks explicitly not to export trust information. So RetroShare has it's own 
  trust DB shared by locations. This means you need to re-trust people. Sorry for that!

- at start, if no keyring is found, RS will propose to copy the gnupg keyring to use your existing keys. Clicking on 
  "OK" will do the copy, and you should find back all existing locations, except for DSA keys.

- locations for which the suitable keypair is not in the keyring will not be displayed in the login window
- locations for which the suitable keypair is not a RSA/RSA key will not be displayed. RetroShare does not
  support DSA/Elgamal keypairs yet.

- a key import/export exchange function has been added in the certificate creation window (you go there from the login
  window by clicking on "manage keys/locations". This allows to easily create a new location with the same pgp key on
  another computer. To obtain a suitable keypair using gnupg, you need to concatenate the encrypted private key and the 
  public key into an ascii file. This can be done using:
  		gpg -a --export-secret-keys [your ID] > mykey.asc
		gpg -a --export [your ID] >> mykey.asc

- importing a key with subkeys in not yet possible. Please remove subkeys before importing.

- The code has been tested for a reasonnable amount of time, but it's not possible to prevent some new bugs 
  to appear. Please report them asap supplying: call-stacks if possible, and terminal output. In particular,
  openpgp has some assert()'s that should not be triggered unless RetroShare is calling it in an improper way.

Internal changes
================
- a specific component, PGPHandler, takes care of the interface between openpgp-sdk and RetroShare
  openpgp-sdk is c-code, with it's own memory management, which has been kept well separated from 
  RetroShare.

- GPG Ids are now a specific class (not a std::string anymore) for code consistency reasons. As strings are
  still used in many places, this requires a few conversions. In particular, AuthGPG takes strings as
  function params and calls GPGHandler with the proper PGPIdType class. In the future, RetroShare should
  only use PGPIdType. The same will be done for SSL ids.

- signature cleaning is still handled by the Retroshare built-in function, not by openpgp, but we will 
  do this later.

Still to do
===========
- DSA needs subkey handling, since the encryption is performed by a Elgamal subkey. Not sure this will be done.
- GPGIds/SSLIds cleaning (meaning replace strings by appropriate types). Lots of confusion throughout the code in retroshare-gui in particular.
- key removal from keyring. This is a challenge to keep locations synchronised.



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5293 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2012-07-13 21:53:39 +00:00
commit fc8dfcf65b
109 changed files with 26549 additions and 2997 deletions

42
README.txt Normal file
View File

@ -0,0 +1,42 @@
To use this branch:
chekcout the last version of openpgp SDK:
# svn co svn://openpgp.nominet.org.uk/openpgpsdk/tags/openpgpsdk-0.9 openpgpsdk
# cd openpgpsdk
# ./configure --without-idea
# make
For the moment, the compilation is not workign on ubuntu
Work to do
==========
Put a 'x' when done. 1,2,3 means started/ongoing/almost finished.
Compilation
00 [1] make sure the library compiles on linux
01 [ ] make sure the library compiles on windows
Project
02 [1] determine what's missing in OpenPGP-SDK
03 [3] make a separate layer in RS to handle PGP. AuthPGP is too close to libretroshare.
04 [1] write the new AuthGPG class
05 [ ] consider removing thread behaviour of AuthGPG
06 [ ] remove callback system and services from AuthGPG, since it's not useful anymore
07 [ ] make all RS use GPGIdType isntead of std::string.
Notes
=====
Questions to answer:
- do we rely on updates from openPGP-sdk ? Probably not. This code seems frozen.
- do we need an abstract layer for PGP handling in RS ?
- what new functionalities do we need in RS ?
* pgp keyring sharing/import/export
* identity import/export
Code struture
- replace current AuthGPG (virtual class) by a class named GPGHandler,
that is responsible for signing, checking signatures, encrypting etc.
- add a specific 8-bytes type for GPG Ids. Could be a uint64_t, or a
uchar[8]

View File

@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
openpgpsdk/src/src.pro \
libbitdht/src/libbitdht.pro \
libretroshare/src/libretroshare.pro \
retroshare-gui/src/RetroShare.pro \

View File

@ -176,6 +176,9 @@ linux-* {
INCLUDEPATH *= /usr/lib/x86_64-linux-gnu/glib-2.0/include/
INCLUDEPATH *= /usr/lib/i386-linux-gnu/glib-2.0/include/
OPENPGPSDK_DIR = ../../openpgpsdk/src
INCLUDEPATH *= $${OPENPGPSDK_DIR}
DESTDIR = lib
QMAKE_CXXFLAGS *= -Wall -D_FILE_OFFSET_BITS=64
QMAKE_CC = g++
@ -293,6 +296,8 @@ win32 {
ZLIB_DIR = ../../../zlib-1.2.3
SSL_DIR = ../../../../OpenSSL
OPENPGPSDK_DIR = ../../openpgpsdk/src
INCLUDEPATH *= $${OPENPGPSDK_DIR}
INCLUDEPATH += . $${SSL_DIR}/include $${UPNPC_DIR} $${PTHREADS_DIR} $${ZLIB_DIR} $${GPGME_DIR}/src $${GPG_ERROR_DIR}/src
}
@ -365,6 +370,8 @@ HEADERS += ft/ftchunkmap.h \
HEADERS += pqi/authssl.h \
pqi/authgpg.h \
pgp/pgphandler.h \
pgp/pgpkeyutil.h \
pqi/cleanupxpgp.h \
pqi/p3cfgmgr.h \
pqi/p3peermgr.h \
@ -483,7 +490,6 @@ HEADERS += util/folderiterator.h \
util/rsrandom.h \
util/pugiconfig.h \
util/radix64.h \
util/pgpkey.h \
util/pugixml.h
SOURCES += dbase/cachestrapper.cc \
@ -507,6 +513,8 @@ SOURCES += ft/ftchunkmap.cc \
SOURCES += pqi/authgpg.cc \
pqi/authssl.cc \
pgp/pgphandler.cc \
pgp/pgpkeyutil.cc \
pqi/cleanupxpgp.cc \
pqi/p3cfgmgr.cc \
pqi/p3peermgr.cc \
@ -626,7 +634,6 @@ SOURCES += util/folderiterator.cc \
util/rsversion.cc \
util/rswin.cc \
util/rsrandom.cc \
util/pgpkey.cc \
util/pugixml.cc
zeroconf {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,174 @@
#pragma once
// This class implements an abstract pgp handler to be used in RetroShare.
//
#include <stdint.h>
#include <string>
#include <list>
#include <map>
#include <set>
#include <util/rsthreads.h>
#include <util/rsid.h>
extern "C" {
#include <openpgpsdk/types.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/keyring_local.h>
}
static const int KEY_ID_SIZE = 8 ;
static const int KEY_FINGERPRINT_SIZE = 20 ;
typedef std::string (*PassphraseCallback)(void *data, const char *uid_hint, const char *passphrase_info, int prev_was_bad) ;
typedef t_RsGenericIdType<KEY_ID_SIZE> PGPIdType;
typedef t_RsGenericIdType<KEY_FINGERPRINT_SIZE> PGPFingerprintType ;
class PGPCertificateInfo
{
public:
PGPCertificateInfo() {}
std::string _name;
std::string _email;
std::string _comment;
std::set<std::string> signers;
uint32_t _trustLvl;
uint32_t _validLvl;
uint32_t _flags ;
PGPFingerprintType _fpr; /* fingerprint */
PGPIdType _key_id ;
uint32_t _key_index ; // index to array of keys in the public keyring
static const uint32_t PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION = 0x0001 ;
static const uint32_t PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE = 0x0002 ;
static const uint32_t PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME = 0x0004 ;
static const uint32_t PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM = 0x0008 ; // set when the key is not RSA, so that RS avoids to use it.
static const uint8_t PGP_CERTIFICATE_TRUST_UNDEFINED = 0x00 ;
static const uint8_t PGP_CERTIFICATE_TRUST_NEVER = 0x02 ;
static const uint8_t PGP_CERTIFICATE_TRUST_MARGINALLY = 0x03 ;
static const uint8_t PGP_CERTIFICATE_TRUST_FULLY = 0x04 ;
static const uint8_t PGP_CERTIFICATE_TRUST_ULTIMATE = 0x05 ;
};
class PGPHandler
{
public:
PGPHandler( const std::string& path_to_public_keyring,
const std::string& path_to_secret_keyring,
const std::string& path_to_trust_database,
const std::string& pgp_lock_file) ;
virtual ~PGPHandler() ;
/**
* @param ids list of gpg certificate ids (note, not the actual certificates)
*/
bool getGPGFilteredList(std::list<PGPIdType>& list,bool (*filter)(const PGPCertificateInfo&) = NULL) const ;
bool haveSecretKey(const PGPIdType& id) const ;
bool importGPGKeyPair(const std::string& filename,PGPIdType& imported_id,std::string& import_error) ;
bool exportGPGKeyPair(const std::string& filename,const PGPIdType& exported_id) const ;
bool availableGPGCertificatesWithPrivateKeys(std::list<PGPIdType>& ids);
bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, PGPIdType& pgpId, std::string& errString) ;
bool LoadCertificateFromString(const std::string& pem, PGPIdType& gpg_id, std::string& error_string);
std::string SaveCertificateToString(const PGPIdType& id,bool include_signatures) ;
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 PGPFingerprintType& withfingerprint) ;
bool privateSignCertificate(const PGPIdType& own_id,const PGPIdType& id_of_key_to_sign) ;
bool encryptTextToFile(const PGPIdType& key_id,const std::string& text,const std::string& outfile) ;
bool decryptTextFromFile(const PGPIdType& key_id,std::string& text,const std::string& inputfile) ;
bool getKeyFingerprint(const PGPIdType& id,PGPFingerprintType& fp) const ;
void setAcceptConnexion(const PGPIdType&,bool) ;
void updateOwnSignatureFlag(const PGPIdType& ownId) ;
//bool isKeySupported(const PGPIdType& id) const ;
bool privateTrustCertificate(const PGPIdType& id,int valid_level) ;
// Write keyring
//bool writeSecretKeyring() ;
//bool writePublicKeyring() ;
const PGPCertificateInfo *getCertificateInfo(const PGPIdType& id) const ;
bool isGPGId(const std::string &id);
bool isGPGSigned(const std::string &id);
bool isGPGAccepted(const std::string &id);
static void setPassphraseCallback(PassphraseCallback cb) ;
static PassphraseCallback passphraseCallback() { return _passphrase_callback ; }
// Debug stuff.
virtual bool printKeys() const ;
// Syncs the keyrings and trust database between memory and disk. The algorithm is:
// 1 - lock the keyrings
// 2 - compare file modification dates with last writing date
// - if file is modified, load it, and merge with memory
// 3 - look into memory modification flags
// - if flag says keyring has changed, write to disk
//
bool syncDatabase() ;
private:
void initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t i) ;
// Returns true if the signatures have been updated
//
bool validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_keydata_t *keydata) ;
const ops_keydata_t *getPublicKey(const PGPIdType&) const ;
const ops_keydata_t *getSecretKey(const PGPIdType&) const ;
void locked_readPrivateTrustDatabase() ;
bool locked_writePrivateTrustDatabase() ;
bool locked_syncPublicKeyring() ;
bool locked_syncTrustDatabase() ;
void mergeKeyringFromDisk(ops_keyring_t *keyring, std::map<std::string,PGPCertificateInfo>& kmap, const std::string& keyring_file) ;
bool addOrMergeKey(ops_keyring_t *keyring,std::map<std::string,PGPCertificateInfo>& kmap,const ops_keydata_t *keydata) ;
// Members.
//
mutable RsMutex pgphandlerMtx ;
ops_keyring_t *_pubring ;
ops_keyring_t *_secring ;
std::map<std::string,PGPCertificateInfo> _public_keyring_map ; // used for fast access to keys. Gives the index in the keyring.
std::map<std::string,PGPCertificateInfo> _secret_keyring_map ;
const std::string _pubring_path ;
const std::string _secring_path ;
const std::string _trustdb_path ;
const std::string _pgp_lock_filename ;
bool _pubring_changed ;
bool _trustdb_changed ;
time_t _pubring_last_update_time ;
time_t _secring_last_update_time ;
time_t _trustdb_last_update_time ;
// Helper functions.
//
static std::string makeRadixEncodedPGPKey(const ops_keydata_t *key) ;
static ops_keyring_t *allocateOPSKeyring() ;
static void addNewKeyToOPSKeyring(ops_keyring_t*, const ops_keydata_t&) ;
static PassphraseCallback _passphrase_callback ;
static bool mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) ; // returns true if signature lists are different
};

View File

@ -1,6 +1,6 @@
#include <stdint.h>
#include <util/radix64.h>
#include "pgpkey.h"
#include "pgpkeyutil.h"
#include <iostream>
#include <stdexcept>
@ -9,10 +9,6 @@
/* #define DEBUG_PGPUTIL 1 */
/****************************/
#define PGP_PACKET_TAG_PUBLIC_KEY 6
#define PGP_PACKET_TAG_USER_ID 13
#define PGP_PACKET_TAG_SIGNATURE 2
#define PGP_CRC24_INIT 0xB704CEL
#define PGP_CRC24_POLY 0x1864CFBL
@ -85,11 +81,11 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
data += packet_length ;
if(packet_tag == PGP_PACKET_TAG_PUBLIC_KEY)
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY)
public_key = true ;
if(packet_tag == PGP_PACKET_TAG_USER_ID)
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID)
user_id = true ;
if(packet_tag == PGP_PACKET_TAG_SIGNATURE)
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE)
own_signature = true ;
if(public_key && own_signature && user_id)
@ -99,28 +95,7 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
break ;
}
std::string outstring ;
Radix64::encode(keydata,(uint64_t)data - (uint64_t)keydata,outstring) ;
uint32_t crc = compute24bitsCRC((unsigned char *)keydata,(uint64_t)data - (uint64_t)keydata) ;
unsigned char tmp[3] = { (crc >> 16) & 0xff, (crc >> 8) & 0xff, crc & 0xff } ;
std::string crc_string ;
Radix64::encode((const char *)tmp,3,crc_string) ;
#ifdef DEBUG_PGPUTIL
std::cerr << "After signature pruning: " << std::endl;
std::cerr << outstring << std::endl;
#endif
cleaned_certificate = std::string(PGP_CERTIFICATE_START_STRING) + "\n" + version_string + "\n\n" ;
for(uint32_t i=0;i<outstring.length();i+=64)
cleaned_certificate += outstring.substr(i,64) + "\n" ;
cleaned_certificate += "=" + crc_string + "\n" ;
cleaned_certificate += std::string(PGP_CERTIFICATE_END_STRING) + "\n" ;
cleaned_certificate = makeArmouredKey((unsigned char*)keydata,(uint64_t)data - (uint64_t)keydata,version_string) ;
return true ;
}
catch(std::exception& e)
@ -131,6 +106,33 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
}
}
std::string PGPKeyManagement::makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string)
{
std::string outstring ;
Radix64::encode((const char *)keydata,key_size,outstring) ;
uint32_t crc = compute24bitsCRC((unsigned char *)keydata,key_size) ;
unsigned char tmp[3] = { (crc >> 16) & 0xff, (crc >> 8) & 0xff, crc & 0xff } ;
std::string crc_string ;
Radix64::encode((const char *)tmp,3,crc_string) ;
#ifdef DEBUG_PGPUTIL
std::cerr << "After signature pruning: " << std::endl;
std::cerr << outstring << std::endl;
#endif
std::string certificate = std::string(PGP_CERTIFICATE_START_STRING) + "\n" + version_string + "\n\n" ;
for(uint32_t i=0;i<outstring.length();i+=64)
certificate += outstring.substr(i,64) + "\n" ;
certificate += "=" + crc_string + "\n" ;
certificate += std::string(PGP_CERTIFICATE_END_STRING) + "\n" ;
return certificate ;
}
uint32_t PGPKeyManagement::compute24bitsCRC(unsigned char *octets, size_t len)
{
long crc = PGP_CRC24_INIT;
@ -171,6 +173,7 @@ uint32_t PGPKeyParser::read_125Size(unsigned char *& data)
return b1 ;
uint8_t b2 = *data ;
++data ;
if(b1 < 224)
return ((b1-192) << 8) + b2 + 192 ;

View File

@ -59,6 +59,7 @@ class PGPKeyManagement
//
static bool createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) ;
static std::string makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) ;
private:
// Computes the 24 bits CRC checksum necessary to all PGP data.
//
@ -70,6 +71,10 @@ class PGPKeyManagement
class PGPKeyParser
{
public:
static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY = 6 ;
static const uint8_t PGP_PACKET_TAG_USER_ID = 13 ;
static const uint8_t PGP_PACKET_TAG_SIGNATURE = 2 ;
static uint64_t read_KeyID(unsigned char *& data) ;
static uint32_t read_125Size(unsigned char *& data) ;
static uint32_t read_partialBodyLength(unsigned char *& data) ;

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,7 @@
#include <set>
#include <map>
#include "pqi/p3cfgmgr.h"
#include "pgp/pgphandler.h"
#define MAX_GPG_SIGNATURE_SIZE 4096
@ -57,39 +58,8 @@ class RsPeerDetails;
/*!
* gpgcert is the identifier for a person.
* It is a wrapper class for a GPGme OpenPGP certificate.
* It is a wrapper class for a OpenPGP certificate.
*/
class AuthGPG;
class gpgcert
{
public:
gpgcert();
~gpgcert();
std::string id;
std::string name;
std::string email;
std::string fpr; /* fingerprint */
std::list<std::string> signers;
uint32_t trustLvl;
uint32_t validLvl;
bool ownsign;
//This is not gpg, but RS data. A gpg peer can be accepted for connecting but not signed.
bool accept_connection;
gpgme_key_t key;
// Cached Certificates...
bool mHaveCachedCert;
std::string mCachedCert;
};
class AuthGPGOperation
{
@ -135,427 +105,289 @@ public:
virtual void setGPGOperation(AuthGPGOperation *operation) = 0;
};
/*!
* The certificate map type
*/
typedef std::map<std::string, gpgcert> certmap;
//! provides basic gpg functionality
/*!
*
* This provides retroshare basic gpg functionality and
* key/web-of-trust management, also handle cert intialisation for retroshare
*/
extern void AuthGPGInit();
extern void AuthGPGExit();
class AuthGPG : public RsThread
{
public:
//AuthGPG();
static AuthGPG *getAuthGPG();
/**
* @param ids list of gpg certificate ids (note, not the actual certificates)
*/
virtual bool availableGPGCertificatesWithPrivateKeys(std::list<std::string> &ids) = 0;
virtual bool printKeys() = 0;
/*********************************************************************************/
/************************* STAGE 1 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions
* will be different. Just move the initialisation functions over....
*
* As GPGMe requires external calls to the GPG executable, which could potentially
* be expensive, We'll want to cache the GPG keys in this class.
* This should be done at initialisation, and saved in a map.
* (see storage at the end of the class)
*
****/
virtual bool active() = 0;
/* Initialize */
virtual bool InitAuth () = 0;
/* Init by generating new Own PGP Cert, or selecting existing PGP Cert */
virtual int GPGInit(const std::string &ownId) = 0;
virtual bool CloseAuth() = 0;
virtual bool GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString) = 0;
/*********************************************************************************/
/************************* STAGE 3 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 3: These are some of the most commonly used functions in Retroshare.
*
* More commonly used functions.
*
* provide access to details in cache list.
*
****/
virtual std::string getGPGName(const std::string &pgp_id) = 0;
virtual std::string getGPGEmail(const std::string &pgp_id) = 0;
/* PGP web of trust management */
virtual std::string getGPGOwnId() = 0;
virtual std::string getGPGOwnName() = 0;
//virtual std::string getGPGOwnEmail() = 0;
virtual bool getGPGDetails(const std::string &id, RsPeerDetails &d) = 0;
virtual bool getGPGAllList(std::list<std::string> &ids) = 0;
virtual bool getGPGValidList(std::list<std::string> &ids) = 0;
virtual bool getGPGAcceptedList(std::list<std::string> &ids) = 0;
virtual bool getGPGSignedList(std::list<std::string> &ids) = 0;
virtual bool isGPGValid(const std::string &id) = 0;
virtual bool isGPGSigned(const std::string &id) = 0;
virtual bool isGPGAccepted(const std::string &id) = 0;
virtual bool isGPGId(const std::string &id) = 0;
/*********************************************************************************/
/************************* STAGE 4 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 4: Loading and Saving Certificates. (Strings and Files)
*
****/
virtual bool LoadCertificateFromString(const std::string &pem, std::string &gpg_id,std::string& error_string) = 0;
virtual std::string SaveCertificateToString(const std::string &id,bool include_signatures) = 0;
/*********************************************************************************/
/************************* STAGE 6 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 6: Authentication, Trust and Signing.
*
* This is some of the harder functions, but they should have been
* done in gpgroot already.
*
****/
virtual bool AllowConnection(const std::string &gpg_id, bool accept) = 0;
virtual bool SignCertificateLevel0(const std::string &id) = 0;
virtual bool RevokeCertificate(const std::string &id) = 0; /* Particularly hard - leave for later */
//virtual bool TrustCertificateNone(std::string id) = 0;
//virtual bool TrustCertificateMarginally(std::string id) = 0;
//virtual bool TrustCertificateFully(std::string id) = 0;
virtual bool TrustCertificate(const std::string &id, int trustlvl) = 0; //trustlvl is 2 for none, 3 for marginal and 4 for full trust
/*********************************************************************************/
/************************* STAGE 7 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 7: Signing Data.
*
* There should also be Encryption Functions... (do later).
*
****/
//virtual bool SignData(std::string input, std::string &sign) = 0;
//virtual bool SignData(const void *data, const uint32_t len, std::string &sign) = 0;
//virtual bool SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen) = 0;
virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) = 0;
virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string &withfingerprint) = 0;
virtual bool decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) = 0;
virtual bool encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) = 0;
//END of PGP public functions
/* GPG service */
virtual bool addService(AuthGPGService *service) = 0;
};
/* The real implementation! */
class AuthGPGimpl : public AuthGPG, public p3Config
class AuthGPG: public p3Config, public RsThread, public PGPHandler
{
public:
AuthGPGimpl();
~AuthGPGimpl();
static void init( const std::string& path_to_pubring,
const std::string& path_to_secring,
const std::string& path_to_trustdb,
const std::string& pgp_lock_file);
/**
* @param ids list of gpg certificate ids (note, not the actual certificates)
*/
virtual bool availableGPGCertificatesWithPrivateKeys(std::list<std::string> &ids);
static void exit();
static AuthGPG *getAuthGPG() { return _instance ; }
virtual bool printKeys();
/**
* @param ids list of gpg certificate ids (note, not the actual certificates)
*/
virtual bool availableGPGCertificatesWithPrivateKeys(std::list<std::string> &ids);
/*********************************************************************************/
/************************* STAGE 1 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions
* will be different. Just move the initialisation functions over....
*
* As GPGMe requires external calls to the GPG executable, which could potentially
* be expensive, We'll want to cache the GPG keys in this class.
* This should be done at initialisation, and saved in a map.
* (see storage at the end of the class)
*
****/
virtual bool active();
/*********************************************************************************/
/************************* STAGE 1 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 1: Initialisation.... As we are switching to OpenPGP the init functions
* will be different. Just move the initialisation functions over....
*
* As GPGMe requires external calls to the GPG executable, which could potentially
* be expensive, We'll want to cache the GPG keys in this class.
* This should be done at initialisation, and saved in a map.
* (see storage at the end of the class)
*
****/
virtual bool active();
/* Initialize */
virtual bool InitAuth ();
// /* Initialize */
// virtual bool InitAuth ();
// virtual bool CloseAuth();
/* Init by generating new Own PGP Cert, or selecting existing PGP Cert */
virtual int GPGInit(const std::string &ownId);
virtual bool CloseAuth();
virtual bool GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString);
/* Init by generating new Own PGP Cert, or selecting existing PGP Cert */
/*********************************************************************************/
/************************* STAGE 3 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 3: These are some of the most commonly used functions in Retroshare.
*
* More commonly used functions.
*
* provide access to details in cache list.
*
****/
virtual std::string getGPGName(const std::string &pgp_id);
virtual std::string getGPGEmail(const std::string &pgp_id);
virtual int GPGInit(const std::string &ownId);
virtual bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, std::string &pgpId, std::string &errString);
/* PGP web of trust management */
virtual std::string getGPGOwnId();
virtual std::string getGPGOwnName();
/*********************************************************************************/
/************************* STAGE 3 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 3: These are some of the most commonly used functions in Retroshare.
*
* More commonly used functions.
*
* provide access to details in cache list.
*
****/
virtual std::string getGPGName(const std::string &pgp_id,bool *success = NULL);
virtual std::string getGPGEmail(const std::string &pgp_id,bool *success = NULL);
//virtual std::string getGPGOwnEmail();
virtual bool getGPGDetails(const std::string &id, RsPeerDetails &d);
virtual bool getGPGAllList(std::list<std::string> &ids);
virtual bool getGPGValidList(std::list<std::string> &ids);
virtual bool getGPGAcceptedList(std::list<std::string> &ids);
virtual bool getGPGSignedList(std::list<std::string> &ids);
virtual bool isGPGValid(const std::string &id);
virtual bool isGPGSigned(const std::string &id);
virtual bool isGPGAccepted(const std::string &id);
virtual bool isGPGId(const std::string &id);
/* PGP web of trust management */
virtual std::string getGPGOwnId();
virtual std::string getGPGOwnName();
/*********************************************************************************/
/************************* STAGE 4 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 4: Loading and Saving Certificates. (Strings and Files)
*
****/
virtual bool LoadCertificateFromString(const std::string &pem, std::string &gpg_id,std::string& error_string);
virtual std::string SaveCertificateToString(const std::string &id,bool include_signatures) ;
//virtual std::string getGPGOwnEmail();
virtual bool isKeySupported(const std::string &id) const ;
virtual bool haveSecretKey(const std::string &id) const ;
virtual bool getGPGDetails(const std::string &id, RsPeerDetails &d);
virtual bool getGPGAllList(std::list<std::string> &ids);
virtual bool getGPGValidList(std::list<std::string> &ids);
virtual bool getGPGAcceptedList(std::list<std::string> &ids);
virtual bool getGPGSignedList(std::list<std::string> &ids);
virtual bool importProfile(const std::string& filename,std::string& gpg_id,std::string& import_error) ;
virtual bool exportProfile(const std::string& filename,const std::string& gpg_id) ;
// Cached certificates.
bool cacheGPGCertificate(const std::string &id, const std::string &certificate);
bool getCachedGPGCertificate(const std::string &id, std::string &certificate);
/*********************************************************************************/
/************************* STAGE 4 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 4: Loading and Saving Certificates. (Strings and Files)
*
****/
virtual bool LoadCertificateFromString(const std::string &pem, std::string &gpg_id,std::string& error_string);
virtual std::string SaveCertificateToString(const std::string &id,bool include_signatures) ;
/*********************************************************************************/
/************************* STAGE 6 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 6: Authentication, Trust and Signing.
*
* This is some of the harder functions, but they should have been
* done in gpgroot already.
*
****/
virtual bool AllowConnection(const std::string &gpg_id, bool accept);
// Cached certificates.
bool getCachedGPGCertificate(const std::string &id, std::string &certificate);
virtual bool SignCertificateLevel0(const std::string &id);
virtual bool RevokeCertificate(const std::string &id); /* Particularly hard - leave for later */
/*********************************************************************************/
/************************* STAGE 6 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 6: Authentication, Trust and Signing.
*
* This is some of the harder functions, but they should have been
* done in gpgroot already.
*
****/
virtual bool AllowConnection(const std::string &gpg_id, bool accept);
//virtual bool TrustCertificateNone(std::string id);
//virtual bool TrustCertificateMarginally(std::string id);
//virtual bool TrustCertificateFully(std::string id);
virtual bool TrustCertificate(const std::string &id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust
virtual bool SignCertificateLevel0(const std::string &id);
virtual bool RevokeCertificate(const std::string &id); /* Particularly hard - leave for later */
/*********************************************************************************/
/************************* STAGE 7 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 7: Signing Data.
*
* There should also be Encryption Functions... (do later).
*
****/
//virtual bool SignData(std::string input, std::string &sign);
//virtual bool SignData(const void *data, const uint32_t len, std::string &sign);
//virtual bool SignDataBin(std::string input, unsigned char *sign, unsigned int *signlen);
virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen);
virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string &withfingerprint);
virtual bool decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN);
virtual bool encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER);
//END of PGP public functions
virtual bool TrustCertificate(const std::string &id, int trustlvl); //trustlvl is 2 for none, 3 for marginal and 4 for full trust
/* GPG service */
virtual bool addService(AuthGPGService *service);
/*********************************************************************************/
/************************* STAGE 7 ***********************************************/
/*********************************************************************************/
/*****
* STAGE 7: Signing Data.
*
* There should also be Encryption Functions... (do later).
*
****/
virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen);
virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const std::string &withfingerprint);
protected:
/*****************************************************************/
/*********************** p3config ******************************/
/* Key Functions to be overloaded for Full Configuration */
virtual RsSerialiser *setupSerialiser();
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
virtual bool loadList(std::list<RsItem *>& load);
/*****************************************************************/
virtual bool decryptTextFromFile( std::string& text,const std::string& filename);
virtual bool encryptTextToFile (const std::string& text,const std::string& filename);
bool getGPGFilteredList(std::list<std::string>& list,bool (*filter)(const PGPCertificateInfo&) = NULL) ;
//END of PGP public functions
/* GPG service */
virtual bool addService(AuthGPGService *service) ;
protected:
AuthGPG(const std::string& path_to_pubring, const std::string& path_to_secring,const std::string& path_to_trustdb,const std::string& pgp_lock_file);
virtual ~AuthGPG();
/*****************************************************************/
/*********************** p3config ******************************/
/* Key Functions to be overloaded for Full Configuration */
virtual RsSerialiser *setupSerialiser();
virtual bool saveList(bool &cleanup, std::list<RsItem *>&);
virtual bool loadList(std::list<RsItem *>& load);
/*****************************************************************/
private:
/* SKTAN */
//void showData(gpgme_data_t dh);
//void createDummyFriends(void); //NYI
/* SKTAN */
//void showData(gpgme_data_t dh);
//void createDummyFriends(void); //NYI
/* Internal functions */
bool DoOwnSignature(const void *, unsigned int, void *, unsigned int *);
bool VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const std::string &withfingerprint);
/* Internal functions */
bool DoOwnSignature(const void *, unsigned int, void *, unsigned int *);
bool VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const std::string &withfingerprint);
/* Sign/Trust stuff */
int privateSignCertificate(const std::string &id);
int privateRevokeCertificate(const std::string &id); /* revoke the signature on Certificate */
int privateTrustCertificate(const std::string &id, int trustlvl);
/* Sign/Trust stuff */
int privateSignCertificate(const std::string &id);
int privateRevokeCertificate(const std::string &id); /* revoke the signature on Certificate */
int privateTrustCertificate(const std::string &id, int trustlvl);
// store all keys in map mKeyList to avoid calling gpgme exe repeatedly
//bool storeAllKeys();
//bool storeAllKeys_tick();
// store all keys in map mKeyList to avoid calling gpgme exe repeatedly
bool storeAllKeys();
bool storeAllKeys_tick();
// Not used anymore
// bool updateTrustAllKeys_locked();
// Not used anymore
// bool updateTrustAllKeys_locked();
/* GPG service */
void processServices();
/* GPG service */
void processServices();
bool printAllKeys_locked();
bool printOwnKeys_locked();
bool printAllKeys_locked();
bool printOwnKeys_locked();
/* own thread */
virtual void run();
/* own thread */
virtual void run();
private:
private:
static AuthGPG *instance_gpg; // pointeur vers le singleton
static AuthGPG *instance_gpg; // pointeur vers le singleton
RsMutex gpgMtxService;
RsMutex gpgMtxEngine;
RsMutex gpgMtxEngine;
/* Below is protected via the mutex */
/* Below is protected via the mutex */
gpgme_engine_info_t INFO;
gpgme_ctx_t CTX;
// gpgme_engine_info_t INFO;
// gpgme_ctx_t CTX;
RsMutex gpgMtxData;
/* Below is protected via the mutex */
RsMutex gpgMtxData;
/* Below is protected via the mutex */
certmap mKeyList;
time_t mStoreKeyTime;
time_t mStoreKeyTime;
bool gpgmeInit;
PGPIdType mOwnGpgId;
bool gpgKeySelected;
bool _force_sync_database ;
bool gpgmeKeySelected;
std::string mOwnGpgId;
gpgcert mOwnGpgCert;
std::list<AuthGPGService*> services ;
std::map<std::string, bool> mAcceptToConnectMap;
RsMutex gpgMtxService;
/* Below is protected via the mutex */
std::list<AuthGPGService*> services;
};
/*!
* Sign a key
**/
typedef enum
{
SIGN_START,
SIGN_COMMAND,
SIGN_UIDS,
SIGN_SET_EXPIRE,
SIGN_SET_CHECK_LEVEL,
SIGN_ENTER_PASSPHRASE,
SIGN_CONFIRM,
SIGN_QUIT,
SIGN_SAVE,
SIGN_ERROR
} SignState;
/*!
* Change the key ownertrust
**/
typedef enum
{
TRUST_START,
TRUST_COMMAND,
TRUST_VALUE,
TRUST_REALLY_ULTIMATE,
TRUST_QUIT,
TRUST_SAVE,
TRUST_ERROR
} TrustState;
/*!
* This is the generic data object passed to the
* callback function in a gpgme_op_edit operation.
* The contents of this object are modified during
* each callback, to keep track of states, errors
* and other data.
*/
class EditParams
{
public:
int state;
/*!
* The return code of gpgme_op_edit() is the return value of
* the last invocation of the callback. But returning an error
* from the callback does not abort the edit operation, so we
* must remember any error.
*/
gpg_error_t err;
/// Parameters specific to the key operation
void *oParams;
EditParams(int state, void *oParams) {
this->state = state;
this->err = gpgme_error(GPG_ERR_NO_ERROR);
this->oParams = oParams;
}
};
/*!
* Data specific to key signing
**/
class SignParams
{
public:
std::string checkLvl;
SignParams(std::string checkLvl) {
this->checkLvl = checkLvl;
}
};
/*!
* Data specific to key signing
**/
class TrustParams
{
public:
std::string trustLvl;
TrustParams(std::string trustLvl) {
this->trustLvl = trustLvl;
}
static AuthGPG *_instance ;
};
/*!
* Sign a key
**/
typedef enum
{
SIGN_START,
SIGN_COMMAND,
SIGN_UIDS,
SIGN_SET_EXPIRE,
SIGN_SET_CHECK_LEVEL,
SIGN_ENTER_PASSPHRASE,
SIGN_CONFIRM,
SIGN_QUIT,
SIGN_SAVE,
SIGN_ERROR
} SignState;
/*!
* Change the key ownertrust
**/
typedef enum
{
TRUST_START,
TRUST_COMMAND,
TRUST_VALUE,
TRUST_REALLY_ULTIMATE,
TRUST_QUIT,
TRUST_SAVE,
TRUST_ERROR
} TrustState;
/*!
* This is the generic data object passed to the
* callback function in a gpgme_op_edit operation.
* The contents of this object are modified during
* each callback, to keep track of states, errors
* and other data.
*/
class EditParams
{
public:
int state;
/*!
* The return code of gpgme_op_edit() is the return value of
* the last invocation of the callback. But returning an error
* from the callback does not abort the edit operation, so we
* must remember any error.
*/
gpg_error_t err;
/// Parameters specific to the key operation
void *oParams;
EditParams(int state, void *oParams) {
this->state = state;
this->err = gpgme_error(GPG_ERR_NO_ERROR);
this->oParams = oParams;
}
};
/*!
* Data specific to key signing
**/
class SignParams
{
public:
std::string checkLvl;
SignParams(std::string checkLvl) {
this->checkLvl = checkLvl;
}
};
/*!
* Data specific to key signing
**/
class TrustParams
{
public:
std::string trustLvl;
TrustParams(std::string trustLvl) {
this->trustLvl = trustLvl;
}
};
#endif

View File

@ -204,7 +204,10 @@ void setAuthSSL(AuthSSL *newssl)
void AuthSSLInit()
{
instance_ssl = new AuthSSLimpl();
if (instance_ssl == NULL)
{
instance_ssl = new AuthSSLimpl();
}
}
AuthSSL *AuthSSL::getAuthSSL()

View File

@ -287,7 +287,18 @@ std::string cleanUpCertificate(const std::string& badCertificate,int& error_code
while(currBadCertIdx < endCertStartIdx1 && (badCertificate[currBadCertIdx] == '=' || badCertificate[currBadCertIdx] == ' ' || badCertificate[currBadCertIdx] == '\n' ))
currBadCertIdx++ ;
cleanCertificate += "==\n=";
switch(cntPerLine % 4)
{
case 0: break ;
case 1: std::cerr<<"Certificate corrupted beyond repair: wrongnumber of chars on last line (n%4=1)"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER;
return badCertificate ;
case 2: cleanCertificate += "==" ;
break ;
case 3: cleanCertificate += "=" ;
break ;
}
cleanCertificate += "\n=";
// if (badCertificate[currBadCertIdx] == '=')
// {

View File

@ -32,6 +32,7 @@
// Initialize failed, result < 0
#define RS_INIT_AUTH_FAILED -1 // AuthGPG::InitAuth failed
#define RS_INIT_BASE_DIR_ERROR -2 // AuthGPG::InitAuth failed
#define RS_INIT_NO_KEYRING -3 // Keyring is empty. Need to import it.
/****
@ -79,6 +80,8 @@ class RsInit
static bool ValidateCertificate(std::string &userName) ;
static bool exportIdentity(const std::string& fname,const std::string& pgp_id) ;
static bool importIdentity(const std::string& fname,std::string& imported_pgp_id,std::string& import_error) ;
/*!
* Generating GPGme Account
@ -87,6 +90,9 @@ class RsInit
static int GetPGPLoginDetails(const std::string& id, std::string &name, std::string &email);
static bool GeneratePGPCertificate(const std::string&, const std::string& email, const std::string& passwd, std::string &pgpId, std::string &errString);
// copies existing gnupg keyrings to the new place of the OpenPGP-SDK version. Returns true on success.
static bool copyGnuPGKeyrings() ;
/*!
* Login GGP
*/

View File

@ -38,12 +38,14 @@
class RsPeers;
extern RsPeers *rsPeers;
/* Trust Levels */
const uint32_t RS_TRUST_LVL_NONE = 2;
const uint32_t RS_TRUST_LVL_MARGINAL = 3;
const uint32_t RS_TRUST_LVL_FULL = 4;
const uint32_t RS_TRUST_LVL_ULTIMATE = 5;
/* Trust Levels. Should be the same values than what is declared in PGPHandler.h */
const uint32_t RS_TRUST_LVL_UNDEFINED = 0;
const uint32_t RS_TRUST_LVL_UNKNOWN = 1;
const uint32_t RS_TRUST_LVL_NEVER = 2;
const uint32_t RS_TRUST_LVL_MARGINAL = 3;
const uint32_t RS_TRUST_LVL_FULL = 4;
const uint32_t RS_TRUST_LVL_ULTIMATE = 5;
/* Net Mode */
const uint32_t RS_NETMODE_UDP = 0x0001;
@ -76,6 +78,7 @@ const int RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR = 0x01 ;
const int RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG = 0x02 ;
const int RS_PEER_CERT_CLEANING_CODE_NO_END_TAG = 0x03 ;
const int RS_PEER_CERT_CLEANING_CODE_NO_CHECKSUM = 0x04 ;
const int RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER = 0x05 ;
/* LinkType Flags */
@ -231,6 +234,7 @@ virtual bool getPeerDetails(const std::string &ssl_or_gpg_id, RsPeerDetails &d)
/* Using PGP Ids */
virtual std::string getGPGOwnId() = 0;
virtual std::string getGPGId(const std::string &sslid_or_gpgid) = 0; //return the gpg id of the given gpg or ssl id
virtual bool isKeySupported(const std::string& gpg_ids) = 0;
virtual bool getGPGAcceptedList(std::list<std::string> &gpg_ids) = 0;
virtual bool getGPGSignedList(std::list<std::string> &gpg_ids) = 0;//friends that we accpet to connect with but we don't want to sign their gpg key
virtual bool getGPGValidList(std::list<std::string> &gpg_ids) = 0;

View File

@ -190,5 +190,5 @@ void RsServer::rsGlobalShutDown()
mBlogs->join();
#endif
AuthGPGExit();
AuthGPG::exit();
}

View File

@ -595,6 +595,10 @@ bool p3Peers::getPeerDetails(const std::string &id, RsPeerDetails &d)
}
#endif
bool p3Peers::isKeySupported(const std::string& id)
{
return AuthGPG::getAuthGPG()->isKeySupported(id);
}
std::string p3Peers::getGPGName(const std::string &gpg_id)
{

View File

@ -63,6 +63,7 @@ virtual bool getPeerDetails(const std::string &ssl_or_gpg_id, RsPeerDetails &d);
/* Using PGP Ids */
virtual std::string getGPGOwnId();
virtual std::string getGPGId(const std::string &ssl_id);
virtual bool isKeySupported(const std::string& ids);
virtual bool getGPGAcceptedList(std::list<std::string> &ids);
virtual bool getGPGSignedList(std::list<std::string> &ids);
virtual bool getGPGValidList(std::list<std::string> &ids);

View File

@ -92,11 +92,7 @@ class RsInitConfig
/* for certificate creation */
//static std::string gpgPasswd;
#ifndef WINDOWS_SYS
static int lockHandle;
#else
static HANDLE lockHandle;
#endif
static rs_lock_handle_t lockHandle;
/* These fields are needed for login */
static std::string loginId;
@ -151,11 +147,7 @@ static const int SSLPWD_LEN = 64;
std::list<accountId> RsInitConfig::accountIds;
std::string RsInitConfig::preferedId;
#ifndef WINDOWS_SYS
int RsInitConfig::lockHandle;
#else
HANDLE RsInitConfig::lockHandle;
#endif
rs_lock_handle_t RsInitConfig::lockHandle;
std::string RsInitConfig::configDir;
std::string RsInitConfig::load_cert;
@ -197,7 +189,7 @@ bool RsInitConfig::udpListenerOnly;
/* Uses private class - so must be hidden */
static bool getAvailableAccounts(std::list<accountId> &ids);
static bool getAvailableAccounts(std::list<accountId> &ids,int& failing_accounts);
static bool checkAccount(std::string accountdir, accountId &id);
static std::string toUpperCase(const std::string& s)
@ -253,7 +245,7 @@ void RsInit::InitRsConfig()
#ifdef WINDOWS_SYS
// test for portable version
if (GetFileAttributes (L"gpg.exe") != (DWORD) -1 && GetFileAttributes (L"gpgme-w32spawn.exe") != (DWORD) -1) {
if (GetFileAttributes(L"portable") != (DWORD) -1) {
// use portable version
RsInitConfig::portable = true;
}
@ -611,9 +603,7 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
*/
/* create singletons */
AuthSSLInit();
AuthGPGInit();
AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL);
AuthSSL::getAuthSSL() -> InitAuth(NULL, NULL, NULL);
// first check config directories, and set bootstrap values.
if(!setupBaseDir())
@ -621,17 +611,31 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
get_configinit(RsInitConfig::basedir, RsInitConfig::preferedId);
std::string pgp_dir = RsInitConfig::basedir + "/pgp" ;
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ;
AuthGPG::init( pgp_dir + "/retroshare_public_keyring.gpg",
pgp_dir + "/retroshare_secret_keyring.gpg",
pgp_dir + "/retroshare_trustdb.gpg",
pgp_dir + "/lock");
/* Initialize AuthGPG */
if (AuthGPG::getAuthGPG()->InitAuth() == false) {
std::cerr << "AuthGPG::InitAuth failed" << std::endl;
return RS_INIT_AUTH_FAILED;
}
// if (AuthGPG::getAuthGPG()->InitAuth() == false) {
// std::cerr << "AuthGPG::InitAuth failed" << std::endl;
// return RS_INIT_AUTH_FAILED;
// }
//std::list<accountId> ids;
std::list<accountId>::iterator it;
getAvailableAccounts(RsInitConfig::accountIds);
int failing_accounts ;
// if a different user id has been passed to cmd line check for that instead
getAvailableAccounts(RsInitConfig::accountIds,failing_accounts);
if(failing_accounts > 0 && RsInitConfig::accountIds.empty())
return RS_INIT_NO_KEYRING ;
// if a different user id has been passed to cmd line check for that instead
std::string lower_case_user_string = toLowerCase(prefUserString) ;
std::string upper_case_user_string = toUpperCase(prefUserString) ;
@ -669,8 +673,9 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
{
std::cerr << " * Preferred * " << std::endl;
userId = it->sslId;
userName = it->pgpName;
userName = it->pgpName;
existingUser = true;
break;
}
}
if (!existingUser)
@ -702,6 +707,54 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored, bool strictCheck
/**************************** Access Functions for Init Data **************************/
bool RsInit::exportIdentity(const std::string& fname,const std::string& id)
{
return AuthGPG::getAuthGPG()->exportProfile(fname,id);
}
bool RsInit::importIdentity(const std::string& fname,std::string& id,std::string& import_error)
{
return AuthGPG::getAuthGPG()->importProfile(fname,id,import_error);
}
bool RsInit::copyGnuPGKeyrings()
{
std::string pgp_dir = RsInitConfig::basedir + "/pgp" ;
if(!RsDirUtil::checkCreateDirectory(pgp_dir))
throw std::runtime_error("Cannot create pgp directory " + pgp_dir) ;
std::string source_public_keyring;
std::string source_secret_keyring;
#ifdef WINDOWS_SYS
if (RsInit::isPortable())
{
source_public_keyring = RsInit::RsConfigDirectory() + "/gnupg/pubring.gpg";
source_secret_keyring = RsInit::RsConfigDirectory() + "/gnupg/secring.gpg" ;
} else {
source_public_keyring = RsInitConfig::basedir + "/../gnupg/pubring.gpg" ;
source_secret_keyring = RsInitConfig::basedir + "/../gnupg/secring.gpg" ;
}
#else
// We need a specific part for MacOS and Linux as well
source_public_keyring = RsInitConfig::basedir + "/../.gnupg/pubring.gpg" ;
source_secret_keyring = RsInitConfig::basedir + "/../.gnupg/secring.gpg" ;
#endif
if(!RsDirUtil::copyFile(source_public_keyring,pgp_dir + "/retroshare_public_keyring.gpg"))
{
std::cerr << "Cannot copy pub keyring " << source_public_keyring << " to destination file " << pgp_dir + "/retroshare_public_keyring.pgp" << std::endl;
return false ;
}
if(!RsDirUtil::copyFile(source_secret_keyring,pgp_dir + "/retroshare_secret_keyring.gpg"))
{
std::cerr << "Cannot copy sec keyring " << source_secret_keyring << " to destination file " << pgp_dir + "/retroshare_secret_keyring.pgp" << std::endl;
return false ;
}
return true ;
}
bool RsInit::getPreferedAccountId(std::string &id)
{
id = RsInitConfig::preferedId;
@ -939,8 +992,9 @@ std::string RsInit::getRetroshareDataDirectory()
/* directories with valid certificates in the expected location */
bool getAvailableAccounts(std::list<accountId> &ids)
bool getAvailableAccounts(std::list<accountId> &ids,int& failing_accounts)
{
failing_accounts = 0 ;
/* get the directories */
std::list<std::string> directories;
std::list<std::string>::iterator it;
@ -1023,6 +1077,8 @@ bool getAvailableAccounts(std::list<accountId> &ids)
#endif
ids.push_back(tmpId);
}
else
++failing_accounts ;
}
return true;
}
@ -1046,35 +1102,39 @@ static bool checkAccount(std::string accountdir, accountId &id)
std::string cert_name = basename + "_cert.pem";
std::string userName, userId;
#ifdef AUTHSSL_DEBUG
#ifdef AUTHSSL_DEBUG
std::cerr << "checkAccount() dir: " << accountdir << std::endl;
#endif
#endif
bool ret = false;
/* check against authmanagers private keys */
if (LoadCheckX509(cert_name.c_str(), id.pgpId, id.location, id.sslId))
{
#ifdef AUTHSSL_DEBUG
std::cerr << "location: " << id.location << " id: " << id.sslId << std::endl;
#endif
if (LoadCheckX509(cert_name.c_str(), id.pgpId, id.location, id.sslId))
{
#ifdef AUTHSSL_DEBUG
std::cerr << "location: " << id.location << " id: " << id.sslId << std::endl;
std::cerr << "issuerName: " << id.pgpId << " id: " << id.sslId << std::endl;
#endif
if(! RsInit::GetPGPLoginDetails(id.pgpId, id.pgpName, id.pgpEmail))
return false ;
#ifdef GPG_DEBUG
std::cerr << "issuerName: " << id.pgpId << " id: " << id.sslId << std::endl;
#endif
RsInit::GetPGPLoginDetails(id.pgpId, id.pgpName, id.pgpEmail);
#ifdef GPG_DEBUG
std::cerr << "PGPLoginDetails: " << id.pgpId << " name: " << id.pgpName;
std::cerr << " email: " << id.pgpEmail << std::endl;
#endif
ret = true;
}
else
{
std::cerr << "GetIssuerName FAILED!" << std::endl;
ret = false;
}
if(!AuthGPG::getAuthGPG()->isKeySupported(id.pgpId))
return false ;
if(!AuthGPG::getAuthGPG()->haveSecretKey(id.pgpId))
return false ;
#ifdef GPG_DEBUG
std::cerr << "PGPLoginDetails: " << id.pgpId << " name: " << id.pgpName;
std::cerr << " email: " << id.pgpEmail << std::endl;
#endif
ret = true;
}
else
{
std::cerr << "GetIssuerName FAILED!" << std::endl;
ret = false;
}
return ret;
}
@ -1101,8 +1161,14 @@ int RsInit::GetPGPLoginDetails(const std::string& id, std::string &name, st
std::cerr << "RsInit::GetPGPLoginDetails for \"" << id << "\"" << std::endl;
#endif
name = AuthGPG::getAuthGPG()->getGPGName(id);
email = AuthGPG::getAuthGPG()->getGPGEmail(id);
bool ok = true ;
name = AuthGPG::getAuthGPG()->getGPGName(id,&ok);
if(!ok)
return 0 ;
email = AuthGPG::getAuthGPG()->getGPGEmail(id,&ok);
if(!ok)
return 0 ;
if (name != "") {
return 1;
} else {
@ -1123,75 +1189,9 @@ int RsInit::GetPGPLoginDetails(const std::string& id, std::string &name, st
int RsInit::LockConfigDirectory(const std::string& accountDir, std::string& lockFilePath)
{
const std::string lockFile = accountDir + "/" + "lock";
lockFilePath = lockFile;
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
if(RsInitConfig::lockHandle != -1)
close(RsInitConfig::lockHandle);
// open the file in write mode, create it if necessary, truncate it (it should be empty)
RsInitConfig::lockHandle = open(lockFile.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if(RsInitConfig::lockHandle == -1)
{
std::cerr << "Could not open lock file " << lockFile.c_str() << std::flush;
perror(NULL);
return 2;
}
// see "man fcntl" for the details, in short: non blocking lock creation on the whole file contents
struct flock lockDetails;
lockDetails.l_type = F_WRLCK;
lockDetails.l_whence = SEEK_SET;
lockDetails.l_start = 0;
lockDetails.l_len = 0;
if(fcntl(RsInitConfig::lockHandle, F_SETLK, &lockDetails) == -1)
{
int fcntlErr = errno;
std::cerr << "Could not request lock on file " << lockFile.c_str() << std::flush;
perror(NULL);
// there's no lock so let's release the file handle immediately
close(RsInitConfig::lockHandle);
RsInitConfig::lockHandle = -1;
if(fcntlErr == EACCES || fcntlErr == EAGAIN)
return 1;
else
return 2;
}
return 0;
#else
if (RsInitConfig::lockHandle) {
CloseHandle(RsInitConfig::lockHandle);
}
std::wstring wlockFile;
librs::util::ConvertUtf8ToUtf16(lockFile, wlockFile);
// open the file in write mode, create it if necessary
RsInitConfig::lockHandle = CreateFile(wlockFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (RsInitConfig::lockHandle == INVALID_HANDLE_VALUE) {
DWORD lasterror = GetLastError();
std::cerr << "Could not open lock file " << lockFile.c_str() << std::endl;
std::cerr << "Last error: " << lasterror << std::endl << std::flush;
perror(NULL);
if (lasterror == ERROR_SHARING_VIOLATION || lasterror == ERROR_ACCESS_DENIED) {
return 1;
}
return 2;
}
return 0;
#endif
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
return RsDirUtil::createLockFile(lockFile,RsInitConfig::lockHandle) ;
}
/*
@ -1200,21 +1200,7 @@ int RsInit::LockConfigDirectory(const std::string& accountDir, std::string& lock
*/
void RsInit::UnlockConfigDirectory()
{
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
if(RsInitConfig::lockHandle != -1)
{
close(RsInitConfig::lockHandle);
RsInitConfig::lockHandle = -1;
}
#else
if(RsInitConfig::lockHandle)
{
CloseHandle(RsInitConfig::lockHandle);
RsInitConfig::lockHandle = NULL;
}
#endif
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
RsDirUtil::releaseLockFile(RsInitConfig::lockHandle) ;
}
@ -2101,7 +2087,7 @@ int RsServer::StartupRetroShare()
/****** New Ft Server **** !!! */
ftserver = new ftServer(mPeerMgr, mLinkMgr);
ftserver->setP3Interface(pqih);
ftserver->setP3Interface(pqih);
ftserver->setConfigDirectory(RsInitConfig::configDir);
ftserver->SetupFtServer(&(getNotify()));
@ -2299,7 +2285,7 @@ int RsServer::StartupRetroShare()
//mConfigMgr->addConfiguration("ftserver.cfg", ftserver);
//
mConfigMgr->addConfiguration("gpg_prefs.cfg", (AuthGPGimpl *) AuthGPG::getAuthGPG());
mConfigMgr->addConfiguration("gpg_prefs.cfg", AuthGPG::getAuthGPG());
mConfigMgr->loadConfiguration();
mConfigMgr->addConfiguration("peers.cfg", mPeerMgr);

View File

@ -635,23 +635,25 @@ bool RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile(const std::string& ssl_id
return true ;
}
sslPassphraseFile = RsDirUtil::rs_fopen(getSSLPasswdFileName(ssl_id).c_str(), "w");
// sslPassphraseFile = RsDirUtil::rs_fopen(getSSLPasswdFileName(ssl_id).c_str(), "w");
if(sslPassphraseFile == NULL)
{
std::cerr << "RsLoginHandler::storeSSLPasswdIntoGPGFile(): could not write to file " << getSSLPasswdFileName(ssl_id) << std::endl;
return false ;
}
else
std::cerr << "openned sslPassphraseFile : " << getSSLPasswdFileName(ssl_id) << std::endl;
gpgme_data_t cipher;
gpgme_data_t plain;
gpgme_data_new_from_mem(&plain, ssl_passwd.c_str(), ssl_passwd.length(), 1);
gpgme_data_new_from_stream (&cipher, sslPassphraseFile);
// if(sslPassphraseFile == NULL)
// {
// std::cerr << "RsLoginHandler::storeSSLPasswdIntoGPGFile(): could not write to file " << getSSLPasswdFileName(ssl_id) << std::endl;
// return false ;
// }
// else
// std::cerr << "openned sslPassphraseFile : " << getSSLPasswdFileName(ssl_id) << std::endl;
//
// gpgme_data_t cipher;
// gpgme_data_t plain;
// gpgme_data_new_from_mem(&plain, ssl_passwd.c_str(), ssl_passwd.length(), 1);
// gpgme_data_new_from_stream (&cipher, sslPassphraseFile);
bool ok ;
if (0 < AuthGPG::getAuthGPG()->encryptText(plain, cipher))
std::string cipher ;
if(AuthGPG::getAuthGPG()->encryptTextToFile(ssl_passwd, getSSLPasswdFileName(ssl_id)))
{
std::cerr << "Encrypting went ok !" << std::endl;
ok= true ;
@ -662,10 +664,9 @@ bool RsLoginHandler::checkAndStoreSSLPasswdIntoGPGFile(const std::string& ssl_id
ok= false ;
}
gpgme_data_release (cipher);
gpgme_data_release (plain);
fclose(sslPassphraseFile);
// gpgme_data_release (cipher);
// gpgme_data_release (plain);
// fclose(sslPassphraseFile);
return ok ;
}
@ -682,34 +683,40 @@ bool RsLoginHandler::getSSLPasswdFromGPGFile(const std::string& ssl_id,std::stri
std::cerr << "No password provided, and no sslPassphraseFile : " << getSSLPasswdFileName(ssl_id).c_str() << std::endl;
return 0;
}
fclose(sslPassphraseFile);
std::cerr << "opening sslPassphraseFile : " << getSSLPasswdFileName(ssl_id).c_str() << std::endl;
gpgme_data_t cipher;
gpgme_data_t plain;
gpgme_data_new (&plain);
// gpgme_data_t cipher;
// gpgme_data_t plain;
// gpgme_data_new (&plain);
if( gpgme_data_new_from_stream (&cipher, sslPassphraseFile) != GPG_ERR_NO_ERROR)
{
std::cerr << "Error while creating stream from ssl passwd file." << std::endl ;
return 0 ;
}
if (0 < AuthGPG::getAuthGPG()->decryptText(cipher, plain))
// if( gpgme_data_new_from_stream (&cipher, sslPassphraseFile) != GPG_ERR_NO_ERROR)
// {
// std::cerr << "Error while creating stream from ssl passwd file." << std::endl ;
// return 0 ;
// }
std::string plain ;
if (AuthGPG::getAuthGPG()->decryptTextFromFile(plain,getSSLPasswdFileName(ssl_id)))
{
std::cerr << "Decrypting went ok !" << std::endl;
gpgme_data_write (plain, "", 1);
sslPassword = std::string(gpgme_data_release_and_get_mem(plain, NULL));
// gpgme_data_write (plain, "", 1);
// sslPassword = std::string(gpgme_data_release_and_get_mem(plain, NULL));
sslPassword = plain ;
std::cerr << "sslpassword: " << "********************" << std::endl;
gpgme_data_release (cipher);
fclose(sslPassphraseFile);
std::cerr << "sslpassword: \"" << sslPassword << "\"" << std::endl;
// gpgme_data_release (cipher);
// fclose(sslPassphraseFile);
return true ;
}
else
{
gpgme_data_release (plain);
gpgme_data_release (cipher);
fclose(sslPassphraseFile);
// gpgme_data_release (plain);
// gpgme_data_release (cipher);
// fclose(sslPassphraseFile);
sslPassword = "" ;
std::cerr << "Error : decrypting went wrong !" << std::endl;

View File

@ -861,28 +861,6 @@ void p3disc::recvDiscReply(RsDiscReply *dri)
void p3disc::removeFriend(std::string /*ssl_id*/)
{
// DON'T KNOW WHY SSL IDS were saved -> the results are never used
#if 0
#ifdef P3DISC_DEBUG
std::cerr << "p3disc::removeFriend() called for : " << ssl_id << std::endl;
#endif
//if we deleted the gpg_id, don't store the friend deletion as if we add back the gpg_id, we won't have the ssl friends back
std::string gpg_id = rsPeers->getGPGId(ssl_id);
#ifdef P3DISC_DEBUG
std::cerr << "p3disc::removeFriend() gpg_id : " << gpg_id << std::endl;
#endif
if (gpg_id == AuthGPG::getAuthGPG()->getGPGOwnId() || rsPeers->isGPGAccepted(rsPeers->getGPGId(ssl_id))) {
#ifdef P3DISC_DEBUG
std::cerr << "p3disc::removeFriend() storing the friend deletion." << ssl_id << std::endl;
#endif
deletedSSLFriendsIds[ssl_id] = time(NULL);//just keep track of the deleted time
IndicateConfigChanged();
}
#endif
}
/*************************************************************************************/

View File

@ -0,0 +1,32 @@
RS_TOP_DIR = ../..
DHT_TOP_DIR = ../../../../libbitdht/src
OPENPGP_INCLUDE_DIR = ../../../../openpgpsdk/src
##### Define any flags that are needed for this section #######
###############################################################
###############################################################
include $(RS_TOP_DIR)/tests/scripts/config.mk
###############################################################
TESTOBJ = test_pgp_handler.o test_pgp_signature_parsing.o test_key_parsing.o
TESTS = test_pgp_handler test_pgp_signature_parsing test_key_parsing
#rsbaseitem_test
all: tests
test_pgp_handler : test_pgp_handler.o
$(CC) $(CFLAGS) -o test_pgp_handler test_pgp_handler.o $(OBJ) $(LIBS) -L../../../../openpgpsdk/src/lib/ -lops -lbz2
test_pgp_signature_parsing : test_pgp_signature_parsing.o
$(CC) $(CFLAGS) -o test_pgp_signature_parsing test_pgp_signature_parsing.o $(OBJ) $(LIBS) -L../../../../openpgpsdk/src/lib/ -lops -lbz2
test_key_parsing : test_key_parsing.o
$(CC) $(CFLAGS) -o test_key_parsing test_key_parsing.o ../../../../openpgpsdk/src/lib/libops.a -lssl -lcrypto -lbz2
###############################################################
include $(RS_TOP_DIR)/scripts/rules.mk
###############################################################

View File

@ -0,0 +1,814 @@
/* Copyright (C) 2004 Xavier Décoret <Xavier.Decoret@imag.fr>
*
* argsteam is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Foobar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef ARGSTREAM_H
#define ARGSTREAM_H
#include <stdlib.h>
#include <string>
#include <list>
#include <deque>
#include <map>
#include <stdexcept>
#include <sstream>
#include <iostream>
namespace
{
class argstream;
template<class T>
class ValueHolder;
template <typename T>
argstream& operator>> (argstream&, const ValueHolder<T>&);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface of ValueHolder<T>
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
template<class T>
class ValueHolder
{
public:
ValueHolder(char s,
const char* l,
T& b,
const char* desc,
bool mandatory);
ValueHolder(const char* l,
T& b,
const char* desc,
bool mandatory);
ValueHolder(char s,
T& b,
const char* desc,
bool mandatory);
friend argstream& operator>><>(argstream& s,const ValueHolder<T>& v);
std::string name() const;
std::string description() const;
private:
std::string shortName_;
std::string longName_;
T* value_;
T initialValue_;
std::string description_;
bool mandatory_;
};
template <class T>
inline ValueHolder<T>
parameter(char s,
const char* l,
T& b,
const char* desc="",
bool mandatory = true)
{
return ValueHolder<T>(s,l,b,desc,mandatory);
}
template <class T>
inline ValueHolder<T>
parameter(char s,
T& b,
const char* desc="",
bool mandatory = true)
{
return ValueHolder<T>(s,b,desc,mandatory);
}
template <class T>
inline ValueHolder<T>
parameter(const char* l,
T& b,
const char* desc="",
bool mandatory = true)
{
return ValueHolder<T>(l,b,desc,mandatory);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface of OptionHolder
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class OptionHolder
{
public:
inline OptionHolder(char s,
const char* l,
bool& b,
const char* desc);
inline OptionHolder(const char* l,
bool& b,
const char* desc);
inline OptionHolder(char s,
bool& b,
const char* desc);
friend argstream& operator>>(argstream& s,const OptionHolder& v);
inline std::string name() const;
inline std::string description() const;
protected:
inline OptionHolder(char s,
const char* l,
const char* desc);
friend OptionHolder help(char s='h',
const char* l="help",
const char* desc="Display this help");
private:
std::string shortName_;
std::string longName_;
bool* value_;
std::string description_;
};
inline OptionHolder
option(char s,
const char* l,
bool& b,
const char* desc="")
{
return OptionHolder(s,l,b,desc);
}
inline OptionHolder
option(char s,
bool& b,
const char* desc="")
{
return OptionHolder(s,b,desc);
}
inline OptionHolder
option(const char* l,
bool& b,
const char* desc="")
{
return OptionHolder(l,b,desc);
}
inline OptionHolder
help(char s,
const char* l,
const char* desc)
{
return OptionHolder(s,l,desc);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface of ValuesHolder
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
template<class T,class O>
class ValuesHolder
{
public:
ValuesHolder(const O& o,
const char* desc,
int len);
template<class A,class B> friend argstream& operator>>(argstream& s,const ValuesHolder<A,B>& v);
std::string name() const;
std::string description() const;
typedef T value_type;
private:
mutable O value_;
std::string description_;
int len_;
char letter_;
};
template<class T,class O>
inline ValuesHolder<T,O>
values(const O& o,
const char* desc="",
int len=-1)
{
return ValuesHolder<T,O>(o,desc,len);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface of ValueParser
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
template <class T>
class ValueParser
{
public:
inline T operator()(const std::string& s) const
{
std::istringstream is(s);
T t;
is>>t;
return t;
}
};
// We need to specialize for string otherwise parsing of a value that
// contains space (for example a string with space passed in quotes on the
// command line) would parse only the first element of the value!!!
template <>
class ValueParser<std::string>
{
public:
inline std::string operator()(const std::string& s) const
{
return s;
}
};
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Interface of argstream
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
class argstream
{
public:
inline argstream(int argc,char** argv);
inline argstream(const char* c);
template<class T>
friend argstream& operator>>(argstream& s,const ValueHolder<T>& v);
friend inline argstream& operator>>(argstream& s,const OptionHolder& v);
template<class T,class O>
friend argstream& operator>>(argstream& s,const ValuesHolder<T,O>& v);
inline bool helpRequested() const;
inline bool isOk() const;
inline std::string errorLog() const;
inline std::string usage() const;
inline void defaultErrorHandling(bool ignoreUnused=false) const;
static inline char uniqueLetter();
protected:
void parse(int argc,char** argv);
private:
typedef std::list<std::string>::iterator value_iterator;
typedef std::pair<std::string,std::string> help_entry;
std::string progName_;
std::map<std::string,value_iterator> options_;
std::list<std::string> values_;
bool minusActive_;
bool isOk_;
std::deque<help_entry> argHelps_;
std::string cmdLine_;
std::deque<std::string> errors_;
bool helpRequested_;
};
//************************************************************
// Implementation of ValueHolder<T>
//************************************************************
template<class T>
ValueHolder<T>::ValueHolder(char s,
const char* l,
T& v,
const char* desc,
bool mandatory)
: shortName_(1,s),
longName_(l),
value_(&v),
initialValue_(v),
description_(desc),
mandatory_(mandatory)
{
}
template<class T>
ValueHolder<T>::ValueHolder(const char* l,
T& v,
const char* desc,
bool mandatory)
: longName_(l),
value_(&v),
initialValue_(v),
description_(desc),
mandatory_(mandatory)
{
}
template<class T>
ValueHolder<T>::ValueHolder(char s,
T& v,
const char* desc,
bool mandatory)
: shortName_(1,s),
value_(&v),
initialValue_(v),
description_(desc),
mandatory_(mandatory)
{
}
template<class T>
std::string
ValueHolder<T>::name() const
{
std::ostringstream os;
if (!shortName_.empty()) os<<'-'<<shortName_;
if (!longName_.empty()) {
if (!shortName_.empty()) os<<'/';
os<<"--"<<longName_;
}
return os.str();
}
template<class T>
std::string
ValueHolder<T>::description() const
{
std::ostringstream os;
os<<description_;
if (mandatory_)
{
os<<"(mandatory)";
}
else
{
os<<"(default="<<initialValue_<<")";
}
return os.str();
}
//************************************************************
// Implementation of OptionHolder
//************************************************************
inline OptionHolder::OptionHolder(char s,
const char* l,
bool& b,
const char* desc)
: shortName_(1,s),
longName_(l),
value_(&b),
description_(desc)
{
}
inline OptionHolder::OptionHolder(const char* l,
bool& b,
const char* desc)
: longName_(l),
value_(&b),
description_(desc)
{
}
inline OptionHolder::OptionHolder(char s,
bool& b,
const char* desc)
: shortName_(1,s),
value_(&b),
description_(desc)
{
}
inline OptionHolder::OptionHolder(char s,
const char* l,
const char* desc)
: shortName_(1,s),
longName_(l),
value_(NULL),
description_(desc)
{
}
inline std::string
OptionHolder::name() const
{
std::ostringstream os;
if (!shortName_.empty()) os<<'-'<<shortName_;
if (!longName_.empty())
{
if (!shortName_.empty()) os<<'/';
os<<"--"<<longName_;
}
return os.str();
}
inline std::string
OptionHolder::description() const
{
return description_;
}
//************************************************************
// Implementation of ValuesHolder<T,O>
//************************************************************
template<class T,class O>
ValuesHolder<T,O>::ValuesHolder(const O& o,
const char* desc,
int len)
: value_(o),
description_(desc),
len_(len)
{
letter_ = argstream::uniqueLetter();
}
template <class T,class O>
std::string
ValuesHolder<T,O>::name() const
{
std::ostringstream os;
os<<letter_<<"i";
return os.str();
}
template <class T,class O>
std::string
ValuesHolder<T,O>::description() const
{
return description_;
}
//************************************************************
// Implementation of argstream
//************************************************************
inline
argstream::argstream(int argc,char** argv)
: progName_(argv[0]),
minusActive_(true),
isOk_(true)
{
parse(argc,argv);
}
inline
argstream::argstream(const char* c)
: progName_(""),
minusActive_(true),
isOk_(true)
{
std::string s(c);
// Build argc, argv from s. We must add a dummy first element for
// progName because parse() expects it!!
std::deque<std::string> args;
args.push_back("");
std::istringstream is(s);
while (is.good())
{
std::string t;
is>>t;
args.push_back(t);
}
char* pargs[args.size()];
char** p = pargs;
for (std::deque<std::string>::const_iterator
iter = args.begin();
iter != args.end();++iter)
{
*p++ = const_cast<char*>(iter->c_str());
}
parse(args.size(),pargs);
}
inline void
argstream::parse(int argc,char** argv)
{
// Run thru all arguments.
// * it has -- in front : it is a long name option, if remainder is empty,
// it is an error
// * it has - in front : it is a sequence of short name options, if
// remainder is empty, deactivates option (- will
// now be considered a char).
// * if any other char, or if option was deactivated
// : it is a value. Values are split in parameters
// (immediately follow an option) and pure values.
// Each time a value is parsed, if the previously parsed argument was an
// option, then the option is linked to the value in case of it is a
// option with parameter. The subtle point is that when several options
// are given with short names (ex: -abc equivalent to -a -b -c), the last
// parsed option is -c).
// Since we use map for option, any successive call overides the previous
// one: foo -a -b -a hello is equivalent to foo -b -a hello
// For values it is not true since we might have several times the same
// value.
value_iterator* lastOption = NULL;
for (char** a = argv,**astop=a+argc;++a!=astop;)
{
std::string s(*a);
if (minusActive_ && s[0] == '-')
{
if (s.size() > 1 && s[1] == '-')
{
if (s.size() == 2)
{
minusActive_ = false;
continue;
}
lastOption = &(options_[s.substr(2)] = values_.end());
}
else
{
if (s.size() > 1)
{
// Parse all chars, if it is a minus we have an error
for (std::string::const_iterator cter = s.begin();
++cter != s.end();)
{
if (*cter == '-')
{
isOk_ = false;
std::ostringstream os;
os<<"- in the middle of a switch "<<a;
errors_.push_back(os.str());
break;
}
lastOption = &(options_[std::string(1,*cter)] = values_.end());
}
}
else
{
isOk_ = false;
errors_.push_back("Invalid argument -");
break;
}
}
}
else
{
values_.push_back(s);
if (lastOption != NULL)
{
*lastOption = --values_.end();
}
lastOption = NULL;
}
}
#ifdef ARGSTREAM_DEBUG
for (std::map<std::string,value_iterator>::const_iterator
iter = options_.begin();iter != options_.end();++iter)
{
std::cout<<"DEBUG: option "<<iter->first;
if (iter->second != values_.end())
{
std::cout<<" -> "<<*(iter->second);
}
std::cout<<std::endl;
}
for (std::list<std::string>::const_iterator
iter = values_.begin();iter != values_.end();++iter)
{
std::cout<<"DEBUG: value "<<*iter<<std::endl;
}
#endif // ARGSTREAM_DEBUG
}
inline bool
argstream::isOk() const
{
return isOk_;
}
inline bool
argstream::helpRequested() const
{
return helpRequested_;
}
inline std::string
argstream::usage() const
{
std::ostringstream os;
os<<"usage: "<<progName_<<cmdLine_<<'\n';
unsigned int lmax = 0;
for (std::deque<help_entry>::const_iterator
iter = argHelps_.begin();iter != argHelps_.end();++iter)
{
if (lmax<iter->first.size()) lmax = iter->first.size();
}
for (std::deque<help_entry>::const_iterator
iter = argHelps_.begin();iter != argHelps_.end();++iter)
{
os<<'\t'<<iter->first<<std::string(lmax-iter->first.size(),' ')
<<" : "<<iter->second<<'\n';
}
return os.str();
}
inline std::string
argstream::errorLog() const
{
std::string s;
for(std::deque<std::string>::const_iterator iter = errors_.begin();
iter != errors_.end();++iter)
{
s += *iter;
s += '\n';
}
return s;
}
inline char
argstream::uniqueLetter()
{
static unsigned int c = 'a';
return c++;
}
template<class T>
argstream&
operator>>(argstream& s,const ValueHolder<T>& v)
{
// Search in the options if there is any such option defined either with a
// short name or a long name. If both are found, only the last one is
// used.
#ifdef ARGSTREAM_DEBUG
std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
#endif
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
if (v.mandatory_)
{
if (!v.shortName_.empty())
{
s.cmdLine_ += " -";
s.cmdLine_ += v.shortName_;
}
else
{
s.cmdLine_ += " --";
s.cmdLine_ += v.longName_;
}
s.cmdLine_ += " value";
}
else
{
if (!v.shortName_.empty())
{
s.cmdLine_ += " [-";
s.cmdLine_ += v.shortName_;
}
else
{
s.cmdLine_ += " [--";
s.cmdLine_ += v.longName_;
}
s.cmdLine_ += " value]";
}
std::map<std::string,argstream::value_iterator>::iterator iter =
s.options_.find(v.shortName_);
if (iter == s.options_.end())
{
iter = s.options_.find(v.longName_);
}
if (iter != s.options_.end())
{
// If we find counterpart for value holder on command line, either it
// has an associated value in which case we assign it, or it has not, in
// which case we have an error.
if (iter->second != s.values_.end())
{
#ifdef ARGSTREAM_DEBUG
std::cout<<"DEBUG: found value "<<*(iter->second)<<std::endl;
#endif
ValueParser<T> p;
*(v.value_) = p(*(iter->second));
// The option and its associated value are removed, the subtle thing
// is that someother options might have this associated value too,
// which we must invalidate.
s.values_.erase(iter->second);
for (std::map<std::string,argstream::value_iterator>::iterator
jter = s.options_.begin();jter != s.options_.end();++jter)
{
if (jter->second == iter->second)
{
jter->second = s.values_.end();
}
}
s.options_.erase(iter);
}
else
{
s.isOk_ = false;
std::ostringstream os;
os<<"No value following switch "<<iter->first
<<" on command line";
s.errors_.push_back(os.str());
}
}
else
{
if (v.mandatory_)
{
s.isOk_ = false;
std::ostringstream os;
os<<"Mandatory parameter ";
if (!v.shortName_.empty()) os<<'-'<<v.shortName_;
if (!v.longName_.empty())
{
if (!v.shortName_.empty()) os<<'/';
os<<"--"<<v.longName_;
}
os<<" missing";
s.errors_.push_back(os.str());
}
}
return s;
}
inline argstream&
operator>>(argstream& s,const OptionHolder& v)
{
// Search in the options if there is any such option defined either with a
// short name or a long name. If both are found, only the last one is
// used.
#ifdef ARGSTREAM_DEBUG
std::cout<<"DEBUG: searching "<<v.shortName_<<" "<<v.longName_<<std::endl;
#endif
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
{
std::string c;
if (!v.shortName_.empty())
{
c += " [-";
c += v.shortName_;
}
else
{
c += " [--";
c += v.longName_;
}
c += "]";
s.cmdLine_ = c+s.cmdLine_;
}
std::map<std::string,argstream::value_iterator>::iterator iter =
s.options_.find(v.shortName_);
if (iter == s.options_.end())
{
iter = s.options_.find(v.longName_);
}
if (iter != s.options_.end())
{
// If we find counterpart for value holder on command line then the
// option is true and if an associated value was found, it is ignored
if (v.value_ != NULL)
{
*(v.value_) = true;
}
else
{
s.helpRequested_ = true;
}
// The option only is removed
s.options_.erase(iter);
}
else
{
if (v.value_ != NULL)
{
*(v.value_) = false;
}
else
{
s.helpRequested_ = false;
}
}
return s;
}
template<class T,class O>
argstream&
operator>>(argstream& s,const ValuesHolder<T,O>& v)
{
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
{
std::ostringstream os;
os<<' '<<v.letter_<<'1';
switch (v.len_)
{
case -1:
os<<"...";
break;
case 1:
break;
default:
os<<"..."<<v.letter_<<v.len_;
break;
}
s.cmdLine_ += os.str();
}
std::list<std::string>::iterator first = s.values_.begin();
// We add to the iterator as much values as we can, limited to the length
// specified (if different of -1)
int n = v.len_ != -1?v.len_:s.values_.size();
while (first != s.values_.end() && n-->0)
{
// Read the value from the string *first
ValueParser<T> p;
*(v.value_++) = p(*first );
s.argHelps_.push_back(argstream::help_entry(v.name(),v.description()));
// The value we just removed was maybe "remembered" by an option so we
// remove it now.
for (std::map<std::string,argstream::value_iterator>::iterator
jter = s.options_.begin();jter != s.options_.end();++jter)
{
if (jter->second == first)
{
jter->second = s.values_.end();
}
}
++first;
}
// Check if we have enough values
if (n != 0)
{
s.isOk_ = false;
std::ostringstream os;
os<<"Expecting "<<v.len_<<" values";
s.errors_.push_back(os.str());
}
// Erase the values parsed
s.values_.erase(s.values_.begin(),first);
return s;
}
inline void
argstream::defaultErrorHandling(bool ignoreUnused) const
{
if (helpRequested_)
{
std::cout<<usage();
exit(1);
}
if (!isOk_)
{
std::cerr<<errorLog();
exit(1);
}
if (!ignoreUnused &&
(!values_.empty() || !options_.empty()))
{
std::cerr<<"Unused arguments"<<std::endl;
exit(1);
}
}
};
#endif // ARGSTREAM_H

View File

@ -0,0 +1,60 @@
// COMPILE_LINE: g++ -o test_key_parsing test_key_parsing.cc -g -I../../../openpgpsdk/include -I../ -L../lib ../../../openpgpsdk/src/lib/libops.a -lssl -lcrypto -lbz2
//
#include <stdlib.h>
#include <iostream>
extern "C"
{
#include <openpgpsdk/std_print.h>
#include <openpgpsdk/keyring_local.h>
#include <openpgpsdk/util.h>
}
#include "argstream.h"
int main(int argc,char *argv[])
{
try
{
// test PGPHandler
//
// 0 - init
bool armoured = false ;
std::string keyfile ;
argstream as(argc,argv) ;
as >> parameter('i',"input-key",keyfile,"input key file.",true)
>> option('a',"armoured",armoured,"input is armoured")
>> help() ;
as.defaultErrorHandling() ;
ops_keyring_t *kr = (ops_keyring_t*)malloc(sizeof(ops_keyring_t)) ;
kr->nkeys = 0 ;
kr->nkeys_allocated = 0 ;
kr->keys = 0 ;
if(ops_false == ops_keyring_read_from_file(kr,armoured, keyfile.c_str()))
throw std::runtime_error("PGPHandler::readKeyRing(): cannot read key file. File corrupted, or missing/superfluous armour parameter.") ;
for(int i=0;i<kr->nkeys;++i)
{
ops_print_public_keydata(&kr->keys[i]) ;
ops_print_public_keydata_verbose(&kr->keys[i]) ;
ops_print_public_key(&kr->keys[i].key.pkey) ;
}
ops_list_packets(const_cast<char *>(keyfile.c_str()),armoured,kr,NULL) ;
return 0 ;
}
catch(std::exception& e)
{
std::cerr << "Caught exception: " << e.what() << std::endl;
return 1 ;
}
}

View File

@ -0,0 +1,155 @@
// COMPILE_LINE: g++ -o test_pgp_handler test_pgp_handler.cc -I../../../openpgpsdk/include -I../ -L../lib -lretroshare ../../../libbitdht/src/lib/libbitdht.a ../../../openpgpsdk/lib/libops.a -lgnome-keyring -lupnp -lssl -lcrypto -lbz2
//
#include <stdlib.h>
#include <iostream>
#include <pgp/pgphandler.h>
static std::string passphrase_callback(void *data,const char *uid_info,const char *what,int prev_was_bad)
{
return std::string(getpass(what)) ;
}
static std::string stringFromBytes(unsigned char *bytes,size_t len)
{
static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
std::string res ;
for(int j = 0; j < len; j++)
{
res += out[ (bytes[j]>>4) ] ;
res += out[ bytes[j] & 0xf ] ;
}
return res ;
}
int main(int argc,char *argv[])
{
// test pgp ids.
//
PGPIdType id = PGPIdType(std::string("3e5b22140ef56abb")) ;
//std::cerr << "Id is : " << std::hex << id.toUInt64() << std::endl;
std::cerr << "Id st : " << id.toStdString() << std::endl;
// test PGPHandler
//
// 0 - init
static const std::string pubring = "pubring.gpg" ;
static const std::string secring = "secring.gpg" ;
static const std::string trustdb = "trustdb.gpg" ;
static const std::string lockfile = "lock" ;
PGPHandler::setPassphraseCallback(&passphrase_callback) ;
PGPHandler pgph(pubring,secring,trustdb,lockfile) ;
// std::cerr << "Writing public keyring to file tmp_keyring.asc" << std::endl;
// pgph.writePublicKeyring("tmp_keyring.asc") ;
pgph.printKeys() ;
std::cerr << std::endl ;
std::cerr << std::endl ;
std::cerr << "Looking for keys with complete secret/public key pair: " << std::endl;
std::list<PGPIdType> lst ;
pgph.availableGPGCertificatesWithPrivateKeys(lst) ;
for(std::list<PGPIdType>::const_iterator it(lst.begin());it!=lst.end();++it)
std::cerr << "Found id : " << (*it).toStdString() << std::endl;
std::string email_str("test@gmail.com") ;
std::string name_str("test") ;
std::string passw_str("test00") ;
std::cerr << "Now generating a new PGP certificate: " << std::endl;
std::cerr << " email: " << email_str << std::endl;
std::cerr << " passw: " << passw_str << std::endl;
std::cerr << " name : " << name_str << std::endl;
PGPIdType newid ;
std::string errString ;
if(!pgph.GeneratePGPCertificate(name_str, email_str, passw_str, newid, errString))
std::cerr << "Generation of certificate returned error: " << errString << std::endl;
else
std::cerr << "Certificate generation success. New id = " << newid.toStdString() << std::endl;
PGPIdType id2 = PGPIdType(std::string("618E54CF7670FF5E")) ;
std::cerr << "Now extracting key " << id2.toStdString() << " from keyring:" << std::endl ;
std::string cert = pgph.SaveCertificateToString(id2,false) ;
std::cerr << "Now, trying to re-read this cert from the string:" << std::endl;
PGPIdType id3 ;
std::string error_string ;
pgph.LoadCertificateFromString(cert,id3,error_string) ;
std::cerr << "Loaded cert id: " << id3.toStdString() << ", Error string=\"" << error_string << "\"" << std::endl;
std::cerr << cert << std::endl;
std::cerr << "Testing password callback: " << std::endl;
std::string pass = passphrase_callback(NULL,newid.toStdString().c_str(),"Please enter password: ",false) ;
std::cerr << "Password = \"" << pass << "\"" << std::endl;
std::cerr << "Testing signature with keypair " << newid.toStdString() << std::endl;
static const size_t BUFF_LEN = 25 ;
unsigned char *test_bin = new unsigned char[BUFF_LEN] ;
for(size_t i=0;i<BUFF_LEN;++i)
test_bin[i] = rand()%26 + 'a' ;
std::cerr << "Text = \"" << std::string((char *)test_bin,BUFF_LEN) << "\"" << std::endl;
unsigned char sign[1000] ;
uint32_t signlen = 1000 ;
if(!pgph.SignDataBin(newid,test_bin,BUFF_LEN,sign,&signlen))
std::cerr << "Signature error." << std::endl;
else
std::cerr << "Signature success." << std::endl;
std::cerr << "Signature length: " << signlen << std::endl;
std::cerr << "Signature: " << stringFromBytes(sign,signlen) << std::endl;
std::cerr << "Now verifying signature..." << std::endl;
PGPFingerprintType fingerprint ;
if(!pgph.getKeyFingerprint(newid,fingerprint) )
std::cerr << "Cannot find fingerprint of key id " << newid.toStdString() << std::endl;
if(!pgph.VerifySignBin(test_bin,BUFF_LEN,sign,signlen,fingerprint))
std::cerr << "Signature verification failed." << std::endl;
else
std::cerr << "Signature verification worked!" << std::endl;
delete[] test_bin ;
std::string outfile = "crypted_toto.pgp" ;
std::string text_to_encrypt = "this is a secret message" ;
std::cerr << "Checking encrypted file creation: streaming chain \"" << text_to_encrypt << "\" to file " << outfile << " with key " << id2.toStdString() << std::endl;
if(!pgph.encryptTextToFile(id2,text_to_encrypt,outfile))
std::cerr << "Encryption failed" << std::endl;
else
std::cerr << "Encryption success" << std::endl;
std::string decrypted_text = "" ;
outfile = "crypted_toto2.pgp" ;
if(!pgph.decryptTextFromFile(id2,decrypted_text,outfile))
std::cerr << "Decryption failed" << std::endl;
else
std::cerr << "Decryption success" << std::endl;
std::cerr << "Decrypted text: \"" << decrypted_text << "\"" << std::endl;
return 0 ;
}

View File

@ -0,0 +1,49 @@
// COMPILE_LINE: g++ -o test_pgp_signature_parsing test_pgp_signature_parsing.cc -g -I../../../openpgpsdk/include -I../ -L../lib -lretroshare ../../../libbitdht/src/lib/libbitdht.a ../../../openpgpsdk/lib/libops.a -lgnome-keyring -lupnp -lssl -lcrypto -lbz2
//
#include <stdlib.h>
#include <iostream>
#include <pgp/pgphandler.h>
static std::string passphrase_callback(void *data,const char *uid_info,const char *what,int prev_was_bad)
{
return std::string(getpass(what)) ;
}
static std::string stringFromBytes(unsigned char *bytes,size_t len)
{
static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
std::string res ;
for(int j = 0; j < len; j++)
{
res += out[ (bytes[j]>>4) ] ;
res += out[ bytes[j] & 0xf ] ;
}
return res ;
}
int main(int argc,char *argv[])
{
// test pgp ids.
//
PGPIdType id("3e5b22140ef56abb") ;
std::cerr << "Id st : " << id.toStdString() << std::endl;
// test PGPHandler
//
// 0 - init
static const std::string pubring = "pubring.gpg" ;
static const std::string secring = "secring.gpg" ;
static const std::string trustdb = "trustdb.gpg" ;
static const std::string lockfil = "lock" ;
PGPHandler::setPassphraseCallback(&passphrase_callback) ;
PGPHandler pgph(pubring,secring,trustdb,lockfil) ;
pgph.printKeys() ;
}

View File

@ -25,7 +25,7 @@ BITDIR = $(DHT_TOP_DIR)/lib
LIBRS = $(LIBDIR)/libretroshare.a
BITDHT = $(BITDIR)/libbitdht.a
# Unix: Linux/Cygwin
INCLUDE = -I $(RS_TOP_DIR)
INCLUDE = -I $(RS_TOP_DIR) -I$(OPENPGP_INCLUDE_DIR)
CFLAGS = -Wall -g $(INCLUDE)
#CFLAGS += -fprofile-arcs -ftest-coverage
CFLAGS += ${DEFINES}

View File

@ -27,6 +27,7 @@
// Includes for directory creation.
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include "util/rsdir.h"
@ -848,6 +849,118 @@ std::string RsDirUtil::makePath(const std::string &path1, const std::string &pat
return path;
}
int RsDirUtil::createLockFile(const std::string& lock_file_path, rs_lock_handle_t &lock_handle)
{
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
// Suspended. The user should make sure he's not already using the file descriptor.
// if(lock_handle != -1)
// close(lock_handle);
// open the file in write mode, create it if necessary, truncate it (it should be empty)
lock_handle = open(lock_file_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if(lock_handle == -1)
{
std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::flush;
perror(NULL);
return 2;
}
// see "man fcntl" for the details, in short: non blocking lock creation on the whole file contents
struct flock lockDetails;
lockDetails.l_type = F_WRLCK;
lockDetails.l_whence = SEEK_SET;
lockDetails.l_start = 0;
lockDetails.l_len = 0;
if(fcntl(lock_handle, F_SETLK, &lockDetails) == -1)
{
int fcntlErr = errno;
std::cerr << "Could not request lock on file " << lock_file_path.c_str() << std::flush;
perror(NULL);
// there's no lock so let's release the file handle immediately
close(lock_handle);
lock_handle = -1;
if(fcntlErr == EACCES || fcntlErr == EAGAIN)
return 1;
else
return 2;
}
return 0;
#else
// Suspended. The user should make sure he's not already using the file descriptor.
//
// if (lock_handle) {
// CloseHandle(lock_handle);
// }
std::wstring wlockFile;
librs::util::ConvertUtf8ToUtf16(lock_file_path, wlockFile);
// open the file in write mode, create it if necessary
lock_handle = CreateFile(wlockFile.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (lock_handle == INVALID_HANDLE_VALUE)
{
DWORD lasterror = GetLastError();
std::cerr << "Could not open lock file " << lock_file_path.c_str() << std::endl;
std::cerr << "Last error: " << lasterror << std::endl << std::flush;
perror(NULL);
if (lasterror == ERROR_SHARING_VIOLATION || lasterror == ERROR_ACCESS_DENIED)
return 1;
return 2;
}
return 0;
#endif
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
}
void RsDirUtil::releaseLockFile(rs_lock_handle_t lockHandle)
{
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
if(lockHandle != -1)
{
close(lockHandle);
lockHandle = -1;
}
#else
if(lockHandle)
{
CloseHandle(lockHandle);
lockHandle = 0;
}
#endif
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
}
RsStackFileLock::RsStackFileLock(const std::string& file_path)
{
while(RsDirUtil::createLockFile(file_path,_file_handle))
{
std::cerr << "Cannot acquire file lock " << file_path << ", waiting 1 sec." << std::endl;
#ifdef WINDOWS_SYS
Sleep(1000) ;
#else
sleep(1) ;
#endif
}
std::cerr << "Acquired file handle " << _file_handle << ", lock file:" << file_path << std::endl;
}
RsStackFileLock::~RsStackFileLock()
{
RsDirUtil::releaseLockFile(_file_handle) ;
std::cerr << "Released file lock with handle " << _file_handle << std::endl;
}
#if 0 // NOT ENABLED YET!
/************************* WIDE STRING ***************************/
/************************* WIDE STRING ***************************/

View File

@ -36,6 +36,27 @@ class RsThread;
#include <retroshare/rstypes.h>
#ifndef WINDOWS_SYS
typedef int rs_lock_handle_t;
#else
typedef /*HANDLE*/ void *rs_lock_handle_t;
#endif
// This is a scope guard on a given file. Works like a mutex. Is blocking.
// We could do that in another way: derive RsMutex into RsLockFileMutex, and
// use RsStackMutex on it transparently. Only issue: this will cost little more
// because of the multiple inheritance.
//
class RsStackFileLock
{
public:
RsStackFileLock(const std::string& file_path) ;
~RsStackFileLock() ;
private:
rs_lock_handle_t _file_handle ;
};
namespace RsDirUtil {
std::string getTopDir(const std::string&);
@ -70,6 +91,15 @@ bool getFileHash(const std::string& filepath,std::string &hash, uint64_t &size
Sha1CheckSum sha1sum(uint8_t *data,uint32_t size) ;
// Creates a lock file with given path, and returns the lock handle
// returns:
// 0: Success
// 1: Another instance already has the lock
// 2 : Unexpected error
int createLockFile(const std::string& lock_file_path, rs_lock_handle_t& lock_handle) ;
// Removes the lock file with specified handle.
void releaseLockFile(rs_lock_handle_t lockHandle) ;
std::wstring getWideTopDir(std::wstring);
std::wstring getWideRootDir(std::wstring);

View File

@ -0,0 +1,112 @@
// This class aims at defining a generic ID type that is a list of bytes. It
// can be converted into a hexadecial string for printing, mainly) or for
// compatibility with old methods.
//
// To use this class, derive your own ID type from it. Examples include:
//
// class PGPIdType: public t_RsGenericIdType<8>
// {
// [..]
// };
//
// class PGPFingerprintType: public t_RsGenericIdType<20>
// {
// [..]
// };
//
// With this, there is no implicit conversion between subtypes, and therefore ID mixup
// is impossible.
//
// A simpler way to make ID types is to
// typedef t_RsGenericIdType<MySize> MyType ;
//
// ID Types with different lengths will be incompatible on compilation.
//
// Warning: never store references to a t_RsGenericIdType accross threads, since the
// cached string convertion is not thread safe.
//
#include <stdexcept>
#include <string>
template<uint32_t ID_SIZE_IN_BYTES> class t_RsGenericIdType
{
public:
t_RsGenericIdType() {}
virtual ~t_RsGenericIdType() {}
// Explicit constructor from a hexadecimal string
//
explicit t_RsGenericIdType(const std::string& hex_string) ;
// Explicit constructor from a byte array. The array should have size at least ID_SIZE_IN_BYTES
//
explicit t_RsGenericIdType(const unsigned char bytes[]) ;
// Converts to a std::string using cached value.
//
std::string toStdString() const ;
const unsigned char *toByteArray() const { return &bytes[0] ; }
static const uint32_t SIZE_IN_BYTES = ID_SIZE_IN_BYTES ;
bool operator==(const t_RsGenericIdType<ID_SIZE_IN_BYTES>& fp) const
{
for(uint32_t i=0;i<ID_SIZE_IN_BYTES;++i)
if(fp.bytes[i] != bytes[i])
return false ;
return true ;
}
bool operator!=(const t_RsGenericIdType<ID_SIZE_IN_BYTES>& fp) const
{
return !operator==(fp) ;
}
private:
unsigned char bytes[ID_SIZE_IN_BYTES] ;
};
template<uint32_t ID_SIZE_IN_BYTES> std::string t_RsGenericIdType<ID_SIZE_IN_BYTES>::toStdString() const
{
static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
std::string res(ID_SIZE_IN_BYTES*2,' ') ;
for(uint32_t j = 0; j < ID_SIZE_IN_BYTES; j++)
{
res[2*j ] = out[ (bytes[j]>>4) ] ;
res[2*j+1] = out[ bytes[j] & 0xf ] ;
}
return res ;
}
template<uint32_t ID_SIZE_IN_BYTES> t_RsGenericIdType<ID_SIZE_IN_BYTES>::t_RsGenericIdType(const std::string& s)
{
int n=0;
if(s.length() != ID_SIZE_IN_BYTES*2)
throw std::runtime_error("t_RsGenericIdType<>::t_RsGenericIdType(std::string&): supplied string in constructor has wrong size.") ;
for(uint32_t i = 0; i < ID_SIZE_IN_BYTES; ++i)
{
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) ;
else if(b >= 'a' && b <= 'f')
bytes[i] += (b-'a'+10) << 4*(1-k) ;
else if(b >= '0' && b <= '9')
bytes[i] += (b-'0') << 4*(1-k) ;
else
throw std::runtime_error("t_RsGenericIdType<>::t_RsGenericIdType(std::string&): supplied string is not purely hexadecimal") ;
}
}
}
template<uint32_t ID_SIZE_IN_BYTES> t_RsGenericIdType<ID_SIZE_IN_BYTES>::t_RsGenericIdType(const unsigned char *mem)
{
memcpy(bytes,mem,ID_SIZE_IN_BYTES) ;
}

View File

@ -0,0 +1,197 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/packet.h>
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/util.h>
#include <openpgpsdk/accumulate.h>
#include "keyring_local.h"
#include "parse_local.h"
#include <openpgpsdk/signature.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <openpgpsdk/final.h>
typedef struct
{
ops_keyring_t *keyring;
} accumulate_arg_t;
/**
* \ingroup Core_Callbacks
*/
static ops_parse_cb_return_t
accumulate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
accumulate_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
const ops_parser_content_union_t *content=&content_->content;
ops_keyring_t *keyring=arg->keyring;
ops_keydata_t *cur=NULL;
const ops_public_key_t *pkey;
if(keyring->nkeys >= 0)
cur=&keyring->keys[keyring->nkeys];
switch(content_->tag)
{
case OPS_PTAG_CT_PUBLIC_KEY:
case OPS_PTAG_CT_SECRET_KEY:
case OPS_PTAG_CT_ENCRYPTED_SECRET_KEY:
// printf("New key\n");
++keyring->nkeys;
EXPAND_ARRAY(keyring,keys);
if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY)
pkey=&content->public_key;
else
pkey=&content->secret_key.public_key;
memset(&keyring->keys[keyring->nkeys],'\0',
sizeof keyring->keys[keyring->nkeys]);
ops_keyid(keyring->keys[keyring->nkeys].key_id,pkey);
ops_fingerprint(&keyring->keys[keyring->nkeys].fingerprint,pkey);
keyring->keys[keyring->nkeys].type=content_->tag;
if(content_->tag == OPS_PTAG_CT_PUBLIC_KEY)
keyring->keys[keyring->nkeys].key.pkey=*pkey;
else
keyring->keys[keyring->nkeys].key.skey=content->secret_key;
return OPS_KEEP_MEMORY;
case OPS_PTAG_CT_USER_ID:
// printf("User ID: %s\n",content->user_id.user_id);
if (!cur)
{
OPS_ERROR(cbinfo->errors,OPS_E_P_NO_USERID, "No user id found");
return OPS_KEEP_MEMORY;
}
// assert(cur);
ops_add_userid_to_keydata(cur, &content->user_id);
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);
free(content->packet.raw);
return OPS_KEEP_MEMORY;
case OPS_PARSER_ERROR:
fprintf(stderr,"Error: %s\n",content->error.error);
assert(0);
break;
case OPS_PARSER_ERRCODE:
switch(content->errcode.errcode)
{
default:
fprintf(stderr,"parse error: %s\n",
ops_errcode(content->errcode.errcode));
//assert(0);
}
break;
default:
break;
}
// XXX: we now exclude so many things, we should either drop this or
// do something to pass on copies of the stuff we keep
return ops_parse_stacked_cb(content_,cbinfo);
}
/**
* \ingroup Core_Parse
*
* Parse packets from an input stream until EOF or error.
*
* Key data found in the parsed data is added to #keyring.
*
* \param keyring Pointer to an existing keyring
* \param parse_info Options to use when parsing
*/
int ops_parse_and_accumulate(ops_keyring_t *keyring,
ops_parse_info_t *parse_info)
{
int rtn;
accumulate_arg_t arg;
assert(!parse_info->rinfo.accumulate);
memset(&arg,'\0',sizeof arg);
arg.keyring=keyring;
/* Kinda weird, but to do with counting, and we put it back after */
--keyring->nkeys;
ops_parse_cb_push(parse_info,accumulate_cb,&arg);
parse_info->rinfo.accumulate=ops_true;
rtn=ops_parse(parse_info);
++keyring->nkeys;
return rtn;
}
static void dump_one_keydata(const ops_keydata_t *key)
{
unsigned n;
printf("Key ID: ");
hexdump(key->key_id,8);
printf("\nFingerpint: ");
hexdump(key->fingerprint.fingerprint,key->fingerprint.length);
printf("\n\nUIDs\n====\n\n");
for(n=0 ; n < key->nuids ; ++n)
printf("%s\n",key->uids[n].user_id);
printf("\nPackets\n=======\n");
for(n=0 ; n < key->npackets ; ++n)
{
printf("\n%03d: ",n);
hexdump(key->packets[n].raw,key->packets[n].length);
}
printf("\n\n");
}
// XXX: not a maintained part of the API - use ops_keyring_list()
/** ops_dump_keyring
*/
void ops_dump_keyring(const ops_keyring_t *keyring)
{
int n;
for(n=0 ; n < keyring->nkeys ; ++n)
dump_one_keydata(&keyring->keys[n]);
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_ACCUMULATE_H
#define OPS_ACCUMULATE_H
#endif
#include "keyring.h"
#include "packet-parse.h"
int ops_parse_and_accumulate(ops_keyring_t *keyring,
ops_parse_info_t *parse_info);

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_ARMOUR_H__
#define __OPS_ARMOUR_H__
#include "packet-parse.h"
#include "signature.h"
unsigned ops_crc24(unsigned checksum,unsigned char c);
void ops_reader_push_dearmour(ops_parse_info_t *parse_info);
void ops_reader_pop_dearmour(ops_parse_info_t *parse_info);
ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
ops_create_signature_t *sig);
void ops_writer_push_armoured_message(ops_create_info_t *info);
ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info);
typedef enum
{
OPS_PGP_MESSAGE=1,
OPS_PGP_PUBLIC_KEY_BLOCK,
OPS_PGP_PRIVATE_KEY_BLOCK,
OPS_PGP_MULTIPART_MESSAGE_PART_X_OF_Y,
OPS_PGP_MULTIPART_MESSAGE_PART_X,
OPS_PGP_SIGNATURE
} ops_armor_type_t;
void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type);
#define CRC24_INIT 0xb704ceL
#endif /* __OPS_ARMOUR_H__ */
// EOF

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_CALLBACK_H__
#define __OPS_CALLBACK_H__
#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if(ops_parse_cb((pc),(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
/*#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)*/
//#define CB(cbinfo,t,pc) do { (pc)->tag=(t); if((cbinfo)->cb(pc,(cbinfo)) == OPS_RELEASE_MEMORY) ops_parser_content_free(pc); } while(0)
#define CBP(info,t,pc) CB(&(info)->cbinfo,t,pc)
#define ERR(cbinfo,err,code) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,(cbinfo)); OPS_ERROR(errors,code,err); return -1; } while(0)
/*#define ERR(err) do { content.content.error.error=err; content.tag=OPS_PARSER_ERROR; ops_parse_cb(&content,cbinfo); return -1; } while(0)*/
#define ERRP(info,err) do { C.error.error=err; CBP(info,OPS_PARSER_ERROR,&content); return ops_false; } while(0)
#endif /*__OPS_CALLBACK_H__*/

View File

@ -0,0 +1,578 @@
/*
* 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.
*/
/** \file
*/
#include <zlib.h>
#include <bzlib.h>
#include <assert.h>
#include <string.h>
#include <openpgpsdk/compress.h>
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/errors.h>
#include "parse_local.h"
#include <openpgpsdk/final.h>
#include <openpgpsdk/partial.h>
static const int debug = 0;
#define DECOMPRESS_BUFFER 1024
#define COMPRESS_BUFFER 32768
typedef struct
{
ops_compression_type_t type;
ops_region_t *region;
unsigned char in[DECOMPRESS_BUFFER];
unsigned char out[DECOMPRESS_BUFFER];
z_stream zstream; // ZIP and ZLIB
size_t offset;
int inflate_ret;
} z_decompress_arg_t;
typedef struct
{
ops_compression_type_t type;
ops_region_t *region;
char in[DECOMPRESS_BUFFER];
char out[DECOMPRESS_BUFFER];
bz_stream bzstream; // BZIP2
size_t offset;
int inflate_ret;
} bz_decompress_arg_t;
typedef struct
{
z_stream stream;
unsigned char *src;
unsigned char *dst;
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)
{
z_decompress_arg_t *arg=ops_reader_get_arg(rinfo);
assert(arg->type==OPS_C_ZIP || arg->type==OPS_C_ZLIB);
//ops_parser_content_t content;
int saved=length;
if(/*arg->region->indeterminate && */ arg->inflate_ret == Z_STREAM_END
&& arg->zstream.next_out == &arg->out[arg->offset])
return 0;
if(arg->region->length_read == arg->region->length)
{
if(arg->inflate_ret != Z_STREAM_END)
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Compressed data didn't end when region ended.");
/*
else
return 0;
www.zlib.org
*/
}
while(length > 0)
{
unsigned len;
if(&arg->out[arg->offset] == arg->zstream.next_out)
{
int ret;
arg->zstream.next_out=arg->out;
arg->zstream.avail_out=sizeof arg->out;
arg->offset=0;
if(arg->zstream.avail_in == 0)
{
unsigned n=arg->region->length;
if(!arg->region->indeterminate)
{
n-=arg->region->length_read;
if(n > sizeof arg->in)
n=sizeof arg->in;
}
else
n=sizeof arg->in;
if(!ops_stacked_limited_read(arg->in,n,arg->region,
errors,rinfo,cbinfo))
return -1;
arg->zstream.next_in=arg->in;
arg->zstream.avail_in=arg->region->indeterminate
? arg->region->last_read : n;
}
ret=inflate(&arg->zstream,Z_SYNC_FLUSH);
if(ret == Z_STREAM_END)
{
if(!arg->region->indeterminate
&& arg->region->length_read != arg->region->length)
OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR,
"Compressed stream ended before packet end.");
}
else if(ret != Z_OK)
{
fprintf(stderr,"ret=%d\n",ret);
OPS_ERROR(cbinfo->errors,OPS_E_P_DECOMPRESSION_ERROR, arg->zstream.msg);
}
arg->inflate_ret=ret;
}
assert(arg->zstream.next_out > &arg->out[arg->offset]);
len=arg->zstream.next_out-&arg->out[arg->offset];
if(len > length)
len=length;
memcpy(dest,&arg->out[arg->offset],len);
arg->offset+=len;
length-=len;
}
return saved;
}
// \todo remove code duplication between this and zlib_compressed_data_reader
static int bzip2_compressed_data_reader(void *dest,size_t length,
ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo)
{
bz_decompress_arg_t *arg=ops_reader_get_arg(rinfo);
assert(arg->type==OPS_C_BZIP2);
//ops_parser_content_t content;
int saved=length;
if(arg->inflate_ret == BZ_STREAM_END
&& arg->bzstream.next_out == &arg->out[arg->offset])
return 0;
if(arg->region->length_read == arg->region->length)
{
if(arg->inflate_ret != BZ_STREAM_END)
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Compressed data didn't end when region ended.");
}
while(length > 0)
{
unsigned len;
if(&arg->out[arg->offset] == arg->bzstream.next_out)
{
int ret;
arg->bzstream.next_out=(char *) arg->out;
arg->bzstream.avail_out=sizeof arg->out;
arg->offset=0;
if(arg->bzstream.avail_in == 0)
{
unsigned n=arg->region->length;
if(!arg->region->indeterminate)
{
n-=arg->region->length_read;
if(n > sizeof arg->in)
n=sizeof arg->in;
}
else
n=sizeof arg->in;
if(!ops_stacked_limited_read(arg->in, n, arg->region, errors,
rinfo, cbinfo))
return -1;
arg->bzstream.next_in=arg->in;
arg->bzstream.avail_in=arg->region->indeterminate
? arg->region->last_read : n;
}
ret=BZ2_bzDecompress(&arg->bzstream);
if(ret == BZ_STREAM_END)
{
if(!arg->region->indeterminate
&& arg->region->length_read != arg->region->length)
OPS_ERROR(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Compressed stream ended before packet end.");
}
else if(ret != BZ_OK)
{
OPS_ERROR_1(cbinfo->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Invalid return %d from BZ2_bzDecompress", ret);
}
arg->inflate_ret=ret;
}
assert(arg->bzstream.next_out > &arg->out[arg->offset]);
len=arg->bzstream.next_out-&arg->out[arg->offset];
if(len > length)
len=length;
memcpy(dest,&arg->out[arg->offset],len);
arg->offset+=len;
length-=len;
}
return saved;
}
/**
* \ingroup Core_Compress
*
* \param *region Pointer to a region
* \param *parse_info How to parse
* \param type Which compression type to expect
*/
int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
ops_compression_type_t type)
{
z_decompress_arg_t z_arg;
bz_decompress_arg_t bz_arg;
int ret;
switch (type)
{
case OPS_C_ZIP:
case OPS_C_ZLIB:
memset(&z_arg,'\0',sizeof z_arg);
z_arg.region=region;
z_arg.offset=0;
z_arg.type=type;
z_arg.zstream.next_in=Z_NULL;
z_arg.zstream.avail_in=0;
z_arg.zstream.next_out=z_arg.out;
z_arg.zstream.zalloc=Z_NULL;
z_arg.zstream.zfree=Z_NULL;
z_arg.zstream.opaque=Z_NULL;
break;
case OPS_C_BZIP2:
memset(&bz_arg,'\0',sizeof bz_arg);
bz_arg.region=region;
bz_arg.offset=0;
bz_arg.type=type;
bz_arg.bzstream.next_in=NULL;
bz_arg.bzstream.avail_in=0;
bz_arg.bzstream.next_out=bz_arg.out;
bz_arg.bzstream.bzalloc=NULL;
bz_arg.bzstream.bzfree=NULL;
bz_arg.bzstream.opaque=NULL;
break;
default:
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG,
"Compression algorithm %d is not yet supported", type);
return 0;
}
switch(type)
{
case OPS_C_ZIP:
ret=inflateInit2(&z_arg.zstream,-15);
break;
case OPS_C_ZLIB:
ret=inflateInit(&z_arg.zstream);
break;
case OPS_C_BZIP2:
/*
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %s is not yet supported", "BZIP2");
return 0;
*/
ret=BZ2_bzDecompressInit(&bz_arg.bzstream, 1, 0);
break;
default:
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG,
"Compression algorithm %d is not yet supported", type);
return 0;
}
switch (type)
{
case OPS_C_ZIP:
case OPS_C_ZLIB:
if(ret != Z_OK)
{
OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Cannot initialise ZIP or ZLIB stream "
"for decompression: error=%d", ret);
return 0;
}
ops_reader_push(parse_info,zlib_compressed_data_reader,NULL,&z_arg);
break;
case OPS_C_BZIP2:
if (ret != BZ_OK)
{
OPS_ERROR_1(&parse_info->errors, OPS_E_P_DECOMPRESSION_ERROR,
"Cannot initialise BZIP2 stream "
"for decompression: error=%d", ret);
return 0;
}
ops_reader_push(parse_info,bzip2_compressed_data_reader,NULL,&bz_arg);
break;
default:
OPS_ERROR_1(&parse_info->errors, OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG,
"Compression algorithm %d is not yet supported", type);
return 0;
}
ret=ops_parse(parse_info);
ops_reader_pop(parse_info);
return ret;
}
/**
\ingroup Core_WritePackets
\brief Writes Compressed packet
\param data Data to write out
\param len Length of data
\param cinfo Write settings
\return ops_true if OK; else ops_false
*/
ops_boolean_t ops_write_compressed(const unsigned char *data,
const unsigned int len,
ops_create_info_t *cinfo)
{
int r=0;
int sz_in=0;
int sz_out=0;
compress_arg_t* compress=ops_mallocz(sizeof *compress);
// compress the data
const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels
compress->stream.zalloc=Z_NULL;
compress->stream.zfree=Z_NULL;
compress->stream.opaque=NULL;
// all other fields set to zero by use of ops_mallocz
if (deflateInit(&compress->stream,level) != Z_OK)
{
// can't initialise
assert(0);
}
// do necessary transformation
// copy input to maintain const'ness of src
assert(compress->src==NULL);
assert(compress->dst==NULL);
sz_in=len * sizeof (unsigned char);
sz_out= (sz_in * 1.01) + 12; // from zlib webpage
compress->src=ops_mallocz(sz_in);
compress->dst=ops_mallocz(sz_out);
memcpy(compress->src,data,len);
// setup stream
compress->stream.next_in=compress->src;
compress->stream.avail_in=sz_in;
compress->stream.total_in=0;
compress->stream.next_out=compress->dst;
compress->stream.avail_out=sz_out;
compress->stream.total_out=0;
r=deflate(&compress->stream, Z_FINISH);
assert(r==Z_STREAM_END); // need to loop if not
// write it out
return (ops_write_ptag(OPS_PTAG_CT_COMPRESSED, cinfo)
&& ops_write_length(1+compress->stream.total_out, cinfo)
&& ops_write_scalar(OPS_C_ZLIB,1,cinfo)
&& ops_write(compress->dst, compress->stream.total_out,cinfo));
}
// Writes out the header for the compressed packet. Invoked by the
// partial stream writer. Note that writing the packet tag and the
// packet length is handled by the partial stream writer.
static ops_boolean_t write_compressed_header(ops_create_info_t *info,
void *header_data)
{
OPS_USED(header_data);
// Write the compression type. Currently we just use ZLIB
ops_write_scalar(OPS_C_ZLIB, 1, info);
return ops_true;
}
static void zlib_error(ops_error_t **errors, z_stream *stream, int error)
{
OPS_ERROR_2(errors,OPS_E_FAIL,
"Error from compression stream %d (%s)", error,
stream->msg == NULL ? "Unknown" : stream->msg);
}
static ops_boolean_t stream_compress_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
// ZLib doesn't like being asked to compress nothing, so return if
// we are given no input.
if (length == 0)
return ops_true;
if (debug)
fprintf(stderr, "Compressing %u bytes\n", length);
compress_arg_t* compress = ops_writer_get_arg(winfo);
compress->bytes_in += length;
compress->stream.next_in = (void*) src;
compress->stream.avail_in = length;
ops_boolean_t result = ops_true;
do
{
compress->stream.next_out = compress->dst;
compress->stream.avail_out = COMPRESS_BUFFER;
int retcode = deflate(&compress->stream, Z_NO_FLUSH);
if (retcode != Z_OK)
{
zlib_error(errors, &compress->stream, retcode);
deflateEnd(&compress->stream);
return ops_false;
}
unsigned bytes_to_write = COMPRESS_BUFFER - compress->stream.avail_out;
if (debug)
fprintf(stderr, "bytes_to_write = %u\n", bytes_to_write);
compress->bytes_out += bytes_to_write;
result = ops_stacked_write(compress->dst, bytes_to_write, errors,
winfo);
}
while (result && compress->stream.avail_out == 0);
return result;
}
static ops_boolean_t stream_compress_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
compress_arg_t* compress = ops_writer_get_arg(winfo);
compress->stream.next_in = NULL;
compress->stream.avail_in = 0;
int retcode = Z_OK;
int output_size = COMPRESS_BUFFER;
ops_boolean_t result = ops_true;
do
{
compress->stream.next_out = compress->dst;
compress->stream.avail_out = output_size;
retcode = deflate(&compress->stream, Z_FINISH);
if (retcode != Z_STREAM_END && retcode != Z_OK)
{
zlib_error(errors, &compress->stream, retcode);
deflateEnd(&compress->stream);
return ops_false;
}
int bytes_to_write = output_size - compress->stream.avail_out;
if (debug)
fprintf(stderr, "At end, bytes_to_write = %u\n", bytes_to_write);
compress->bytes_out += bytes_to_write;
result = ops_stacked_write(compress->dst, bytes_to_write, errors,
winfo);
// If deflate returns Z_OK after we have asked to flush, it means
// that there was not enough space in the output buffer. Increase
// the buffer size and try again.
if (retcode != Z_STREAM_END)
{
if (debug)
fprintf(stderr, "Reallocating %u\n", output_size * 2);
output_size *= 2;
compress->dst = realloc(compress->dst, output_size);
}
}
while (result && retcode != Z_STREAM_END);
int error = deflateEnd(&compress->stream);
if (error != Z_OK)
{
zlib_error(errors, &compress->stream, error);
return ops_false;
}
return result;
}
static void stream_compress_destroyer(ops_writer_info_t *winfo)
{
compress_arg_t* compress = ops_writer_get_arg(winfo);
if (debug)
fprintf(stderr, "Compressed %zu to %zu\n", compress->bytes_in,
compress->bytes_out);
free(compress->dst);
free(compress);
}
/**
\ingroup Core_WritePackets
\brief Pushes a compressed writer onto the stack. Data written
will be encoded as a compressed packet.
\param cinfo Write settings
*/
void ops_writer_push_compressed(ops_create_info_t *cinfo)
{
// This is a streaming writer, so we don't know the length in
// advance. Use a partial writer to handle the partial body
// packet lengths.
ops_writer_push_partial(COMPRESS_BUFFER,
cinfo, OPS_PTAG_CT_COMPRESSED,
write_compressed_header, NULL);
// Create arg to be used with this writer
// Remember to free this in the destroyer
compress_arg_t *compress = ops_mallocz(sizeof *compress);
compress->dst = malloc(COMPRESS_BUFFER);
const int level=Z_DEFAULT_COMPRESSION; // \todo allow varying levels
compress->stream.zalloc=Z_NULL;
compress->stream.zfree=Z_NULL;
compress->stream.opaque=NULL;
compress->stream.avail_out = COMPRESS_BUFFER;
// all other fields set to zero by use of ops_mallocz
if (deflateInit(&compress->stream, level) != Z_OK)
// can't initialise. Is there a better way to handle this?
assert(0);
// And push writer on stack
ops_writer_push(cinfo, stream_compress_writer, stream_compress_finaliser,
stream_compress_destroyer, compress);
}
// EOF

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include "packet-parse.h"
int ops_decompress(ops_region_t *region,ops_parse_info_t *parse_info,
ops_compression_type_t type);
ops_boolean_t ops_write_compressed(const unsigned char* data,
const unsigned int len,
ops_create_info_t *cinfo);
void ops_writer_push_compressed(ops_create_info_t *cinfo);

View File

@ -0,0 +1,15 @@
/* generated by configure from include/openpgpsdk/configure.h.template. Don't edit. */
#define HAVE_ALLOCA_H 0
#define TIME_T_FMT "%ld"
/* for silencing unused parameter warnings */
#define OPS_USED(x) (x)=(x)
/* for tests, flag to tell gpg not to use blocking randomness */
#define GNUPG_QUICK_RANDOM "--quick-random"
/* Avoid a bunch of #ifs */
#ifndef O_BINARY
# define O_BINARY 0
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_CREATE_H
#define OPS_CREATE_H
#include <openpgpsdk/types.h>
#include <openpgpsdk/packet.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/memory.h>
#include <openpgpsdk/errors.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/writer.h>
/**
* \ingroup Create
* This struct contains the required information about how to write this stream
*/
struct ops_create_info
{
ops_writer_info_t winfo;
ops_error_t *errors; /*!< an error stack */
};
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);
ops_memory_t* ops_write_mem_from_file(const char *filename, int* errnum);
int ops_write_file_from_buf(const char *filename, const char* buf, const size_t len, const ops_boolean_t overwrite);
ops_boolean_t ops_calc_session_key_checksum(ops_pk_session_key_t *session_key, unsigned char *cs);
void ops_build_public_key(ops_memory_t *out,const ops_public_key_t *key,
ops_boolean_t make_packet);
ops_boolean_t ops_write_struct_user_id(ops_user_id_t *id,
ops_create_info_t *info);
ops_boolean_t ops_write_struct_public_key(const ops_public_key_t *key,
ops_create_info_t *info);
ops_boolean_t ops_write_ss_header(unsigned length,ops_content_tag_t type,
ops_create_info_t *info);
ops_boolean_t ops_write_struct_secret_key(const ops_secret_key_t *key,
const unsigned char* passphrase,
const size_t pplen,
ops_create_info_t *info);
ops_boolean_t ops_write_one_pass_sig(const ops_secret_key_t* skey,
const ops_hash_algorithm_t hash_alg,
const ops_sig_type_t sig_type,
ops_create_info_t* info);
ops_boolean_t ops_write_literal_data_from_buf(const unsigned char *data,
const int maxlen,
const ops_literal_data_type_t type,
ops_create_info_t *info);
ops_pk_session_key_t *ops_create_pk_session_key(const ops_keydata_t *key);
ops_boolean_t ops_write_pk_session_key(ops_create_info_t *info,
ops_pk_session_key_t *pksk);
ops_boolean_t ops_write_transferable_public_key(const ops_keydata_t *key, ops_boolean_t armoured, ops_create_info_t *info);
ops_boolean_t ops_write_transferable_secret_key(const ops_keydata_t *key, const unsigned char* passphrase, const size_t pplen, ops_boolean_t armoured, ops_create_info_t *info);
ops_boolean_t ops_write_transferable_public_key_from_packet_data(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info);
ops_boolean_t ops_write_transferable_secret_key_from_packet_data(const ops_keydata_t *keydata, ops_boolean_t armoured, ops_create_info_t *info);
#endif /*OPS_CREATE_H*/
// eof

View File

@ -0,0 +1,544 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <openpgpsdk/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"
#include <assert.h>
#include <string.h>
#include <fcntl.h>
#include <openpgpsdk/final.h>
/**
\ingroup Core_MPI
\brief Decrypt and unencode MPI
\param buf Buffer in which to write decrypted unencoded MPI
\param buflen Length of buffer
\param encmpi
\param skey
\return length of MPI
\note only RSA at present
*/
int ops_decrypt_and_unencode_mpi(unsigned char *buf, unsigned buflen,
const BIGNUM *encmpi,
const ops_secret_key_t *skey)
{
unsigned char encmpibuf[8192];
unsigned char mpibuf[8192];
unsigned mpisize;
int n;
int i;
mpisize=BN_num_bytes(encmpi);
/* MPI can't be more than 65,536 */
assert(mpisize <= sizeof encmpibuf);
BN_bn2bin(encmpi, encmpibuf);
assert(skey->public_key.algorithm == OPS_PKA_RSA);
/*
fprintf(stderr,"\nDECRYPTING\n");
fprintf(stderr,"encrypted data : ");
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", encmpibuf[i]);
fprintf(stderr,"\n");
*/
n=ops_rsa_private_decrypt(mpibuf, encmpibuf, (BN_num_bits(encmpi)+7)/8,
&skey->key.rsa, &skey->public_key.key.rsa);
assert(n != -1);
/*
fprintf(stderr,"decrypted encoded m buf : ");
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", mpibuf[i]);
fprintf(stderr,"\n");
*/
if(n <= 0)
return -1;
/*
printf(" decrypted=%d ",n);
hexdump(mpibuf,n);
printf("\n");
*/
// Decode EME-PKCS1_V1_5 (RFC 2437).
if(mpibuf[0] != 0 || mpibuf[1] != 2)
return ops_false;
// Skip the random bytes.
for(i=2 ; i < n && mpibuf[i] ; ++i)
;
if(i == n || i < 10)
return ops_false;
// Skip the zero
++i;
// this is the unencoded m buf
if((unsigned)(n-i) <= buflen)
memcpy(buf, mpibuf+i, n-i);
/*
printf("decoded m buf:\n");
int j;
for (j=0; j<n-i; j++)
printf("%2x ",buf[j]);
printf("\n");
*/
return n-i;
}
/**
\ingroup Core_MPI
\brief RSA-encrypt an MPI
*/
ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *encoded_m_buf,
const size_t sz_encoded_m_buf,
const ops_public_key_t *pkey,
ops_pk_session_key_parameters_t *skp)
{
assert(sz_encoded_m_buf==(size_t) BN_num_bytes(pkey->key.rsa.n));
unsigned char encmpibuf[8192];
int n=0;
n=ops_rsa_public_encrypt(encmpibuf, encoded_m_buf, sz_encoded_m_buf,
&pkey->key.rsa);
assert(n!=-1);
if(n <= 0)
return ops_false;
skp->rsa.encrypted_m=BN_bin2bn(encmpibuf, n, NULL);
/*
fprintf(stderr,"encrypted mpi buf : ");
int i;
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", encmpibuf[i]);
fprintf(stderr,"\n");
*/
return ops_true;
}
#define MAXBUF 1024
static ops_parse_cb_return_t
callback_write_parsed(const ops_parser_content_t *content_,
ops_parse_cb_info_t *cbinfo);
/**
\ingroup HighLevel_Crypto
Encrypt a file
\param input_filename Name of file to be encrypted
\param output_filename Name of file to write to. If NULL, name is constructed from input_filename
\param pub_key Public Key to encrypt file for
\param use_armour Write armoured text, if set
\param allow_overwrite Allow output file to be overwrwritten if it exists
\return ops_true if OK; else ops_false
*/
ops_boolean_t ops_encrypt_file(const char* input_filename,
const char* output_filename,
const ops_keydata_t *pub_key,
const ops_boolean_t use_armour,
const ops_boolean_t allow_overwrite)
{
int fd_in=0;
int fd_out=0;
ops_create_info_t *cinfo;
#ifdef WINDOWS_SYS
fd_in=open(input_filename, O_RDONLY | O_BINARY);
#else
fd_in=open(input_filename, O_RDONLY );
#endif
if(fd_in < 0)
{
perror(input_filename);
return ops_false;
}
fd_out=ops_setup_file_write(&cinfo, output_filename, allow_overwrite);
if (fd_out < 0)
return ops_false;
// set armoured/not armoured here
if (use_armour)
ops_writer_push_armoured_message(cinfo);
// Push the encrypted writer
ops_writer_push_stream_encrypt_se_ip(cinfo, pub_key);
ops_writer_push_literal(cinfo);
// Do the writing
unsigned buffer[10240];
for (;;)
{
int n=0;
n=read(fd_in, buffer, sizeof buffer);
if (!n)
break;
assert(n >= 0);
// FIXME: apparently writing can't fail.
ops_write(buffer, n, cinfo);
}
// tidy up
close(fd_in);
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 chunk of memory, containing a encrypted stream.
\param input_filename Name of file to be decrypted
\param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions.
\param keyring Keyring to use
\param use_armour Expect armoured text, if set
\param allow_overwrite Allow output file to overwritten, if set.
\param cb_get_passphrase Callback to use to get passphrase
*/
ops_boolean_t ops_decrypt_memory(const unsigned char *encrypted_memory,int em_length,
unsigned char **decrypted_memory,int *out_length,
ops_keyring_t* keyring,
const ops_boolean_t use_armour,
ops_parse_cb_t* cb_get_passphrase)
{
int fd_in=0;
int fd_out=0;
char* myfilename=NULL;
//
ops_parse_info_t *pinfo=NULL;
// setup for reading from given input file
ops_memory_t *input_mem = ops_memory_new() ;
ops_memory_add(input_mem,encrypted_memory,em_length) ;
ops_setup_memory_read(&pinfo, input_mem, NULL, callback_write_parsed, ops_false);
if (pinfo == NULL)
{
perror("cannot create memory read");
return ops_false;
}
// setup memory chunk
ops_memory_t *output_mem;
ops_setup_memory_write(&pinfo->cbinfo.cinfo, &output_mem,0) ;
if (output_mem == NULL)
{
perror("Cannot create output memory");
ops_teardown_memory_read(pinfo, input_mem);
return ops_false;
}
// \todo check for suffix matching armour param
// setup keyring and passphrase callback
pinfo->cbinfo.cryptinfo.keyring=keyring;
pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase;
// Set up armour/passphrase options
if (use_armour)
ops_reader_push_dearmour(pinfo);
// Do it
ops_parse_and_print_errors(pinfo);
// Unsetup
if (use_armour)
ops_reader_pop_dearmour(pinfo);
ops_boolean_t res = ops_true ;
// copy output memory to supplied buffer.
//
*out_length = ops_memory_get_length(output_mem) ;
*decrypted_memory = ops_mallocz(*out_length) ;
memcpy(*decrypted_memory,ops_memory_get_data(output_mem),*out_length) ;
ops_decrypt_memory_ABORT:
ops_teardown_memory_write(pinfo->cbinfo.cinfo, output_mem);
ops_teardown_memory_read(pinfo, input_mem);
return res ;
}
/**
\ingroup HighLevel_Crypto
\brief Decrypt a file.
\param input_filename Name of file to be decrypted
\param output_filename Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions.
\param keyring Keyring to use
\param use_armour Expect armoured text, if set
\param allow_overwrite Allow output file to overwritten, if set.
\param cb_get_passphrase Callback to use to get passphrase
*/
ops_boolean_t ops_decrypt_file(const char* input_filename,
const char* output_filename,
ops_keyring_t* keyring,
const ops_boolean_t use_armour,
const ops_boolean_t allow_overwrite,
ops_parse_cb_t* cb_get_passphrase)
{
int fd_in=0;
int fd_out=0;
char* myfilename=NULL;
//
ops_parse_info_t *pinfo=NULL;
// setup for reading from given input file
fd_in=ops_setup_file_read(&pinfo, input_filename,
NULL,
callback_write_parsed,
ops_false);
if (fd_in < 0)
{
perror(input_filename);
return ops_false;
}
// setup output filename
if (output_filename)
{
fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, output_filename,
allow_overwrite);
if (fd_out < 0)
{
perror(output_filename);
ops_teardown_file_read(pinfo, fd_in);
return ops_false;
}
}
else
{
int suffixlen=4;
char *defaultsuffix=".decrypted";
const char *suffix=input_filename+strlen(input_filename)-suffixlen;
if (!strcmp(suffix, ".gpg") || !strcmp(suffix, ".asc"))
{
myfilename=ops_mallocz(strlen(input_filename)-suffixlen+1);
strncpy(myfilename, input_filename,
strlen(input_filename)-suffixlen);
}
else
{
unsigned filenamelen=strlen(input_filename)+strlen(defaultsuffix)+1;
myfilename=ops_mallocz(filenamelen);
snprintf(myfilename, filenamelen, "%s%s", input_filename,
defaultsuffix);
}
fd_out=ops_setup_file_write(&pinfo->cbinfo.cinfo, myfilename,
allow_overwrite);
if (fd_out < 0)
{
perror(myfilename);
free(myfilename);
ops_teardown_file_read(pinfo, fd_in);
return ops_false;
}
free (myfilename);
}
// \todo check for suffix matching armour param
// setup for writing decrypted contents to given output file
// setup keyring and passphrase callback
pinfo->cbinfo.cryptinfo.keyring=keyring;
pinfo->cbinfo.cryptinfo.cb_get_passphrase=cb_get_passphrase;
// Set up armour/passphrase options
if (use_armour)
ops_reader_push_dearmour(pinfo);
// Do it
ops_parse_and_print_errors(pinfo);
// Unsetup
if (use_armour)
ops_reader_pop_dearmour(pinfo);
ops_teardown_file_write(pinfo->cbinfo.cinfo, fd_out);
ops_teardown_file_read(pinfo, fd_in);
// \todo cleardown crypt
return ops_true;
}
static ops_parse_cb_return_t
callback_write_parsed(const ops_parser_content_t *content_,
ops_parse_cb_info_t *cbinfo)
{
ops_parser_content_union_t* content
=(ops_parser_content_union_t *)&content_->content;
static ops_boolean_t skipping;
// ops_boolean_t write=ops_true;
OPS_USED(cbinfo);
// ops_print_packet(content_);
if(content_->tag != OPS_PTAG_CT_UNARMOURED_TEXT && skipping)
{
puts("...end of skip");
skipping=ops_false;
}
switch(content_->tag)
{
case OPS_PTAG_CT_UNARMOURED_TEXT:
printf("OPS_PTAG_CT_UNARMOURED_TEXT\n");
if(!skipping)
{
puts("Skipping...");
skipping=ops_true;
}
fwrite(content->unarmoured_text.data, 1,
content->unarmoured_text.length, stdout);
break;
case OPS_PTAG_CT_PK_SESSION_KEY:
return callback_pk_session_key(content_, cbinfo);
break;
case OPS_PARSER_CMD_GET_SECRET_KEY:
return callback_cmd_get_secret_key(content_, cbinfo);
break;
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
case OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD:
// return callback_cmd_get_secret_key_passphrase(content_,cbinfo);
return cbinfo->cryptinfo.cb_get_passphrase(content_, cbinfo);
break;
case OPS_PTAG_CT_LITERAL_DATA_BODY:
return callback_literal_data(content_, cbinfo);
break;
case OPS_PTAG_CT_ARMOUR_HEADER:
case OPS_PTAG_CT_ARMOUR_TRAILER:
case OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY:
case OPS_PTAG_CT_COMPRESSED:
case OPS_PTAG_CT_LITERAL_DATA_HEADER:
case OPS_PTAG_CT_SE_IP_DATA_BODY:
case OPS_PTAG_CT_SE_IP_DATA_HEADER:
case OPS_PTAG_CT_SE_DATA_BODY:
case OPS_PTAG_CT_SE_DATA_HEADER:
// Ignore these packets
// They're handled in ops_parse_one_packet()
// and nothing else needs to be done
break;
default:
// return callback_general(content_,cbinfo);
break;
// fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag,
// content_->tag);
// assert(0);
}
return OPS_RELEASE_MEMORY;
}
// EOF

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_CRYPTO_H
#define OPS_CRYPTO_H
#include "keyring.h"
#include "util.h"
#include "packet.h"
#include "packet-parse.h"
#include <openssl/dsa.h>
#include <openssl/opensslv.h>
#include <openssl/opensslconf.h>
#if OPENSSL_VERSION_NUMBER < 0x00908030L
# define OPENSSL_NO_CAMELLIA
#endif
#define OPS_MIN_HASH_SIZE 16
typedef void ops_hash_init_t(ops_hash_t *hash);
typedef void ops_hash_add_t(ops_hash_t *hash,const unsigned char *data,
unsigned length);
typedef unsigned ops_hash_finish_t(ops_hash_t *hash,unsigned char *out);
/** _ops_hash_t */
struct _ops_hash_t
{
ops_hash_algorithm_t algorithm;
size_t size;
const char *name;
ops_hash_init_t *init;
ops_hash_add_t *add;
ops_hash_finish_t *finish;
void *data;
};
typedef void ops_crypt_set_iv_t(ops_crypt_t *crypt,
const unsigned char *iv);
typedef void ops_crypt_set_key_t(ops_crypt_t *crypt,
const unsigned char *key);
typedef void ops_crypt_init_t(ops_crypt_t *crypt);
typedef void ops_crypt_resync_t(ops_crypt_t *crypt);
typedef void ops_crypt_block_encrypt_t(ops_crypt_t *crypt,void *out,
const void *in);
typedef void ops_crypt_block_decrypt_t(ops_crypt_t *crypt,void *out,
const void *in);
typedef void ops_crypt_cfb_encrypt_t(ops_crypt_t *crypt,void *out,
const void *in, size_t count);
typedef void ops_crypt_cfb_decrypt_t(ops_crypt_t *crypt,void *out,
const void *in, size_t count);
typedef void ops_crypt_finish_t(ops_crypt_t *crypt);
/** _ops_crypt_t */
struct _ops_crypt_t
{
ops_symmetric_algorithm_t algorithm;
size_t blocksize;
size_t keysize;
ops_crypt_set_iv_t *set_iv; /* Call this before decrypt init! */
ops_crypt_set_key_t *set_key; /* Call this before init! */
ops_crypt_init_t *base_init;
ops_crypt_resync_t *decrypt_resync;
// encrypt/decrypt one block
ops_crypt_block_encrypt_t *block_encrypt;
ops_crypt_block_decrypt_t *block_decrypt;
// Standard CFB encrypt/decrypt (as used by Sym Enc Int Prot packets)
ops_crypt_cfb_encrypt_t *cfb_encrypt;
ops_crypt_cfb_decrypt_t *cfb_decrypt;
ops_crypt_finish_t *decrypt_finish;
unsigned char iv[OPS_MAX_BLOCK_SIZE];
unsigned char civ[OPS_MAX_BLOCK_SIZE];
unsigned char siv[OPS_MAX_BLOCK_SIZE]; /* Needed for weird v3 resync */
unsigned char key[OPS_MAX_KEY_SIZE];
size_t num; /* Offset - see openssl _encrypt doco */
void *encrypt_key;
void *decrypt_key;
};
void ops_crypto_init(void);
void ops_crypto_finish(void);
void ops_hash_md5(ops_hash_t *hash);
void ops_hash_sha1(ops_hash_t *hash);
void ops_hash_sha256(ops_hash_t *hash);
void ops_hash_sha512(ops_hash_t *hash);
void ops_hash_sha384(ops_hash_t *hash);
void ops_hash_sha224(ops_hash_t *hash);
void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg);
ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash);
const char *ops_text_from_hash(ops_hash_t *hash);
unsigned ops_hash_size(ops_hash_algorithm_t alg);
unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in,
size_t length);
void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length);
ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
const ops_dsa_signature_t *sig,
const ops_dsa_public_key_t *dsa);
int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_public_key_t *rsa);
int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_public_key_t *rsa);
int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_secret_key_t *srsa,
const ops_rsa_public_key_t *rsa);
int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_secret_key_t *srsa,
const ops_rsa_public_key_t *rsa);
unsigned ops_block_size(ops_symmetric_algorithm_t alg);
unsigned ops_key_size(ops_symmetric_algorithm_t alg);
int ops_decrypt_data(ops_content_tag_t tag,ops_region_t *region,
ops_parse_info_t *parse_info);
int ops_crypt_any(ops_crypt_t *decrypt,ops_symmetric_algorithm_t alg);
void ops_decrypt_init(ops_crypt_t *decrypt);
void ops_encrypt_init(ops_crypt_t *encrypt);
size_t ops_decrypt_se(ops_crypt_t *decrypt,void *out,const void *in,
size_t count);
size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out,const void *in,
size_t count);
size_t ops_decrypt_se_ip(ops_crypt_t *decrypt,void *out,const void *in,
size_t count);
size_t ops_encrypt_se_ip(ops_crypt_t *encrypt,void *out,const void *in,
size_t count);
ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg);
void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt,
ops_region_t *region);
void ops_reader_pop_decrypt(ops_parse_info_t *pinfo);
// Hash everything that's read
void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash);
void ops_reader_pop_hash(ops_parse_info_t *pinfo);
int ops_decrypt_and_unencode_mpi(unsigned char *buf,unsigned buflen,const BIGNUM *encmpi,
const ops_secret_key_t *skey);
ops_boolean_t ops_rsa_encrypt_mpi(const unsigned char *buf, const size_t buflen,
const ops_public_key_t *pkey,
ops_pk_session_key_parameters_t *spk);
// Encrypt everything that's written
struct ops_key_data;
void ops_writer_push_encrypt(ops_create_info_t *info,
const struct ops_key_data *key);
ops_boolean_t ops_encrypt_file(const char* input_filename, const char* output_filename, const ops_keydata_t *pub_key, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite);
ops_boolean_t ops_decrypt_file(const char* input_filename, const char* output_filename, ops_keyring_t *keyring, const ops_boolean_t use_armour, const ops_boolean_t allow_overwrite,ops_parse_cb_t* cb_get_passphrase);
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);
ops_boolean_t ops_decrypt_memory(const unsigned char *encrypted_memory,int em_length, unsigned char **decrypted_memory,int *out_length, ops_keyring_t* keyring, const ops_boolean_t use_armour, ops_parse_cb_t* cb_get_passphrase) ;
// Keys
ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata);
ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid);
int ops_dsa_size(const ops_dsa_public_key_t *dsa);
DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa);
#endif

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_DEFS_H
#define OPS_DEFS_H
#define OPS_ARMOURED ops_true
#define OPS_UNARMOURED ops_false
#define OPS_OVERWRITE_YES ops_true
#define OPS_OVERWRITE_NO ops_false
#define OPS_ACCUMULATE_YES ops_true
#define OPS_ACCUMULATE_NO ops_false
#endif /* OPS_DEFS_H */

View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
* \brief Error Handling
*/
#include <openpgpsdk/errors.h>
#include <openpgpsdk/util.h>
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#define vsnprintf _vsnprintf
#endif
#include <openpgpsdk/packet-show.h>
#include <openpgpsdk/final.h>
#define ERRNAME(code) { code, #code }
static ops_errcode_name_map_t errcode_name_map[] =
{
ERRNAME(OPS_E_OK),
ERRNAME(OPS_E_FAIL),
ERRNAME(OPS_E_SYSTEM_ERROR),
ERRNAME(OPS_E_UNIMPLEMENTED),
ERRNAME(OPS_E_R),
ERRNAME(OPS_E_R_READ_FAILED),
ERRNAME(OPS_E_R_EARLY_EOF),
ERRNAME(OPS_E_R_BAD_FORMAT),
ERRNAME(OPS_E_R_UNCONSUMED_DATA),
ERRNAME(OPS_E_W),
ERRNAME(OPS_E_W_WRITE_FAILED),
ERRNAME(OPS_E_W_WRITE_TOO_SHORT),
ERRNAME(OPS_E_P),
ERRNAME(OPS_E_P_NOT_ENOUGH_DATA),
ERRNAME(OPS_E_P_UNKNOWN_TAG),
ERRNAME(OPS_E_P_PACKET_CONSUMED),
ERRNAME(OPS_E_P_MPI_FORMAT_ERROR),
ERRNAME(OPS_E_C),
ERRNAME(OPS_E_V),
ERRNAME(OPS_E_V_BAD_SIGNATURE),
ERRNAME(OPS_E_V_NO_SIGNATURE),
ERRNAME(OPS_E_V_UNKNOWN_SIGNER),
ERRNAME(OPS_E_ALG),
ERRNAME(OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG),
ERRNAME(OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG),
ERRNAME(OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG),
ERRNAME(OPS_E_ALG_UNSUPPORTED_HASH_ALG),
ERRNAME(OPS_E_PROTO),
ERRNAME(OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT),
ERRNAME(OPS_E_PROTO_UNKNOWN_SS),
ERRNAME(OPS_E_PROTO_CRITICAL_SS_IGNORED),
ERRNAME(OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN),
ERRNAME(OPS_E_PROTO_BAD_SIGNATURE_VRSN),
ERRNAME(OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN),
ERRNAME(OPS_E_PROTO_BAD_PKSK_VRSN),
ERRNAME(OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN),
ERRNAME(OPS_E_PROTO_BAD_SK_CHECKSUM),
{ 0x00, NULL }, /* this is the end-of-array marker */
};
/**
* \ingroup Core_Errors
* \brief returns error code name
* \param errcode
* \return error code name or "Unknown"
*/
char *ops_errcode(const ops_errcode_t errcode)
{
return(ops_str_from_map((int) errcode, (ops_map_t *) errcode_name_map));
}
/**
* \ingroup Core_Errors
* \brief Pushes the given error on the given errorstack
* \param errstack Error stack to use
* \param errcode Code of error to push
* \param sys_errno System errno (used if errcode=OPS_E_SYSTEM_ERROR)
* \param file Source filename where error occurred
* \param line Line in source file where error occurred
* \param fmt Comment
*
*/
void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
const char *file,int line,const char *fmt,...)
{
// first get the varargs and generate the comment
char *comment;
int maxbuf=128;
va_list args;
ops_error_t *err;
comment=malloc(maxbuf+1);
assert(comment);
va_start(args, fmt);
vsnprintf(comment,maxbuf+1,fmt,args);
va_end(args);
// alloc a new error and add it to the top of the stack
err=malloc(sizeof(ops_error_t));
assert(err);
err->next=*errstack;
*errstack=err;
// fill in the details
err->errcode=errcode;
err->sys_errno=sys_errno;
err->file=file;
err->line=line;
err->comment=comment;
}
/**
\ingroup Core_Errors
\brief print this error
\param err Error to print
*/
void ops_print_error(ops_error_t *err)
{
printf("%s:%d: ",err->file,err->line);
if(err->errcode==OPS_E_SYSTEM_ERROR)
printf("system error %d returned from %s()\n",err->sys_errno,
err->comment);
else
printf("%s, %s\n",ops_errcode(err->errcode),err->comment);
}
/**
\ingroup Core_Errors
\brief Print all errors on stack
\param errstack Error stack to print
*/
void ops_print_errors(ops_error_t *errstack)
{
ops_error_t *err;
for(err=errstack ; err!=NULL ; err=err->next)
ops_print_error(err);
}
/**
\ingroup Core_Errors
\brief Return true if given error is present anywhere on stack
\param errstack Error stack to check
\param errcode Error code to look for
\return 1 if found; else 0
*/
int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode)
{
ops_error_t *err;
for (err=errstack; err!=NULL; err=err->next)
{
if (err->errcode==errcode)
return 1;
}
return 0;
}
/**
\ingroup Core_Errors
\brief Frees all errors on stack
\param errstack Error stack to free
*/
void ops_free_errors(ops_error_t *errstack)
{
ops_error_t *next;
while(errstack!=NULL) {
next=errstack->next;
free(errstack->comment);
free(errstack);
errstack=next;
}
}
/**
\ingroup InternalAPI
\brief Moves errors from a create info structure to another error stack.
The error stack wil be moved from the source structure to the destination
stack. If the destination already has errors defined, the errors will
be appended.
*/
void ops_move_errors(ops_create_info_t *source, ops_error_t **dest)
{
if (*dest == NULL)
*dest = source->errors;
else
{
ops_error_t *last = *dest;
while(last->next != NULL)
last = last->next;
last->next = source->errors;
}
source->errors = NULL;
}
// EOF

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_ERRORS
#define OPS_ERRORS
#include "openpgpsdk/types.h"
#include <errno.h>
/** error codes */
// Remember to add names to map in errors.c
typedef enum
{
OPS_E_OK=0x0000, /* no error */
OPS_E_FAIL=0x0001, /* general error */
OPS_E_SYSTEM_ERROR=0x0002, /* system error, look at errno for details */
OPS_E_UNIMPLEMENTED=0x0003, /* feature not yet implemented */
/* reader errors */
OPS_E_R=0x1000, /* general reader error */
OPS_E_R_READ_FAILED =OPS_E_R+1,
OPS_E_R_EARLY_EOF =OPS_E_R+2,
OPS_E_R_BAD_FORMAT =OPS_E_R+3, // For example, malformed armour
OPS_E_R_UNSUPPORTED =OPS_E_R+4,
OPS_E_R_UNCONSUMED_DATA =OPS_E_R+5,
/* writer errors */
OPS_E_W=0x2000, /* general writer error */
OPS_E_W_WRITE_FAILED = OPS_E_W+1,
OPS_E_W_WRITE_TOO_SHORT = OPS_E_W+2,
/* parser errors */
OPS_E_P=0x3000, /* general parser error */
OPS_E_P_NOT_ENOUGH_DATA =OPS_E_P+1,
OPS_E_P_UNKNOWN_TAG =OPS_E_P+2,
OPS_E_P_PACKET_CONSUMED =OPS_E_P+3,
OPS_E_P_MPI_FORMAT_ERROR =OPS_E_P+4,
OPS_E_P_PACKET_NOT_CONSUMED =OPS_E_P+5,
OPS_E_P_DECOMPRESSION_ERROR =OPS_E_P+6,
OPS_E_P_NO_USERID =OPS_E_P+7,
/* creator errors */
OPS_E_C=0x4000, /* general creator error */
/* validation errors */
OPS_E_V=0x5000, /* general validation error */
OPS_E_V_BAD_SIGNATURE =OPS_E_V+1,
OPS_E_V_NO_SIGNATURE =OPS_E_V+2,
OPS_E_V_UNKNOWN_SIGNER =OPS_E_V+3,
OPS_E_V_BAD_HASH =OPS_E_V+4,
/* Algorithm support errors */
OPS_E_ALG=0x6000, /* general algorithm error */
OPS_E_ALG_UNSUPPORTED_SYMMETRIC_ALG =OPS_E_ALG+1,
OPS_E_ALG_UNSUPPORTED_PUBLIC_KEY_ALG =OPS_E_ALG+2,
OPS_E_ALG_UNSUPPORTED_SIGNATURE_ALG =OPS_E_ALG+3,
OPS_E_ALG_UNSUPPORTED_HASH_ALG =OPS_E_ALG+4,
OPS_E_ALG_UNSUPPORTED_COMPRESS_ALG =OPS_E_ALG+5,
/* Protocol errors */
OPS_E_PROTO=0x7000, /* general protocol error */
OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT =OPS_E_PROTO+2,
OPS_E_PROTO_UNKNOWN_SS =OPS_E_PROTO+3,
OPS_E_PROTO_CRITICAL_SS_IGNORED =OPS_E_PROTO+4,
OPS_E_PROTO_BAD_PUBLIC_KEY_VRSN =OPS_E_PROTO+5,
OPS_E_PROTO_BAD_SIGNATURE_VRSN =OPS_E_PROTO+6,
OPS_E_PROTO_BAD_ONE_PASS_SIG_VRSN =OPS_E_PROTO+7,
OPS_E_PROTO_BAD_PKSK_VRSN =OPS_E_PROTO+8,
OPS_E_PROTO_DECRYPTED_MSG_WRONG_LEN =OPS_E_PROTO+9,
OPS_E_PROTO_BAD_SK_CHECKSUM =OPS_E_PROTO+10,
} ops_errcode_t;
/** ops_errcode_name_map_t */
typedef ops_map_t ops_errcode_name_map_t;
/** one entry in a linked list of errors */
typedef struct ops_error
{
ops_errcode_t errcode;
int sys_errno; /*!< irrelevent unless errcode == OPS_E_SYSTEM_ERROR */
char *comment;
const char *file;
int line;
struct ops_error *next;
} ops_error_t;
char *ops_errcode(const ops_errcode_t errcode);
void ops_push_error(ops_error_t **errstack,ops_errcode_t errcode,int sys_errno,
const char *file,int line,const char *comment,...);
void ops_print_error(ops_error_t *err);
void ops_print_errors(ops_error_t *errstack);
void ops_free_errors(ops_error_t *errstack);
int ops_has_error(ops_error_t *errstack, ops_errcode_t errcode);
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
#define OPS_ERROR(err,code,fmt) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt); } while(0)
#define OPS_ERROR_1(err,code,fmt,arg) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg); } while(0)
#define OPS_ERROR_2(err,code,fmt,arg,arg2) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2); } while(0)
#define OPS_ERROR_3(err,code,fmt,arg,arg2,arg3) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3); } while(0)
#define OPS_ERROR_4(err,code,fmt,arg,arg2,arg3,arg4) do { ops_push_error(err,code,0,__FILE__,__LINE__,fmt,arg,arg2,arg3,arg4); } while(0)
#endif /* OPS_ERRORS */

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* A header that is always included last, for things that need to come last */
#ifdef DMALLOC
# include <dmalloc.h>
#endif

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/packet.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/create.h>
#include <assert.h>
#include <string.h>
#include <openpgpsdk/configure.h>
#if HAVE_ALLOCA_H
# include <alloca.h>
#endif
#ifdef WIN32
#define alloca _alloca
#endif
#include <openpgpsdk/final.h>
static int debug=0;
/**
* \ingroup Core_Keys
* \brief Calculate a public key fingerprint.
* \param fp Where to put the calculated fingerprint
* \param key The key for which the fingerprint is calculated
*/
void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key)
{
if(key->version == 2 || key->version == 3)
{
unsigned char *bn;
int n;
ops_hash_t md5;
assert(key->algorithm == OPS_PKA_RSA
|| key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY
|| key->algorithm == OPS_PKA_RSA_SIGN_ONLY );
ops_hash_md5(&md5);
md5.init(&md5);
n=BN_num_bytes(key->key.rsa.n);
bn=alloca(n);
BN_bn2bin(key->key.rsa.n,bn);
md5.add(&md5,bn,n);
n=BN_num_bytes(key->key.rsa.e);
bn=alloca(n);
BN_bn2bin(key->key.rsa.e,bn);
md5.add(&md5,bn,n);
md5.finish(&md5,fp->fingerprint);
fp->length=16;
}
else
{
ops_memory_t *mem=ops_memory_new();
ops_hash_t sha1;
size_t l;
ops_build_public_key(mem,key,ops_false);
if (debug)
{ fprintf(stderr,"--- creating key fingerprint\n"); }
ops_hash_sha1(&sha1);
sha1.init(&sha1);
l=ops_memory_get_length(mem);
ops_hash_add_int(&sha1,0x99,1);
ops_hash_add_int(&sha1,l,2);
sha1.add(&sha1,ops_memory_get_data(mem),l);
sha1.finish(&sha1,fp->fingerprint);
if (debug)
{ fprintf(stderr,"--- finished creating key fingerprint\n"); }
fp->length=20;
ops_memory_free(mem);
}
}
/**
* \ingroup Core_Keys
* \brief Calculate the Key ID from the public key.
* \param keyid Space for the calculated ID to be stored
* \param key The key for which the ID is calculated
*/
void ops_keyid(unsigned char keyid[8],const ops_public_key_t *key)
{
if(key->version == 2 || key->version == 3)
{
unsigned char bn[8192];
unsigned n=BN_num_bytes(key->key.rsa.n);
assert(n <= sizeof bn);
assert(key->algorithm == OPS_PKA_RSA
|| key->algorithm == OPS_PKA_RSA_ENCRYPT_ONLY
|| key->algorithm == OPS_PKA_RSA_SIGN_ONLY );
BN_bn2bin(key->key.rsa.n,bn);
memcpy(keyid,bn+n-8,8);
}
else
{
ops_fingerprint_t fingerprint;
ops_fingerprint(&fingerprint,key);
memcpy(keyid,fingerprint.fingerprint+fingerprint.length-8,8);
}
}
// EOF

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/crypto.h>
#include <assert.h>
#include <string.h>
#include <openpgpsdk/final.h>
static int debug=0;
/**
\ingroup Core_Hashes
\brief Add to the hash
\param hash Hash to add to
\param n Int to add
\param length Length of int in bytes
*/
void ops_hash_add_int(ops_hash_t *hash,unsigned n,unsigned length)
{
while(length--)
{
unsigned char c[1];
c[0]=n >> (length*8);
hash->add(hash,c,1);
}
}
/**
\ingroup Core_Hashes
\brief Setup hash for given hash algorithm
\param hash Hash to set up
\param alg Hash algorithm to use
*/
void ops_hash_any(ops_hash_t *hash,ops_hash_algorithm_t alg)
{
switch(alg)
{
case OPS_HASH_MD5:
ops_hash_md5(hash);
break;
case OPS_HASH_SHA1:
ops_hash_sha1(hash);
break;
case OPS_HASH_SHA256:
ops_hash_sha256(hash);
break;
case OPS_HASH_SHA384:
ops_hash_sha384(hash);
break;
case OPS_HASH_SHA512:
ops_hash_sha512(hash);
break;
case OPS_HASH_SHA224:
ops_hash_sha224(hash);
break;
default:
assert(0);
}
}
/**
\ingroup Core_Hashes
\brief Returns size of hash for given hash algorithm
\param alg Hash algorithm to use
\return Size of hash algorithm in bytes
*/
unsigned ops_hash_size(ops_hash_algorithm_t alg)
{
switch(alg)
{
case OPS_HASH_MD5:
return 16;
case OPS_HASH_SHA1:
return 20;
case OPS_HASH_SHA256:
return 32;
case OPS_HASH_SHA224:
return 28;
case OPS_HASH_SHA512:
return 64;
case OPS_HASH_SHA384:
return 48;
default:
assert(0);
}
return 0;
}
/**
\ingroup Core_Hashes
\brief Returns hash enum corresponding to given string
\param hash Text name of hash algorithm i.e. "SHA1"
\returns Corresponding enum i.e. OPS_HASH_SHA1
*/
ops_hash_algorithm_t ops_hash_algorithm_from_text(const char *hash)
{
if(!strcmp(hash,"SHA1"))
return OPS_HASH_SHA1;
else if(!strcmp(hash,"MD5"))
return OPS_HASH_MD5;
else if (!strcmp(hash,"SHA256"))
return OPS_HASH_SHA256;
/*
else if (!strcmp(hash,"SHA224"))
return OPS_HASH_SHA224;
*/
else if (!strcmp(hash,"SHA512"))
return OPS_HASH_SHA512;
else if (!strcmp(hash,"SHA384"))
return OPS_HASH_SHA384;
return OPS_HASH_UNKNOWN;
}
/**
\ingroup Core_Hashes
\brief Hash given data
\param out Where to write the hash
\param alg Hash algorithm to use
\param in Data to hash
\param length Length of data
\return Size of hash created
*/
unsigned ops_hash(unsigned char *out,ops_hash_algorithm_t alg,const void *in,
size_t length)
{
ops_hash_t hash;
ops_hash_any(&hash,alg);
hash.init(&hash);
hash.add(&hash,in,length);
return hash.finish(&hash,out);
}
/**
\ingroup Core_Hashes
\brief Calculate hash for MDC packet
\param preamble Preamble to hash
\param sz_preamble Size of preamble
\param plaintext Plaintext to hash
\param sz_plaintext Size of plaintext
\param hashed Resulting hash
*/
void ops_calc_mdc_hash(const unsigned char* preamble, const size_t sz_preamble, const unsigned char* plaintext, const unsigned int sz_plaintext, unsigned char *hashed)
{
ops_hash_t hash;
unsigned char c[1];
if (debug)
{
unsigned int i=0;
fprintf(stderr,"ops_calc_mdc_hash():\n");
fprintf(stderr,"\npreamble: ");
for (i=0; i<sz_preamble;i++)
fprintf(stderr," 0x%02x", preamble[i]);
fprintf(stderr,"\n");
fprintf(stderr,"\nplaintext (len=%d): ",sz_plaintext);
for (i=0; i<sz_plaintext;i++)
fprintf(stderr," 0x%02x", plaintext[i]);
fprintf(stderr,"\n");
}
// init
ops_hash_any(&hash, OPS_HASH_SHA1);
hash.init(&hash);
// preamble
hash.add(&hash,preamble,sz_preamble);
// plaintext
hash.add(&hash,plaintext,sz_plaintext);
// MDC packet tag
c[0]=0xD3;
hash.add(&hash,&c[0],1);
// MDC packet len
c[0]=0x14;
hash.add(&hash,&c[0],1);
//finish
hash.finish(&hash,hashed);
if (debug)
{
unsigned int i=0;
fprintf(stderr,"\nhashed (len=%d): ",OPS_SHA1_HASH_SIZE);
for (i=0; i<OPS_SHA1_HASH_SIZE;i++)
fprintf(stderr," 0x%02x", hashed[i]);
fprintf(stderr,"\n");
}
}
/**
\ingroup HighLevel_Supported
\brief Is this Hash Algorithm supported?
\param hash_alg Hash Algorithm to check
\return ops_true if supported; else ops_false
*/
ops_boolean_t ops_is_hash_alg_supported(const ops_hash_algorithm_t *hash_alg)
{
switch (*hash_alg)
{
case OPS_HASH_MD5:
case OPS_HASH_SHA1:
case OPS_HASH_SHA256:
return ops_true;
default:
return ops_false;
}
}
// EOF

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_HASH_H__
#define __OPS_HASH_H__
#include "openpgpsdk/packet.h"
void ops_calc_mdc_hash(const unsigned char* preamble, const size_t sz_preamble, const unsigned char* plaintext, const unsigned int sz_plaintext, unsigned char *hashed);
ops_boolean_t ops_is_hash_alg_supported(const ops_hash_algorithm_t *hash_alg);
#endif /*__OPS_HASH_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_KEYRING_H
#define OPS_KEYRING_H
#include "packet.h"
#include "memory.h"
typedef struct ops_keydata ops_keydata_t;
/** \struct ops_keyring_t
* A keyring
*/
typedef struct
{
int nkeys; // while we are constructing a key, this is the offset
int nkeys_allocated;
ops_keydata_t *keys;
} ops_keyring_t;
const ops_keydata_t *
ops_keyring_find_key_by_id(const ops_keyring_t *keyring,
const unsigned char keyid[OPS_KEY_ID_SIZE]);
const ops_keydata_t *
ops_keyring_find_key_by_userid(const ops_keyring_t *keyring,
const char* userid);
void ops_keydata_free(ops_keydata_t *key);
void ops_keydata_copy(ops_keydata_t *dst,const ops_keydata_t *src);
void ops_keyring_free(ops_keyring_t *keyring);
void ops_dump_keyring(const ops_keyring_t *keyring);
const ops_public_key_t *
ops_get_public_key_from_data(const ops_keydata_t *data);
ops_boolean_t ops_is_key_secret(const ops_keydata_t *data);
const ops_secret_key_t *
ops_get_secret_key_from_data(const ops_keydata_t *data);
ops_secret_key_t *
ops_get_writable_secret_key_from_data(ops_keydata_t *data);
ops_secret_key_t *ops_decrypt_secret_key_from_data(const ops_keydata_t *key,
const char *pphrase);
ops_boolean_t ops_keyring_read_from_file(ops_keyring_t *keyring, const ops_boolean_t armour, const char *filename);
ops_boolean_t ops_keyring_read_from_mem(ops_keyring_t *keyring, const ops_boolean_t armour, ops_memory_t *mem);
ops_boolean_t ops_write_keyring_to_file(const ops_keyring_t *keyring,ops_boolean_t armoured,const char *filename,ops_boolean_t write_all_packets);
char *ops_malloc_passphrase(char *passphrase);
char *ops_get_passphrase(void);
void ops_keyring_list(const ops_keyring_t* keyring);
void ops_set_secret_key(ops_parser_content_union_t* content,const ops_keydata_t *key);
const unsigned char* ops_get_key_id(const ops_keydata_t *key);
unsigned ops_get_user_id_count(const ops_keydata_t *key);
const unsigned char* ops_get_user_id(const ops_keydata_t *key, unsigned index);
ops_boolean_t ops_is_key_supported(const ops_keydata_t *key);
const ops_keydata_t* ops_keyring_get_key_by_index(const ops_keyring_t *keyring, int index);
ops_user_id_t* ops_add_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid);
ops_packet_t* ops_add_packet_to_keydata(ops_keydata_t* keydata, const ops_packet_t* packet);
void ops_add_signed_userid_to_keydata(ops_keydata_t* keydata, const ops_user_id_t* userid, const ops_packet_t* packet);
ops_boolean_t ops_add_selfsigned_userid_to_keydata(ops_keydata_t* keydata, ops_user_id_t* userid);
ops_boolean_t ops_sign_key(ops_keydata_t* keydata_to_sign, const unsigned char *signers_key_id,ops_secret_key_t *signers_decrypted_private_key);
ops_keydata_t *ops_keydata_new(void);
void ops_keydata_init(ops_keydata_t* keydata, const ops_content_tag_t type);
#endif

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/packet.h>
#define DECLARE_ARRAY(type,arr) unsigned n##arr; unsigned n##arr##_allocated; type *arr
#define EXPAND_ARRAY(str,arr) do if(str->n##arr == str->n##arr##_allocated) \
{ \
str->n##arr##_allocated=str->n##arr##_allocated*2+10; \
str->arr=realloc(str->arr,str->n##arr##_allocated*sizeof *str->arr); \
} while(0)
/** ops_keydata_key_t
*/
typedef union
{
ops_public_key_t pkey;
ops_secret_key_t skey;
} ops_keydata_key_t;
/** sigpacket_t */
typedef struct
{
ops_user_id_t* userid;
ops_packet_t* packet;
} sigpacket_t;
// XXX: gonna have to expand this to hold onto subkeys, too...
/** \struct ops_keydata
* \todo expand to hold onto subkeys
*/
struct ops_keydata
{
DECLARE_ARRAY(ops_user_id_t,uids);
DECLARE_ARRAY(ops_packet_t,packets);
DECLARE_ARRAY(sigpacket_t, sigs);
unsigned char key_id[8];
ops_fingerprint_t fingerprint;
ops_content_tag_t type;
ops_keydata_key_t key;
};

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file
*
* Set of functions to manage a dynamic list
*/
#include <openpgpsdk/lists.h>
#include <stdlib.h>
#include <openpgpsdk/final.h>
/**
* \ingroup Core_Lists
* \brief Initialises ulong list
* \param *list Pointer to existing list structure
*/
void ops_ulong_list_init(ops_ulong_list_t *list)
{
list->size=0;
list->used=0;
list->ulongs=NULL;
}
/**
* \ingroup Core_Lists
* \brief Frees allocated memory in ulong list. Does not free *list itself.
* \param *list
*/
void ops_ulong_list_free(ops_ulong_list_t *list)
{
if (list->ulongs)
free(list->ulongs);
ops_ulong_list_init(list);
}
/**
* \ingroup Core_Lists
* \brief Resizes ulong list.
*
* We only resize in one direction - upwards.
* Algorithm used : double the current size then add 1
*
* \param *list Pointer to list
* \return 1 if success, else 0
*/
static unsigned int ops_ulong_list_resize(ops_ulong_list_t *list)
{
int newsize=0;
newsize=list->size*2 + 1;
list->ulongs=realloc(list->ulongs,newsize*sizeof *list->ulongs);
if (list->ulongs)
{
list->size=newsize;
return 1;
}
else
{
/* xxx - realloc failed. error message? - rachel */
return 0;
}
}
/**
* \ingroup Core_Lists
* Adds entry to ulong list
*
* \param *list
* \param *ulong
*
* \return 1 if success, else 0
*/
unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong)
{
if (list->size==list->used)
if (!ops_ulong_list_resize(list))
return 0;
list->ulongs[list->used]=*ulong;
list->used++;
return 1;
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_LISTS_H
#define OPS_LISTS_H
/** ops_ulong_list_t */
typedef struct
{
unsigned int size;/* num of array slots allocated */
unsigned int used; /* num of array slots currently used */
unsigned long *ulongs;
} ops_ulong_list_t;
void ops_ulong_list_init(ops_ulong_list_t *list);
void ops_ulong_list_free(ops_ulong_list_t *list);
unsigned int ops_ulong_list_add(ops_ulong_list_t *list, unsigned long *ulong);
#endif /* OPS_LISTS_H */

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2005-2009 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_LITERAL_H__
#define __OPS_LITERAL_H__
ops_boolean_t write_literal_header(ops_create_info_t *info,
void *header_data);
void ops_writer_push_literal(ops_create_info_t *info);
void ops_writer_push_literal_with_opts(ops_create_info_t *info,
unsigned int buf_size);
#endif /* __OPS_LITERAL_H__ */
// EOF

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/create.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <openpgpsdk/final.h>
struct ops_memory
{
unsigned char *buf;
size_t length;
size_t allocated;
};
/**
\ingroup HighLevel_Memory
\brief Memory to initialise
\param mem memory to initialise
\param initial_size Size to initialise to
*/
void ops_memory_init(ops_memory_t *mem,size_t initial_size)
{
mem->length=0;
if(mem->buf)
{
if(mem->allocated < initial_size)
{
mem->buf=realloc(mem->buf,initial_size);
mem->allocated=initial_size;
}
return;
}
mem->buf=malloc(initial_size);
mem->allocated=initial_size;
}
/**
\ingroup HighLevel_Memory
\brief Pad memory to required length
\param mem Memory to use
\param length New size
*/
void ops_memory_pad(ops_memory_t *mem,size_t length)
{
assert(mem->allocated >= mem->length);
if(mem->allocated < mem->length+length)
{
mem->allocated=mem->allocated*2+length;
mem->buf=realloc(mem->buf,mem->allocated);
}
assert(mem->allocated >= mem->length+length);
}
/**
\ingroup HighLevel_Memory
\brief Add data to memory
\param mem Memory to which to add
\param src Data to add
\param length Length of data to add
*/
void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length)
{
ops_memory_pad(mem,length);
memcpy(mem->buf+mem->length,src,length);
mem->length+=length;
}
// XXX: this could be refactored via the writer, but an awful lot of
// hoops to jump through for 2 lines of code!
void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n,
size_t length)
{
assert(mem->allocated >= offset+length);
while(length--)
mem->buf[offset++]=n >> (length*8);
}
/**
* \ingroup HighLevel_Memory
* \brief Retains allocated memory and set length of stored data to zero.
* \param mem Memory to clear
* \sa ops_memory_release()
* \sa ops_memory_free()
*/
void ops_memory_clear(ops_memory_t *mem)
{ mem->length=0; }
/**
\ingroup HighLevel_Memory
\brief Free memory and associated data
\param mem Memory to free
\note This does not free mem itself
\sa ops_memory_clear()
\sa ops_memory_free()
*/
void ops_memory_release(ops_memory_t *mem)
{
free(mem->buf);
mem->buf=NULL;
mem->length=0;
}
void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag)
{
size_t extra;
if(out->length < 192)
extra=1;
else if(out->length < 8384)
extra=2;
else
extra=5;
ops_memory_pad(out,extra+1);
memmove(out->buf+extra+1,out->buf,out->length);
out->buf[0]=OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT|tag;
if(out->length < 192)
out->buf[1]=out->length;
else if(out->length < 8384)
{
out->buf[1]=((out->length-192) >> 8)+192;
out->buf[2]=out->length-192;
}
else
{
out->buf[1]=0xff;
out->buf[2]=out->length >> 24;
out->buf[3]=out->length >> 16;
out->buf[4]=out->length >> 8;
out->buf[5]=out->length;
}
out->length+=extra+1;
}
/**
\ingroup HighLevel_Memory
\brief Create a new zeroed ops_memory_t
\return Pointer to new ops_memory_t
\note Free using ops_memory_free() after use.
\sa ops_memory_free()
*/
ops_memory_t *ops_memory_new()
{ return ops_mallocz(sizeof(ops_memory_t)); }
/**
\ingroup HighLevel_Memory
\brief Free memory ptr and associated memory
\param mem Memory to be freed
\sa ops_memory_release()
\sa ops_memory_clear()
*/
void ops_memory_free(ops_memory_t *mem)
{
ops_memory_release(mem);
free(mem);
}
/**
\ingroup HighLevel_Memory
\brief Get length of data stored in ops_memory_t struct
\return Number of bytes in data
*/
size_t ops_memory_get_length(const ops_memory_t *mem)
{ return mem->length; }
/**
\ingroup HighLevel_Memory
\brief Get data stored in ops_memory_t struct
\return Pointer to data
*/
void *ops_memory_get_data(ops_memory_t *mem)
{ return mem->buf; }
// EOF

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <sys/types.h>
#include <openssl/bn.h>
#include "packet.h"
#ifndef OPS_MEMORY_H
#define OPS_MEMORY_H
/** ops_memory_t
*/
typedef struct ops_memory ops_memory_t;
ops_memory_t *ops_memory_new(void);
void ops_memory_free(ops_memory_t *mem);
void ops_memory_init(ops_memory_t *mem,size_t initial_size);
void ops_memory_pad(ops_memory_t *mem,size_t length);
void ops_memory_add(ops_memory_t *mem,const unsigned char *src,size_t length);
void ops_memory_place_int(ops_memory_t *mem,unsigned offset,unsigned n,
size_t length);
void ops_memory_make_packet(ops_memory_t *out,ops_content_tag_t tag);
void ops_memory_clear(ops_memory_t *mem);
void ops_memory_release(ops_memory_t *mem);
void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem);
size_t ops_memory_get_length(const ops_memory_t *mem);
void *ops_memory_get_data(ops_memory_t *mem);
#endif

View File

@ -0,0 +1,812 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <assert.h>
#include <stdlib.h>
#include <openpgpsdk/configure.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/readerwriter.h>
#include "keyring_local.h"
#include <openpgpsdk/std_print.h>
#include <openpgpsdk/final.h>
static int debug=0;
void test_secret_key(const ops_secret_key_t *skey)
{
RSA* test=RSA_new();
test->n=BN_dup(skey->public_key.key.rsa.n);
test->e=BN_dup(skey->public_key.key.rsa.e);
test->d=BN_dup(skey->key.rsa.d);
test->p=BN_dup(skey->key.rsa.p);
test->q=BN_dup(skey->key.rsa.q);
assert(RSA_check_key(test)==1);
RSA_free(test);
}
static void md5_init(ops_hash_t *hash)
{
assert(!hash->data);
hash->data=malloc(sizeof(MD5_CTX));
MD5_Init(hash->data);
}
static void md5_add(ops_hash_t *hash,const unsigned char *data,unsigned length)
{
MD5_Update(hash->data,data,length);
}
static unsigned md5_finish(ops_hash_t *hash,unsigned char *out)
{
MD5_Final(out,hash->data);
free(hash->data);
hash->data=NULL;
return 16;
}
static ops_hash_t md5={OPS_HASH_MD5,MD5_DIGEST_LENGTH,"MD5",md5_init,md5_add,
md5_finish,NULL};
/**
\ingroup Core_Crypto
\brief Initialise to MD5
\param hash Hash to initialise
*/
void ops_hash_md5(ops_hash_t *hash)
{
*hash=md5;
}
static void sha1_init(ops_hash_t *hash)
{
if (debug)
{
fprintf(stderr,"***\n***\nsha1_init\n***\n");
}
assert(!hash->data);
hash->data=malloc(sizeof(SHA_CTX));
SHA1_Init(hash->data);
}
static void sha1_add(ops_hash_t *hash,const unsigned char *data,
unsigned length)
{
if (debug)
{
unsigned int i=0;
fprintf(stderr,"adding %d to hash:\n ", length);
for (i=0; i<length; i++)
{
fprintf(stderr,"0x%02x ", data[i]);
if (!((i+1) % 16))
fprintf(stderr,"\n");
else if (!((i+1) % 8))
fprintf(stderr," ");
}
fprintf(stderr,"\n");
}
SHA1_Update(hash->data,data,length);
}
static unsigned sha1_finish(ops_hash_t *hash,unsigned char *out)
{
SHA1_Final(out,hash->data);
if (debug)
{
unsigned i=0;
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
for (i=0; i<SHA_DIGEST_LENGTH; i++)
fprintf(stderr,"0x%02x ",out[i]);
fprintf(stderr,"\n");
}
free(hash->data);
hash->data=NULL;
return SHA_DIGEST_LENGTH;
}
static ops_hash_t sha1={OPS_HASH_SHA1,SHA_DIGEST_LENGTH,"SHA1",sha1_init,
sha1_add,sha1_finish,NULL};
/**
\ingroup Core_Crypto
\brief Initialise to SHA1
\param hash Hash to initialise
*/
void ops_hash_sha1(ops_hash_t *hash)
{
*hash=sha1;
}
static void sha256_init(ops_hash_t *hash)
{
if (debug)
{
fprintf(stderr,"***\n***\nsha256_init\n***\n");
}
assert(!hash->data);
hash->data=malloc(sizeof(SHA256_CTX));
SHA256_Init(hash->data);
}
static void sha256_add(ops_hash_t *hash,const unsigned char *data,
unsigned length)
{
if (debug)
{
unsigned int i=0;
fprintf(stderr,"adding %d to hash:\n ", length);
for (i=0; i<length; i++)
{
fprintf(stderr,"0x%02x ", data[i]);
if (!((i+1) % 16))
fprintf(stderr,"\n");
else if (!((i+1) % 8))
fprintf(stderr," ");
}
fprintf(stderr,"\n");
}
SHA256_Update(hash->data,data,length);
}
static unsigned sha256_finish(ops_hash_t *hash,unsigned char *out)
{
SHA256_Final(out,hash->data);
if (debug)
{
unsigned i=0;
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
for (i=0; i<SHA256_DIGEST_LENGTH; i++)
fprintf(stderr,"0x%02x ",out[i]);
fprintf(stderr,"\n");
}
free(hash->data);
hash->data=NULL;
return SHA256_DIGEST_LENGTH;
}
static ops_hash_t sha256={OPS_HASH_SHA256,SHA256_DIGEST_LENGTH,"SHA256",sha256_init,
sha256_add,sha256_finish,NULL};
void ops_hash_sha256(ops_hash_t *hash)
{
*hash=sha256;
}
/*
* SHA384
*/
static void sha384_init(ops_hash_t *hash)
{
if (debug)
{
fprintf(stderr,"***\n***\nsha384_init\n***\n");
}
assert(!hash->data);
hash->data=malloc(sizeof(SHA512_CTX));
SHA384_Init(hash->data);
}
static void sha384_add(ops_hash_t *hash,const unsigned char *data,
unsigned length)
{
if (debug)
{
unsigned int i=0;
fprintf(stderr,"adding %d to hash:\n ", length);
for (i=0; i<length; i++)
{
fprintf(stderr,"0x%02x ", data[i]);
if (!((i+1) % 16))
fprintf(stderr,"\n");
else if (!((i+1) % 8))
fprintf(stderr," ");
}
fprintf(stderr,"\n");
}
SHA384_Update(hash->data,data,length);
}
static unsigned sha384_finish(ops_hash_t *hash,unsigned char *out)
{
SHA384_Final(out,hash->data);
if (debug)
{
unsigned i=0;
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
for (i=0; i<SHA384_DIGEST_LENGTH; i++)
fprintf(stderr,"0x%02x ",out[i]);
fprintf(stderr,"\n");
}
free(hash->data);
hash->data=NULL;
return SHA384_DIGEST_LENGTH;
}
static ops_hash_t sha384={OPS_HASH_SHA384,SHA384_DIGEST_LENGTH,"SHA384",sha384_init,
sha384_add,sha384_finish,NULL};
void ops_hash_sha384(ops_hash_t *hash)
{
*hash=sha384;
}
/*
* SHA512
*/
static void sha512_init(ops_hash_t *hash)
{
if (debug)
{
fprintf(stderr,"***\n***\nsha512_init\n***\n");
}
assert(!hash->data);
hash->data=malloc(sizeof(SHA512_CTX));
SHA512_Init(hash->data);
}
static void sha512_add(ops_hash_t *hash,const unsigned char *data,
unsigned length)
{
if (debug)
{
unsigned int i=0;
fprintf(stderr,"adding %d to hash:\n ", length);
for (i=0; i<length; i++)
{
fprintf(stderr,"0x%02x ", data[i]);
if (!((i+1) % 16))
fprintf(stderr,"\n");
else if (!((i+1) % 8))
fprintf(stderr," ");
}
fprintf(stderr,"\n");
}
SHA512_Update(hash->data,data,length);
}
static unsigned sha512_finish(ops_hash_t *hash,unsigned char *out)
{
SHA512_Final(out,hash->data);
if (debug)
{
unsigned i=0;
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
for (i=0; i<SHA512_DIGEST_LENGTH; i++)
fprintf(stderr,"0x%02x ",out[i]);
fprintf(stderr,"\n");
}
free(hash->data);
hash->data=NULL;
return SHA512_DIGEST_LENGTH;
}
static ops_hash_t sha512={OPS_HASH_SHA512,SHA512_DIGEST_LENGTH,"SHA512",sha512_init,
sha512_add,sha512_finish,NULL};
void ops_hash_sha512(ops_hash_t *hash)
{
*hash=sha512;
}
/*
* SHA224
*/
static void sha224_init(ops_hash_t *hash)
{
if (debug)
{
fprintf(stderr,"***\n***\nsha1_init\n***\n");
}
assert(!hash->data);
hash->data=malloc(sizeof(SHA256_CTX));
SHA224_Init(hash->data);
}
static void sha224_add(ops_hash_t *hash,const unsigned char *data,
unsigned length)
{
if (debug)
{
unsigned int i=0;
fprintf(stderr,"adding %d to hash:\n ", length);
for (i=0; i<length; i++)
{
fprintf(stderr,"0x%02x ", data[i]);
if (!((i+1) % 16))
fprintf(stderr,"\n");
else if (!((i+1) % 8))
fprintf(stderr," ");
}
fprintf(stderr,"\n");
}
SHA224_Update(hash->data,data,length);
}
static unsigned sha224_finish(ops_hash_t *hash,unsigned char *out)
{
SHA224_Final(out,hash->data);
if (debug)
{
unsigned i=0;
fprintf(stderr,"***\n***\nsha1_finish\n***\n");
for (i=0; i<SHA224_DIGEST_LENGTH; i++)
fprintf(stderr,"0x%02x ",out[i]);
fprintf(stderr,"\n");
}
free(hash->data);
hash->data=NULL;
return SHA224_DIGEST_LENGTH;
}
static ops_hash_t sha224={OPS_HASH_SHA224,SHA224_DIGEST_LENGTH,"SHA224",sha224_init,
sha224_add,sha224_finish,NULL};
void ops_hash_sha224(ops_hash_t *hash)
{
*hash=sha224;
}
ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
const ops_dsa_signature_t *sig,
const ops_dsa_public_key_t *dsa)
{
DSA_SIG *osig;
DSA *odsa;
int ret;
osig=DSA_SIG_new();
osig->r=sig->r;
osig->s=sig->s;
if(BN_num_bits(dsa->q) != 160)
{
fprintf(stderr,"(WW) ops_dsa_verify: openssl does only supports 'q' of 160 bits. Current is %d bits.\n",BN_num_bits(dsa->q)) ;
return ops_false ;
}
odsa=DSA_new();
odsa->p=dsa->p;
odsa->q=dsa->q;
odsa->g=dsa->g;
odsa->pub_key=dsa->y;
if (debug)
{
fprintf(stderr,"hash passed in:\n");
unsigned i;
for (i=0; i<hash_length; i++)
{
fprintf(stderr,"%02x ", hash[i]);
}
fprintf(stderr,"\n");
}
//printf("hash_length=%ld\n", hash_length);
//printf("Q=%d\n", BN_num_bytes(odsa->q));
unsigned int qlen=BN_num_bytes(odsa->q);
if (qlen < hash_length)
hash_length=qlen;
// ret=DSA_do_verify(hash,hash_length,osig,odsa);
ret=DSA_do_verify(hash,hash_length,osig,odsa);
if (debug)
{
fprintf(stderr,"ret=%d\n",ret);
}
if(ret < 0)
{
ERR_load_crypto_strings() ;
unsigned long err = 0 ;
while(err = ERR_get_error())
fprintf(stderr,"DSA_do_verify(): ERR = %ld. lib error:\"%s\", func_error:\"%s\", reason:\"%s\"\n",err,ERR_lib_error_string(err),ERR_func_error_string(err),ERR_reason_error_string(err)) ;
//assert(ret >= 0);
return ops_false ;
}
odsa->p=odsa->q=odsa->g=odsa->pub_key=NULL;
DSA_free(odsa);
osig->r=osig->s=NULL;
DSA_SIG_free(osig);
return ret != 0;
}
/**
\ingroup Core_Crypto
\brief Recovers message digest from the signature
\param out Where to write decrypted data to
\param in Encrypted data
\param length Length of encrypted data
\param rsa RSA public key
\return size of recovered message digest
*/
int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_public_key_t *rsa)
{
RSA *orsa;
int n;
orsa=RSA_new();
orsa->n=rsa->n;
orsa->e=rsa->e;
n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING);
orsa->n=orsa->e=NULL;
RSA_free(orsa);
return n;
}
/**
\ingroup Core_Crypto
\brief Signs data with RSA
\param out Where to write signature
\param in Data to sign
\param length Length of data
\param srsa RSA secret key
\param rsa RSA public key
\return number of bytes decrypted
*/
int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_secret_key_t *srsa,
const ops_rsa_public_key_t *rsa)
{
RSA *orsa;
int n;
orsa=RSA_new();
orsa->n=rsa->n; // XXX: do we need n?
orsa->d=srsa->d;
orsa->p=srsa->q;
orsa->q=srsa->p;
/* debug */
orsa->e=rsa->e;
// If this isn't set, it's very likely that the programmer hasn't
// decrypted the secret key. RSA_check_key segfaults in that case.
// Use ops_decrypt_secret_key_from_data() to do that.
assert(orsa->d);
assert(RSA_check_key(orsa) == 1);
orsa->e=NULL;
/* end debug */
n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING);
orsa->n=orsa->d=orsa->p=orsa->q=NULL;
RSA_free(orsa);
return n;
}
/**
\ingroup Core_Crypto
\brief Decrypts RSA-encrypted data
\param out Where to write the plaintext
\param in Encrypted data
\param length Length of encrypted data
\param srsa RSA secret key
\param rsa RSA public key
\return size of recovered plaintext
*/
int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_secret_key_t *srsa,
const ops_rsa_public_key_t *rsa)
{
RSA *orsa;
int n;
char errbuf[1024];
orsa=RSA_new();
orsa->n=rsa->n; // XXX: do we need n?
orsa->d=srsa->d;
orsa->p=srsa->q;
orsa->q=srsa->p;
/* debug */
orsa->e=rsa->e;
assert(RSA_check_key(orsa) == 1);
orsa->e=NULL;
/* end debug */
n=RSA_private_decrypt(length,in,out,orsa,RSA_NO_PADDING);
// printf("ops_rsa_private_decrypt: n=%d\n",n);
errbuf[0]='\0';
if (n==-1)
{
unsigned long err=ERR_get_error();
ERR_error_string(err,&errbuf[0]);
fprintf(stderr,"openssl error : %s\n",errbuf);
}
orsa->n=orsa->d=orsa->p=orsa->q=NULL;
RSA_free(orsa);
return n;
}
/**
\ingroup Core_Crypto
\brief RSA-encrypts data
\param out Where to write the encrypted data
\param in Plaintext
\param length Size of plaintext
\param rsa RSA Public Key
*/
int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
size_t length,const ops_rsa_public_key_t *rsa)
{
RSA *orsa;
int n;
// printf("ops_rsa_public_encrypt: length=%ld\n", length);
orsa=RSA_new();
orsa->n=rsa->n;
orsa->e=rsa->e;
// printf("len: %ld\n", length);
// ops_print_bn("n: ", orsa->n);
// ops_print_bn("e: ", orsa->e);
n=RSA_public_encrypt(length,in,out,orsa,RSA_NO_PADDING);
if (n==-1)
{
BIO *fd_out;
fd_out=BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
ERR_print_errors(fd_out);
}
orsa->n=orsa->e=NULL;
RSA_free(orsa);
return n;
}
/**
\ingroup Core_Crypto
\brief initialises openssl
\note Would usually call ops_init() instead
\sa ops_init()
*/
void ops_crypto_init()
{
#ifdef DMALLOC
CRYPTO_malloc_debug_init();
CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
#endif
}
/**
\ingroup Core_Crypto
\brief Finalise openssl
\note Would usually call ops_finish() instead
\sa ops_finish()
*/
void ops_crypto_finish()
{
CRYPTO_cleanup_all_ex_data();
// FIXME: what should we do instead (function is deprecated)?
// ERR_remove_state(0);
#ifdef DMALLOC
CRYPTO_mem_leaks_fp(stderr);
#endif
}
/**
\ingroup Core_Hashes
\brief Get Hash name
\param hash Hash struct
\return Hash name
*/
const char *ops_text_from_hash(ops_hash_t *hash)
{ return hash->name; }
/**
\ingroup HighLevel_KeyGenerate
\brief Generates an RSA keypair
\param numbits Modulus size
\param e Public Exponent
\param keydata Pointer to keydata struct to hold new key
\return ops_true if key generated successfully; otherwise ops_false
\note It is the caller's responsibility to call ops_keydata_free(keydata)
*/
ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e,
ops_keydata_t* keydata)
{
ops_secret_key_t *skey=NULL;
RSA *rsa=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
BN_set_word(ebn,e);
RSA_generate_key_ex(rsa,numbits,ebn,NULL);
// populate ops key from ssl key
skey->public_key.version=4;
skey->public_key.creation_time=time(NULL);
skey->public_key.days_valid=0;
skey->public_key.algorithm= OPS_PKA_RSA;
skey->public_key.key.rsa.n=BN_dup(rsa->n);
skey->public_key.key.rsa.e=BN_dup(rsa->e);
skey->s2k_usage=OPS_S2KU_ENCRYPTED_AND_HASHED;
skey->s2k_specifier=OPS_S2KS_SALTED;
//skey->s2k_specifier=OPS_S2KS_SIMPLE;
skey->algorithm=OPS_SA_CAST5; // \todo make param
skey->hash_algorithm=OPS_HASH_SHA1; // \todo make param
skey->octet_count=0;
skey->checksum=0;
skey->key.rsa.d=BN_dup(rsa->d);
skey->key.rsa.p=BN_dup(rsa->p);
skey->key.rsa.q=BN_dup(rsa->q);
skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx);
assert(skey->key.rsa.u);
BN_CTX_free(ctx);
RSA_free(rsa);
ops_keyid(keydata->key_id, &keydata->key.skey.public_key);
ops_fingerprint(&keydata->fingerprint, &keydata->key.skey.public_key);
// Generate checksum
ops_create_info_t *cinfo=NULL;
ops_memory_t *mem=NULL;
ops_setup_memory_write(&cinfo, &mem, 128);
ops_push_skey_checksum_writer(cinfo, skey);
switch(skey->public_key.algorithm)
{
// case OPS_PKA_DSA:
// return ops_write_mpi(key->key.dsa.x,info);
case OPS_PKA_RSA:
case OPS_PKA_RSA_ENCRYPT_ONLY:
case OPS_PKA_RSA_SIGN_ONLY:
if(!ops_write_mpi(skey->key.rsa.d,cinfo)
|| !ops_write_mpi(skey->key.rsa.p,cinfo)
|| !ops_write_mpi(skey->key.rsa.q,cinfo)
|| !ops_write_mpi(skey->key.rsa.u,cinfo))
return ops_false;
break;
// case OPS_PKA_ELGAMAL:
// return ops_write_mpi(key->key.elgamal.x,info);
default:
assert(0);
break;
}
// close rather than pop, since its the only one on the stack
ops_writer_close(cinfo);
ops_teardown_memory_write(cinfo, mem);
// should now have checksum in skey struct
// test
if (debug)
test_secret_key(skey);
return ops_true;
}
/**
\ingroup HighLevel_KeyGenerate
\brief Creates a self-signed RSA keypair
\param numbits Modulus size
\param e Public Exponent
\param userid User ID
\return The new keypair or NULL
\note It is the caller's responsibility to call ops_keydata_free(keydata)
\sa ops_rsa_generate_keypair()
\sa ops_keydata_free()
*/
ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid)
{
ops_keydata_t *keydata=NULL;
keydata=ops_keydata_new();
if (ops_rsa_generate_keypair(numbits, e, keydata) != ops_true
|| ops_add_selfsigned_userid_to_keydata(keydata, userid) != ops_true)
{
ops_keydata_free(keydata);
free(keydata) ;
return NULL;
}
return keydata;
}
/*
int ops_dsa_size(const ops_dsa_public_key_t *dsa)
{
int size;
DSA *odsa;
odsa=DSA_new();
odsa->p=dsa->p;
odsa->q=dsa->q;
odsa->g=dsa->g;
odsa->pub_key=dsa->y;
DSAparams_print_fp(stderr, odsa);
size=DSA_size(odsa);
odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL;
DSA_free(odsa);
return size;
}
*/
DSA_SIG* ops_dsa_sign(unsigned char* hashbuf, unsigned hashsize, const ops_dsa_secret_key_t *sdsa, const ops_dsa_public_key_t *dsa)
{
DSA *odsa;
DSA_SIG *dsasig;
odsa=DSA_new();
odsa->p=dsa->p;
odsa->q=dsa->q;
odsa->g=dsa->g;
odsa->pub_key=dsa->y;
odsa->priv_key=sdsa->x;
dsasig=DSA_do_sign(hashbuf,hashsize,odsa);
odsa->p=odsa->q=odsa->g=odsa->pub_key=odsa->priv_key=NULL;
DSA_free(odsa);
return dsasig;
}
// eof

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
* Parser for OpenPGP packets - headers.
*/
#ifndef OPS_PACKET_PARSE_H
#define OPS_PACKET_PARSE_H
#include "types.h"
#include "packet.h"
#include "lists.h"
/** ops_region_t */
typedef struct ops_region
{
struct ops_region *parent;
unsigned length;
unsigned length_read;
unsigned last_read; /*!< length of last read, only valid in deepest child */
ops_boolean_t indeterminate:1;
} ops_region_t;
void ops_init_subregion(ops_region_t *subregion,ops_region_t *region);
#if 0
/** Return values for reader functions e.g. ops_packet_reader_t() */
enum ops_reader_ret_t
{
OPS_R_OK =0, /*!< success */
OPS_R_EOF =1, /*!< reached end of file, no data has been returned */
OPS_R_EARLY_EOF =2, /*!< could not read the requested
number of bytes and either
OPS_RETURN_LENGTH was not set and at
least 1 byte was read, or there was
an abnormal end to the file (or
armoured block) */
OPS_R_PARTIAL_READ =3, /*!< if OPS_RETURN_LENGTH is set and
the buffer was not filled */
OPS_R_ERROR =4, /*!< if there was an error reading */
};
#endif
/** ops_parse_callback_return_t */
typedef enum
{
OPS_RELEASE_MEMORY,
OPS_KEEP_MEMORY,
OPS_FINISHED
} ops_parse_cb_return_t;
typedef struct ops_parse_cb_info ops_parse_cb_info_t;
typedef ops_parse_cb_return_t
ops_parse_cb_t(const ops_parser_content_t *content,
ops_parse_cb_info_t *cbinfo);
typedef struct ops_parse_info ops_parse_info_t;
typedef struct ops_reader_info ops_reader_info_t;
typedef struct ops_crypt_info ops_crypt_info_t;
/*
A reader MUST read at least one byte if it can, and should read up
to the number asked for. Whether it reads more for efficiency is
its own decision, but if it is a stacked reader it should never
read more than the length of the region it operates in (which it
would have to be given when it is stacked).
If a read is short because of EOF, then it should return the short
read (obviously this will be zero on the second attempt, if not the
first). Because a reader is not obliged to do a full read, only a
zero return can be taken as an indication of EOF.
If there is an error, then the callback should be notified, the
error stacked, and -1 should be returned.
Note that although length is a size_t, a reader will never be asked
to read more than INT_MAX in one go.
*/
typedef int ops_reader_t(void *dest,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo);
typedef void ops_reader_destroyer_t(ops_reader_info_t *rinfo);
ops_parse_info_t *ops_parse_info_new(void);
void ops_parse_info_delete(ops_parse_info_t *pinfo);
ops_error_t *ops_parse_info_get_errors(ops_parse_info_t *pinfo);
ops_crypt_t *ops_parse_get_decrypt(ops_parse_info_t *pinfo);
void ops_parse_cb_set(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg);
void ops_parse_cb_push(ops_parse_info_t *pinfo,ops_parse_cb_t *cb,void *arg);
void *ops_parse_cb_get_arg(ops_parse_cb_info_t *cbinfo);
void *ops_parse_cb_get_errors(ops_parse_cb_info_t *cbinfo);
void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg);
void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg);
void ops_reader_pop(ops_parse_info_t *pinfo);
void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo);
void *ops_reader_get_arg(ops_reader_info_t *rinfo);
ops_parse_cb_return_t ops_parse_cb(const ops_parser_content_t *content,
ops_parse_cb_info_t *cbinfo);
ops_parse_cb_return_t ops_parse_stacked_cb(const ops_parser_content_t *content,
ops_parse_cb_info_t *cbinfo);
ops_reader_info_t *ops_parse_get_rinfo(ops_parse_info_t *pinfo);
int ops_parse(ops_parse_info_t *parse_info);
int ops_parse_and_print_errors(ops_parse_info_t *parse_info);
int ops_parse_and_save_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs);
int ops_parse_errs(ops_parse_info_t *parse_info,ops_ulong_list_t *errs);
void ops_parse_and_validate(ops_parse_info_t *parse_info);
void ops_parse_options(ops_parse_info_t *pinfo,ops_content_tag_t tag,
ops_parse_type_t type);
ops_boolean_t ops_limited_read(unsigned char *dest,size_t length,
ops_region_t *region,ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo);
ops_boolean_t ops_stacked_limited_read(void *dest,unsigned length,
ops_region_t *region,
ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo);
void ops_parse_hash_init(ops_parse_info_t *pinfo,ops_hash_algorithm_t type,
const unsigned char *keyid);
void ops_parse_hash_data(ops_parse_info_t *pinfo,const void *data,
size_t length);
void ops_parse_hash_finish(ops_parse_info_t *pinfo);
ops_hash_t *ops_parse_hash_find(ops_parse_info_t *pinfo,
const unsigned char keyid[OPS_KEY_ID_SIZE]);
ops_reader_t ops_stacked_read;
/* vim:set textwidth=120: */
/* vim:set ts=8: */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,38 @@
/* Generated from packet-show.cast by ../../util/caster.pl, do not edit. */
#include "types.h"
/* (line 4) char *show_packet_tag(ops_packet_tag_t packet_tag, packet_tag_map_t *packet_tag_map) -> char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map) */
char *ops_str_from_map(int packet_tag, ops_map_t *packet_tag_map);
#define show_packet_tag(packet_tag,packet_tag_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_packet_tag_t , packet_tag),CHECKED_INSTANCE_OF( packet_tag_map_t *, packet_tag_map))
typedef char * show_packet_tag_t(ops_packet_tag_t , packet_tag_map_t *);
/* (line 5) char *show_sig_type(ops_sig_type_t sig_type, sig_type_map_t *sig_type_map) -> char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map) */
char *ops_str_from_map(int sig_type, ops_map_t *sig_type_map);
#define show_sig_type(sig_type,sig_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_sig_type_t , sig_type),CHECKED_INSTANCE_OF( sig_type_map_t *, sig_type_map))
typedef char * show_sig_type_t(ops_sig_type_t , sig_type_map_t *);
/* (line 6) char *show_pka(ops_public_key_algorithm_t pka, public_key_algorithm_map_t *pka_map) -> char *ops_str_from_map(int pka, ops_map_t *pka_map) */
char *ops_str_from_map(int pka, ops_map_t *pka_map);
#define show_pka(pka,pka_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_public_key_algorithm_t , pka),CHECKED_INSTANCE_OF( public_key_algorithm_map_t *, pka_map))
typedef char * show_pka_t(ops_public_key_algorithm_t , public_key_algorithm_map_t *);
/* (line 7) char *show_ss_type(ops_ss_type_t ss_type, ss_type_map_t *ss_type_map) -> char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map) */
char *ops_str_from_map(int ss_type, ops_map_t *ss_type_map);
#define show_ss_type(ss_type,ss_type_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_type_t , ss_type),CHECKED_INSTANCE_OF( ss_type_map_t *, ss_type_map))
typedef char * show_ss_type_t(ops_ss_type_t , ss_type_map_t *);
/* (line 8) char *show_ss_rr_code(ops_ss_rr_code_t ss_rr_code, ss_rr_code_map_t *ss_rr_code_map) -> char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map) */
char *ops_str_from_map(int ss_rr_code, ops_map_t *ss_rr_code_map);
#define show_ss_rr_code(ss_rr_code,ss_rr_code_map) ops_str_from_map(CHECKED_INSTANCE_OF(ops_ss_rr_code_t , ss_rr_code),CHECKED_INSTANCE_OF( ss_rr_code_map_t *, ss_rr_code_map))
typedef char * show_ss_rr_code_t(ops_ss_rr_code_t , ss_rr_code_map_t *);
/* (line 9) char *show_hash_algorithm(unsigned char hash,+ops_map_t *hash_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map) */
char *ops_str_from_map(int hash,ops_map_t *hash_algorithm_map);
#define show_hash_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, hash_algorithm_map))
typedef char * show_hash_algorithm_t(unsigned char );
/* (line 10) char *show_symmetric_algorithm(unsigned char hash,+ops_map_t *symmetric_algorithm_map) -> char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map) */
char *ops_str_from_map(int hash,ops_map_t *symmetric_algorithm_map);
#define show_symmetric_algorithm(hash) ops_str_from_map(CHECKED_INSTANCE_OF(unsigned char , hash),CHECKED_INSTANCE_OF(ops_map_t *, symmetric_algorithm_map))
typedef char * show_symmetric_algorithm_t(unsigned char );

View File

@ -0,0 +1,857 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*
* Creates printable text strings from packet contents
*
*/
#include <openpgpsdk/configure.h>
#include <stdlib.h>
#include <string.h>
#include <openpgpsdk/packet-show.h>
#include <openpgpsdk/util.h>
#include <openpgpsdk/final.h>
/*
* Arrays of value->text maps
*/
static ops_map_t packet_tag_map[] =
{
{ OPS_PTAG_CT_RESERVED, "Reserved" },
{ OPS_PTAG_CT_PK_SESSION_KEY, "Public-Key Encrypted Session Key" },
{ OPS_PTAG_CT_SIGNATURE, "Signature" },
{ OPS_PTAG_CT_SK_SESSION_KEY, "Symmetric-Key Encrypted Session Key" },
{ OPS_PTAG_CT_ONE_PASS_SIGNATURE, "One-Pass Signature" },
{ OPS_PTAG_CT_SECRET_KEY, "Secret Key" },
{ OPS_PTAG_CT_PUBLIC_KEY, "Public Key" },
{ OPS_PTAG_CT_SECRET_SUBKEY, "Secret Subkey" },
{ OPS_PTAG_CT_COMPRESSED, "Compressed Data" },
{ OPS_PTAG_CT_SE_DATA, "Symmetrically Encrypted Data" },
{ OPS_PTAG_CT_MARKER, "Marker" },
{ OPS_PTAG_CT_LITERAL_DATA, "Literal Data" },
{ OPS_PTAG_CT_TRUST, "Trust" },
{ OPS_PTAG_CT_USER_ID, "User ID" },
{ OPS_PTAG_CT_PUBLIC_SUBKEY, "Public Subkey" },
{ OPS_PTAG_CT_RESERVED2, "reserved" },
{ OPS_PTAG_CT_RESERVED3, "reserved" },
{ OPS_PTAG_CT_USER_ATTRIBUTE, "User Attribute" },
{ OPS_PTAG_CT_SE_IP_DATA, "Sym. Encrypted and Integrity Protected Data" },
{ OPS_PTAG_CT_MDC, "Modification Detection Code" },
{ OPS_PARSER_PTAG, "OPS_PARSER_PTAG" },
{ OPS_PTAG_RAW_SS, "OPS_PTAG_RAW_SS" },
{ OPS_PTAG_SS_ALL, "OPS_PTAG_SS_ALL" },
{ OPS_PARSER_PACKET_END, "OPS_PARSER_PACKET_END" },
{ OPS_PTAG_SIGNATURE_SUBPACKET_BASE, "OPS_PTAG_SIGNATURE_SUBPACKET_BASE" },
{ OPS_PTAG_SS_CREATION_TIME, "SS: Signature Creation Time" },
{ OPS_PTAG_SS_EXPIRATION_TIME, "SS: Signature Expiration Time" },
{ OPS_PTAG_SS_EXPORTABLE_CERTIFICATION, "SS: Exportable Certification" },
{ OPS_PTAG_SS_TRUST, "SS: Trust Signature" },
{ OPS_PTAG_SS_REGEXP, "SS: Regular Expression" },
{ OPS_PTAG_SS_REVOCABLE, "SS: Revocable" },
{ OPS_PTAG_SS_KEY_EXPIRATION_TIME, "SS: Key Expiration Time" },
{ OPS_PTAG_SS_RESERVED, "SS: Reserved" },
{ OPS_PTAG_SS_PREFERRED_SKA, "SS: Preferred Secret Key Algorithm" },
{ OPS_PTAG_SS_REVOCATION_KEY, "SS: Revocation Key" },
{ OPS_PTAG_SS_ISSUER_KEY_ID, "SS: Issuer Key Id" },
{ OPS_PTAG_SS_NOTATION_DATA, "SS: Notation Data" },
{ OPS_PTAG_SS_PREFERRED_HASH, "SS: Preferred Hash Algorithm" },
{ OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Compression Algorithm" },
{ OPS_PTAG_SS_KEY_SERVER_PREFS, "SS: Key Server Preferences" },
{ OPS_PTAG_SS_PREFERRED_COMPRESSION,"SS: Preferred Key Server" },
{ OPS_PTAG_SS_PRIMARY_USER_ID, "SS: Primary User ID" },
{ OPS_PTAG_SS_POLICY_URI, "SS: Policy URI" },
{ OPS_PTAG_SS_KEY_FLAGS, "SS: Key Flags" },
{ OPS_PTAG_SS_SIGNERS_USER_ID, "SS: Signer's User ID" },
{ OPS_PTAG_SS_REVOCATION_REASON, "SS: Reason for Revocation" },
{ OPS_PTAG_SS_FEATURES, "SS: Features" },
{ OPS_PTAG_SS_SIGNATURE_TARGET, "SS: Signature Target" },
{ OPS_PTAG_SS_EMBEDDED_SIGNATURE, "SS: Embedded Signature" },
{ OPS_PTAG_CT_LITERAL_DATA_HEADER, "CT: Literal Data Header" },
{ OPS_PTAG_CT_LITERAL_DATA_BODY, "CT: Literal Data Body" },
{ OPS_PTAG_CT_SIGNATURE_HEADER, "CT: Signature Header" },
{ OPS_PTAG_CT_SIGNATURE_FOOTER, "CT: Signature Footer" },
{ OPS_PTAG_CT_ARMOUR_HEADER, "CT: Armour Header" },
{ OPS_PTAG_CT_ARMOUR_TRAILER, "CT: Armour Trailer" },
{ OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER, "CT: Signed Cleartext Header" },
{ OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY, "CT: Signed Cleartext Body" },
{ OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER, "CT: Signed Cleartext Trailer" },
{ OPS_PTAG_CT_UNARMOURED_TEXT, "CT: Unarmoured Text" },
{ OPS_PTAG_CT_ENCRYPTED_SECRET_KEY, "CT: Encrypted Secret Key" },
{ OPS_PTAG_CT_SE_DATA_HEADER, "CT: Sym Encrypted Data Header" },
{ OPS_PTAG_CT_SE_DATA_BODY, "CT: Sym Encrypted Data Body" },
{ OPS_PTAG_CT_SE_IP_DATA_HEADER, "CT: Sym Encrypted IP Data Header" },
{ OPS_PTAG_CT_SE_IP_DATA_BODY, "CT: Sym Encrypted IP Data Body" },
{ OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY, "CT: Encrypted PK Session Key" },
{ OPS_PARSER_CMD_GET_SK_PASSPHRASE, "CMD: Get Secret Key Passphrase" },
{ OPS_PARSER_CMD_GET_SECRET_KEY, "CMD: Get Secret Key" },
{ OPS_PARSER_ERROR, "OPS_PARSER_ERROR" },
{ OPS_PARSER_ERRCODE, "OPS_PARSER_ERRCODE" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
typedef ops_map_t packet_tag_map_t;
static ops_map_t ss_type_map[] =
{
{ OPS_PTAG_SS_CREATION_TIME, "Signature Creation Time" },
{ OPS_PTAG_SS_EXPIRATION_TIME, "Signature Expiration Time" },
{ OPS_PTAG_SS_TRUST, "Trust Signature" },
{ OPS_PTAG_SS_REGEXP, "Regular Expression" },
{ OPS_PTAG_SS_REVOCABLE, "Revocable" },
{ OPS_PTAG_SS_KEY_EXPIRATION_TIME, "Key Expiration Time" },
{ OPS_PTAG_SS_PREFERRED_SKA, "Preferred Symmetric Algorithms" },
{ OPS_PTAG_SS_REVOCATION_KEY, "Revocation Key" },
{ OPS_PTAG_SS_ISSUER_KEY_ID, "Issuer key ID" },
{ OPS_PTAG_SS_NOTATION_DATA, "Notation Data" },
{ OPS_PTAG_SS_PREFERRED_HASH, "Preferred Hash Algorithms" },
{ OPS_PTAG_SS_PREFERRED_COMPRESSION,"Preferred Compression Algorithms" },
{ OPS_PTAG_SS_KEY_SERVER_PREFS, "Key Server Preferences" },
{ OPS_PTAG_SS_PREFERRED_KEY_SERVER, "Preferred Key Server" },
{ OPS_PTAG_SS_PRIMARY_USER_ID, "Primary User ID" },
{ OPS_PTAG_SS_POLICY_URI, "Policy URI" },
{ OPS_PTAG_SS_KEY_FLAGS, "Key Flags" },
{ OPS_PTAG_SS_REVOCATION_REASON, "Reason for Revocation" },
{ OPS_PTAG_SS_FEATURES, "Features" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
typedef ops_map_t ss_type_map_t;
static ops_map_t ss_rr_code_map[] =
{
{ 0x00, "No reason specified" },
{ 0x01, "Key is superseded" },
{ 0x02, "Key material has been compromised" },
{ 0x03, "Key is retired and no longer used" },
{ 0x20, "User ID information is no longer valid" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
typedef ops_map_t ss_rr_code_map_t;
static ops_map_t sig_type_map[] =
{
{ OPS_SIG_BINARY, "Signature of a binary document" },
{ OPS_SIG_TEXT, "Signature of a canonical text document" },
{ OPS_SIG_STANDALONE, "Standalone signature" },
{ OPS_CERT_GENERIC, "Generic certification of a User ID and Public Key packet" },
{ OPS_CERT_PERSONA, "Persona certification of a User ID and Public Key packet" },
{ OPS_CERT_CASUAL, "Casual certification of a User ID and Public Key packet" },
{ OPS_CERT_POSITIVE, "Positive certification of a User ID and Public Key packet" },
{ OPS_SIG_SUBKEY, "Subkey Binding Signature" },
{ OPS_SIG_PRIMARY, "Primary Key Binding Signature" },
{ OPS_SIG_DIRECT, "Signature directly on a key" },
{ OPS_SIG_REV_KEY, "Key revocation signature" },
{ OPS_SIG_REV_SUBKEY, "Subkey revocation signature" },
{ OPS_SIG_REV_CERT, "Certification revocation signature" },
{ OPS_SIG_TIMESTAMP, "Timestamp signature" },
{ OPS_SIG_3RD_PARTY, "Third-Party Confirmation signature" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
typedef ops_map_t sig_type_map_t;
static ops_map_t public_key_algorithm_map[] =
{
{ OPS_PKA_RSA, "RSA (Encrypt or Sign)" },
{ OPS_PKA_RSA_ENCRYPT_ONLY, "RSA Encrypt-Only" },
{ OPS_PKA_RSA_SIGN_ONLY, "RSA Sign-Only" },
{ OPS_PKA_ELGAMAL, "Elgamal (Encrypt-Only)" },
{ OPS_PKA_DSA, "DSA" },
{ OPS_PKA_RESERVED_ELLIPTIC_CURVE, "Reserved for Elliptic Curve" },
{ OPS_PKA_RESERVED_ECDSA, "Reserved for ECDSA" },
{ OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN, "Reserved (formerly Elgamal Encrypt or Sign" },
{ OPS_PKA_RESERVED_DH, "Reserved for Diffie-Hellman (X9.42)" },
{ OPS_PKA_PRIVATE00, "Private/Experimental" },
{ OPS_PKA_PRIVATE01, "Private/Experimental" },
{ OPS_PKA_PRIVATE02, "Private/Experimental" },
{ OPS_PKA_PRIVATE03, "Private/Experimental" },
{ OPS_PKA_PRIVATE04, "Private/Experimental" },
{ OPS_PKA_PRIVATE05, "Private/Experimental" },
{ OPS_PKA_PRIVATE06, "Private/Experimental" },
{ OPS_PKA_PRIVATE07, "Private/Experimental" },
{ OPS_PKA_PRIVATE08, "Private/Experimental" },
{ OPS_PKA_PRIVATE09, "Private/Experimental" },
{ OPS_PKA_PRIVATE10, "Private/Experimental" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
typedef ops_map_t public_key_algorithm_map_t;
static ops_map_t symmetric_algorithm_map[] =
{
{ OPS_SA_PLAINTEXT, "Plaintext or unencrypted data" },
{ OPS_SA_IDEA, "IDEA" },
{ OPS_SA_TRIPLEDES, "TripleDES" },
{ OPS_SA_CAST5, "CAST5" },
{ OPS_SA_BLOWFISH, "Blowfish" },
{ OPS_SA_AES_128, "AES (128-bit key)" },
{ OPS_SA_AES_192, "AES (192-bit key)" },
{ OPS_SA_AES_256, "AES (256-bit key)" },
{ OPS_SA_TWOFISH, "Twofish(256-bit key)" },
{ 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 */
};
static ops_map_t hash_algorithm_map[] =
{
{ OPS_HASH_MD5, "MD5" },
{ OPS_HASH_SHA1, "SHA1" },
{ OPS_HASH_RIPEMD, "RIPEMD160" },
{ OPS_HASH_SHA256, "SHA256" },
{ OPS_HASH_SHA384, "SHA384" },
{ OPS_HASH_SHA512, "SHA512" },
{ OPS_HASH_SHA224, "SHA224" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
static ops_map_t compression_algorithm_map[] =
{
{ OPS_C_NONE, "Uncompressed" },
{ OPS_C_ZIP, "ZIP(RFC1951)" },
{ OPS_C_ZLIB, "ZLIB(RFC1950)" },
{ OPS_C_BZIP2, "Bzip2(BZ2)" },
{ 0x00, NULL }, /* this is the end-of-array marker */
};
static ops_bit_map_t ss_notation_data_map_byte0[] =
{
{ 0x80, "Human-readable" },
{ 0x00, NULL },
};
static ops_bit_map_t *ss_notation_data_map[] =
{
ss_notation_data_map_byte0,
};
static ops_bit_map_t ss_feature_map_byte0[] =
{
{ 0x01, "Modification Detection" },
{ 0x00, NULL },
};
static ops_bit_map_t *ss_feature_map[] =
{
ss_feature_map_byte0,
};
static ops_bit_map_t ss_key_flags_map[] =
{
{ 0x01, "May be used to certify other keys" },
{ 0x02, "May be used to sign data" },
{ 0x04, "May be used to encrypt communications" },
{ 0x08, "May be used to encrypt storage" },
{ 0x10, "Private component may have been split by a secret-sharing mechanism"},
{ 0x80, "Private component may be in possession of more than one person"},
{ 0x00, NULL },
};
static ops_bit_map_t ss_key_server_prefs_map[] =
{
{ 0x80, "Key holder requests that this key only be modified or updated by the key holder or an administrator of the key server" },
{ 0x00, NULL },
};
#include <openpgpsdk/packet-show-cast.h>
/*
* Private functions
*/
static void list_init(ops_list_t *list)
{
list->size=0;
list->used=0;
list->strings=NULL;
}
static void list_free_strings(ops_list_t *list)
{
unsigned i;
for(i=0; i < list->used ; i++)
{
free(list->strings[i]);
list->strings[i]=NULL;
}
}
static void list_free(ops_list_t *list)
{
if (list->strings)
free(list->strings);
list_init(list);
}
static unsigned int list_resize(ops_list_t *list)
{
/* We only resize in one direction - upwards.
Algorithm used : double the current size then add 1
*/
int newsize=0;
newsize=list->size*2 + 1;
list->strings=realloc(list->strings,newsize*sizeof(char *));
if (list->strings)
{
list->size=newsize;
return 1;
}
else
{
/* xxx - realloc failed. error message? - rachel */
return 0;
}
}
static unsigned int add_str(ops_list_t *list,char *str)
{
if (list->size==list->used)
if (!list_resize(list))
return 0;
list->strings[list->used]=str;
list->used++;
return 1;
}
static char *str_from_bitfield_or_null(unsigned char octet, ops_bit_map_t *map)
{
ops_bit_map_t *row;
for ( row=map; row->string != NULL; row++ )
if (row->mask == octet)
return row->string;
return NULL;
}
static char *str_from_bitfield(unsigned char octet, ops_bit_map_t *map)
{
char *str;
str=str_from_bitfield_or_null(octet,map);
if (str)
return str;
else
return "Unknown";
}
/*! generic function to initialise ops_text_t structure */
void ops_text_init(ops_text_t *text)
{
list_init(&text->known);
list_init(&text->unknown);
}
/**
* \ingroup Core_Print
*
* ops_text_free() frees the memory used by an ops_text_t structure
*
* \param text Pointer to a previously allocated structure. This structure and its contents will be freed.
*/
void ops_text_free(ops_text_t *text)
{
/* Strings in "known" array will be constants, so don't free them */
list_free(&text->known);
/* Strings in "unknown" array will be dynamically allocated, so do free them */
list_free_strings(&text->unknown);
list_free(&text->unknown);
/* finally, free the text structure itself */
free(text);
}
// XXX: should this (and many others) be ops_boolean_t?
/*! generic function which adds text derived from single octet map to text */
static unsigned int add_str_from_octet_map(ops_text_t *text,char *str,
unsigned char octet)
{
if (str && !add_str(&text->known,str))
{
/* value recognised, but there was a problem adding it to the list */
/* XXX - should print out error msg here, Ben? - rachel */
return 0;
}
else if (!str)
{
/* value not recognised and there was a problem adding it to the unknown list */
unsigned len=2+2+1; /* 2 for "0x", 2 for single octet in hex format, 1 for NULL */
str=malloc(len);
snprintf(str,len,"0x%x",octet);
if (!add_str(&text->unknown,str))
return 0;
}
return 1;
}
/*! generic function which adds text derived from single bit map to text */
static unsigned int add_str_from_bit_map(ops_text_t *text, char *str, unsigned char bit)
{
char *fmt_unknown="Unknown bit(0x%x)";
if (str && !add_str(&text->known,str))
{
/* value recognised, but there was a problem adding it to the list */
/* XXX - should print out error msg here, Ben? - rachel */
return 0;
}
else if (!str)
{
/* value not recognised and there was a problem adding it to the unknown list */
/* 2 chars of the string are the format definition,
this will be replaced in the output by 2 chars of hex,
so the length will be correct */
unsigned len=strlen(fmt_unknown)+1;
str=malloc(len);
snprintf(str,len,fmt_unknown,bit);
if (!add_str(&text->unknown,str))
return 0;
}
return 1;
}
/**
* Produce a structure containing human-readable textstrings
* representing the recognised and unrecognised contents
* of this byte array. text_fn() will be called on each octet in turn.
* Each octet will generate one string representing the whole byte.
*
*/
static ops_text_t *text_from_bytemapped_octets(ops_data_t *data,
const char *(*text_fn)(unsigned char octet))
{
ops_text_t *text=NULL;
const char *str;
unsigned i;
/*! allocate and initialise ops_text_t structure to store derived strings */
text=malloc(sizeof(ops_text_t));
if (!text)
return NULL;
ops_text_init(text);
/*! for each octet in field ... */
for(i=0 ; i < data->len ; i++)
{
/*! derive string from octet */
str=(*text_fn)(data->contents[i]);
/*! and add to text */
if (!add_str_from_octet_map(text,strdup(str),data->contents[i]))
{
ops_text_free(text);
return NULL;
}
}
/*! All values have been added to either the known or the unknown list */
/*! Return text */
return text;
}
/**
* Produce a structure containing human-readable textstrings
* representing the recognised and unrecognised contents
* of this byte array, derived from each bit of each octet.
*
*/
static ops_text_t *showall_octets_bits(ops_data_t *data,ops_bit_map_t **map,
size_t nmap)
{
ops_text_t *text=NULL;
char *str;
unsigned i;
int j=0;
unsigned char mask, bit;
/*! allocate and initialise ops_text_t structure to store derived strings */
text=malloc(sizeof(ops_text_t));
if (!text)
return NULL;
ops_text_init(text);
/*! for each octet in field ... */
for(i=0 ; i < data->len ; i++)
{
/*! for each bit in octet ... */
for (j=0, mask=0x80; j<8; j++, mask = mask>>1 )
{
bit = data->contents[i]&mask;
if (bit)
{
if(i >= nmap)
str="Unknown";
else
str=str_from_bitfield ( bit, map[i] );
if (!add_str_from_bit_map( text, str, bit))
{
ops_text_free(text);
return NULL;
}
}
}
}
return text;
}
/*
* Public Functions
*/
/**
* \ingroup Core_Print
* returns description of the Packet Tag
* \param packet_tag
* \return string or "Unknown"
*/
const char *ops_show_packet_tag(ops_packet_tag_t packet_tag)
{
char *rtn=NULL;
rtn=show_packet_tag(packet_tag,packet_tag_map);
if (!rtn)
rtn="Unknown Tag";
return rtn;
}
/**
* \ingroup Core_Print
*
* returns description of the Signature Sub-Packet type
* \param ss_type Signature Sub-Packet type
* \return string or "Unknown"
*/
const char *ops_show_ss_type(ops_ss_type_t ss_type)
{
return show_ss_type(ss_type,ss_type_map);
}
/**
* \ingroup Core_Print
*
* returns description of the Revocation Reason code
* \param ss_rr_code Revocation Reason code
* \return string or "Unknown"
*/
const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code)
{
return show_ss_rr_code(ss_rr_code,ss_rr_code_map);
}
/**
* \ingroup Core_Print
*
* returns description of the given Signature type
* \param sig_type Signature type
* \return string or "Unknown"
*/
const char *ops_show_sig_type(ops_sig_type_t sig_type)
{
return show_sig_type(sig_type, sig_type_map);
}
/**
* \ingroup Core_Print
*
* returns description of the given Public Key Algorithm
* \param pka Public Key Algorithm type
* \return string or "Unknown"
*/
const char *ops_show_pka(ops_public_key_algorithm_t pka)
{
return show_pka(pka, public_key_algorithm_map);
}
/**
* \ingroup Core_Print
* returns description of the Preferred Compression
* \param octet Preferred Compression
* \return string or "Unknown"
*/
const char *ops_show_ss_preferred_compression(unsigned char octet)
{
return ops_str_from_map(octet,compression_algorithm_map);
}
/**
* \ingroup Core_Print
*
* returns set of descriptions of the given Preferred Compression Algorithms
* \param ss_preferred_compression Array of Preferred Compression Algorithms
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*/
ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression)
{
return text_from_bytemapped_octets(&ss_preferred_compression.data,
&ops_show_ss_preferred_compression);
}
/**
* \ingroup Core_Print
*
* returns description of the Hash Algorithm type
* \param hash Hash Algorithm type
* \return string or "Unknown"
*/
const char *ops_show_hash_algorithm(unsigned char hash)
{
return show_hash_algorithm(hash);
}
/**
* \ingroup Core_Print
*
* returns set of descriptions of the given Preferred Hash Algorithms
* \param ss_preferred_hash Array of Preferred Hash Algorithms
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*/
ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash)
{
return text_from_bytemapped_octets(&ss_preferred_hash.data,
&ops_show_hash_algorithm);
}
const char *ops_show_symmetric_algorithm(unsigned char hash)
{
return show_symmetric_algorithm(hash);
}
/**
* \ingroup Core_Print
* returns description of the given Preferred Symmetric Key Algorithm
* \param octet
* \return string or "Unknown"
*/
const char *ops_show_ss_preferred_ska(unsigned char octet)
{
return ops_str_from_map(octet,symmetric_algorithm_map);
}
/**
* \ingroup Core_Print
*
* returns set of descriptions of the given Preferred Symmetric Key Algorithms
* \param ss_preferred_ska Array of Preferred Symmetric Key Algorithms
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*/
ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska)
{
return text_from_bytemapped_octets(&ss_preferred_ska.data,
&ops_show_ss_preferred_ska);
}
/**
* \ingroup Core_Print
* returns description of one SS Feature
* \param octet
* \return string or "Unknown"
*/
static char *ops_show_ss_feature(unsigned char octet,unsigned offset)
{
if(offset >= OPS_ARRAY_SIZE(ss_feature_map))
return "Unknown";
return str_from_bitfield(octet,ss_feature_map[offset]);
}
/**
* \ingroup Core_Print
*
* returns set of descriptions of the given SS Features
* \param ss_features Signature Sub-Packet Features
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*/
/* XXX: shouldn't this use show_all_octets_bits? */
ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features)
{
ops_text_t *text=NULL;
char *str;
unsigned i;
int j=0;
unsigned char mask, bit;
text=malloc(sizeof(ops_text_t));
if (!text)
return NULL;
ops_text_init(text);
for(i=0 ; i < ss_features.data.len ; i++)
{
for (j=0, mask=0x80; j<8; j++, mask = mask>>1 )
{
bit = ss_features.data.contents[i]&mask;
if (bit)
{
str=ops_show_ss_feature ( bit, i );
if (!add_str_from_bit_map( text, str, bit))
{
ops_text_free(text);
return NULL;
}
}
}
}
return text;
}
/**
* \ingroup Core_Print
* returns description of SS Key Flag
* \param octet
* \param map
* \return
*/
const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map)
{
return str_from_bitfield(octet,map);
}
/**
* \ingroup Core_Print
*
* returns set of descriptions of the given Preferred Key Flags
* \param ss_key_flags Array of Key Flags
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*/
ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags)
{
ops_text_t *text=NULL;
const char *str;
int i=0;
unsigned char mask, bit;
text=malloc(sizeof(ops_text_t));
if (!text)
return NULL;
ops_text_init(text);
/* xxx - TBD: extend to handle multiple octets of bits - rachel */
for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1)
{
bit=ss_key_flags.data.contents[0]&mask;
if(bit)
{
str=ops_show_ss_key_flag(bit,&ss_key_flags_map[0]);
if(!add_str_from_bit_map(text,strdup(str),bit))
{
ops_text_free(text);
return NULL;
}
}
}
/* xxx - must add error text if more than one octet. Only one currently specified -- rachel */
return text;
}
/**
* \ingroup Core_Print
*
* returns description of one given Key Server Preference
*
* \param prefs Byte containing bitfield of preferences
* \param map
* \return string or "Unknown"
*/
const char *ops_show_ss_key_server_prefs(unsigned char prefs,
ops_bit_map_t *map)
{
return str_from_bitfield(prefs,map);
}
/**
* \ingroup Core_Print
* returns set of descriptions of given Key Server Preferences
* \param ss_key_server_prefs
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*
*/
ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs)
{
ops_text_t *text=NULL;
const char *str;
int i=0;
unsigned char mask, bit;
text=malloc(sizeof(ops_text_t));
if (!text)
return NULL;
ops_text_init(text);
/* xxx - TBD: extend to handle multiple octets of bits - rachel */
for (i=0,mask=0x80 ; i < 8 ; i++,mask=mask >> 1)
{
bit=ss_key_server_prefs.data.contents[0]&mask;
if (bit)
{
str=ops_show_ss_key_server_prefs(bit,
&ss_key_server_prefs_map[0]);
if(!add_str_from_bit_map( text, strdup(str), bit))
{
ops_text_free(text);
return NULL;
}
}
}
/* xxx - must add error text if more than one octet. Only one currently specified -- rachel */
return text;
}
/**
* \ingroup Core_Print
*
* returns set of descriptions of the given SS Notation Data Flags
* \param ss_notation_data Signature Sub-Packet Notation Data
* \return NULL if cannot allocate memory or other error
* \return pointer to structure, if no error
*/
ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data)
{
return showall_octets_bits(&ss_notation_data.flags,ss_notation_data_map,
OPS_ARRAY_SIZE(ss_notation_data_map));
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_PACKET_TO_TEXT_H
#define OPS_PACKET_TO_TEXT_H
#ifndef OPS_PACKET_H
#include "packet.h"
#endif
/** ops_list_t
*/
typedef struct
{
unsigned int size;/* num of array slots allocated */
unsigned int used; /* num of array slots currently used */
char **strings;
} ops_list_t;
/** ops_text_t
*/
typedef struct
{
ops_list_t known;
ops_list_t unknown;
} ops_text_t;
/** ops_bit_map_t
*/
typedef struct
{
unsigned char mask;
char *string;
} ops_bit_map_t;
void ops_text_init(ops_text_t *text);
void ops_text_free(ops_text_t *text);
const char *ops_show_packet_tag(ops_packet_tag_t packet_tag);
const char *ops_show_ss_type(ops_ss_type_t ss_type);
const char *ops_show_sig_type(ops_sig_type_t sig_type);
const char *ops_show_pka(ops_public_key_algorithm_t pka);
ops_text_t *ops_showall_ss_preferred_compression(ops_ss_preferred_compression_t ss_preferred_compression);
const char *ops_show_ss_preferred_compression(unsigned char octet);
ops_text_t *ops_showall_ss_preferred_hash(ops_ss_preferred_hash_t ss_preferred_hash);
const char *ops_show_hash_algorithm(unsigned char octet);
const char *ops_show_symmetric_algorithm(unsigned char hash);
ops_text_t *ops_showall_ss_preferred_ska(ops_ss_preferred_ska_t ss_preferred_ska);
const char *ops_show_ss_preferred_ska(unsigned char octet);
const char *ops_show_ss_rr_code(ops_ss_rr_code_t ss_rr_code);
ops_text_t *ops_showall_ss_features(ops_ss_features_t ss_features);
ops_text_t *ops_showall_ss_key_flags(ops_ss_key_flags_t ss_key_flags);
const char *ops_show_ss_key_flag(unsigned char octet, ops_bit_map_t *map);
ops_text_t *ops_showall_ss_key_server_prefs(ops_ss_key_server_prefs_t ss_key_server_prefs);
const char *ops_show_ss_key_server_prefs(unsigned char octet,
ops_bit_map_t *map);
ops_text_t *ops_showall_ss_notation_data_flags(ops_ss_notation_data_t ss_notation_data);
char *ops_str_from_map(int code, ops_map_t *map);
/* vim:set textwidth=120: */
/* vim:set ts=8: */
#endif /* OPS_PACKET_TO_TEXT_H */

View File

@ -0,0 +1,948 @@
/*
* 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
* packet related headers.
*/
#ifndef OPS_PACKET_H
#define OPS_PACKET_H
#include "configure.h"
#include <time.h>
#include <openssl/bn.h>
#include <openssl/sha.h>
#include "types.h"
#include "errors.h"
/** General-use structure for variable-length data
*/
typedef struct
{
size_t len;
unsigned char *contents;
} ops_data_t;
/************************************/
/* Packet Tags - RFC4880, 4.2 */
/************************************/
/** Packet Tag - Bit 7 Mask (this bit is always set).
* The first byte of a packet is the "Packet Tag". It always
* has bit 7 set. This is the mask for it.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_ALWAYS_SET 0x80
/** Packet Tag - New Format Flag.
* Bit 6 of the Packet Tag is the packet format indicator.
* If it is set, the new format is used, if cleared the
* old format is used.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_NEW_FORMAT 0x40
/** Old Packet Format: Mask for content tag.
* In the old packet format bits 5 to 2 (including)
* are the content tag. This is the mask to apply
* to the packet tag. Note that you need to
* shift by #OPS_PTAG_OF_CONTENT_TAG_SHIFT bits.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_OF_CONTENT_TAG_MASK 0x3c
/** Old Packet Format: Offset for the content tag.
* As described at #OPS_PTAG_OF_CONTENT_TAG_MASK the
* content tag needs to be shifted after being masked
* out from the Packet Tag.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_OF_CONTENT_TAG_SHIFT 2
/** Old Packet Format: Mask for length type.
* Bits 1 and 0 of the packet tag are the length type
* in the old packet format.
*
* See #ops_ptag_of_lt_t for the meaning of the values.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_OF_LENGTH_TYPE_MASK 0x03
/** Old Packet Format Lengths.
* Defines the meanings of the 2 bits for length type in the
* old packet format.
*
* \see RFC4880 4.2.1
*/
typedef enum
{
OPS_PTAG_OF_LT_ONE_BYTE =0x00, /*!< Packet has a 1 byte length - header is 2 bytes long. */
OPS_PTAG_OF_LT_TWO_BYTE =0x01, /*!< Packet has a 2 byte length - header is 3 bytes long. */
OPS_PTAG_OF_LT_FOUR_BYTE =0x02, /*!< Packet has a 4 byte length - header is 5 bytes long. */
OPS_PTAG_OF_LT_INDETERMINATE =0x03 /*!< Packet has a indeterminate length. */
} ops_ptag_of_lt_t;
/** New Packet Format: Mask for content tag.
* In the new packet format the 6 rightmost bits
* are the content tag. This is the mask to apply
* to the packet tag. Note that you need to
* shift by #OPS_PTAG_NF_CONTENT_TAG_SHIFT bits.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_NF_CONTENT_TAG_MASK 0x3f
/** New Packet Format: Offset for the content tag.
* As described at #OPS_PTAG_NF_CONTENT_TAG_MASK the
* content tag needs to be shifted after being masked
* out from the Packet Tag.
*
* \see RFC4880 4.2
*/
#define OPS_PTAG_NF_CONTENT_TAG_SHIFT 0
/** Structure to hold one parse error string. */
typedef struct
{
const char *error; /*!< error message. */
} ops_parser_error_t;
/** Structure to hold one error code */
typedef struct
{
ops_errcode_t errcode;
} ops_parser_errcode_t;
/** Structure to hold one packet tag.
* \see RFC4880 4.2
*/
typedef struct
{
unsigned new_format; /*!< Whether this packet tag is new (true) or old format (false) */
unsigned content_tag; /*!< content_tag value - See #ops_content_tag_t for meanings */
ops_ptag_of_lt_t length_type; /*!< Length type (#ops_ptag_of_lt_t) - only if this packet tag is old format. Set to 0 if new format. */
unsigned length; /*!< The length of the packet. This value is set when we read and compute the
length information, not at the same moment we create the packet tag structure.
Only defined if #length_read is set. */ /* XXX: Ben, is this correct? */
unsigned position; /*!< The position (within the current reader) of the packet */
} ops_ptag_t;
/** Public Key Algorithm Numbers.
* OpenPGP assigns a unique Algorithm Number to each algorithm that is part of OpenPGP.
*
* This lists algorithm numbers for public key algorithms.
*
* \see RFC4880 9.1
*/
typedef enum
{
OPS_PKA_RSA =1, /*!< RSA (Encrypt or Sign) */
OPS_PKA_RSA_ENCRYPT_ONLY =2, /*!< RSA Encrypt-Only (deprecated - \see RFC4880 13.5) */
OPS_PKA_RSA_SIGN_ONLY =3, /*!< RSA Sign-Only (deprecated - \see RFC4880 13.5) */
OPS_PKA_ELGAMAL =16, /*!< Elgamal (Encrypt-Only) */
OPS_PKA_DSA =17, /*!< DSA (Digital Signature Algorithm) */
OPS_PKA_RESERVED_ELLIPTIC_CURVE =18, /*!< Reserved for Elliptic Curve */
OPS_PKA_RESERVED_ECDSA =19, /*!< Reserved for ECDSA */
OPS_PKA_ELGAMAL_ENCRYPT_OR_SIGN =20, /*!< Deprecated. */
OPS_PKA_RESERVED_DH =21, /*!< Reserved for Diffie-Hellman (X9.42, as defined for IETF-S/MIME) */
OPS_PKA_PRIVATE00 =100, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE01 =101, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE02 =102, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE03 =103, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE04 =104, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE05 =105, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE06 =106, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE07 =107, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE08 =108, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE09 =109, /*!< Private/Experimental Algorithm */
OPS_PKA_PRIVATE10 =110, /*!< Private/Experimental Algorithm */
} ops_public_key_algorithm_t;
/** Structure to hold one DSA public key parameters.
*
* \see RFC4880 5.5.2
*/
typedef struct
{
BIGNUM *p; /*!< DSA prime p */
BIGNUM *q; /*!< DSA group order q */
BIGNUM *g; /*!< DSA group generator g */
BIGNUM *y; /*!< DSA public key value y (= g^x mod p with x being the secret) */
} ops_dsa_public_key_t;
/** Structure to hold on RSA public key.
*
* \see RFC4880 5.5.2
*/
typedef struct
{
BIGNUM *n; /*!< RSA public modulus n */
BIGNUM *e; /*!< RSA public encryptiong exponent e */
} ops_rsa_public_key_t;
/** Structure to hold on ElGamal public key parameters.
*
* \see RFC4880 5.5.2
*/
typedef struct
{
BIGNUM *p; /*!< ElGamal prime p */
BIGNUM *g; /*!< ElGamal group generator g */
BIGNUM *y; /*!< ElGamal public key value y (= g^x mod p with x being the secret) */
} ops_elgamal_public_key_t;
/** Union to hold public key parameters of any algorithm */
typedef union
{
ops_dsa_public_key_t dsa; /*!< A DSA public key */
ops_rsa_public_key_t rsa; /*!< An RSA public key */
ops_elgamal_public_key_t elgamal; /*!< An ElGamal public key */
} ops_public_key_union_t;
/** Version.
* OpenPGP has two different protocol versions: version 3 and version 4.
*
* \see RFC4880 5.2
*/
typedef enum
{
OPS_V2=2, /*<! Version 2 (essentially the same as v3) */
OPS_V3=3, /*<! Version 3 */
OPS_V4=4, /*<! Version 4 */
} ops_version_t;
/** Structure to hold one pgp public key */
typedef struct
{
ops_version_t version; /*!< version of the key (v3, v4...) */
time_t creation_time; /*!< when the key was created. Note that interpretation varies with key
version. */
unsigned days_valid; /*!< validity period of the key in days since creation. A value of 0
has a special meaning indicating this key does not expire. Only
used with v3 keys. */
ops_public_key_algorithm_t algorithm; /*!< Public Key Algorithm type */
ops_public_key_union_t key; /*!< Public Key Parameters */
} ops_public_key_t;
/** Structure to hold data for one RSA secret key
*/
typedef struct
{
BIGNUM *d;
BIGNUM *p;
BIGNUM *q;
BIGNUM *u;
} ops_rsa_secret_key_t;
/** ops_dsa_secret_key_t */
typedef struct
{
BIGNUM *x;
} ops_dsa_secret_key_t;
/** ops_secret_key_union_t */
typedef struct
{
ops_rsa_secret_key_t rsa;
ops_dsa_secret_key_t dsa;
} ops_secret_key_union_t;
/** s2k_usage_t
*/
typedef enum
{
OPS_S2KU_NONE=0,
OPS_S2KU_ENCRYPTED_AND_HASHED=254,
OPS_S2KU_ENCRYPTED=255,
} ops_s2k_usage_t;
/** s2k_specifier_t
*/
typedef enum
{
OPS_S2KS_SIMPLE=0,
OPS_S2KS_SALTED=1,
OPS_S2KS_ITERATED_AND_SALTED=3
} ops_s2k_specifier_t;
/** Symmetric Key Algorithm Numbers.
* OpenPGP assigns a unique Algorithm Number to each algorithm that is part of OpenPGP.
*
* This lists algorithm numbers for symmetric key algorithms.
*
* \see RFC4880 9.2
*/
typedef enum
{
OPS_SA_PLAINTEXT =0, /*!< Plaintext or unencrypted data */
OPS_SA_IDEA =1, /*!< IDEA */
OPS_SA_TRIPLEDES =2, /*!< TripleDES */
OPS_SA_CAST5 =3, /*!< CAST5 */
OPS_SA_BLOWFISH =4, /*!< Blowfish */
OPS_SA_AES_128 =7, /*!< AES with 128-bit key (AES) */
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.
* OpenPGP assigns a unique Algorithm Number to each algorithm that is part of OpenPGP.
*
* This lists algorithm numbers for hash algorithms.
*
* \see RFC4880 9.4
*/
typedef enum
{
OPS_HASH_UNKNOWN =-1, /*!< used to indicate errors */
OPS_HASH_MD5 = 1, /*!< MD5 */
OPS_HASH_SHA1 = 2, /*!< SHA-1 */
OPS_HASH_RIPEMD = 3, /*!< RIPEMD160 */
OPS_HASH_SHA256 = 8, /*!< SHA256 */
OPS_HASH_SHA384 = 9, /*!< SHA384 */
OPS_HASH_SHA512 =10, /*!< SHA512 */
OPS_HASH_SHA224 = 11, /*!< SHA224 */
} ops_hash_algorithm_t;
// Maximum block size for symmetric crypto
#define OPS_MAX_BLOCK_SIZE 16
// Maximum key size for symmetric crypto
#define OPS_MAX_KEY_SIZE 32
// Salt size for hashing
#define OPS_SALT_SIZE 8
// Hash size for secret key check
#define OPS_CHECKHASH_SIZE 20
// SHA1 Hash Size \todo is this the same as OPS_CHECKHASH_SIZE??
#define OPS_SHA1_HASH_SIZE SHA_DIGEST_LENGTH
#define OPS_SHA256_HASH_SIZE SHA256_DIGEST_LENGTH
// Max hash size
#define OPS_MAX_HASH_SIZE 64
/** ops_secret_key_t
*/
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; // the algorithm used to encrypt
// the key
ops_hash_algorithm_t hash_algorithm;
unsigned char salt[OPS_SALT_SIZE];
unsigned octet_count;
unsigned char iv[OPS_MAX_BLOCK_SIZE];
ops_secret_key_union_t key;
unsigned checksum;
unsigned char checkhash[OPS_CHECKHASH_SIZE];
} ops_secret_key_t;
/** Structure to hold one trust packet's data */
typedef struct
{
ops_data_t data; /*<! Trust Packet */
} ops_trust_t;
/** Structure to hold one user id */
typedef struct
{
unsigned char *user_id; /*!< User ID - UTF-8 string */
} ops_user_id_t;
/** Structure to hold one user attribute */
typedef struct
{
ops_data_t data; /*!< User Attribute */
} ops_user_attribute_t;
/** Signature Type.
* OpenPGP defines different signature types that allow giving different meanings to signatures. Signature types
* include 0x10 for generitc User ID certifications (used when Ben signs Weasel's key), Subkey binding signatures,
* document signatures, key revocations, etc.
*
* Different types are used in different places, and most make only sense in their intended location (for instance a
* subkey binding has no place on a UserID).
*
* \see RFC4880 5.2.1
*/
typedef enum
{
OPS_SIG_BINARY =0x00, /*<! Signature of a binary document */
OPS_SIG_TEXT =0x01, /*<! Signature of a canonical text document */
OPS_SIG_STANDALONE =0x02, /*<! Standalone signature */
OPS_CERT_GENERIC =0x10, /*<! Generic certification of a User ID and Public Key packet */
OPS_CERT_PERSONA =0x11, /*<! Persona certification of a User ID and Public Key packet */
OPS_CERT_CASUAL =0x12, /*<! Casual certification of a User ID and Public Key packet */
OPS_CERT_POSITIVE =0x13, /*<! Positive certification of a User ID and Public Key packet */
OPS_SIG_SUBKEY =0x18, /*<! Subkey Binding Signature */
OPS_SIG_PRIMARY =0x19, /*<! Primary Key Binding Signature */
OPS_SIG_DIRECT =0x1f, /*<! Signature directly on a key */
OPS_SIG_REV_KEY =0x20, /*<! Key revocation signature */
OPS_SIG_REV_SUBKEY =0x28, /*<! Subkey revocation signature */
OPS_SIG_REV_CERT =0x30, /*<! Certification revocation signature */
OPS_SIG_TIMESTAMP =0x40, /*<! Timestamp signature */
OPS_SIG_3RD_PARTY =0x50, /*<! Third-Party Confirmation signature */
} ops_sig_type_t;
/** Struct to hold parameters of an RSA signature */
typedef struct
{
BIGNUM *sig; /*!< the signature value (m^d % n) */
} ops_rsa_signature_t;
/** Struct to hold parameters of a DSA signature */
typedef struct
{
BIGNUM *r; /*!< DSA value r */
BIGNUM *s; /*!< DSA value s */
} ops_dsa_signature_t;
/** ops_elgamal_signature_t */
typedef struct
{
BIGNUM *r;
BIGNUM *s;
} ops_elgamal_signature_t;
/** Struct to hold data for a private/experimental signature */
typedef struct
{
ops_data_t data;
} ops_unknown_signature_t;
/** Union to hold signature parameters of any algorithm */
typedef union
{
ops_rsa_signature_t rsa; /*!< An RSA Signature */
ops_dsa_signature_t dsa; /*!< A DSA Signature */
ops_elgamal_signature_t elgamal; /* deprecated */
ops_unknown_signature_t unknown; /* private or experimental */
} ops_signature_union_t;
#define OPS_KEY_ID_SIZE 8
/** Struct to hold a signature packet.
*
* \see RFC4880 5.2.2
* \see RFC4880 5.2.3
*/
typedef struct
{
ops_version_t version; /*!< signature version number */
ops_sig_type_t type; /*!< signature type value */
time_t creation_time; /*!< creation time of the signature */
unsigned char signer_id[OPS_KEY_ID_SIZE]; /*!< Eight-octet key ID of signer*/
ops_public_key_algorithm_t key_algorithm; /*!< public key algorithm number */
ops_hash_algorithm_t hash_algorithm; /*!< hashing algorithm number */
ops_signature_union_t signature; /*!< signature parameters */
size_t v4_hashed_data_length;
unsigned char* v4_hashed_data;
ops_boolean_t creation_time_set:1;
ops_boolean_t signer_id_set:1;
} ops_signature_info_t;
/** Struct used when parsing a signature */
typedef struct
{
ops_signature_info_t info; /*!< The signature information */
/* The following fields are only used while parsing the signature */
unsigned char hash2[2]; /*!< high 2 bytes of hashed value - for quick test */
size_t v4_hashed_data_start; /* only valid if accumulate is set */
ops_hash_t *hash; /*!< if set, the hash filled in for the data so far */
} ops_signature_t;
/** The raw bytes of a signature subpacket */
typedef struct
{
ops_content_tag_t tag;
size_t length;
unsigned char *raw;
} ops_ss_raw_t;
/** Signature Subpacket : Trust Level */
typedef struct
{
unsigned char level; /*<! Trust Level */
unsigned char amount; /*<! Amount */
} ops_ss_trust_t;
/** Signature Subpacket : Revocable */
typedef struct
{
ops_boolean_t revocable;
} ops_ss_revocable_t;
/** Signature Subpacket : Time */
typedef struct
{
time_t time;
} ops_ss_time_t;
/** Signature Subpacket : Key ID */
typedef struct
{
unsigned char key_id[OPS_KEY_ID_SIZE];
} ops_ss_key_id_t;
/** Signature Subpacket : Notation Data */
typedef struct
{
ops_data_t flags;
ops_data_t name;
ops_data_t value;
} ops_ss_notation_data_t;
/** Signature Subpacket : User Defined */
typedef struct
{
ops_data_t data;
} ops_ss_userdefined_t;
/** Signature Subpacket : Unknown */
typedef struct
{
ops_data_t data;
} ops_ss_unknown_t;
/** Signature Subpacket : Preferred Symmetric Key Algorithm */
typedef struct
{
ops_data_t data;
/* Note that value 0 may represent the plaintext algorithm
so we cannot expect data->contents to be a null-terminated list */
} ops_ss_preferred_ska_t;
/** Signature Subpacket : Preferrred Hash Algorithm */
typedef struct
{
ops_data_t data;
} ops_ss_preferred_hash_t;
/** Signature Subpacket : Preferred Compression */
typedef struct
{
ops_data_t data;
} ops_ss_preferred_compression_t;
/** Signature Subpacket : Key Flags */
typedef struct
{
ops_data_t data;
} ops_ss_key_flags_t;
/** Signature Subpacket : Key Server Preferences */
typedef struct
{
ops_data_t data;
} ops_ss_key_server_prefs_t;
/** Signature Subpacket : Features */
typedef struct
{
ops_data_t data;
} ops_ss_features_t;
/** Signature Subpacket : Signature Target */
typedef struct
{
ops_public_key_algorithm_t pka_alg;
ops_hash_algorithm_t hash_alg;
ops_data_t hash;
} ops_ss_signature_target_t;
/** Signature Subpacket : Embedded Signature */
typedef struct
{
ops_data_t sig;
} ops_ss_embedded_signature_t;
/** ops_packet_t */
typedef struct
{
size_t length;
unsigned char *raw;
} ops_packet_t;
/** Types of Compression */
typedef enum
{
OPS_C_NONE=0,
OPS_C_ZIP=1,
OPS_C_ZLIB=2,
OPS_C_BZIP2=3,
} ops_compression_type_t;
/* unlike most structures, this will feed its data as a stream
* to the application instead of directly including it */
/** ops_compressed_t */
typedef struct
{
ops_compression_type_t type;
} ops_compressed_t;
/** ops_one_pass_signature_t */
typedef struct
{
unsigned char version;
ops_sig_type_t sig_type;
ops_hash_algorithm_t hash_algorithm;
ops_public_key_algorithm_t key_algorithm;
unsigned char keyid[OPS_KEY_ID_SIZE];
ops_boolean_t nested;
} ops_one_pass_signature_t;
/** Signature Subpacket : Primary User ID */
typedef struct
{
ops_boolean_t primary_user_id;
} ops_ss_primary_user_id_t;
/** Signature Subpacket : Regexp */
typedef struct
{
char *text;
} ops_ss_regexp_t;
/** Signature Subpacket : Policy URL */
typedef struct
{
char *text;
} ops_ss_policy_url_t;
/** Signature Subpacket : Preferred Key Server */
typedef struct
{
char *text;
} ops_ss_preferred_key_server_t;
/** Signature Subpacket : Revocation Key */
typedef struct
{
unsigned char clss; /* class - name changed for C++ */
unsigned char algid;
unsigned char fingerprint[20];
} ops_ss_revocation_key_t;
/** Signature Subpacket : Revocation Reason */
typedef struct
{
unsigned char code;
char *text;
} ops_ss_revocation_reason_t;
/** literal_data_type_t */
typedef enum
{
OPS_LDT_BINARY='b',
OPS_LDT_TEXT='t',
OPS_LDT_UTF8='u',
OPS_LDT_LOCAL='l',
OPS_LDT_LOCAL2='1'
} ops_literal_data_type_t;
/** ops_literal_data_header_t */
typedef struct
{
ops_literal_data_type_t format;
char filename[256];
time_t modification_time;
} ops_literal_data_header_t;
/** ops_literal_data_body_t */
typedef struct
{
unsigned length;
unsigned char *data;//[8192];
} ops_literal_data_body_t;
/** ops_mdc_t */
typedef struct
{
unsigned char data[20]; // size of SHA1 hash
} ops_mdc_t;
/** ops_armoured_header_value_t */
typedef struct
{
char *key;
char *value;
} ops_armoured_header_value_t;
/** ops_headers_t */
typedef struct
{
ops_armoured_header_value_t *headers;
unsigned nheaders;
} ops_headers_t;
/** ops_armour_header_t */
typedef struct
{
const char *type;
ops_headers_t headers;
} ops_armour_header_t;
/** ops_armour_trailer_t */
typedef struct
{
const char *type;
} ops_armour_trailer_t;
/** ops_signed_cleartext_header_t */
typedef struct
{
ops_headers_t headers;
} ops_signed_cleartext_header_t;
/** ops_signed_cleartext_body_t */
typedef struct
{
unsigned length;
unsigned char *data; // \todo fix hard-coded value?
} ops_signed_cleartext_body_t;
/** ops_signed_cleartext_trailer_t */
typedef struct
{
struct _ops_hash_t *hash; /*!< This will not have been finalised, but will have seen all the cleartext data in canonical form */
} ops_signed_cleartext_trailer_t;
/** ops_unarmoured_text_t */
typedef struct
{
unsigned length;
unsigned char *data;
} ops_unarmoured_text_t;
typedef enum
{
SE_IP_DATA_VERSION=1
} ops_se_ip_data_version_t;
typedef enum
{
OPS_PKSK_V3=3
} ops_pk_session_key_version_t;
/** ops_pk_session_key_parameters_rsa_t */
typedef struct
{
BIGNUM *encrypted_m;
BIGNUM *m;
} ops_pk_session_key_parameters_rsa_t;
/** ops_pk_session_key_parameters_elgamal_t */
typedef struct
{
BIGNUM *g_to_k;
BIGNUM *encrypted_m;
} ops_pk_session_key_parameters_elgamal_t;
/** ops_pk_session_key_parameters_t */
typedef union
{
ops_pk_session_key_parameters_rsa_t rsa;
ops_pk_session_key_parameters_elgamal_t elgamal;
} ops_pk_session_key_parameters_t;
/** ops_pk_session_key_t */
typedef struct
{
ops_pk_session_key_version_t version;
unsigned char key_id[OPS_KEY_ID_SIZE];
ops_public_key_algorithm_t algorithm;
ops_pk_session_key_parameters_t parameters;
ops_symmetric_algorithm_t symmetric_algorithm;
unsigned char key[OPS_MAX_KEY_SIZE];
unsigned short checksum;
} ops_pk_session_key_t;
/** ops_secret_key_passphrase_t */
typedef struct
{
const ops_secret_key_t *secret_key;
char **passphrase; /* point somewhere that gets filled in to work around constness of content */
} ops_secret_key_passphrase_t;
typedef enum
{
OPS_SE_IP_V1=1
} ops_se_ip_version_t;
/** ops_se_ip_data_header_t */
typedef struct
{
ops_se_ip_version_t version;
} ops_se_ip_data_header_t;
/** ops_se_ip_data_body_t */
typedef struct
{
unsigned length;
unsigned char* data; // \todo remember to free this
} ops_se_ip_data_body_t;
/** ops_se_data_body_t */
typedef struct
{
unsigned length;
unsigned char data[8192]; // \todo parameterise this!
} ops_se_data_body_t;
/** ops_get_secret_key_t */
typedef struct
{
const ops_secret_key_t **secret_key;
const ops_pk_session_key_t *pk_session_key;
} ops_get_secret_key_t;
/** ops_parser_union_content_t */
typedef union
{
ops_parser_error_t error;
ops_parser_errcode_t errcode;
ops_ptag_t ptag;
ops_public_key_t public_key;
ops_trust_t trust;
ops_user_id_t user_id;
ops_user_attribute_t user_attribute;
ops_signature_t signature;
ops_ss_raw_t ss_raw;
ops_ss_trust_t ss_trust;
ops_ss_revocable_t ss_revocable;
ops_ss_time_t ss_time;
ops_ss_key_id_t ss_issuer_key_id;
ops_ss_notation_data_t ss_notation_data;
ops_packet_t packet;
ops_compressed_t compressed;
ops_one_pass_signature_t one_pass_signature;
ops_ss_preferred_ska_t ss_preferred_ska;
ops_ss_preferred_hash_t ss_preferred_hash;
ops_ss_preferred_compression_t ss_preferred_compression;
ops_ss_key_flags_t ss_key_flags;
ops_ss_key_server_prefs_t ss_key_server_prefs;
ops_ss_primary_user_id_t ss_primary_user_id;
ops_ss_regexp_t ss_regexp;
ops_ss_policy_url_t ss_policy_url;
ops_ss_preferred_key_server_t ss_preferred_key_server;
ops_ss_revocation_key_t ss_revocation_key;
ops_ss_userdefined_t ss_userdefined;
ops_ss_unknown_t ss_unknown;
ops_literal_data_header_t literal_data_header;
ops_literal_data_body_t literal_data_body;
ops_mdc_t mdc;
ops_ss_features_t ss_features;
ops_ss_signature_target_t ss_signature_target;
ops_ss_embedded_signature_t ss_embedded_signature;
ops_ss_revocation_reason_t ss_revocation_reason;
ops_secret_key_t secret_key;
ops_user_id_t ss_signers_user_id;
ops_armour_header_t armour_header;
ops_armour_trailer_t armour_trailer;
ops_signed_cleartext_header_t signed_cleartext_header;
ops_signed_cleartext_body_t signed_cleartext_body;
ops_signed_cleartext_trailer_t signed_cleartext_trailer;
ops_unarmoured_text_t unarmoured_text;
ops_pk_session_key_t pk_session_key;
ops_secret_key_passphrase_t secret_key_passphrase;
ops_se_ip_data_header_t se_ip_data_header;
ops_se_ip_data_body_t se_ip_data_body;
ops_se_data_body_t se_data_body;
ops_get_secret_key_t get_secret_key;
} ops_parser_content_union_t;
/** ops_parser_content_t */
struct ops_parser_content_t
{
ops_content_tag_t tag;
unsigned char critical; /* for signature subpackets */
ops_parser_content_union_t content;
};
/** ops_fingerprint_t */
typedef struct
{
unsigned char fingerprint[20];
unsigned length;
} ops_fingerprint_t;
void ops_init(void);
void ops_finish(void);
void ops_keyid(unsigned char keyid[OPS_KEY_ID_SIZE],
const ops_public_key_t *key);
void ops_fingerprint(ops_fingerprint_t *fp,const ops_public_key_t *key);
void ops_public_key_free(ops_public_key_t *key);
void ops_public_key_copy(ops_public_key_t *dst,const ops_public_key_t *src);
void ops_user_id_free(ops_user_id_t *id);
void ops_user_attribute_free(ops_user_attribute_t *att);
void ops_signature_free(ops_signature_t *sig);
void ops_trust_free(ops_trust_t *trust);
void ops_ss_preferred_ska_free(ops_ss_preferred_ska_t *ss_preferred_ska);
void ops_ss_preferred_hash_free(ops_ss_preferred_hash_t *ss_preferred_hash);
void ops_ss_preferred_compression_free(ops_ss_preferred_compression_t *ss_preferred_compression);
void ops_ss_key_flags_free(ops_ss_key_flags_t *ss_key_flags);
void ops_ss_key_server_prefs_free(ops_ss_key_server_prefs_t *ss_key_server_prefs);
void ops_ss_features_free(ops_ss_features_t *ss_features);
void ops_ss_notation_data_free(ops_ss_notation_data_t *ss_notation_data);
void ops_ss_policy_url_free(ops_ss_policy_url_t *ss_policy_url);
void ops_ss_preferred_key_server_free(ops_ss_preferred_key_server_t *ss_preferred_key_server);
void ops_ss_regexp_free(ops_ss_regexp_t *ss_regexp);
void ops_ss_userdefined_free(ops_ss_userdefined_t *ss_userdefined);
void ops_ss_reserved_free(ops_ss_unknown_t *ss_unknown);
void ops_ss_revocation_reason_free(ops_ss_revocation_reason_t *ss_revocation_reason);
void ops_ss_signature_target_free(ops_ss_signature_target_t *ss_signature_target);
void ops_ss_embedded_signature_free(ops_ss_embedded_signature_t *ss_embedded_signature);
void ops_packet_free(ops_packet_t *packet);
void ops_parser_content_free(ops_parser_content_t *c);
void ops_secret_key_free(ops_secret_key_t *key);
void ops_secret_key_copy(ops_secret_key_t *dst,const ops_secret_key_t *src);
void ops_pk_session_key_free(ops_pk_session_key_t *sk);
/* vim:set textwidth=120: */
/* vim:set ts=8: */
#endif

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file */
#include <openpgpsdk/types.h>
#include <openpgpsdk/crypto.h>
/** ops_reader_info */
struct ops_reader_info
{
ops_reader_t *reader; /*!< the reader function to use to get the
data to be parsed */
ops_reader_destroyer_t *destroyer;
void *arg; /*!< the args to pass to the reader function */
ops_boolean_t accumulate:1; /*!< set to accumulate packet data */
unsigned char *accumulated; /*!< the accumulated data */
unsigned asize; /*!< size of the buffer */
unsigned alength; /*!< used buffer */
/* XXX: what do we do about offsets into compressed packets? */
unsigned position; /*!< the offset from the beginning (with this reader) */
ops_reader_info_t *next;
ops_parse_info_t *pinfo; /*!< A pointer back to the parent parse_info structure */
};
/** ops_crypt_info
Encrypt/decrypt settings
*/
struct ops_crypt_info
{
char *passphrase; /*<! passphrase to use, this is set by cb_get_passphrase */
ops_keyring_t *keyring; /*<! keyring to use */
const ops_keydata_t *keydata; /*<! keydata to use */
ops_parse_cb_t *cb_get_passphrase; /*<! callback to use to get the passphrase */
};
/** ops_parse_cb_info */
struct ops_parse_cb_info
{
ops_parse_cb_t *cb; /*!< the callback function to use when parsing */
void *arg; /*!< the args to pass to the callback function */
ops_error_t** errors; /*!< the address of the error stack to use */
ops_parse_cb_info_t *next;
ops_create_info_t *cinfo; /*!< used if writing out parsed info */
ops_crypt_info_t cryptinfo; /*!< used when decrypting */
};
/** ops_parse_hash_info_t */
typedef struct
{
ops_hash_t hash; /*!< hashes we should hash data with */
unsigned char keyid[OPS_KEY_ID_SIZE];
} ops_parse_hash_info_t;
#define NTAGS 0x100
/** \brief Structure to hold information about a packet parse.
*
* This information includes options about the parse:
* - whether the packet contents should be accumulated or not
* - whether signature subpackets should be parsed or left raw
*
* It contains options specific to the parsing of armoured data:
* - whether headers are allowed in armoured data without a gap
* - whether a blank line is allowed at the start of the armoured data
*
* It also specifies :
* - the callback function to use and its arguments
* - the reader function to use and its arguments
*
* It also contains information about the current state of the parse:
* - offset from the beginning
* - the accumulated data, if any
* - the size of the buffer, and how much has been used
*
* It has a linked list of errors.
*/
struct ops_parse_info
{
unsigned char ss_raw[NTAGS/8]; /*!< one bit per signature-subpacket type;
set to get raw data */
unsigned char ss_parsed[NTAGS/8]; /*!< one bit per signature-subpacket type;
set to get parsed data */
ops_reader_info_t rinfo;
ops_parse_cb_info_t cbinfo;
ops_error_t *errors;
ops_crypt_t decrypt;
ops_crypt_info_t cryptinfo;
size_t nhashes;
ops_parse_hash_info_t *hashes;
ops_boolean_t reading_v3_secret:1;
ops_boolean_t reading_mpi_length:1;
ops_boolean_t exact_read:1;
};

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2005-2009 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* The Contributors have asserted their moral rights under the
* UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_PARTIAL_H__
#define __OPS_PARTIAL_H__
#include "types.h"
#include "writer.h"
/**
* Function that writes out a packet header. See
* ops_writer_push_partial
*/
typedef ops_boolean_t ops_write_partial_header_t(ops_create_info_t *info,
void *data);
typedef ops_boolean_t ops_write_partial_trailer_t(ops_create_info_t *info,
void *data);
void ops_writer_push_partial(size_t packet_size,
ops_create_info_t *info,
ops_content_tag_t tag,
ops_write_partial_header_t *header_writer,
void *header_data);
void ops_writer_push_partial_with_trailer(
size_t packet_size,
ops_create_info_t *cinfo,
ops_content_tag_t tag,
ops_write_partial_header_t *header_writer,
void *header_data,
ops_write_partial_trailer_t *trailer_writer,
void *trailer_data);
#endif /* __OPS_PARTIAL_H__ */

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <openpgpsdk/random.h>
#include <openssl/rand.h>
void ops_random(void *dest,size_t length)
{
RAND_bytes(dest,length);
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WIN32
#include <malloc.h>
#else
#include <unistd.h>
#endif
void ops_random(void *dest,size_t length);

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fcntl.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <direct.h>
#endif
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <openpgpsdk/readerwriter.h>
#include <openpgpsdk/callback.h>
#include "parse_local.h"
/**
* \ingroup Internal_Readers_Generic
* \brief Starts reader stack
* \param pinfo Parse settings
* \param reader Reader to use
* \param destroyer Destroyer to use
* \param arg Reader-specific arg
*/
void ops_reader_set(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg)
{
pinfo->rinfo.reader=reader;
pinfo->rinfo.destroyer=destroyer;
pinfo->rinfo.arg=arg;
}
/**
* \ingroup Internal_Readers_Generic
* \brief Adds to reader stack
* \param pinfo Parse settings
* \param reader Reader to use
* \param destroyer Reader's destroyer
* \param arg Reader-specific arg
*/
void ops_reader_push(ops_parse_info_t *pinfo,ops_reader_t *reader,ops_reader_destroyer_t *destroyer,void *arg)
{
ops_reader_info_t *rinfo=malloc(sizeof *rinfo);
*rinfo=pinfo->rinfo;
memset(&pinfo->rinfo,'\0',sizeof pinfo->rinfo);
pinfo->rinfo.next=rinfo;
pinfo->rinfo.pinfo=pinfo;
// should copy accumulate flags from other reader? RW
pinfo->rinfo.accumulate=rinfo->accumulate;
ops_reader_set(pinfo,reader,destroyer,arg);
}
/**
* \ingroup Internal_Readers_Generic
* \brief Removes from reader stack
* \param pinfo Parse settings
*/
void ops_reader_pop(ops_parse_info_t *pinfo)
{
ops_reader_info_t *next=pinfo->rinfo.next;
// 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);
}
/**
* \ingroup Internal_Readers_Generic
* \brief Gets arg from reader
* \param rinfo Reader info
* \return Pointer to reader info's arg
*/
void *ops_reader_get_arg(ops_reader_info_t *rinfo)
{ return rinfo->arg; }
/**
* \ingroup Internal_Readers_Generic
* \brief Gets reader's arg from parse_info
* \param pinfo
* \return Pointer to parse_info's reader_info's arg
*/
void *ops_reader_get_arg_from_pinfo(ops_parse_info_t *pinfo)
{ return pinfo->rinfo.arg; }
// EOF

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,213 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <openpgpsdk/crypto.h>
#include <string.h>
#include <assert.h>
#include <openssl/cast.h>
#ifndef OPENSSL_NO_IDEA
#include <openssl/idea.h>
#endif
#include <openssl/aes.h>
#include <openssl/des.h>
#include "parse_local.h"
#include <openpgpsdk/packet-show.h>
#include <openpgpsdk/final.h>
static int debug=0;
#ifndef ATTRIBUTE_UNUSED
#ifndef WIN32
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif // #ifndef WIN32
#endif /* ATTRIBUTE_UNUSED */
// \todo there's also a encrypted_arg_t in adv_create.c
// which is used for *encrypting* whereas this is used
// for *decrypting*
typedef struct
{
unsigned char decrypted[1024];
size_t decrypted_count;
size_t decrypted_offset;
ops_crypt_t *decrypt;
ops_region_t *region;
ops_boolean_t prev_read_was_plain:1;
} encrypted_arg_t;
static int encrypted_data_reader(void *dest,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo)
{
encrypted_arg_t *arg=ops_reader_get_arg(rinfo);
int saved=length;
// V3 MPIs have the count plain and the cipher is reset after each count
if(arg->prev_read_was_plain && !rinfo->pinfo->reading_mpi_length)
{
assert(rinfo->pinfo->reading_v3_secret);
arg->decrypt->decrypt_resync(arg->decrypt);
arg->prev_read_was_plain=ops_false;
}
else if(rinfo->pinfo->reading_v3_secret
&& rinfo->pinfo->reading_mpi_length)
{
arg->prev_read_was_plain=ops_true;
}
while(length > 0)
{
if(arg->decrypted_count)
{
unsigned n;
// if we are reading v3 we should never read more than
// we're asked for
assert(length >= arg->decrypted_count
|| (!rinfo->pinfo->reading_v3_secret
&& !rinfo->pinfo->exact_read));
if(length > arg->decrypted_count)
n=arg->decrypted_count;
else
n=length;
memcpy(dest,arg->decrypted+arg->decrypted_offset,n);
arg->decrypted_count-=n;
arg->decrypted_offset+=n;
length-=n;
dest+=n;
}
else
{
unsigned n=arg->region->length;
unsigned char buffer[1024];
if(!n)
{
return -1;
}
if(!arg->region->indeterminate)
{
n-=arg->region->length_read;
if(n == 0)
return saved-length;
if(n > sizeof buffer)
n=sizeof buffer;
}
else
{
n=sizeof buffer;
}
// we can only read as much as we're asked for in v3 keys
// because they're partially unencrypted!
if((rinfo->pinfo->reading_v3_secret || rinfo->pinfo->exact_read)
&& n > length)
n=length;
if(!ops_stacked_limited_read(buffer,n,arg->region,errors,rinfo,
cbinfo))
{
return -1;
}
if(!rinfo->pinfo->reading_v3_secret
|| !rinfo->pinfo->reading_mpi_length)
{
arg->decrypted_count=ops_decrypt_se_ip(arg->decrypt,
arg->decrypted,
buffer,n);
if (debug)
{
fprintf(stderr,"READING:\nencrypted: ");
int i=0;
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", buffer[i]);
fprintf(stderr,"\n");
fprintf(stderr,"decrypted: ");
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", arg->decrypted[i]);
fprintf(stderr,"\n");
}
}
else
{
memcpy(arg->decrypted,buffer,n);
arg->decrypted_count=n;
}
assert(arg->decrypted_count > 0);
arg->decrypted_offset=0;
}
}
return saved;
}
static void encrypted_data_destroyer(ops_reader_info_t *rinfo)
{ free(ops_reader_get_arg(rinfo)); }
/**
* \ingroup Core_Readers_SE
* \brief Pushes decryption reader onto stack
* \sa ops_reader_pop_decrypt()
*/
void ops_reader_push_decrypt(ops_parse_info_t *pinfo,ops_crypt_t *decrypt,
ops_region_t *region)
{
encrypted_arg_t *arg=ops_mallocz(sizeof *arg);
arg->decrypt=decrypt;
arg->region=region;
ops_decrypt_init(arg->decrypt);
ops_reader_push(pinfo,encrypted_data_reader,encrypted_data_destroyer,arg);
}
/**
* \ingroup Core_Readers_Encrypted
* \brief Pops decryption reader from stack
* \sa ops_reader_push_decrypt()
*/
void ops_reader_pop_decrypt(ops_parse_info_t *pinfo)
{
encrypted_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
arg->decrypt->decrypt_finish(arg->decrypt);
free(arg);
ops_reader_pop(pinfo);
}
// eof

View File

@ -0,0 +1,248 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
* \brief Parser for OpenPGP packets
*/
#include <openssl/cast.h>
#include <openpgpsdk/callback.h>
#include <openpgpsdk/packet.h>
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/util.h>
#include <openpgpsdk/compress.h>
#include <openpgpsdk/errors.h>
#include <openpgpsdk/readerwriter.h>
#include <openpgpsdk/packet-show.h>
#include <openpgpsdk/std_print.h>
#include <openpgpsdk/create.h>
#include <openpgpsdk/hash.h>
#include "parse_local.h"
#include <assert.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <errno.h>
#include <limits.h>
#include <openpgpsdk/final.h>
static int debug=0;
typedef struct
{
// boolean: false once we've done the preamble/MDC checks
// and are reading from the plaintext
int passed_checks;
unsigned char *plaintext;
size_t plaintext_available;
size_t plaintext_offset;
ops_region_t *region;
ops_crypt_t *decrypt;
} decrypt_se_ip_arg_t;
static int se_ip_data_reader(void *dest_, size_t len, ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo)
{
/*
Gets entire SE_IP data packet.
Verifies leading preamble
Verifies trailing MDC packet
Then passes up plaintext as requested
*/
unsigned int n=0;
ops_region_t decrypted_region;
decrypt_se_ip_arg_t *arg=ops_reader_get_arg(rinfo);
if (!arg->passed_checks)
{
unsigned char*buf=NULL;
ops_hash_t hash;
unsigned char hashed[SHA_DIGEST_LENGTH];
size_t b;
size_t sz_preamble;
size_t sz_mdc_hash;
size_t sz_mdc;
size_t sz_plaintext;
unsigned char* preamble;
unsigned char* plaintext;
unsigned char* mdc;
unsigned char* mdc_hash;
ops_hash_any(&hash,OPS_HASH_SHA1);
hash.init(&hash);
ops_init_subregion(&decrypted_region,NULL);
decrypted_region.length = arg->region->length - arg->region->length_read;
buf=ops_mallocz(decrypted_region.length);
// read entire SE IP packet
if (!ops_stacked_limited_read(buf,decrypted_region.length, &decrypted_region,errors,rinfo,cbinfo))
{
free (buf);
return -1;
}
if (debug)
{
unsigned int i=0;
fprintf(stderr,"\n\nentire SE IP packet (len=%d):\n",decrypted_region.length);
for (i=0; i<decrypted_region.length; i++)
{
fprintf(stderr,"0x%02x ", buf[i]);
if (!((i+1)%8))
fprintf(stderr,"\n");
}
fprintf(stderr,"\n");
fprintf(stderr,"\n");
}
// verify leading preamble
if (debug)
{
unsigned int i=0;
fprintf(stderr,"\npreamble: ");
for (i=0; i<arg->decrypt->blocksize+2;i++)
fprintf(stderr," 0x%02x", buf[i]);
fprintf(stderr,"\n");
}
b=arg->decrypt->blocksize;
if(buf[b-2] != buf[b] || buf[b-1] != buf[b+1])
{
fprintf(stderr,"Bad symmetric decrypt (%02x%02x vs %02x%02x)\n",
buf[b-2],buf[b-1],buf[b],buf[b+1]);
OPS_ERROR(errors, OPS_E_PROTO_BAD_SYMMETRIC_DECRYPT,"Bad symmetric decrypt when parsing SE IP packet");
free(buf);
return -1;
}
// Verify trailing MDC hash
sz_preamble=arg->decrypt->blocksize+2;
sz_mdc_hash=OPS_SHA1_HASH_SIZE;
sz_mdc=1+1+sz_mdc_hash;
sz_plaintext=decrypted_region.length-sz_preamble-sz_mdc;
preamble=buf;
plaintext=buf+sz_preamble;
mdc=plaintext+sz_plaintext;
mdc_hash=mdc+2;
#ifdef DEBUG
if (debug)
{
unsigned int i=0;
fprintf(stderr,"\nplaintext (len=%ld): ",sz_plaintext);
for (i=0; i<sz_plaintext;i++)
fprintf(stderr," 0x%02x", plaintext[i]);
fprintf(stderr,"\n");
fprintf(stderr,"\nmdc (len=%ld): ",sz_mdc);
for (i=0; i<sz_mdc;i++)
fprintf(stderr," 0x%02x", mdc[i]);
fprintf(stderr,"\n");
}
#endif /*DEBUG*/
ops_calc_mdc_hash(preamble,sz_preamble,plaintext,sz_plaintext,&hashed[0]);
if (memcmp(mdc_hash,hashed,OPS_SHA1_HASH_SIZE))
{
OPS_ERROR(errors, OPS_E_V_BAD_HASH, "Bad hash in MDC packet");
free(buf);
return 0;
}
// all done with the checks
// now can start reading from the plaintext
assert(!arg->plaintext);
arg->plaintext=ops_mallocz(sz_plaintext);
memcpy(arg->plaintext, plaintext, sz_plaintext);
arg->plaintext_available=sz_plaintext;
arg->passed_checks=1;
free(buf);
}
n=len;
if (n > arg->plaintext_available)
n=arg->plaintext_available;
memcpy(dest_, arg->plaintext+arg->plaintext_offset, n);
arg->plaintext_available-=n;
arg->plaintext_offset+=n;
len-=n;
return n;
}
static void se_ip_data_destroyer(ops_reader_info_t *rinfo)
{
decrypt_se_ip_arg_t* arg=ops_reader_get_arg(rinfo);
free (arg->plaintext);
free (arg);
// free(ops_reader_get_arg(rinfo));
}
/**
\ingroup Internal_Readers_SEIP
*/
void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt,
ops_region_t *region)
{
decrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
arg->region=region;
arg->decrypt=decrypt;
ops_reader_push(pinfo, se_ip_data_reader, se_ip_data_destroyer,arg);
}
/**
\ingroup Internal_Readers_SEIP
*/
void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo)
{
// decrypt_se_ip_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
// free(arg);
ops_reader_pop(pinfo);
}
// eof

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/util.h>
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/create.h>
#include <openpgpsdk/errors.h>
#include <stdio.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <string.h>
#include <openpgpsdk/final.h>
/** Arguments for reader_fd
*/
typedef struct
{
int fd; /*!< file descriptor */
} reader_fd_arg_t;
/**
* \ingroup Core_Readers
*
* ops_reader_fd() attempts to read up to "plength" bytes from the file
* descriptor in "parse_info" into the buffer starting at "dest" using the
* rules contained in "flags"
*
* \param dest Pointer to previously allocated buffer
* \param plength Number of bytes to try to read
* \param flags Rules about reading to use
* \param parse_info Gets cast to ops_reader_fd_arg_t
*
* \return OPS_R_EOF if no bytes were read
* \return OPS_R_PARTIAL_READ if not enough bytes were read, and OPS_RETURN_LENGTH is set in "flags"
* \return OPS_R_EARLY_EOF if not enough bytes were read, and OPS_RETURN_LENGTH was not set in "flags"
* \return OPS_R_OK if expected length was read
* \return OPS_R_ERROR if cannot read
*
* OPS_R_EARLY_EOF and OPS_R_ERROR push errors on the stack
*
* \sa enum opt_reader_ret_t
*
* \todo change arg_ to typesafe?
*/
static int fd_reader(void *dest,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
{
reader_fd_arg_t *arg=ops_reader_get_arg(rinfo);
int n=read(arg->fd,dest,length);
OPS_USED(cbinfo);
if(n == 0)
return 0;
if(n < 0)
{
OPS_SYSTEM_ERROR_1(errors,OPS_E_R_READ_FAILED,"read",
"file descriptor %d",arg->fd);
return -1;
}
return n;
}
static void fd_destroyer(ops_reader_info_t *rinfo)
{ free(ops_reader_get_arg(rinfo)); }
/**
\ingroup Core_Readers_First
\brief Starts stack with file reader
*/
void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd)
{
reader_fd_arg_t *arg=malloc(sizeof *arg);
arg->fd=fd;
ops_reader_set(pinfo,fd_reader,fd_destroyer,arg);
}
// eof

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/crypto.h>
#include <assert.h>
#include <string.h>
#include <openpgpsdk/final.h>
static int hash_reader(void *dest,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
{
ops_hash_t *hash=ops_reader_get_arg(rinfo);
int r=ops_stacked_read(dest,length,errors,rinfo,cbinfo);
if(r <= 0)
return r;
hash->add(hash,dest,r);
return r;
}
/**
\ingroup Internal_Readers_Hash
\brief Push hashed data reader on stack
*/
void ops_reader_push_hash(ops_parse_info_t *pinfo,ops_hash_t *hash)
{
hash->init(hash);
ops_reader_push(pinfo,hash_reader,NULL,hash);
}
/**
\ingroup Internal_Readers_Hash
\brief Pop hashed data reader from stack
*/
void ops_reader_pop_hash(ops_parse_info_t *pinfo)
{ ops_reader_pop(pinfo); }
// EOF

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/util.h>
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/create.h>
#include <openpgpsdk/errors.h>
#include <stdio.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <string.h>
#include <openpgpsdk/final.h>
typedef struct
{
const unsigned char *buffer;
size_t length;
size_t offset;
} reader_mem_arg_t;
static int mem_reader(void *dest,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
{
reader_mem_arg_t *arg=ops_reader_get_arg(rinfo);
unsigned n;
OPS_USED(cbinfo);
OPS_USED(errors);
if(arg->offset+length > arg->length)
n=arg->length-arg->offset;
else
n=length;
if(n == 0)
return 0;
memcpy(dest,arg->buffer+arg->offset,n);
arg->offset+=n;
return n;
}
static void mem_destroyer(ops_reader_info_t *rinfo)
{ free(ops_reader_get_arg(rinfo)); }
/**
\ingroup Core_Readers_First
\brief Starts stack with memory reader
*/
void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer,
size_t length)
{
reader_mem_arg_t *arg=malloc(sizeof *arg);
arg->buffer=buffer;
arg->length=length;
arg->offset=0;
ops_reader_set(pinfo,mem_reader,mem_destroyer,arg);
}
/* eof */

View File

@ -0,0 +1,494 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fcntl.h>
#ifndef WIN32
#include <unistd.h>
#include <termios.h>
#else
#include <direct.h>
#endif
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <openpgpsdk/readerwriter.h>
#include <openpgpsdk/callback.h>
#include "parse_local.h"
#ifdef WIN32
#include <conio.h>
#include <stdio.h>
#define PASS_MAX 512
char *getpass (const char *prompt)
{
static char getpassbuf [PASS_MAX + 1];
size_t i = 0;
int c;
if (prompt) {
fputs (prompt, stderr);
fflush (stderr);
}
for (;;) {
c = _getch ();
if (c == '\r') {
getpassbuf [i] = '\0';
break;
}
else if (i < PASS_MAX) {
getpassbuf[i++] = c;
}
if (i >= PASS_MAX) {
getpassbuf [i] = '\0';
break;
}
}
if (prompt) {
fputs ("\r\n", stderr);
fflush (stderr);
}
return getpassbuf;
}
#endif
/**
\ingroup Core_Writers
\brief Create and initialise cinfo and mem; Set for writing to mem
\param cinfo Address where new cinfo pointer will be set
\param mem Address when new mem pointer will be set
\param bufsz Initial buffer size (will automatically be increased when necessary)
\note It is the caller's responsiblity to free cinfo and mem.
\sa ops_teardown_memory_write()
*/
void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz)
{
/*
* initialise needed structures for writing to memory
*/
*cinfo=ops_create_info_new();
*mem=ops_memory_new();
ops_memory_init(*mem,bufsz);
ops_writer_set_memory(*cinfo,*mem);
}
/**
\ingroup Core_Writers
\brief Closes writer and frees cinfo and mem
\param cinfo
\param mem
\sa ops_setup_memory_write()
*/
void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem)
{
ops_writer_close(cinfo); // new
ops_create_info_delete(cinfo);
ops_memory_free(mem);
}
/**
\ingroup Core_Readers
\brief Create parse_info and sets to read from memory
\param pinfo Address where new parse_info will be set
\param mem Memory to read from
\param arg Reader-specific arg
\param callback Callback to use with reader
\param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification)
\note It is the caller's responsiblity to free parse_info
\sa ops_teardown_memory_read()
*/
void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem,
void* arg,
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),
ops_boolean_t accumulate)
{
/*
* initialise needed uctures for reading
*/
*pinfo=ops_parse_info_new();
ops_parse_cb_set(*pinfo,callback,arg);
ops_reader_set_memory(*pinfo,
ops_memory_get_data(mem),
ops_memory_get_length(mem));
if (accumulate)
(*pinfo)->rinfo.accumulate=ops_true;
}
/**
\ingroup Core_Readers
\brief Frees pinfo and mem
\param pinfo
\param mem
\sa ops_setup_memory_read()
*/
void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem)
{
ops_parse_info_delete(pinfo);
ops_memory_free(mem);
}
/**
\ingroup Core_Writers
\brief Create and initialise cinfo and mem; Set for writing to file
\param cinfo Address where new cinfo pointer will be set
\param filename File to write to
\param allow_overwrite Allows file to be overwritten, if set.
\return Newly-opened file descriptor
\note It is the caller's responsiblity to free cinfo and to close fd.
\sa ops_teardown_file_write()
*/
int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite)
{
int fd=0;
int flags=0;
/*
* initialise needed structures for writing to file
*/
flags=O_WRONLY | O_CREAT;
if (allow_overwrite==ops_true)
flags |= O_TRUNC;
else
flags |= O_EXCL;
flags |= O_BINARY;
fd=open(filename, flags, 0600);
if(fd < 0)
{
perror(filename);
return fd;
}
*cinfo=ops_create_info_new();
ops_writer_set_fd(*cinfo,fd);
return fd;
}
/**
\ingroup Core_Writers
\brief Closes writer, frees info, closes fd
\param cinfo
\param fd
*/
void ops_teardown_file_write(ops_create_info_t *cinfo, int fd)
{
ops_writer_close(cinfo);
close(fd);
ops_create_info_delete(cinfo);
}
/**
\ingroup Core_Writers
\brief As ops_setup_file_write, but appends to file
*/
int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename)
{
int fd;
/*
* initialise needed structures for writing to file
*/
fd=open(filename,O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600);
if(fd < 0)
{
perror(filename);
return fd;
}
*cinfo=ops_create_info_new();
ops_writer_set_fd(*cinfo,fd);
return fd;
}
/**
\ingroup Core_Writers
\brief As ops_teardown_file_write()
*/
void ops_teardown_file_append(ops_create_info_t *cinfo, int fd)
{
ops_teardown_file_write(cinfo,fd);
}
/**
\ingroup Core_Readers
\brief Creates parse_info, opens file, and sets to read from file
\param pinfo Address where new parse_info will be set
\param filename Name of file to read
\param arg Reader-specific arg
\param callback Callback to use when reading
\param accumulate Set if we need to accumulate as we read. (Usually false unless doing signature verification)
\note It is the caller's responsiblity to free parse_info and to close fd
\sa ops_teardown_file_read()
*/
int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename,
void* arg,
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),
ops_boolean_t accumulate)
{
int fd=0;
/*
* initialise needed structures for reading
*/
fd=open(filename,O_RDONLY | O_BINARY);
if (fd < 0)
{
perror(filename);
return fd;
}
*pinfo=ops_parse_info_new();
ops_parse_cb_set(*pinfo,callback,arg);
ops_reader_set_fd(*pinfo,fd);
if (accumulate)
(*pinfo)->rinfo.accumulate=ops_true;
return fd;
}
/**
\ingroup Core_Readers
\brief Frees pinfo and closes fd
\param pinfo
\param fd
\sa ops_setup_file_read()
*/
void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd)
{
close(fd);
ops_parse_info_delete(pinfo);
}
ops_parse_cb_return_t
callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
OPS_USED(cbinfo);
// ops_print_packet(content_);
// Read data from packet into static buffer
switch(content_->tag)
{
case OPS_PTAG_CT_LITERAL_DATA_BODY:
// if writer enabled, use it
if (cbinfo->cinfo)
{
ops_write(content->literal_data_body.data,
content->literal_data_body.length,
cbinfo->cinfo);
}
/*
ops_memory_add(mem_literal_data,
content->literal_data_body.data,
content->literal_data_body.length);
*/
break;
case OPS_PTAG_CT_LITERAL_DATA_HEADER:
// ignore
break;
default:
// return callback_general(content_,cbinfo);
break;
}
return OPS_RELEASE_MEMORY;
}
ops_parse_cb_return_t
callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
OPS_USED(cbinfo);
// ops_print_packet(content_);
// Read data from packet into static buffer
switch(content_->tag)
{
case OPS_PTAG_CT_PK_SESSION_KEY:
// printf ("OPS_PTAG_CT_PK_SESSION_KEY\n");
assert(cbinfo->cryptinfo.keyring);
cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,
content->pk_session_key.key_id);
if(!cbinfo->cryptinfo.keydata)
break;
break;
default:
// return callback_general(content_,cbinfo);
break;
}
return OPS_RELEASE_MEMORY;
}
/**
\ingroup Core_Callbacks
\brief Callback to get secret key, decrypting if necessary.
@verbatim
This callback does the following:
* finds the session key in the keyring
* gets a passphrase if required
* decrypts the secret key, if necessary
* sets the secret_key in the content struct
@endverbatim
*/
ops_parse_cb_return_t
callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
const ops_secret_key_t *secret;
ops_parser_content_t pc;
OPS_USED(cbinfo);
// ops_print_packet(content_);
switch(content_->tag)
{
case OPS_PARSER_CMD_GET_SECRET_KEY:
cbinfo->cryptinfo.keydata=ops_keyring_find_key_by_id(cbinfo->cryptinfo.keyring,content->get_secret_key.pk_session_key->key_id);
if (!cbinfo->cryptinfo.keydata || !ops_is_key_secret(cbinfo->cryptinfo.keydata))
return 0;
/* now get the key from the data */
secret=ops_get_secret_key_from_data(cbinfo->cryptinfo.keydata);
int tag_to_use = OPS_PARSER_CMD_GET_SK_PASSPHRASE ;
int nbtries = 0 ;
while( (!secret) && nbtries++ < 3)
{
if (!cbinfo->cryptinfo.passphrase)
{
memset(&pc,'\0',sizeof pc);
pc.content.secret_key_passphrase.passphrase=&cbinfo->cryptinfo.passphrase;
CB(cbinfo,tag_to_use,&pc);
if (!cbinfo->cryptinfo.passphrase)
{
fprintf(stderr,"can't get passphrase\n");
assert(0);
}
}
/* then it must be encrypted */
secret=ops_decrypt_secret_key_from_data(cbinfo->cryptinfo.keydata,cbinfo->cryptinfo.passphrase);
free(cbinfo->cryptinfo.passphrase) ;
cbinfo->cryptinfo.passphrase = NULL ;
tag_to_use = OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD ;
}
if(!secret)
return 0 ;
*content->get_secret_key.secret_key=secret;
break;
default:
// return callback_general(content_,cbinfo);
break;
}
return OPS_RELEASE_MEMORY;
}
char *ops_get_passphrase(void)
{
return ops_malloc_passphrase(getpass("Passphrase: "));
}
char *ops_malloc_passphrase(char *pp)
{
char *passphrase;
size_t n;
n=strlen(pp);
passphrase=malloc(n+1);
strncpy(passphrase,pp,n+1);
return passphrase;
}
/**
\ingroup HighLevel_Callbacks
\brief Callback to use when you need to prompt user for passphrase
\param content_
\param cbinfo
*/
ops_parse_cb_return_t
callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
OPS_USED(cbinfo);
// ops_print_packet(content_);
switch(content_->tag)
{
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
*(content->secret_key_passphrase.passphrase)=ops_get_passphrase();
return OPS_KEEP_MEMORY;
break;
default:
// return callback_general(content_,cbinfo);
break;
}
return OPS_RELEASE_MEMORY;
}
ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state)
{
pinfo->rinfo.accumulate=state;
return state;
}
// EOF

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_READERWRITER_H__
#define __OPS_READERWRITER_H__
#include <openpgpsdk/memory.h>
#include <openpgpsdk/create.h>
void ops_reader_set_fd(ops_parse_info_t *pinfo,int fd);
void ops_reader_set_memory(ops_parse_info_t *pinfo,const void *buffer,
size_t length);
// Do a sum mod 65536 of all bytes read (as needed for secret keys)
void ops_reader_push_sum16(ops_parse_info_t *pinfo);
unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo);
void ops_reader_push_se_ip_data(ops_parse_info_t *pinfo, ops_crypt_t *decrypt,
ops_region_t *region);
void ops_reader_pop_se_ip_data(ops_parse_info_t* pinfo);
//
ops_boolean_t ops_write_mdc(const unsigned char *hashed,
ops_create_info_t* info);
ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
const unsigned int len,
ops_crypt_t *crypt,
ops_create_info_t *info);
void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo,
ops_crypt_t *crypt);
void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo,
const ops_keydata_t *pub_key);
// Secret Key checksum
void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey);
ops_boolean_t ops_pop_skey_checksum_writer(ops_create_info_t *cinfo);
// memory writing
void ops_setup_memory_write(ops_create_info_t **cinfo, ops_memory_t **mem, size_t bufsz);
void ops_teardown_memory_write(ops_create_info_t *cinfo, ops_memory_t *mem);
// memory reading
void ops_setup_memory_read(ops_parse_info_t **pinfo, ops_memory_t *mem,
void* arg,
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *),ops_boolean_t accumulate);
void ops_teardown_memory_read(ops_parse_info_t *pinfo, ops_memory_t *mem);
// file writing
int ops_setup_file_write(ops_create_info_t **cinfo, const char* filename, ops_boolean_t allow_overwrite);
void ops_teardown_file_write(ops_create_info_t *cinfo, int fd);
// file appending
int ops_setup_file_append(ops_create_info_t **cinfo, const char* filename);
void ops_teardown_file_append(ops_create_info_t *cinfo, int fd);
// file reading
int ops_setup_file_read(ops_parse_info_t **pinfo, const char *filename, void* arg,
ops_parse_cb_return_t callback(const ops_parser_content_t *, ops_parse_cb_info_t *), ops_boolean_t accumulate);
void ops_teardown_file_read(ops_parse_info_t *pinfo, int fd);
ops_boolean_t ops_reader_set_accumulate(ops_parse_info_t* pinfo, ops_boolean_t state);
// useful callbacks
ops_parse_cb_return_t
callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
ops_parse_cb_return_t
callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
ops_parse_cb_return_t
callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
ops_parse_cb_return_t
callback_cmd_get_passphrase_from_cmdline(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
#endif /*OPS_READERWRITER_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_SIGNATURE_H
#define OPS_SIGNATURE_H
#include "packet.h"
#include "util.h"
#include "create.h"
typedef struct ops_create_signature ops_create_signature_t;
ops_create_signature_t *ops_create_signature_new(void);
void ops_create_signature_delete(ops_create_signature_t *sig);
ops_boolean_t
ops_check_user_id_certification_signature(const ops_public_key_t *key,
const ops_user_id_t *id,
const ops_signature_t *sig,
const ops_public_key_t *signer,
const unsigned char *raw_packet);
ops_boolean_t
ops_check_user_attribute_certification_signature(const ops_public_key_t *key,
const ops_user_attribute_t *attribute,
const ops_signature_t *sig,
const ops_public_key_t *signer,
const unsigned char *raw_packet);
ops_boolean_t
ops_check_subkey_signature(const ops_public_key_t *key,
const ops_public_key_t *subkey,
const ops_signature_t *sig,
const ops_public_key_t *signer,
const unsigned char *raw_packet);
ops_boolean_t
ops_check_direct_signature(const ops_public_key_t *key,
const ops_signature_t *sig,
const ops_public_key_t *signer,
const unsigned char *raw_packet);
ops_boolean_t
ops_check_hash_signature(ops_hash_t *hash,
const ops_signature_t *sig,
const ops_public_key_t *signer);
void ops_signature_start_key_signature(ops_create_signature_t *sig,
const ops_public_key_t *key,
const ops_user_id_t *id,
ops_sig_type_t type);
void ops_signature_start_cleartext_signature(ops_create_signature_t *sig,
const ops_secret_key_t *key,
const ops_hash_algorithm_t hash,
const ops_sig_type_t type);
void ops_signature_start_message_signature(ops_create_signature_t *sig,
const ops_secret_key_t *key,
const ops_hash_algorithm_t hash,
const ops_sig_type_t type);
void ops_signature_add_data(ops_create_signature_t *sig,const void *buf,
size_t length);
ops_hash_t *ops_signature_get_hash(ops_create_signature_t *sig);
ops_boolean_t ops_signature_hashed_subpackets_end(ops_create_signature_t *sig);
ops_boolean_t ops_write_signature(ops_create_signature_t *sig,const ops_public_key_t *key,
const ops_secret_key_t *skey, ops_create_info_t *opt);
ops_boolean_t ops_signature_add_creation_time(ops_create_signature_t *sig,time_t when);
ops_boolean_t ops_signature_add_issuer_key_id(ops_create_signature_t *sig,
const unsigned char keyid[OPS_KEY_ID_SIZE]);
void ops_signature_add_primary_user_id(ops_create_signature_t *sig,
ops_boolean_t primary);
// Standard Interface
ops_boolean_t ops_sign_file_as_cleartext(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t overwrite);
ops_boolean_t ops_sign_buf_as_cleartext(const char* input, const size_t len, ops_memory_t** output, const ops_secret_key_t *skey);
ops_boolean_t ops_sign_file(const char* input_filename, const char* output_filename, const ops_secret_key_t *skey, const ops_boolean_t use_armour, const ops_boolean_t overwrite);
ops_memory_t * ops_sign_buf(const void* input, const size_t input_len, const ops_sig_type_t sig_type, const ops_secret_key_t *skey, const ops_boolean_t use_armour,ops_boolean_t include_data);
ops_boolean_t ops_writer_push_signed(ops_create_info_t *cinfo, const ops_sig_type_t sig_type, const ops_secret_key_t *skey);
#endif

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_STD_PRINT_H
#define OPS_STD_PRINT_H
#include "openpgpsdk/packet.h"
#include "openpgpsdk/packet-parse.h"
#include "openpgpsdk/keyring.h"
void print_bn( const char *name,
const BIGNUM *bn);
void ops_print_pk_session_key(ops_content_tag_t tag,
const ops_pk_session_key_t *key);
void ops_print_public_keydata(const ops_keydata_t *key);
void ops_print_public_keydata_verbose(const ops_keydata_t *key);
void ops_print_public_key(const ops_public_key_t *pkey);
void ops_print_secret_keydata(const ops_keydata_t *key);
void ops_print_secret_keydata_verbose(const ops_keydata_t *key);
//void ops_print_secret_key(const ops_content_tag_t type, const ops_secret_key_t* skey);
int ops_print_packet(const ops_parser_content_t *content_);
void ops_list_packets(char *filename, ops_boolean_t armour, ops_keyring_t* pubring, ops_parse_cb_t* cb_get_passphrase);
#endif

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __OPS_STREAMWRITER_H__
#define __OPS_STREAMWRITER_H__
#include <openpgpsdk/readerwriter.h>
void ops_writer_push_stream_encrypt_se_ip(ops_create_info_t *cinfo,
const ops_keydata_t *pub_key);
#endif /*__OPS_STREAMWRITER_H__*/

View File

@ -0,0 +1,683 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <openpgpsdk/crypto.h>
#include <string.h>
#include <assert.h>
#include <openssl/cast.h>
#ifndef OPENSSL_NO_IDEA
# include <openssl/idea.h>
#endif
#include <openssl/aes.h>
#ifndef OPENSSL_NO_CAMELLIA
# include <openssl/camellia.h>
#endif
#include <openssl/des.h>
#include "parse_local.h"
#include <openpgpsdk/packet-show.h>
#include <openpgpsdk/final.h>
//static int debug=0;
#ifndef ATTRIBUTE_UNUSED
#ifndef WIN32
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif // #ifndef WIN32
#endif /* ATTRIBUTE_UNUSED */
static void std_set_iv(ops_crypt_t *crypt,const unsigned char *iv)
{
memcpy(crypt->iv,iv,crypt->blocksize);
crypt->num=0;
}
static void std_set_key(ops_crypt_t *crypt,const unsigned char *key)
{ memcpy(crypt->key,key,crypt->keysize); }
static void std_resync(ops_crypt_t *decrypt)
{
if(decrypt->num == decrypt->blocksize)
return;
memmove(decrypt->civ+decrypt->blocksize-decrypt->num,decrypt->civ,
decrypt->num);
memcpy(decrypt->civ,decrypt->siv+decrypt->num,
decrypt->blocksize-decrypt->num);
decrypt->num=0;
}
static void std_finish(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
{
free(crypt->encrypt_key);
crypt->encrypt_key=NULL;
}
if (crypt->decrypt_key)
{
free(crypt->decrypt_key);
crypt->decrypt_key=NULL;
}
}
static void cast5_init(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(CAST_KEY));
CAST_set_key(crypt->encrypt_key,crypt->keysize,crypt->key);
crypt->decrypt_key=malloc(sizeof(CAST_KEY));
CAST_set_key(crypt->decrypt_key,crypt->keysize,crypt->key);
}
static void cast5_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
{ CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_ENCRYPT); }
static void cast5_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
{ CAST_ecb_encrypt(in,out,crypt->encrypt_key,CAST_DECRYPT); }
static void cast5_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
CAST_cfb64_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
CAST_ENCRYPT);
}
static void cast5_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
CAST_cfb64_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
CAST_DECRYPT);
}
#define TRAILER "","","","",0,NULL,NULL
static ops_crypt_t cast5=
{
OPS_SA_CAST5,
CAST_BLOCK,
CAST_KEY_LENGTH,
std_set_iv,
std_set_key,
cast5_init,
std_resync,
cast5_block_encrypt,
cast5_block_decrypt,
cast5_cfb_encrypt,
cast5_cfb_decrypt,
std_finish,
TRAILER
};
#ifndef OPENSSL_NO_IDEA
static void idea_init(ops_crypt_t *crypt)
{
assert(crypt->keysize == IDEA_KEY_LENGTH);
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE));
// note that we don't invert the key when decrypting for CFB mode
idea_set_encrypt_key(crypt->key,crypt->encrypt_key);
if (crypt->decrypt_key)
free(crypt->decrypt_key);
crypt->decrypt_key=malloc(sizeof(IDEA_KEY_SCHEDULE));
idea_set_decrypt_key(crypt->encrypt_key,crypt->decrypt_key);
}
static void idea_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
{ idea_ecb_encrypt(in,out,crypt->encrypt_key); }
static void idea_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
{ idea_ecb_encrypt(in,out,crypt->decrypt_key); }
static void idea_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
idea_cfb64_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
CAST_ENCRYPT);
}
static void idea_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
idea_cfb64_encrypt(in,out,count,
crypt->decrypt_key, crypt->iv, (int *)&crypt->num,
CAST_DECRYPT);
}
static const ops_crypt_t idea=
{
OPS_SA_IDEA,
IDEA_BLOCK,
IDEA_KEY_LENGTH,
std_set_iv,
std_set_key,
idea_init,
std_resync,
idea_block_encrypt,
idea_block_decrypt,
idea_cfb_encrypt,
idea_cfb_decrypt,
std_finish,
TRAILER
};
#endif /* OPENSSL_NO_IDEA */
// AES with 128-bit key (AES)
#define KEYBITS_AES128 128
static void aes128_init(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(AES_KEY));
if (AES_set_encrypt_key(crypt->key,KEYBITS_AES128,crypt->encrypt_key))
fprintf(stderr,"aes128_init: Error setting encrypt_key\n");
if (crypt->decrypt_key)
free(crypt->decrypt_key);
crypt->decrypt_key=malloc(sizeof(AES_KEY));
if (AES_set_decrypt_key(crypt->key,KEYBITS_AES128,crypt->decrypt_key))
fprintf(stderr,"aes128_init: Error setting decrypt_key\n");
}
static void aes_block_encrypt(ops_crypt_t *crypt,void *out,const void *in)
{ AES_encrypt(in,out,crypt->encrypt_key); }
static void aes_block_decrypt(ops_crypt_t *crypt,void *out,const void *in)
{ AES_decrypt(in,out,crypt->decrypt_key); }
static void aes_cfb_encrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
AES_cfb128_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
AES_ENCRYPT);
}
static void aes_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count)
{
AES_cfb128_encrypt(in,out,count,
crypt->encrypt_key, crypt->iv, (int *)&crypt->num,
AES_DECRYPT);
}
static const ops_crypt_t aes128=
{
OPS_SA_AES_128,
AES_BLOCK_SIZE,
KEYBITS_AES128/8,
std_set_iv,
std_set_key,
aes128_init,
std_resync,
aes_block_encrypt,
aes_block_decrypt,
aes_cfb_encrypt,
aes_cfb_decrypt,
std_finish,
TRAILER
};
// AES with 256-bit key
#define KEYBITS_AES256 256
static void aes256_init(ops_crypt_t *crypt)
{
if (crypt->encrypt_key)
free(crypt->encrypt_key);
crypt->encrypt_key=malloc(sizeof(AES_KEY));
if (AES_set_encrypt_key(crypt->key,KEYBITS_AES256,crypt->encrypt_key))
fprintf(stderr,"aes256_init: Error setting encrypt_key\n");
if (crypt->decrypt_key)
free(crypt->decrypt_key);
crypt->decrypt_key=malloc(sizeof(AES_KEY));
if (AES_set_decrypt_key(crypt->key,KEYBITS_AES256,crypt->decrypt_key))
fprintf(stderr,"aes256_init: Error setting decrypt_key\n");
}
static const ops_crypt_t aes256=
{
OPS_SA_AES_256,
AES_BLOCK_SIZE,
KEYBITS_AES256/8,
std_set_iv,
std_set_key,
aes256_init,
std_resync,
aes_block_encrypt,
aes_block_decrypt,
aes_cfb_encrypt,
aes_cfb_decrypt,
std_finish,
TRAILER
};
#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)
{
DES_key_schedule *keys;
int n;
if (crypt->encrypt_key)
free(crypt->encrypt_key);
keys=crypt->encrypt_key=malloc(3*sizeof(DES_key_schedule));
for(n=0 ; n < 3 ; ++n)
DES_set_key((DES_cblock *)(crypt->key+n*8),&keys[n]);
}
static void tripledes_block_encrypt(ops_crypt_t *crypt,void *out,
const void *in)
{
DES_key_schedule *keys=crypt->encrypt_key;
DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_ENCRYPT);
}
static void tripledes_block_decrypt(ops_crypt_t *crypt,void *out,
const void *in)
{
DES_key_schedule *keys=crypt->encrypt_key;
DES_ecb3_encrypt((void *)in,out,&keys[0],&keys[1],&keys[2],DES_DECRYPT);
}
static void tripledes_cfb_encrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED,
void *out ATTRIBUTE_UNUSED,
const void *in ATTRIBUTE_UNUSED,
size_t count ATTRIBUTE_UNUSED)
{
DES_key_schedule *keys=crypt->encrypt_key;
DES_ede3_cfb64_encrypt(in,out,count,
&keys[0],&keys[1],&keys[2],
(DES_cblock *)crypt->iv, (int *)&crypt->num,
DES_ENCRYPT);
}
static void tripledes_cfb_decrypt(ops_crypt_t *crypt ATTRIBUTE_UNUSED,
void *out ATTRIBUTE_UNUSED,
const void *in ATTRIBUTE_UNUSED,
size_t count ATTRIBUTE_UNUSED)
{
DES_key_schedule *keys=crypt->encrypt_key;
DES_ede3_cfb64_encrypt(in,out,count,
&keys[0],&keys[1],&keys[2],
(DES_cblock *)crypt->iv, (int *)&crypt->num,
DES_DECRYPT);
}
static const ops_crypt_t tripledes=
{
OPS_SA_TRIPLEDES,
8,
24,
std_set_iv,
std_set_key,
tripledes_init,
std_resync,
tripledes_block_encrypt,
tripledes_block_decrypt,
tripledes_cfb_encrypt,
tripledes_cfb_decrypt,
std_finish,
TRAILER
};
static const ops_crypt_t *get_proto(ops_symmetric_algorithm_t alg)
{
switch(alg)
{
case OPS_SA_CAST5:
return &cast5;
#ifndef OPENSSL_NO_IDEA
case OPS_SA_IDEA:
return &idea;
#endif /* OPENSSL_NO_IDEA */
case OPS_SA_AES_128:
return &aes128;
case OPS_SA_AES_256:
return &aes256;
#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));
// assert(0);
}
return NULL;
}
int ops_crypt_any(ops_crypt_t *crypt,ops_symmetric_algorithm_t alg)
{
const ops_crypt_t *ptr=get_proto(alg);
if (ptr)
{
*crypt=*ptr;
return 1;
}
else
{
memset(crypt,'\0',sizeof *crypt);
return 0;
}
}
unsigned ops_block_size(ops_symmetric_algorithm_t alg)
{
const ops_crypt_t *p=get_proto(alg);
if(!p)
return 0;
return p->blocksize;
}
unsigned ops_key_size(ops_symmetric_algorithm_t alg)
{
const ops_crypt_t *p=get_proto(alg);
if(!p)
return 0;
return p->keysize;
}
void ops_encrypt_init(ops_crypt_t * encrypt)
{
// \todo should there be a separate ops_encrypt_init?
ops_decrypt_init(encrypt);
}
void ops_decrypt_init(ops_crypt_t *decrypt)
{
decrypt->base_init(decrypt);
decrypt->block_encrypt(decrypt,decrypt->siv,decrypt->iv);
memcpy(decrypt->civ,decrypt->siv,decrypt->blocksize);
decrypt->num=0;
}
size_t ops_decrypt_se
(ops_crypt_t *decrypt,void *out_,const void *in_,
size_t count)
{
unsigned char *out=out_;
const unsigned char *in=in_;
int saved=count;
/* in order to support v3's weird resyncing we have to implement CFB mode
ourselves */
while(count-- > 0)
{
unsigned char t;
if(decrypt->num == decrypt->blocksize)
{
memcpy(decrypt->siv,decrypt->civ,decrypt->blocksize);
decrypt->block_decrypt(decrypt,decrypt->civ,decrypt->civ);
decrypt->num=0;
}
t=decrypt->civ[decrypt->num];
*out++=t^(decrypt->civ[decrypt->num++]=*in++);
}
return saved;
}
size_t ops_encrypt_se(ops_crypt_t *encrypt,void *out_,const void *in_,
size_t count)
{
unsigned char *out=out_;
const unsigned char *in=in_;
int saved=count;
/* in order to support v3's weird resyncing we have to implement CFB mode
ourselves */
while(count-- > 0)
{
if(encrypt->num == encrypt->blocksize)
{
memcpy(encrypt->siv,encrypt->civ,encrypt->blocksize);
encrypt->block_encrypt(encrypt,encrypt->civ,encrypt->civ);
encrypt->num=0;
}
encrypt->civ[encrypt->num]=*out++=encrypt->civ[encrypt->num]^*in++;
++encrypt->num;
}
return saved;
}
/**
\ingroup HighLevel_Supported
\brief Is this Symmetric Algorithm supported?
\param alg Symmetric Algorithm to check
\return ops_true if supported; else ops_false
*/
ops_boolean_t ops_is_sa_supported(ops_symmetric_algorithm_t alg)
{
switch (alg)
{
case OPS_SA_AES_128:
case OPS_SA_AES_256:
case OPS_SA_CAMELLIA_128:
case OPS_SA_CAMELLIA_192:
case OPS_SA_CAMELLIA_256:
case OPS_SA_CAST5:
case OPS_SA_TRIPLEDES:
#ifndef OPENSSL_NO_IDEA
case OPS_SA_IDEA:
#endif
return ops_true;
break;
default:
fprintf(stderr,"\nWarning: %s not supported\n",
ops_show_symmetric_algorithm(alg));
return ops_false;
}
}
size_t ops_encrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_,
size_t count)
{
if (!ops_is_sa_supported(crypt->algorithm))
return -1;
crypt->cfb_encrypt(crypt, out_, in_, count);
// \todo test this number was encrypted
return count;
}
size_t ops_decrypt_se_ip(ops_crypt_t *crypt,void *out_,const void *in_,
size_t count)
{
if (!ops_is_sa_supported(crypt->algorithm))
return -1;
crypt->cfb_decrypt(crypt, out_, in_, count);
// \todo check this number was in fact decrypted
return count;
}
// EOF

View File

@ -0,0 +1,223 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_TYPES_H
#define OPS_TYPES_H
/** Special type for intermediate function casting, avoids warnings on
some platforms
*/
typedef void (*ops_void_fptr)(void);
#define ops_fcast(f) ((ops_void_fptr)f)
/** ops_map_t
*/
typedef struct
{
int type;
char *string;
} ops_map_t;
/** Boolean type */
typedef unsigned ops_boolean_t;
/** ops_content_tag_t */
/* PTag Content Tags */
/***************************/
/** Package Tags (aka Content Tags) and signature subpacket types.
* This enumerates all rfc-defined packet tag values and the
* signature subpacket type values that we understand.
*
* \see RFC4880 4.3
* \see RFC4880 5.2.3.1
*/
#ifndef __cplusplus
typedef enum ops_content_tag_t ops_content_tag_t ;
#endif
enum ops_content_tag_t
{
OPS_PTAG_CT_RESERVED = 0, /*!< Reserved - a packet tag must not have this value */
OPS_PTAG_CT_PK_SESSION_KEY = 1, /*!< Public-Key Encrypted Session Key Packet */
OPS_PTAG_CT_SIGNATURE = 2, /*!< Signature Packet */
OPS_PTAG_CT_SK_SESSION_KEY = 3, /*!< Symmetric-Key Encrypted Session Key Packet */
OPS_PTAG_CT_ONE_PASS_SIGNATURE = 4, /*!< One-Pass Signature Packet */
OPS_PTAG_CT_SECRET_KEY = 5, /*!< Secret Key Packet */
OPS_PTAG_CT_PUBLIC_KEY = 6, /*!< Public Key Packet */
OPS_PTAG_CT_SECRET_SUBKEY = 7, /*!< Secret Subkey Packet */
OPS_PTAG_CT_COMPRESSED = 8, /*!< Compressed Data Packet */
OPS_PTAG_CT_SE_DATA = 9, /*!< Symmetrically Encrypted Data Packet */
OPS_PTAG_CT_MARKER =10, /*!< Marker Packet */
OPS_PTAG_CT_LITERAL_DATA =11, /*!< Literal Data Packet */
OPS_PTAG_CT_TRUST =12, /*!< Trust Packet */
OPS_PTAG_CT_USER_ID =13, /*!< User ID Packet */
OPS_PTAG_CT_PUBLIC_SUBKEY =14, /*!< Public Subkey Packet */
OPS_PTAG_CT_RESERVED2 =15, /*!< reserved */
OPS_PTAG_CT_RESERVED3 =16, /*!< reserved */
OPS_PTAG_CT_USER_ATTRIBUTE =17, /*!< User Attribute Packet */
OPS_PTAG_CT_SE_IP_DATA =18, /*!< Sym. Encrypted and Integrity Protected Data Packet */
OPS_PTAG_CT_MDC =19, /*!< Modification Detection Code Packet */
OPS_PARSER_PTAG =0x100, /*!< Internal Use: The packet is the "Packet Tag" itself - used when
callback sends back the PTag. */
OPS_PTAG_RAW_SS =0x101, /*!< Internal Use: content is raw sig subtag */
OPS_PTAG_SS_ALL =0x102, /*!< Internal Use: select all subtags */
OPS_PARSER_PACKET_END =0x103,
/* signature subpackets (0x200-2ff) (type+0x200) */
/* only those we can parse are listed here */
OPS_PTAG_SIGNATURE_SUBPACKET_BASE =0x200, /*!< Base for signature subpacket types - All signature type
values are relative to this value. */
OPS_PTAG_SS_CREATION_TIME =0x200+2, /*!< signature creation time */
OPS_PTAG_SS_EXPIRATION_TIME =0x200+3, /*!< signature expiration time */
OPS_PTAG_SS_EXPORTABLE_CERTIFICATION =0x200+4, /*!< exportable certification */
OPS_PTAG_SS_TRUST =0x200+5, /*!< trust signature */
OPS_PTAG_SS_REGEXP =0x200+6, /*!< regular expression */
OPS_PTAG_SS_REVOCABLE =0x200+7, /*!< revocable */
OPS_PTAG_SS_KEY_EXPIRATION_TIME =0x200+9, /*!< key expiration time */
OPS_PTAG_SS_RESERVED =0x200+10, /*!< reserved */
OPS_PTAG_SS_PREFERRED_SKA =0x200+11, /*!< preferred symmetric algorithms */
OPS_PTAG_SS_REVOCATION_KEY =0x200+12, /*!< revocation key */
OPS_PTAG_SS_ISSUER_KEY_ID =0x200+16, /*!< issuer key ID */
OPS_PTAG_SS_NOTATION_DATA =0x200+20, /*!< notation data */
OPS_PTAG_SS_PREFERRED_HASH =0x200+21, /*!< preferred hash algorithms */
OPS_PTAG_SS_PREFERRED_COMPRESSION =0x200+22, /*!< preferred compression algorithms */
OPS_PTAG_SS_KEY_SERVER_PREFS =0x200+23, /*!< key server preferences */
OPS_PTAG_SS_PREFERRED_KEY_SERVER =0x200+24, /*!< Preferred Key Server */
OPS_PTAG_SS_PRIMARY_USER_ID =0x200+25, /*!< primary User ID */
OPS_PTAG_SS_POLICY_URI =0x200+26, /*!< Policy URI */
OPS_PTAG_SS_KEY_FLAGS =0x200+27, /*!< key flags */
OPS_PTAG_SS_SIGNERS_USER_ID =0x200+28, /*!< Signer's User ID */
OPS_PTAG_SS_REVOCATION_REASON =0x200+29, /*!< reason for revocation */
OPS_PTAG_SS_FEATURES =0x200+30, /*!< features */
OPS_PTAG_SS_SIGNATURE_TARGET =0x200+31, /*!< signature target */
OPS_PTAG_SS_EMBEDDED_SIGNATURE=0x200+32, /*!< embedded signature */
OPS_PTAG_SS_USERDEFINED00 =0x200+100, /*!< internal or user-defined */
OPS_PTAG_SS_USERDEFINED01 =0x200+101,
OPS_PTAG_SS_USERDEFINED02 =0x200+102,
OPS_PTAG_SS_USERDEFINED03 =0x200+103,
OPS_PTAG_SS_USERDEFINED04 =0x200+104,
OPS_PTAG_SS_USERDEFINED05 =0x200+105,
OPS_PTAG_SS_USERDEFINED06 =0x200+106,
OPS_PTAG_SS_USERDEFINED07 =0x200+107,
OPS_PTAG_SS_USERDEFINED08 =0x200+108,
OPS_PTAG_SS_USERDEFINED09 =0x200+109,
OPS_PTAG_SS_USERDEFINED10 =0x200+110,
/* pseudo content types */
OPS_PTAG_CT_LITERAL_DATA_HEADER =0x300,
OPS_PTAG_CT_LITERAL_DATA_BODY =0x300+1,
OPS_PTAG_CT_SIGNATURE_HEADER =0x300+2,
OPS_PTAG_CT_SIGNATURE_FOOTER =0x300+3,
OPS_PTAG_CT_ARMOUR_HEADER =0x300+4,
OPS_PTAG_CT_ARMOUR_TRAILER =0x300+5,
OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER =0x300+6,
OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY =0x300+7,
OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER=0x300+8,
OPS_PTAG_CT_UNARMOURED_TEXT =0x300+9,
OPS_PTAG_CT_ENCRYPTED_SECRET_KEY =0x300+10, // In this case the algorithm specific fields will not be initialised
OPS_PTAG_CT_SE_DATA_HEADER =0x300+11,
OPS_PTAG_CT_SE_DATA_BODY =0x300+12,
OPS_PTAG_CT_SE_IP_DATA_HEADER =0x300+13,
OPS_PTAG_CT_SE_IP_DATA_BODY =0x300+14,
OPS_PTAG_CT_ENCRYPTED_PK_SESSION_KEY=0x300+15,
/* commands to the callback */
OPS_PARSER_CMD_GET_SK_PASSPHRASE =0x400,
OPS_PARSER_CMD_GET_SECRET_KEY =0x400+1,
OPS_PARSER_CMD_GET_SK_PASSPHRASE_PREV_WAS_BAD =0x400+2,
/* Errors */
OPS_PARSER_ERROR =0x500, /*!< Internal Use: Parser Error */
OPS_PARSER_ERRCODE =0x500+1, /*! < Internal Use: Parser Error with errcode returned */
};
/** Used to specify whether subpackets should be returned raw, parsed or ignored.
*/
enum ops_parse_type_t
{
OPS_PARSE_RAW, /*!< Callback Raw */
OPS_PARSE_PARSED, /*!< Callback Parsed */
OPS_PARSE_IGNORE, /*!< Don't callback */
};
typedef struct _ops_crypt_t ops_crypt_t;
/** ops_hash_t */
typedef struct _ops_hash_t ops_hash_t;
/**
keep both ops_content_tag_t and ops_packet_tag_t because we might
want to introduce some bounds checking i.e. is this really a valid value
for a packet tag?
*/
typedef enum ops_content_tag_t ops_packet_tag_t;
/** SS types are a subset of all content types.
*/
typedef enum ops_content_tag_t ops_ss_type_t;
/* typedef enum ops_sig_type_t ops_sig_type_t; */
/** Revocation Reason type */
typedef unsigned char ops_ss_rr_code_t;
/** ops_parse_type_t */
/** 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 */
typedef struct ops_parser_content_t ops_parser_content_t;
/** Reader Flags */
/*
typedef enum
{
OPS_RETURN_LENGTH=1,
} ops_reader_flags_t;
typedef enum ops_reader_ret_t ops_reader_ret_t;
*/
/** Writer flags */
typedef enum
{
OPS_WF_DUMMY,
} ops_writer_flags_t;
/**
* \ingroup Create
* Contains the required information about how to write
*/
typedef struct ops_create_info ops_create_info_t;
#endif

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/util.h>
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/crypto.h>
#include <openpgpsdk/create.h>
#include <openpgpsdk/errors.h>
#include <stdio.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <string.h>
#include <openpgpsdk/final.h>
/**
* Searches the given map for the given type.
* Returns a human-readable descriptive string if found,
* returns NULL if not found
*
* It is the responsibility of the calling function to handle the
* error case sensibly (i.e. don't just print out the return string.
*
*/
static char *str_from_map_or_null(int type, ops_map_t *map)
{
ops_map_t *row;
for ( row=map; row->string != NULL; row++ )
if (row->type == type)
return row->string;
return NULL;
}
/**
* \ingroup Core_Print
*
* Searches the given map for the given type.
* Returns a readable string if found, "Unknown" if not.
*/
char *ops_str_from_map(int type, ops_map_t *map)
{
char *str;
str=str_from_map_or_null(type,map);
if (str)
return(str);
else
return("Unknown");
}
void hexdump(const unsigned char *src,size_t length)
{
while(length--)
printf("%02X",*src++);
}
/**
* \ingroup HighLevel_Functions
* \brief Initialises OpenPGP::SDK. To be called before any other OPS function.
*
* Initialises OpenPGP::SDK and the underlying openssl library.
*/
void ops_init(void)
{
ops_crypto_init();
}
/**
* \ingroup HighLevel_Functions
* \brief Closes down OpenPGP::SDK.
*
* Close down OpenPGP:SDK, release any resources under the control of
* the library. No OpenPGP:SDK function other than ops_init() should
* be called after this function.
*/
void ops_finish(void)
{
ops_crypto_finish();
}
/**
\ingroup HighLevel_Misc
\brief mallocs and zeros memory
\param n Number of bytes to be alloc-ed.
\return Pointer to new memory.
\note Should be freed after use with free().
*/
void *ops_mallocz(size_t n)
{
void *m=malloc(n);
memset(m,'\0',n);
return m;
}
typedef struct
{
unsigned short sum;
} sum16_arg_t;
static int sum16_reader(void *dest_,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,ops_parse_cb_info_t *cbinfo)
{
const unsigned char *dest=dest_;
sum16_arg_t *arg=ops_reader_get_arg(rinfo);
int r=ops_stacked_read(dest_,length,errors,rinfo,cbinfo);
int n;
if(r < 0)
return r;
for(n=0 ; n < r ; ++n)
arg->sum=(arg->sum+dest[n])&0xffff;
return r;
}
static void sum16_destroyer(ops_reader_info_t *rinfo)
{ free(ops_reader_get_arg(rinfo)); }
/**
\ingroup Internal_Readers_Sum16
\param pinfo Parse settings
*/
void ops_reader_push_sum16(ops_parse_info_t *pinfo)
{
sum16_arg_t *arg=ops_mallocz(sizeof *arg);
ops_reader_push(pinfo,sum16_reader,sum16_destroyer,arg);
}
/**
\ingroup Internal_Readers_Sum16
\param pinfo Parse settings
\return sum
*/
unsigned short ops_reader_pop_sum16(ops_parse_info_t *pinfo)
{
sum16_arg_t *arg=ops_reader_get_arg(ops_parse_get_rinfo(pinfo));
unsigned short sum=arg->sum;
ops_reader_pop(pinfo);
free(arg);
return sum;
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_UTIL_H
#define OPS_UTIL_H
#include "openpgpsdk/types.h"
#include "openpgpsdk/create.h"
#include "openpgpsdk/packet-parse.h"
#include <stdlib.h>
#define ops_false 0
#define ops_true 1
void hexdump(const unsigned char *src,size_t length);
/*
* These macros code ensures that you are casting what you intend to cast.
* It works because in "a ? b : c", b and c must have the same type.
* This is a copy of the macro defined in openssl/asn1.h.
*/
#ifndef CHECKED_PTR_OF
#define CHECKED_PTR_OF(type, p) ((void*) (1 ? p : (type *)0))
#endif
#define CHECKED_INSTANCE_OF(type, p) (1 ? p : (type)0)
#define DECONST(type,p) ((type *)CHECKED_PTR_OF(const type, p))
/* number of elements in an array */
#define OPS_ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
void *ops_mallocz(size_t n);
#endif

View File

@ -0,0 +1,826 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <openpgpsdk/packet-parse.h>
#include <openpgpsdk/packet-show.h>
#include <openpgpsdk/keyring.h>
#include "keyring_local.h"
#include "parse_local.h"
#include <openpgpsdk/util.h>
#include <openpgpsdk/armour.h>
#include <openpgpsdk/signature.h>
#include <openpgpsdk/memory.h>
#include <openpgpsdk/validate.h>
#include <openpgpsdk/readerwriter.h>
#include <assert.h>
#include <string.h>
#include <openpgpsdk/final.h>
static int debug=0;
static ops_boolean_t check_binary_signature(const unsigned len,
const unsigned char *data,
const ops_signature_t *sig,
const ops_public_key_t *signer __attribute__((unused)))
{
// Does the signed hash match the given hash?
int n=0;
ops_hash_t hash;
unsigned char hashout[OPS_MAX_HASH_SIZE];
unsigned char trailer[6];
unsigned int hashedlen;
//common_init_signature(&hash,sig);
ops_hash_any(&hash,sig->info.hash_algorithm);
hash.init(&hash);
hash.add(&hash,data,len);
switch (sig->info.version)
{
case OPS_V3:
trailer[0]=sig->info.type;
trailer[1]=sig->info.creation_time >> 24;
trailer[2]=sig->info.creation_time >> 16;
trailer[3]=sig->info.creation_time >> 8;
trailer[4]=sig->info.creation_time;
hash.add(&hash,&trailer[0],5);
break;
case OPS_V4:
hash.add(&hash,sig->info.v4_hashed_data,sig->info.v4_hashed_data_length);
trailer[0]=0x04; // version
trailer[1]=0xFF;
hashedlen=sig->info.v4_hashed_data_length;
trailer[2]=hashedlen >> 24;
trailer[3]=hashedlen >> 16;
trailer[4]=hashedlen >> 8;
trailer[5]=hashedlen;
hash.add(&hash,&trailer[0],6);
break;
default:
fprintf(stderr,"Invalid signature version %d\n", sig->info.version);
return ops_false;
}
n=hash.finish(&hash,hashout);
// return ops_false;
return ops_check_signature(hashout,n,sig,signer);
}
static int keydata_reader(void *dest,size_t length,ops_error_t **errors,
ops_reader_info_t *rinfo,
ops_parse_cb_info_t *cbinfo)
{
validate_reader_arg_t *arg=ops_reader_get_arg(rinfo);
OPS_USED(errors);
OPS_USED(cbinfo);
if(arg->offset == arg->key->packets[arg->packet].length)
{
++arg->packet;
arg->offset=0;
}
if(arg->packet == arg->key->npackets)
return 0;
// we should never be asked to cross a packet boundary in a single read
assert(arg->key->packets[arg->packet].length >= arg->offset+length);
memcpy(dest,&arg->key->packets[arg->packet].raw[arg->offset],length);
arg->offset+=length;
return length;
}
static void free_signature_info(ops_signature_info_t *sig,int n)
{
int i ;
for(i=0;i<n;++i)
free (sig[i].v4_hashed_data);
free (sig);
}
static void copy_signature_info(ops_signature_info_t* dst, const ops_signature_info_t* src)
{
memcpy(dst,src,sizeof *src);
dst->v4_hashed_data=ops_mallocz(src->v4_hashed_data_length);
memcpy(dst->v4_hashed_data,src->v4_hashed_data,src->v4_hashed_data_length);
}
static void add_sig_to_valid_list(ops_validate_result_t * result, const ops_signature_info_t* sig)
{
size_t newsize;
size_t start;
// increment count
++result->valid_count;
// increase size of array
newsize=(sizeof *sig) * result->valid_count;
if (!result->valid_sigs)
result->valid_sigs=malloc(newsize);
else
result->valid_sigs=realloc(result->valid_sigs, newsize);
// copy key ptr to array
copy_signature_info(&result->valid_sigs[result->valid_count-1],sig);
}
static void add_sig_to_invalid_list(ops_validate_result_t * result, const ops_signature_info_t *sig)
{
size_t newsize;
size_t start;
// increment count
++result->invalid_count;
// increase size of array
newsize=(sizeof *sig) * result->invalid_count;
if (!result->invalid_sigs)
result->invalid_sigs=malloc(newsize);
else
result->invalid_sigs=realloc(result->invalid_sigs, newsize);
// copy key ptr to array
copy_signature_info(&result->invalid_sigs[result->invalid_count-1],sig);
}
static void add_sig_to_unknown_list(ops_validate_result_t * result, const ops_signature_info_t *sig)
{
size_t newsize;
size_t start;
// increment count
++result->unknown_signer_count;
// increase size of array
newsize=(sizeof *sig) * result->unknown_signer_count;
if (!result->unknown_sigs)
result->unknown_sigs=malloc(newsize);
else
result->unknown_sigs=realloc(result->unknown_sigs, newsize);
// copy key id to array
copy_signature_info(&result->unknown_sigs[result->unknown_signer_count-1],sig);
}
ops_parse_cb_return_t
ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
const ops_parser_content_union_t *content=&content_->content;
validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
const ops_keydata_t *signer;
ops_boolean_t valid=ops_false;
if (debug)
printf("%s\n",ops_show_packet_tag(content_->tag));
switch(content_->tag)
{
case OPS_PTAG_CT_PUBLIC_KEY:
assert(arg->pkey.version == 0);
arg->pkey=content->public_key;
return OPS_KEEP_MEMORY;
case OPS_PTAG_CT_PUBLIC_SUBKEY:
if(arg->subkey.version)
ops_public_key_free(&arg->subkey);
arg->subkey=content->public_key;
return OPS_KEEP_MEMORY;
case OPS_PTAG_CT_SECRET_KEY:
arg->skey=content->secret_key;
arg->pkey=arg->skey.public_key;
return OPS_KEEP_MEMORY;
case OPS_PTAG_CT_USER_ID:
if(arg->user_id.user_id)
ops_user_id_free(&arg->user_id);
arg->user_id=content->user_id;
arg->last_seen=ID;
return OPS_KEEP_MEMORY;
case OPS_PTAG_CT_USER_ATTRIBUTE:
assert(content->user_attribute.data.len);
printf("user attribute, length=%d\n",(int)content->user_attribute.data.len);
if(arg->user_attribute.data.len)
ops_user_attribute_free(&arg->user_attribute);
arg->user_attribute=content->user_attribute;
arg->last_seen=ATTRIBUTE;
return OPS_KEEP_MEMORY;
case OPS_PTAG_CT_SIGNATURE: // V3 sigs
case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs
if(debug)
{
printf(" type=%02x signer_id=",content->signature.info.type);
hexdump(content->signature.info.signer_id,
sizeof content->signature.info.signer_id);
printf("\n");
}
signer=ops_keyring_find_key_by_id(arg->keyring,
content->signature.info.signer_id);
if(!signer)
{
add_sig_to_unknown_list(arg->result, &content->signature.info);
break;
}
switch(content->signature.info.type)
{
case OPS_CERT_GENERIC:
case OPS_CERT_PERSONA:
case OPS_CERT_CASUAL:
case OPS_CERT_POSITIVE:
case OPS_SIG_REV_CERT:
if(arg->last_seen == ID)
valid=ops_check_user_id_certification_signature(&arg->pkey,
&arg->user_id,
&content->signature,
ops_get_public_key_from_data(signer),
arg->rarg->key->packets[arg->rarg->packet].raw);
else
valid=ops_check_user_attribute_certification_signature(&arg->pkey,
&arg->user_attribute,
&content->signature,
ops_get_public_key_from_data(signer),
arg->rarg->key->packets[arg->rarg->packet].raw);
break;
case OPS_SIG_SUBKEY:
// XXX: we should also check that the signer is the key we are validating, I think.
valid=ops_check_subkey_signature(&arg->pkey,&arg->subkey,
&content->signature,
ops_get_public_key_from_data(signer),
arg->rarg->key->packets[arg->rarg->packet].raw);
break;
case OPS_SIG_DIRECT:
valid=ops_check_direct_signature(&arg->pkey,&content->signature,
ops_get_public_key_from_data(signer),
arg->rarg->key->packets[arg->rarg->packet].raw);
break;
case OPS_SIG_STANDALONE:
case OPS_SIG_PRIMARY:
case OPS_SIG_REV_KEY:
case OPS_SIG_REV_SUBKEY:
case OPS_SIG_TIMESTAMP:
case OPS_SIG_3RD_PARTY:
OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
"Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type);
break;
default:
OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
"Unexpected signature type 0x%02x\n", content->signature.info.type);
}
if(valid)
{
// printf(" validated\n");
//++arg->result->valid_count;
add_sig_to_valid_list(arg->result, &content->signature.info);
}
else
{
OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature");
// printf(" BAD SIGNATURE\n");
// ++arg->result->invalid_count;
add_sig_to_invalid_list(arg->result, &content->signature.info);
}
break;
// ignore these
case OPS_PARSER_PTAG:
case OPS_PTAG_CT_SIGNATURE_HEADER:
case OPS_PARSER_PACKET_END:
case OPS_PTAG_CT_TRUST:
break;
case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
if (arg->cb_get_passphrase)
{
return arg->cb_get_passphrase(content_,cbinfo);
}
break;
default:
fprintf(stderr,"unexpected tag=0x%x\n",content_->tag);
assert(0);
break;
}
return OPS_RELEASE_MEMORY;
}
ops_parse_cb_return_t
validate_data_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
{
const ops_parser_content_union_t *content=&content_->content;
validate_data_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
const ops_keydata_t *signer;
ops_boolean_t valid=ops_false;
ops_memory_t* mem=NULL;
if (debug)
printf("%s\n",ops_show_packet_tag(content_->tag));
switch(content_->tag)
{
case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
// ignore - this gives us the "Armor Header" line "Hash: SHA1" or similar
break;
case OPS_PTAG_CT_LITERAL_DATA_HEADER:
// ignore
break;
case OPS_PTAG_CT_LITERAL_DATA_BODY:
arg->literal_data_body=content->literal_data_body;
arg->use=LITERAL_DATA;
return OPS_KEEP_MEMORY;
break;
case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
arg->signed_cleartext_body=content->signed_cleartext_body;
arg->use=SIGNED_CLEARTEXT;
return OPS_KEEP_MEMORY;
break;
case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
// this gives us an ops_hash_t struct
break;
case OPS_PTAG_CT_SIGNATURE: // V3 sigs
case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs
if (debug)
{
printf("\n*** hashed data:\n");
unsigned int zzz=0;
for (zzz=0; zzz<content->signature.info.v4_hashed_data_length; zzz++)
printf("0x%02x ", content->signature.info.v4_hashed_data[zzz]);
printf("\n");
printf(" type=%02x signer_id=",content->signature.info.type);
hexdump(content->signature.info.signer_id,
sizeof content->signature.info.signer_id);
}
signer=ops_keyring_find_key_by_id(arg->keyring,
content->signature.info.signer_id);
if(!signer)
{
OPS_ERROR(errors,OPS_E_V_UNKNOWN_SIGNER,"Unknown Signer");
add_sig_to_unknown_list(arg->result, &content->signature.info);
break;
}
mem=ops_memory_new();
ops_memory_init(mem,128);
switch(content->signature.info.type)
{
case OPS_SIG_BINARY:
case OPS_SIG_TEXT:
switch(arg->use)
{
case LITERAL_DATA:
ops_memory_add(mem,
arg->literal_data_body.data,
arg->literal_data_body.length);
break;
case SIGNED_CLEARTEXT:
ops_memory_add(mem,
arg->signed_cleartext_body.data,
arg->signed_cleartext_body.length);
break;
default:
OPS_ERROR_1(errors,OPS_E_UNIMPLEMENTED,"Unimplemented Sig Use %d", arg->use);
printf(" Unimplemented Sig Use %d\n", arg->use);
break;
}
valid=check_binary_signature(ops_memory_get_length(mem),
ops_memory_get_data(mem),
&content->signature,
ops_get_public_key_from_data(signer));
break;
default:
OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
"Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type);
break;
}
ops_memory_free(mem);
if(valid)
{
add_sig_to_valid_list(arg->result, &content->signature.info);
}
else
{
OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature");
add_sig_to_invalid_list(arg->result, &content->signature.info);
}
break;
// ignore these
case OPS_PARSER_PTAG:
case OPS_PTAG_CT_SIGNATURE_HEADER:
case OPS_PTAG_CT_ARMOUR_HEADER:
case OPS_PTAG_CT_ARMOUR_TRAILER:
case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
case OPS_PARSER_PACKET_END:
break;
default:
fprintf(stderr,"unexpected tag=0x%x\n",content_->tag);
assert(0);
break;
}
return OPS_RELEASE_MEMORY;
}
static void keydata_destroyer(ops_reader_info_t *rinfo)
{ free(ops_reader_get_arg(rinfo)); }
void ops_keydata_reader_set(ops_parse_info_t *pinfo,const ops_keydata_t *key)
{
validate_reader_arg_t *arg=malloc(sizeof *arg);
memset(arg,'\0',sizeof *arg);
arg->key=key;
arg->packet=0;
arg->offset=0;
ops_reader_set(pinfo,keydata_reader,keydata_destroyer,arg);
}
/**
* \ingroup HighLevel_Verify
* \brief Indicicates whether any errors were found
* \param result Validation result to check
* \return ops_false if any invalid signatures or unknown signers or no valid signatures; else ops_true
*/
ops_boolean_t validate_result_status(ops_validate_result_t* result)
{
if (result->invalid_count || result->unknown_signer_count || !result->valid_count)
return ops_false;
else
return ops_true;
}
/**
* \ingroup HighLevel_Verify
* \brief Validate all signatures on a single key against the given keyring
* \param result Where to put the result
* \param key Key to validate
* \param keyring Keyring to use for validation
* \param cb_get_passphrase Callback to use to get passphrase
* \return ops_true if all signatures OK; else ops_false
* \note It is the caller's responsiblity to free result after use.
* \sa ops_validate_result_free()
Example Code:
\code
void example(const ops_keydata_t* key, const ops_keyring_t *keyring)
{
ops_validate_result_t *result=NULL;
if (ops_validate_key_signatures(result, key, keyring, callback_cmd_get_passphrase_from_cmdline)==ops_true)
printf("OK");
else
printf("ERR");
printf("valid=%d, invalid=%d, unknown=%d\n",
result->valid_count,
result->invalid_count,
result->unknown_signer_count);
ops_validate_result_free(result);
}
\endcode
*/
ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,const ops_keydata_t *key,
const ops_keyring_t *keyring,
ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *)
)
{
ops_parse_info_t *pinfo;
validate_key_cb_arg_t carg;
memset(&carg,'\0',sizeof carg);
carg.result=result;
carg.cb_get_passphrase=cb_get_passphrase;
pinfo=ops_parse_info_new();
// ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED);
carg.keyring=keyring;
ops_parse_cb_set(pinfo,ops_validate_key_cb,&carg);
pinfo->rinfo.accumulate=ops_true;
ops_keydata_reader_set(pinfo,key);
// Note: Coverity incorrectly reports an error that carg.rarg
// is never used.
carg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
ops_parse(pinfo);
ops_public_key_free(&carg.pkey);
if(carg.subkey.version)
ops_public_key_free(&carg.subkey);
ops_user_id_free(&carg.user_id);
ops_user_attribute_free(&carg.user_attribute);
ops_parse_info_delete(pinfo);
/* if(carg.literal_data_body.data != NULL)
free(carg.literal_data_body.data) ; */
if (result->invalid_count || result->unknown_signer_count || !result->valid_count)
return ops_false;
else
return ops_true;
}
/**
\ingroup HighLevel_Verify
\param result Where to put the result
\param ring Keyring to use
\param cb_get_passphrase Callback to use to get passphrase
\note It is the caller's responsibility to free result after use.
\sa ops_validate_result_free()
*/
ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result,
const ops_keyring_t *ring,
ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *)
)
{
int n;
memset(result,'\0',sizeof *result);
for(n=0 ; n < ring->nkeys ; ++n)
ops_validate_key_signatures(result,&ring->keys[n],ring, cb_get_passphrase);
return validate_result_status(result);
}
/**
\ingroup HighLevel_Verify
\brief Frees validation result and associated memory
\param result Struct to be freed
\note Must be called after validation functions
*/
void ops_validate_result_free(ops_validate_result_t *result)
{
if (!result)
return;
if (result->valid_sigs)
free_signature_info(result->valid_sigs,result->valid_count);
if (result->invalid_sigs)
free_signature_info(result->invalid_sigs,result->invalid_count);
if (result->unknown_sigs)
free_signature_info(result->unknown_sigs,result->unknown_signer_count);
free(result);
result=NULL;
}
/**
\ingroup HighLevel_Verify
\brief Verifies the signatures in a signed file
\param result Where to put the result
\param filename Name of file to be validated
\param armoured Treat file as armoured, if set
\param keyring Keyring to use
\return ops_true if signatures validate successfully; ops_false if signatures fail or there are no signatures
\note After verification, result holds the details of all keys which
have passed, failed and not been recognised.
\note It is the caller's responsiblity to call ops_validate_result_free(result) after use.
Example code:
\code
void example(const char* filename, const int armoured, const ops_keyring_t* keyring)
{
ops_validate_result_t* result=ops_mallocz(sizeof *result);
if (ops_validate_file(result, filename, armoured, keyring)==ops_true)
{
printf("OK");
// look at result for details of keys with good signatures
}
else
{
printf("ERR");
// look at result for details of failed signatures or unknown signers
}
ops_validate_result_free(result);
}
\endcode
*/
ops_boolean_t ops_validate_file(ops_validate_result_t *result, const char* filename, const int armoured, const ops_keyring_t* keyring)
{
ops_parse_info_t *pinfo=NULL;
validate_data_cb_arg_t validate_arg;
int fd=0;
//
fd=ops_setup_file_read(&pinfo, filename, &validate_arg, validate_data_cb, ops_true);
if (fd < 0)
return ops_false;
// Set verification reader and handling options
memset(&validate_arg,'\0',sizeof validate_arg);
validate_arg.result=result;
validate_arg.keyring=keyring;
// Note: Coverity incorrectly reports an error that carg.rarg
// is never used.
validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
if (armoured)
ops_reader_push_dearmour(pinfo);
// Do the verification
ops_parse(pinfo);
if (debug)
{
printf("valid=%d, invalid=%d, unknown=%d\n",
result->valid_count,
result->invalid_count,
result->unknown_signer_count);
}
// Tidy up
if (armoured)
ops_reader_pop_dearmour(pinfo);
ops_teardown_file_read(pinfo, fd);
if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ;
return validate_result_status(result);
}
/**
\ingroup HighLevel_Verify
\brief Verifies the signatures in a ops_memory_t struct
\param result Where to put the result
\param mem Memory to be validated
\param armoured Treat data as armoured, if set
\param keyring Keyring to use
\return ops_true if signature validates successfully; ops_false if not
\note After verification, result holds the details of all keys which
have passed, failed and not been recognised.
\note It is the caller's responsiblity to call ops_validate_result_free(result) after use.
*/
ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring)
{
ops_parse_info_t *pinfo=NULL;
validate_data_cb_arg_t validate_arg;
//
ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true);
// Set verification reader and handling options
memset(&validate_arg,'\0',sizeof validate_arg);
validate_arg.result=result;
validate_arg.keyring=keyring;
// Note: Coverity incorrectly reports an error that carg.rarg
// is never used.
validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
if (armoured)
ops_reader_push_dearmour(pinfo);
// Do the verification
ops_parse(pinfo);
if (debug)
{
printf("valid=%d, invalid=%d, unknown=%d\n",
result->valid_count,
result->invalid_count,
result->unknown_signer_count);
}
// Tidy up
if (armoured)
ops_reader_pop_dearmour(pinfo);
ops_teardown_memory_read(pinfo, mem);
if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ;
if(validate_arg.signed_cleartext_body.data != NULL) free(validate_arg.signed_cleartext_body.data) ;
return validate_result_status(result);
}
/**
\ingroup HighLevel_Verify
\brief Verifies the signature in a detached signature data packet, given the literal data
\param literal_data Literal data that is signed
\param literal_data_length length of the literal data that is signed
\param signature_packet signature packet in binary PGP format
\param signature_packet_length length of the signature packet
\param signers_key Public key of the signer to check the signature for.
\return ops_true if signature validates successfully; ops_false if not
*/
ops_boolean_t ops_validate_detached_signature(const void *literal_data, unsigned int literal_data_length, const unsigned char *signature_packet, unsigned int signature_packet_length,const ops_keydata_t *signers_key)
{
ops_validate_result_t *result = (ops_validate_result_t*)ops_mallocz(sizeof(ops_validate_result_t));
ops_memory_t *mem = ops_memory_new() ;
ops_memory_add(mem,signature_packet,signature_packet_length) ;
ops_parse_info_t *pinfo=NULL;
validate_data_cb_arg_t validate_arg;
ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true);
// Set verification reader and handling options
ops_keyring_t tmp_keyring ;
tmp_keyring.nkeys = 1 ;
tmp_keyring.nkeys_allocated = 1 ;
tmp_keyring.keys = (ops_keydata_t *)signers_key ; // this is a const_cast, somehow
memset(&validate_arg,'\0',sizeof validate_arg);
validate_arg.result=result;
validate_arg.keyring=&tmp_keyring;
int length = literal_data_length ;
validate_arg.literal_data_body.data = (unsigned char *)malloc(length) ;
memcpy(validate_arg.literal_data_body.data, literal_data, length) ;
validate_arg.literal_data_body.length = length ;
// Note: Coverity incorrectly reports an error that carg.rarg
// is never used.
validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
//if (armoured)
// ops_reader_push_dearmour(pinfo);
// Do the verification
ops_parse(pinfo);
printf("valid=%d, invalid=%d, unknown=%d\n", result->valid_count, result->invalid_count, result->unknown_signer_count);
// Tidy up
//if (armoured)
// ops_reader_pop_dearmour(pinfo);
ops_teardown_memory_read(pinfo, mem);
ops_boolean_t res = validate_result_status(result);
ops_validate_result_free(result) ;
if(validate_arg.literal_data_body.data != NULL) free(validate_arg.literal_data_body.data) ;
if(validate_arg.signed_cleartext_body.data != NULL) free(validate_arg.signed_cleartext_body.data) ;
return res ;
}
// eof

View File

@ -0,0 +1,104 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
typedef struct
{
unsigned int valid_count;
ops_signature_info_t * valid_sigs;
unsigned int invalid_count;
ops_signature_info_t * invalid_sigs;
unsigned int unknown_signer_count;
ops_signature_info_t * unknown_sigs;
} ops_validate_result_t;
void ops_validate_result_free(ops_validate_result_t *result);
ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,
const ops_keydata_t* keydata,
const ops_keyring_t *ring,
ops_parse_cb_return_t cb (const ops_parser_content_t *, ops_parse_cb_info_t *));
ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result,
const ops_keyring_t *ring,
ops_parse_cb_return_t (const ops_parser_content_t *, ops_parse_cb_info_t *));
void ops_keydata_reader_set(ops_parse_info_t *pinfo,
const ops_keydata_t *key);
typedef struct
{
const ops_keydata_t *key;
unsigned packet;
unsigned offset;
} validate_reader_arg_t;
/** Struct used with the validate_key_cb callback */
typedef struct
{
ops_public_key_t pkey;
ops_public_key_t subkey;
ops_secret_key_t skey;
enum
{
ATTRIBUTE=1,
ID,
} last_seen;
ops_user_id_t user_id;
ops_user_attribute_t user_attribute;
unsigned char hash[OPS_MAX_HASH_SIZE];
const ops_keyring_t *keyring;
validate_reader_arg_t *rarg;
ops_validate_result_t *result;
ops_parse_cb_return_t (*cb_get_passphrase) (const ops_parser_content_t *, ops_parse_cb_info_t *);
} validate_key_cb_arg_t;
/** Struct use with the validate_data_cb callback */
typedef struct validate_data_cb_arg
{
enum
{
LITERAL_DATA,
SIGNED_CLEARTEXT
} use; /*<! this is set to indicate what kind of data we have */
ops_literal_data_body_t literal_data_body; /*<! Used to hold Literal Data */
ops_signed_cleartext_body_t signed_cleartext_body; /*<! Used to hold Signed Cleartext */
unsigned char hash[OPS_MAX_HASH_SIZE]; /*<! the hash */
const ops_keyring_t *keyring; /*<! keyring to use */
validate_reader_arg_t *rarg; /*<! reader-specific arg */
ops_validate_result_t *result; /*<! where to put the result */
} validate_data_cb_arg_t; /*<! used with validate_data_cb callback */
ops_boolean_t ops_check_signature(const unsigned char *hash,
unsigned length,
const ops_signature_t *sig,
const ops_public_key_t *signer);
ops_parse_cb_return_t
ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
ops_boolean_t ops_validate_file(ops_validate_result_t* result, const char* filename, const int armoured, const ops_keyring_t* keyring);
ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring);
ops_boolean_t ops_validate_detached_signature(const void *literal_data, unsigned int literal_data_length, const unsigned char *signature_packet, unsigned int signature_packet_length,const ops_keydata_t *signers_key) ;
// EOF

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define OPS_VERSION_MAJOR 0
/* Set to the version next to be released */
#define OPS_VERSION_MINOR 9
/* 0 for development version, 1 for release */
#define OPS_VERSION_RELEASE 1
#define OPS_VERSION ((OPS_VERSION_MAJOR << 16)+(OPS_VERSION_MINOR << 1)+OPS_VERSION_RELEASE)
#if OPS_VERSION_RELEASE
# define OPS_DEV_STRING ""
#else
# define OPS_DEV_STRING " (dev)"
#endif
#define OPS_VERSION_CAT(a,b) "OpenPGP:SDK v" #a "." #b OPS_DEV_STRING
#define OPS_VERSION_CAT2(a,b) OPS_VERSION_CAT(a,b)
#define OPS_VERSION_STRING OPS_VERSION_CAT2(OPS_VERSION_MAJOR,OPS_VERSION_MINOR)

View File

@ -0,0 +1,331 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
* This file contains the base functions used by the writers.
*/
#include <openssl/cast.h>
#include <openpgpsdk/armour.h>
#include <openpgpsdk/writer.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/memory.h>
#include <openpgpsdk/random.h>
#include <openpgpsdk/readerwriter.h>
#include "keyring_local.h"
#include <openpgpsdk/packet.h>
#include <openpgpsdk/util.h>
#include <openpgpsdk/std_print.h>
#include <string.h>
#include <assert.h>
#include <fcntl.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <openpgpsdk/final.h>
//static int debug=0;
/*
* return true if OK, otherwise false
*/
static ops_boolean_t base_write(const void *src,unsigned length,
ops_create_info_t *info)
{
return info->winfo.writer(src,length,&info->errors,&info->winfo);
}
/**
* \ingroup Core_WritePackets
*
* \param src
* \param length
* \param info
* \return 1 if OK, otherwise 0
*/
ops_boolean_t ops_write(const void *src,unsigned length,
ops_create_info_t *info)
{
return base_write(src,length,info);
}
/**
* \ingroup Core_WritePackets
* \param n
* \param length
* \param info
* \return ops_true if OK, otherwise ops_false
*/
ops_boolean_t ops_write_scalar(unsigned n,unsigned length,
ops_create_info_t *info)
{
while(length-- > 0)
{
unsigned char c[1];
c[0]=n >> (length*8);
if(!base_write(c,1,info))
return ops_false;
}
return ops_true;
}
/**
* \ingroup Core_WritePackets
* \param bn
* \param info
* \return 1 if OK, otherwise 0
*/
ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *info)
{
unsigned char buf[8192];
int bits=BN_num_bits(bn);
assert(bits <= 65535);
BN_bn2bin(bn,buf);
return ops_write_scalar(bits,2,info)
&& ops_write(buf,(bits+7)/8,info);
}
/**
* \ingroup Core_WritePackets
* \param tag
* \param info
* \return 1 if OK, otherwise 0
*/
ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *info)
{
unsigned char c[1];
c[0]=tag|OPS_PTAG_ALWAYS_SET|OPS_PTAG_NEW_FORMAT;
return base_write(c,1,info);
}
/**
* \ingroup Core_WritePackets
* \param length
* \param info
* \return 1 if OK, otherwise 0
*/
ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *info)
{
unsigned char c[2];
if(length < 192)
{
c[0]=length;
return base_write(c,1,info);
}
else if(length < 8384)
{
c[0]=((length-192) >> 8)+192;
c[1]=(length-192)%256;
return base_write(c,2,info);
}
return ops_write_scalar(0xff,1,info) && ops_write_scalar(length,4,info);
}
/* Note that we finalise from the top down, so we don't use writers below
* that have already been finalised
*/
ops_boolean_t writer_info_finalise(ops_error_t **errors,
ops_writer_info_t *winfo)
{
ops_boolean_t ret=ops_true;
if(winfo->finaliser)
{
ret=winfo->finaliser(errors,winfo);
winfo->finaliser=NULL;
}
if(winfo->next && !writer_info_finalise(errors,winfo->next))
{
winfo->finaliser=NULL;
return ops_false;
}
return ret;
}
void writer_info_delete(ops_writer_info_t *winfo)
{
// we should have finalised before deleting
assert(!winfo->finaliser);
if(winfo->next)
{
writer_info_delete(winfo->next);
free(winfo->next);
winfo->next=NULL;
}
if(winfo->destroyer)
{
winfo->destroyer(winfo);
winfo->destroyer=NULL;
}
winfo->writer=NULL;
}
/**
* \ingroup Core_Writers
*
* Set a writer in info. There should not be another writer set.
*
* \param info The info structure
* \param writer
* \param finaliser
* \param destroyer
* \param arg The argument for the writer and destroyer
*/
void ops_writer_set(ops_create_info_t *info,
ops_writer_t *writer,
ops_writer_finaliser_t *finaliser,
ops_writer_destroyer_t *destroyer,
void *arg)
{
assert(!info->winfo.writer);
info->winfo.writer=writer;
info->winfo.finaliser=finaliser;
info->winfo.destroyer=destroyer;
info->winfo.arg=arg;
}
/**
* \ingroup Core_Writers
*
* Push a writer in info. There must already be another writer set.
*
* \param info The info structure
* \param writer
* \param finaliser
* \param destroyer
* \param arg The argument for the writer and destroyer
*/
void ops_writer_push(ops_create_info_t *info,
ops_writer_t *writer,
ops_writer_finaliser_t *finaliser,
ops_writer_destroyer_t *destroyer,
void *arg)
{
ops_writer_info_t *copy=ops_mallocz(sizeof *copy);
assert(info->winfo.writer);
*copy=info->winfo;
info->winfo.next=copy;
info->winfo.writer=writer;
info->winfo.finaliser=finaliser;
info->winfo.destroyer=destroyer;
info->winfo.arg=arg;
}
void ops_writer_pop(ops_create_info_t *info)
{
ops_writer_info_t *next;
// Make sure the finaliser has been called.
assert(!info->winfo.finaliser);
// Make sure this is a stacked writer
assert(info->winfo.next);
if(info->winfo.destroyer)
info->winfo.destroyer(&info->winfo);
next=info->winfo.next;
info->winfo=*next;
free(next);
}
/**
* \ingroup Core_Writers
*
* Close the writer currently set in info.
*
* \param info The info structure
*/
ops_boolean_t ops_writer_close(ops_create_info_t *info)
{
ops_boolean_t ret=writer_info_finalise(&info->errors,&info->winfo);
writer_info_delete(&info->winfo);
return ret;
}
/**
* \ingroup Core_Writers
*
* Get the arg supplied to ops_create_info_set_writer().
*
* \param winfo The writer_info structure
* \return The arg
*/
void *ops_writer_get_arg(ops_writer_info_t *winfo)
{ return winfo->arg; }
/**
* \ingroup Core_Writers
*
* Write to the next writer down in the stack.
*
* \param src The data to write.
* \param length The length of src.
* \param errors A place to store errors.
* \param winfo The writer_info structure.
* \return Success - if ops_false, then errors should contain the error.
*/
ops_boolean_t ops_stacked_write(const void *src,unsigned length,
ops_error_t **errors,ops_writer_info_t *winfo)
{
return winfo->next->writer(src,length,errors,winfo->next);
}
/**
* \ingroup Core_Writers
*
* Free the arg. Many writers just have a malloc()ed lump of storage, this
* function releases it.
*
* \param winfo the info structure.
*/
void ops_writer_generic_destroyer(ops_writer_info_t *winfo)
{ free(ops_writer_get_arg(winfo)); }
/**
* \ingroup Core_Writers
*
* A writer that just writes to the next one down. Useful for when you
* want to insert just a finaliser into the stack.
*/
ops_boolean_t ops_writer_passthrough(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{ return ops_stacked_write(src,length,errors,winfo); }
// EOF

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef OPS_WRITER_H
#define OPS_WRITER_H
#include "types.h"
#include "packet.h"
#include "crypto.h"
#include "memory.h"
#include "errors.h"
#include "keyring.h"
/**
* \ingroup Create
* This struct contains the required information about one writer
*/
/**
* \ingroup Writer
* the writer function prototype
*/
typedef struct ops_writer_info ops_writer_info_t;
typedef ops_boolean_t ops_writer_t(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo);
typedef ops_boolean_t ops_writer_finaliser_t(ops_error_t **errors,
ops_writer_info_t *winfo);
typedef void ops_writer_destroyer_t(ops_writer_info_t *winfo);
/** Writer settings */
struct ops_writer_info
{
ops_writer_t *writer; /*!< the writer itself */
ops_writer_finaliser_t *finaliser; /*!< the writer's finaliser */
ops_writer_destroyer_t *destroyer; /*!< the writer's destroyer */
void *arg; /* writer-specific argument */
ops_writer_info_t *next; /*!< next writer in the stack */
};
void *ops_writer_get_arg(ops_writer_info_t *winfo);
ops_boolean_t ops_stacked_write(const void *src,unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo);
void ops_writer_set(ops_create_info_t *info,
ops_writer_t *writer,
ops_writer_finaliser_t *finaliser,
ops_writer_destroyer_t *destroyer,
void *arg);
void ops_writer_push(ops_create_info_t *info,
ops_writer_t *writer,
ops_writer_finaliser_t *finaliser,
ops_writer_destroyer_t *destroyer,
void *arg);
void ops_writer_pop(ops_create_info_t *info);
void ops_writer_generic_destroyer(ops_writer_info_t *winfo);
ops_boolean_t ops_writer_passthrough(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo);
void ops_writer_set_fd(ops_create_info_t *info,int fd);
ops_boolean_t ops_writer_close(ops_create_info_t *info);
ops_boolean_t ops_write(const void *src,unsigned length,
ops_create_info_t *opt);
ops_boolean_t ops_write_length(unsigned length,ops_create_info_t *opt);
ops_boolean_t ops_write_ptag(ops_content_tag_t tag,ops_create_info_t *opt);
ops_boolean_t ops_write_scalar(unsigned n,unsigned length,
ops_create_info_t *opt);
ops_boolean_t ops_write_mpi(const BIGNUM *bn,ops_create_info_t *opt);
ops_boolean_t ops_write_encrypted_mpi(const BIGNUM *bn, ops_crypt_t* crypt, ops_create_info_t *info);
void writer_info_delete(ops_writer_info_t *winfo);
ops_boolean_t writer_info_finalise(ops_error_t **errors, ops_writer_info_t *winfo);
#endif

View File

@ -0,0 +1,517 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <assert.h>
#include <string.h>
#include <openpgpsdk/armour.h>
#include <openpgpsdk/create.h>
#include <openpgpsdk/signature.h>
#include <openpgpsdk/version.h>
#include <openpgpsdk/final.h>
static int debug=0;
#define LINE_LENGTH 64
static const char newline[] = "\r\n";
/**
* \struct dash_escaped_arg_t
*/
typedef struct
{
ops_boolean_t seen_nl:1;
ops_boolean_t seen_cr:1;
ops_create_signature_t *sig;
ops_memory_t *trailing;
} dash_escaped_arg_t;
static ops_boolean_t dash_escaped_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
dash_escaped_arg_t *arg=ops_writer_get_arg(winfo);
unsigned n;
if (debug)
{
unsigned int i=0;
fprintf(stderr,"dash_escaped_writer writing %d:\n", length);
for (i=0; i<length; i++)
{
fprintf(stderr,"0x%02x ", src[i]);
if (!((i+1) % 16))
fprintf(stderr,"\n");
else if (!((i+1) % 8))
fprintf(stderr," ");
}
fprintf(stderr,"\n");
}
// XXX: make this efficient
for(n=0 ; n < length ; ++n)
{
unsigned l;
if(arg->seen_nl)
{
if(src[n] == '-' && !ops_stacked_write("- ",2,errors,winfo))
return ops_false;
arg->seen_nl=ops_false;
}
arg->seen_nl=src[n] == '\n';
if(arg->seen_nl && !arg->seen_cr)
{
if(!ops_stacked_write("\r",1,errors,winfo))
return ops_false;
ops_signature_add_data(arg->sig,"\r",1);
}
arg->seen_cr=src[n] == '\r';
if(!ops_stacked_write(&src[n],1,errors,winfo))
return ops_false;
/* trailing whitespace isn't included in the signature */
if(src[n] == ' ' || src[n] == '\t')
ops_memory_add(arg->trailing,&src[n],1);
else
{
if((l=ops_memory_get_length(arg->trailing)))
{
if(!arg->seen_nl && !arg->seen_cr)
ops_signature_add_data(arg->sig,
ops_memory_get_data(arg->trailing),
l);
ops_memory_clear(arg->trailing);
}
ops_signature_add_data(arg->sig,&src[n],1);
}
}
return ops_true;
}
/**
* \param winfo
*/
static void dash_escaped_destroyer(ops_writer_info_t *winfo)
{
dash_escaped_arg_t *arg=ops_writer_get_arg(winfo);
ops_memory_free(arg->trailing);
free(arg);
}
/**
* \ingroup Core_WritersNext
* \brief Push Clearsigned Writer onto stack
* \param info
* \param sig
*/
ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
ops_create_signature_t *sig)
{
static char header[]="-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: ";
const char *hash=ops_text_from_hash(ops_signature_get_hash(sig));
dash_escaped_arg_t *arg=ops_mallocz(sizeof *arg);
ops_boolean_t rtn;
rtn= ( ops_write(header,sizeof header-1,info)
&& ops_write(hash,strlen(hash),info)
&& ops_write("\r\n\r\n",4,info));
if (rtn==ops_false)
{
OPS_ERROR(&info->errors, OPS_E_W, "Error pushing clearsigned header");
free(arg);
return rtn;
}
arg->seen_nl=ops_true;
arg->sig=sig;
arg->trailing=ops_memory_new();
ops_writer_push(info,dash_escaped_writer,NULL,dash_escaped_destroyer,arg);
return rtn;
}
/**
* \struct base64_arg_t
*/
typedef struct
{
size_t chars_written;
ops_boolean_t writing_trailer;
unsigned pos;
unsigned char t;
unsigned checksum;
} base64_arg_t;
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)
{
base64_arg_t *arg=ops_writer_get_arg(winfo);
unsigned n;
for(n=0 ; n < length ; )
{
arg->checksum=ops_crc24(arg->checksum,src[n]);
if(arg->pos == 0)
{
/* XXXXXX00 00000000 00000000 */
if(!ops_stacked_write(&b64map[src[n] >> 2],1,errors,winfo))
return ops_false;
/* 000000XX xxxx0000 00000000 */
arg->t=(src[n++]&3) << 4;
arg->pos=1;
}
else if(arg->pos == 1)
{
/* 000000xx XXXX0000 00000000 */
arg->t+=src[n] >> 4;
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
return ops_false;
/* 00000000 0000XXXX xx000000 */
arg->t=(src[n++]&0xf) << 2;
arg->pos=2;
}
else if(arg->pos == 2)
{
/* 00000000 0000xxxx XX000000 */
arg->t+=src[n] >> 6;
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
return ops_false;
if(!check_newline(arg, errors, winfo))
return ops_false;
/* 00000000 00000000 00XXXXXX */
if(!ops_stacked_write(&b64map[src[n++]&0x3f],1,errors,winfo))
return ops_false;
arg->pos=0;
}
if (!check_newline(arg, errors, winfo))
return ops_false;
}
return ops_true;
}
static ops_boolean_t signature_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
base64_arg_t *arg=ops_writer_get_arg(winfo);
static char trailer[]="\r\n-----END PGP SIGNATURE-----\r\n";
unsigned char c[3];
if(arg->pos)
{
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
return ops_false;
if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo))
return ops_false;
if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo))
return ops_false;
}
/* Ready for the checksum */
if(!ops_stacked_write("\r\n=",3,errors,winfo))
return ops_false;
arg->pos=0; /* get ready to write the checksum */
c[0]=arg->checksum >> 16;
c[1]=arg->checksum >> 8;
c[2]=arg->checksum;
/* push the checksum through our own writer. 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;
return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo);
}
/**
* \struct linebreak_arg_t
*/
typedef struct
{
unsigned pos;
} linebreak_arg_t;
#define BREAKPOS 65
static ops_boolean_t linebreak_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
linebreak_arg_t *arg=ops_writer_get_arg(winfo);
unsigned n;
for(n=0 ; n < length ; ++n,++arg->pos)
{
if(src[n] == '\r' || src[n] == '\n')
arg->pos=0;
if(arg->pos == BREAKPOS)
{
if(!ops_stacked_write(newline,strlen(newline),errors,winfo))
return ops_false;
arg->pos=0;
}
if(!ops_stacked_write(&src[n],1,errors,winfo))
return ops_false;
}
return ops_true;
}
/**
* \ingroup Core_WritersNext
* \brief Push armoured signature on stack
* \param info
*/
ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info)
{
static char header[]="\r\n-----BEGIN PGP SIGNATURE-----\r\nVersion: "
OPS_VERSION_STRING "\r\n\r\n";
base64_arg_t *base64;
ops_writer_pop(info);
if (ops_write(header,sizeof header-1,info)==ops_false)
{
OPS_ERROR(&info->errors, OPS_E_W, "Error switching to armoured signature");
return ops_false;
}
ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer,
ops_mallocz(sizeof(linebreak_arg_t)));
base64=ops_mallocz(sizeof *base64);
if (!base64)
{
OPS_MEMORY_ERROR(&info->errors);
return ops_false;
}
base64->checksum=CRC24_INIT;
ops_writer_push(info,base64_writer,signature_finaliser,
ops_writer_generic_destroyer,base64);
return ops_true;
}
static ops_boolean_t armoured_message_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
// TODO: This is same as signature_finaliser apart from trailer.
base64_arg_t *arg=ops_writer_get_arg(winfo);
static char trailer[]="\r\n-----END PGP MESSAGE-----\r\n";
unsigned char c[3];
if(arg->pos)
{
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
return ops_false;
if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo))
return ops_false;
if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo))
return ops_false;
}
/* Ready for the checksum */
if(!ops_stacked_write("\r\n=",3,errors,winfo))
return ops_false;
arg->pos=0; /* get ready to write the checksum */
c[0]=arg->checksum >> 16;
c[1]=arg->checksum >> 8;
c[2]=arg->checksum;
/* push the checksum through our own writer. 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;
return ops_stacked_write(trailer,sizeof trailer-1,errors,winfo);
}
/**
\ingroup Core_WritersNext
\brief Write a PGP MESSAGE
\todo replace with generic function
*/
void ops_writer_push_armoured_message(ops_create_info_t *info)
// ops_create_signature_t *sig)
{
static char header[]="-----BEGIN PGP MESSAGE-----\r\n";
base64_arg_t *base64;
ops_write(header,sizeof header-1,info);
ops_write(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);
}
static ops_boolean_t armoured_finaliser(ops_armor_type_t type, ops_error_t **errors,
ops_writer_info_t *winfo)
{
static char tail_public_key[]="\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n";
static char tail_private_key[]="\r\n-----END PGP PRIVATE KEY BLOCK-----\r\n";
char* tail=NULL;
unsigned int sz_tail=0;
switch(type)
{
case OPS_PGP_PUBLIC_KEY_BLOCK:
tail=tail_public_key;
sz_tail=sizeof tail_public_key-1;
break;
case OPS_PGP_PRIVATE_KEY_BLOCK:
tail=tail_private_key;
sz_tail=sizeof tail_private_key-1;
break;
default:
assert(0);
}
base64_arg_t *arg=ops_writer_get_arg(winfo);
unsigned char c[3];
if(arg->pos)
{
if(!ops_stacked_write(&b64map[arg->t],1,errors,winfo))
return ops_false;
if(arg->pos == 1 && !ops_stacked_write("==",2,errors,winfo))
return ops_false;
if(arg->pos == 2 && !ops_stacked_write("=",1,errors,winfo))
return ops_false;
}
/* Ready for the checksum */
if(!ops_stacked_write("\r\n=",3,errors,winfo))
return ops_false;
arg->pos=0; /* get ready to write the checksum */
c[0]=arg->checksum >> 16;
c[1]=arg->checksum >> 8;
c[2]=arg->checksum;
/* push the checksum through our own writer. 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;
return ops_stacked_write(tail,sz_tail,errors,winfo);
}
static ops_boolean_t armoured_public_key_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
return armoured_finaliser(OPS_PGP_PUBLIC_KEY_BLOCK,errors,winfo);
}
static ops_boolean_t armoured_private_key_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
return armoured_finaliser(OPS_PGP_PRIVATE_KEY_BLOCK,errors,winfo);
}
// \todo use this for other armoured types
/**
\ingroup Core_WritersNext
\brief Push Armoured Writer on stack (generic)
*/
void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type)
{
static char hdr_public_key[]="-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: "
OPS_VERSION_STRING "\r\n\r\n";
static char hdr_private_key[]="-----BEGIN PGP PRIVATE KEY BLOCK-----\r\nVersion: "
OPS_VERSION_STRING "\r\n\r\n";
char* header=NULL;
unsigned int sz_hdr=0;
ops_boolean_t (* finaliser)(ops_error_t **errors, ops_writer_info_t *winfo);
switch(type)
{
case OPS_PGP_PUBLIC_KEY_BLOCK:
header=hdr_public_key;
sz_hdr=sizeof hdr_public_key-1;
finaliser=armoured_public_key_finaliser;
break;
case OPS_PGP_PRIVATE_KEY_BLOCK:
header=hdr_private_key;
sz_hdr=sizeof hdr_private_key-1;
finaliser=armoured_private_key_finaliser;
break;
default:
assert(0);
}
ops_write(header,sz_hdr,info);
ops_writer_push(info,linebreak_writer,NULL,ops_writer_generic_destroyer,
ops_mallocz(sizeof(linebreak_arg_t)));
base64_arg_t *arg=ops_mallocz(sizeof *arg);
arg->checksum=CRC24_INIT;
ops_writer_push(info,base64_writer,finaliser,ops_writer_generic_destroyer,arg);
}
// EOF

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <openpgpsdk/armour.h>
ops_boolean_t ops_writer_push_clearsigned(ops_create_info_t *info,
ops_create_signature_t *sig);
void ops_writer_push_armoured_message(ops_create_info_t *info);
ops_boolean_t ops_writer_switch_to_armoured_signature(ops_create_info_t *info);
void ops_writer_push_armoured(ops_create_info_t *info, ops_armor_type_t type);
// EOF

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <assert.h>
#include <string.h>
#include <openpgpsdk/readerwriter.h>
static int debug=0;
typedef struct
{
ops_crypt_t* crypt;
int free_crypt;
} crypt_arg_t;
/*
* This writer simply takes plaintext as input,
* encrypts it with the given key
* and outputs the resulting encrypted text
*/
static ops_boolean_t encrypt_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
#define BUFSZ 1024 // arbitrary number
unsigned char encbuf[BUFSZ];
unsigned remaining=length;
unsigned done=0;
crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo);
if (!ops_is_sa_supported(arg->crypt->algorithm))
assert(0); // \todo proper error handling
while (remaining)
{
unsigned len = remaining < BUFSZ ? remaining : BUFSZ;
// memcpy(buf,src,len); // \todo copy needed here?
arg->crypt->cfb_encrypt(arg->crypt, encbuf, src+done, len);
if (debug)
{
int i=0;
fprintf(stderr,"WRITING:\nunencrypted: ");
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", src[done+i]);
fprintf(stderr,"\n");
fprintf(stderr,"encrypted: ");
for (i=0; i<16; i++)
fprintf(stderr,"%2x ", encbuf[i]);
fprintf(stderr,"\n");
}
if (!ops_stacked_write(encbuf,len,errors,winfo))
{
if (debug)
{ fprintf(stderr, "encrypted_writer got error from stacked write, returning\n"); }
return ops_false;
}
remaining-=len;
done+=len;
}
return ops_true;
}
static void encrypt_destroyer (ops_writer_info_t *winfo)
{
crypt_arg_t *arg=(crypt_arg_t *)ops_writer_get_arg(winfo);
if (arg->free_crypt)
free(arg->crypt);
free (arg);
}
/**
\ingroup Core_WritersNext
\brief Push Encrypted Writer onto stack (create SE packets)
*/
void ops_writer_push_encrypt_crypt(ops_create_info_t *cinfo,
ops_crypt_t *crypt)
{
// Create arg to be used with this writer
// Remember to free this in the destroyer
crypt_arg_t *arg=ops_mallocz(sizeof *arg);
// Setup the arg
arg->crypt=crypt;
arg->free_crypt=0;
// And push writer on stack
ops_writer_push(cinfo,encrypt_writer,NULL,encrypt_destroyer,arg);
}
// EOF

View File

@ -0,0 +1,247 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <string.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <openssl/cast.h>
#include "keyring_local.h"
#include <openpgpsdk/compress.h>
#include <openpgpsdk/create.h>
#include <openpgpsdk/hash.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/random.h>
#include <openpgpsdk/readerwriter.h>
static int debug=0;
typedef struct
{
ops_crypt_t* crypt;
} encrypt_se_ip_arg_t;
static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo);
static void encrypt_se_ip_destroyer(ops_writer_info_t *winfo);
//
/**
\ingroup Core_WritersNext
\brief Push Encrypted SE IP Writer onto stack
*/
void ops_writer_push_encrypt_se_ip(ops_create_info_t *cinfo,
const ops_keydata_t *pub_key)
{
ops_crypt_t *encrypt;
unsigned char *iv=NULL;
// Create arg to be used with this writer
// Remember to free this in the destroyer
encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
// Create and write encrypted PK session key
ops_pk_session_key_t *encrypted_pk_session_key;
encrypted_pk_session_key=ops_create_pk_session_key(pub_key);
ops_write_pk_session_key(cinfo, encrypted_pk_session_key);
// Setup the arg
encrypt=ops_mallocz(sizeof *encrypt);
ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm);
iv=ops_mallocz(encrypt->blocksize);
encrypt->set_iv(encrypt, iv);
encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]);
ops_encrypt_init(encrypt);
arg->crypt=encrypt;
// And push writer on stack
ops_writer_push(cinfo, encrypt_se_ip_writer, NULL, encrypt_se_ip_destroyer,
arg);
// tidy up
ops_pk_session_key_free(encrypted_pk_session_key);
free(encrypted_pk_session_key);
free(iv);
}
static ops_boolean_t encrypt_se_ip_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
ops_boolean_t rtn=ops_true;
ops_memory_t *mem_literal;
ops_create_info_t *cinfo_literal;
ops_memory_t *mem_compressed;
ops_create_info_t *cinfo_compressed;
ops_memory_t *my_mem;
ops_create_info_t *my_cinfo;
const unsigned int bufsz=128; // initial value; gets expanded as necessary
ops_setup_memory_write(&cinfo_literal, &mem_literal, bufsz);
ops_setup_memory_write(&cinfo_compressed, &mem_compressed, bufsz);
ops_setup_memory_write(&my_cinfo, &my_mem, bufsz);
// create literal data packet from source data
ops_write_literal_data_from_buf(src, length, OPS_LDT_BINARY, cinfo_literal);
assert(ops_memory_get_length(mem_literal) > length);
// create compressed packet from literal data packet
ops_write_compressed(ops_memory_get_data(mem_literal),
ops_memory_get_length(mem_literal),
cinfo_compressed);
// create SE IP packet set from this compressed literal data
ops_write_se_ip_pktset(ops_memory_get_data(mem_compressed),
ops_memory_get_length(mem_compressed),
arg->crypt, my_cinfo);
assert(ops_memory_get_length(my_mem)
> ops_memory_get_length(mem_compressed));
// now write memory to next writer
rtn=ops_stacked_write(ops_memory_get_data(my_mem),
ops_memory_get_length(my_mem),
errors, winfo);
ops_memory_free(my_mem);
ops_memory_free(mem_compressed);
ops_memory_free(mem_literal);
return rtn;
}
static void encrypt_se_ip_destroyer (ops_writer_info_t *winfo)
{
encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
free(arg->crypt);
free(arg);
}
ops_boolean_t ops_write_se_ip_pktset(const unsigned char *data,
const unsigned int len,
ops_crypt_t *crypt,
ops_create_info_t *cinfo)
{
unsigned char hashed[SHA_DIGEST_LENGTH];
const size_t sz_mdc=1+1+SHA_DIGEST_LENGTH;
size_t sz_preamble=crypt->blocksize+2;
unsigned char* preamble=ops_mallocz(sz_preamble);
size_t sz_buf=sz_preamble+len+sz_mdc;
ops_memory_t *mem_mdc;
ops_create_info_t *cinfo_mdc;
if (!ops_write_ptag(OPS_PTAG_CT_SE_IP_DATA, cinfo)
|| !ops_write_length(1+sz_buf, cinfo)
|| !ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo))
{
free (preamble);
return 0;
}
ops_random(preamble, crypt->blocksize);
preamble[crypt->blocksize]=preamble[crypt->blocksize-2];
preamble[crypt->blocksize+1]=preamble[crypt->blocksize-1];
if (debug)
{
unsigned int i=0;
fprintf(stderr,"\npreamble: ");
for (i=0; i<sz_preamble;i++)
fprintf(stderr," 0x%02x", preamble[i]);
fprintf(stderr,"\n");
}
// now construct MDC packet and add to the end of the buffer
ops_setup_memory_write(&cinfo_mdc, &mem_mdc,sz_mdc);
ops_calc_mdc_hash(preamble, sz_preamble, data, len, &hashed[0]);
ops_write_mdc(hashed, cinfo_mdc);
if (debug)
{
unsigned int i=0;
size_t sz_plaintext=len;
size_t sz_mdc=1+1+OPS_SHA1_HASH_SIZE;
unsigned char* mdc=NULL;
fprintf(stderr,"\nplaintext: ");
for (i=0; i<sz_plaintext;i++)
fprintf(stderr, " 0x%02x", data[i]);
fprintf(stderr,"\n");
fprintf(stderr,"\nmdc: ");
mdc=ops_memory_get_data(mem_mdc);
for (i=0; i<sz_mdc;i++)
fprintf(stderr, " 0x%02x", mdc[i]);
fprintf(stderr,"\n");
}
// and write it out
ops_writer_push_encrypt_crypt(cinfo, crypt);
#ifdef DEBUG
if (debug)
{
fprintf(stderr,"writing %ld + %d + %ld\n", sz_preamble, len,
ops_memory_get_length(mem_mdc));
}
#endif /*DEBUG*/
if (!ops_write(preamble, sz_preamble, cinfo)
|| !ops_write(data, len, cinfo)
|| !ops_write(ops_memory_get_data(mem_mdc),
ops_memory_get_length(mem_mdc), cinfo))
// \todo fix cleanup here and in old code functions
return 0;
ops_writer_pop(cinfo);
// cleanup
ops_teardown_memory_write(cinfo_mdc, mem_mdc);
free (preamble);
return 1;
}
// EOF

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#ifndef WIN32
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#endif
#include <openpgpsdk/create.h>
#include <openpgpsdk/final.h>
typedef struct
{
int fd;
} writer_fd_arg_t;
static ops_boolean_t fd_writer(const unsigned char *src,unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
writer_fd_arg_t *arg=ops_writer_get_arg(winfo);
int n=write(arg->fd,src,length);
if(n == -1)
{
OPS_SYSTEM_ERROR_1(errors,OPS_E_W_WRITE_FAILED,"write",
"file descriptor %d",arg->fd);
return ops_false;
}
if((unsigned)n != length)
{
OPS_ERROR_1(errors,OPS_E_W_WRITE_TOO_SHORT,
"file descriptor %d",arg->fd);
return ops_false;
}
return ops_true;
}
static void fd_destroyer(ops_writer_info_t *winfo)
{
free(ops_writer_get_arg(winfo));
}
/**
* \ingroup Core_WritersFirst
* \brief Write to a File
*
* Set the writer in info to be a stock writer that writes to a file
* descriptor. If another writer has already been set, then that is
* first destroyed.
*
* \param info The info structure
* \param fd The file descriptor
*
*/
void ops_writer_set_fd(ops_create_info_t *info,int fd)
{
writer_fd_arg_t *arg=malloc(sizeof *arg);
arg->fd=fd;
ops_writer_set(info,fd_writer,NULL,fd_destroyer,arg);
}
// EOF

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2005-2009 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer, Alasdair Mackintosh.
* The Contributors have asserted their moral rights under the
* UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** Writes a literal data packet, using the partial data length encoding.
*/
#include <string.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <openpgpsdk/create.h>
#include <openpgpsdk/literal.h>
#include <openpgpsdk/partial.h>
#define MIN_PARTIAL_DATA_LENGTH 512
#define MAX_PARTIAL_DATA_LENGTH 1073741824
ops_boolean_t write_literal_header(ops_create_info_t *info,
void *header_data)
{
OPS_USED(header_data);
// \todo add the literal type as a header_data argument
// \todo add filename
// \todo add date
// \todo do we need to check text data for <cr><lf> line endings ?
ops_write_scalar(OPS_LDT_BINARY, 1, info); // data type
ops_write_scalar(0, 1, info); // Filename (length = 0)
ops_write_scalar(0, 4, info); // Date (unspecified)
return ops_true;
}
/**
* \ingroup InternalAPI
* \brief Pushes a literal writer onto the stack.
* \param cinfo the writer info
* \param buf_size the size of the internal buffer. For best
* throughput, write data in multiples of buf_size
*/
void ops_writer_push_literal_with_opts(ops_create_info_t *cinfo,
unsigned int buf_size)
{
// The literal writer doesn't need to transform the data, so we just
// push a partial packet writer onto the stack. This will handle
// the packet length encoding. All we need to provide is a function
// to write the header.
ops_writer_push_partial(buf_size, cinfo, OPS_PTAG_CT_LITERAL_DATA,
write_literal_header, NULL);
}
/**
* \ingroup InternalAPI
* \brief Pushes a literal writer onto the stack.
* \param cinfo the writer info
*/
void ops_writer_push_literal(ops_create_info_t *cinfo)
{
ops_writer_push_literal_with_opts(cinfo, 0);
}
// EOF

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/create.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <openpgpsdk/final.h>
static ops_boolean_t memory_writer(const unsigned char *src,unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
ops_memory_t *mem=ops_writer_get_arg(winfo);
OPS_USED(errors);
ops_memory_add(mem,src,length);
return ops_true;
}
/**
* \ingroup Core_WritersFirst
* \brief Write to memory
*
* Set a memory writer.
*
* \param info The info structure
* \param mem The memory structure
* \note It is the caller's responsiblity to call ops_memory_free(mem)
* \sa ops_memory_free()
*/
void ops_writer_set_memory(ops_create_info_t *info,ops_memory_t *mem)
{
ops_writer_set(info,memory_writer,NULL,NULL,mem);
}
// EOF

View File

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

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
* All rights reserved.
* Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
* their moral rights under the UK Copyright Design and Patents Act 1988 to
* be recorded as the authors of this copyright work.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License.
*
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** \file
*/
#include <openpgpsdk/create.h>
#include <openpgpsdk/final.h>
//static int debug=0;
typedef struct
{
ops_hash_algorithm_t hash_algorithm;
ops_hash_t hash;
unsigned char *hashed;
} skey_checksum_arg_t;
static ops_boolean_t skey_checksum_writer(const unsigned char *src, const unsigned length, ops_error_t **errors, ops_writer_info_t *winfo)
{
skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
ops_boolean_t rtn=ops_true;
// add contents to hash
arg->hash.add(&arg->hash, src, length);
// write to next stacked writer
rtn=ops_stacked_write(src,length,errors,winfo);
// tidy up and return
return rtn;
}
static ops_boolean_t skey_checksum_finaliser(ops_error_t **errors __attribute__((unused)), ops_writer_info_t *winfo)
{
skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
arg->hash.finish(&arg->hash, arg->hashed);
return ops_true;
}
static void skey_checksum_destroyer(ops_writer_info_t* winfo)
{
skey_checksum_arg_t *arg=ops_writer_get_arg(winfo);
free(arg);
}
/**
\ingroup Core_WritersNext
\param cinfo
\param skey
*/
void ops_push_skey_checksum_writer(ops_create_info_t *cinfo, ops_secret_key_t *skey)
{
// OPS_USED(info);
// XXX: push a SHA-1 checksum writer (and change s2k to 254).
skey_checksum_arg_t *arg=ops_mallocz(sizeof *arg);
// configure the arg
arg->hash_algorithm=skey->hash_algorithm;
arg->hashed=&skey->checkhash[0];
// init the hash
ops_hash_any(&arg->hash, arg->hash_algorithm);
arg->hash.init(&arg->hash);
ops_writer_push(cinfo, skey_checksum_writer, skey_checksum_finaliser, skey_checksum_destroyer, arg);
}
// EOF

View File

@ -0,0 +1,256 @@
/*
* 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.
*/
/** \file
*/
#include <string.h>
#include <assert.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <openssl/cast.h>
#include "keyring_local.h"
#include <openpgpsdk/create.h>
#include <openpgpsdk/keyring.h>
#include <openpgpsdk/partial.h>
#include <openpgpsdk/random.h>
#include <openpgpsdk/streamwriter.h>
typedef struct
{
ops_crypt_t*crypt;
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 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;
unsigned char *iv=NULL;
const unsigned int bufsz=1024; // initial value; gets expanded as necessary
// Create arg to be used with this writer
// Remember to free this in the destroyer
stream_encrypt_se_ip_arg_t *arg=ops_mallocz(sizeof *arg);
// Create and write encrypted PK session key
ops_pk_session_key_t *encrypted_pk_session_key;
encrypted_pk_session_key=ops_create_pk_session_key(pub_key);
ops_write_pk_session_key(cinfo, encrypted_pk_session_key);
// Setup the arg
encrypt=ops_mallocz(sizeof *encrypt);
ops_crypt_any(encrypt, encrypted_pk_session_key->symmetric_algorithm);
iv=ops_mallocz(encrypt->blocksize);
encrypt->set_iv(encrypt, iv);
encrypt->set_key(encrypt, &encrypted_pk_session_key->key[0]);
ops_encrypt_init(encrypt);
arg->crypt=encrypt;
ops_setup_memory_write(&arg->cinfo_se_ip, &arg->mem_se_ip, bufsz);
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);
// tidy up
ops_pk_session_key_free(encrypted_pk_session_key);
free(encrypted_pk_session_key);
free(iv);
}
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)
{
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;
}
// 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;
unsigned char* preamble = ops_mallocz(sz_preamble);
ops_write_scalar(SE_IP_DATA_VERSION, 1, cinfo);
ops_writer_push_encrypt_crypt(cinfo, arg->crypt);
ops_random(preamble, arg->crypt->blocksize);
preamble[arg->crypt->blocksize]=preamble[arg->crypt->blocksize-2];
preamble[arg->crypt->blocksize+1]=preamble[arg->crypt->blocksize-1];
ops_write(preamble, sz_preamble, cinfo);
arg->hash.add(&arg->hash, preamble, sz_preamble);
ops_writer_pop(cinfo);
free(preamble);
return ops_true;
}
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;
ops_memory_t *mem_mdc;
ops_create_info_t *cinfo_mdc;
// MDC packet tag
c[0]=0xD3;
arg->hash.add(&arg->hash, &c[0], 1);
// MDC packet len
c[0]=0x14;
arg->hash.add(&arg->hash, &c[0], 1);
//finish
arg->hash.finish(&arg->hash, hashed);
ops_setup_memory_write(&cinfo_mdc, &mem_mdc, sz_mdc);
ops_write_mdc(hashed, cinfo_mdc);
// encode everthing
ops_writer_push_encrypt_crypt(cinfo, arg->crypt);
ops_write(ops_memory_get_data(mem_mdc), ops_memory_get_length(mem_mdc),
cinfo);
ops_writer_pop(cinfo);
ops_teardown_memory_write(cinfo_mdc, mem_mdc);
return ops_true;
}
static ops_boolean_t stream_encrypt_se_ip_writer(const unsigned char *src,
unsigned length,
ops_error_t **errors,
ops_writer_info_t *winfo)
{
stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
ops_boolean_t rtn=ops_true;
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_se_ip);
return rtn;
}
static ops_boolean_t stream_encrypt_se_ip_finaliser(ops_error_t **errors,
ops_writer_info_t *winfo)
{
stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
// write 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)
{
stream_encrypt_se_ip_arg_t *arg=ops_writer_get_arg(winfo);
ops_teardown_memory_write(arg->cinfo_se_ip, arg->mem_se_ip);
arg->crypt->decrypt_finish(arg->crypt);
free(arg->crypt);
free(arg);
}
// EOF

99
openpgpsdk/src/src.pro Normal file
View File

@ -0,0 +1,99 @@
TEMPLATE = lib
CONFIG = staticlib debug
DEFINES *= OPENSSL_NO_IDEA
QMAKE_CXXFLAGS *= -Wall -Werror -W
TARGET = ops
DESTDIR = lib
DEPENDPATH += .
INCLUDEPATH += .
#################################### Windows #####################################
linux-* {
OBJECTS_DIR = temp/linux/obj
}
win32 {
SSL_DIR = ../../../../OpenSSL
ZLIB_DIR = ../../../zlib-1.2.3
BZIP_DIR = ../../../bzip2-1.0.6
INCLUDEPATH += $${SSL_DIR}/include $${ZLIB_DIR} $${BZIP_DIR}
}
# Input
HEADERS += openpgpsdk/writer.h \
openpgpsdk/writer_armoured.h \
openpgpsdk/version.h \
openpgpsdk/validate.h \
openpgpsdk/util.h \
openpgpsdk/types.h \
openpgpsdk/streamwriter.h \
openpgpsdk/std_print.h \
openpgpsdk/signature.h \
openpgpsdk/readerwriter.h \
openpgpsdk/random.h \
openpgpsdk/partial.h \
openpgpsdk/packet-show.h \
openpgpsdk/packet-show-cast.h \
openpgpsdk/packet-parse.h \
openpgpsdk/packet.h \
openpgpsdk/memory.h \
openpgpsdk/literal.h \
openpgpsdk/lists.h \
openpgpsdk/keyring.h \
openpgpsdk/hash.h \
openpgpsdk/final.h \
openpgpsdk/defs.h \
openpgpsdk/errors.h \
openpgpsdk/crypto.h \
openpgpsdk/create.h \
openpgpsdk/configure.h \
openpgpsdk/compress.h \
openpgpsdk/callback.h \
openpgpsdk/accumulate.h \
openpgpsdk/armour.h \
openpgpsdk/parse_local.h \
openpgpsdk/keyring_local.h
SOURCES += openpgpsdk/accumulate.c \
openpgpsdk/compress.c \
openpgpsdk/create.c \
openpgpsdk/crypto.c \
openpgpsdk/errors.c \
openpgpsdk/fingerprint.c \
openpgpsdk/hash.c \
openpgpsdk/keyring.c \
openpgpsdk/lists.c \
openpgpsdk/memory.c \
openpgpsdk/openssl_crypto.c \
openpgpsdk/packet-parse.c \
openpgpsdk/packet-print.c \
openpgpsdk/packet-show.c \
openpgpsdk/random.c \
openpgpsdk/reader.c \
openpgpsdk/reader_armoured.c \
openpgpsdk/reader_encrypted_se.c \
openpgpsdk/reader_encrypted_seip.c \
openpgpsdk/reader_fd.c \
openpgpsdk/reader_hashed.c \
openpgpsdk/reader_mem.c \
openpgpsdk/readerwriter.c \
openpgpsdk/signature.c \
openpgpsdk/symmetric.c \
openpgpsdk/util.c \
openpgpsdk/validate.c \
openpgpsdk/writer.c \
openpgpsdk/writer_armour.c \
openpgpsdk/writer_partial.c \
openpgpsdk/writer_literal.c \
openpgpsdk/writer_encrypt.c \
openpgpsdk/writer_encrypt_se_ip.c \
openpgpsdk/writer_fd.c \
openpgpsdk/writer_memory.c \
openpgpsdk/writer_skey_checksum.c \
openpgpsdk/writer_stream_encrypt_se_ip.c

View File

@ -26,16 +26,12 @@ linux-* {
#CONFIG += version_detail_bash_script
QMAKE_CXXFLAGS *= -D_FILE_OFFSET_BITS=64
system(which gpgme-config >/dev/null 2>&1) {
INCLUDEPATH += $$system(gpgme-config --cflags | sed -e "s/-I//g")
} else {
message(Could not find gpgme-config on your system, assuming gpgme.h is in /usr/include)
}
PRE_TARGETDEPS *= ../../libretroshare/src/lib/libretroshare.a
PRE_TARGETDEPS *= ../../openpgpsdk/src/lib/libops.a
LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += -lssl -lgpgme -lupnp -lixml -lXss -lgnome-keyring
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -lssl -lupnp -lixml -lXss -lgnome-keyring
LIBS *= -rdynamic
DEFINES *= HAVE_XSS # for idle time, libx screensaver extensions
DEFINES *= UBUNTU
@ -110,6 +106,7 @@ win32 {
PRE_TARGETDEPS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../libretroshare/src/lib/libretroshare.a
LIBS += ../../openpgpsdk/src/lib/libops.a -lbz2
LIBS += -L"../../../lib"
LIBS += -lssl -lcrypto -lgpgme -lpthreadGC2d -lminiupnpc -lz
# added after bitdht

Some files were not shown because too many files have changed in this diff Show More