now secure channel enabled

master
Marc Wäckerlin 15 years ago
parent 9a3ea17b11
commit 7840897598
  1. 12
      src/cryptaux.hxx
  2. 15
      src/cryptoki.cxx
  3. 5
      src/cryptoki.hxx
  4. 204
      src/openssl.hxx
  5. 34
      src/pcsc.hxx

@ -30,7 +30,15 @@ namespace crypto {
static const std::string VALID_CHARS
(LETTER_CHARS+NUMBER_CHARS+GRAFIC_CHARS+BLANK_CHARS);
inline std::string hex(const std::string& data,
inline std::string hex(const std::string& data) {
std::stringstream res;
for (std::string::const_iterator it(data.begin()); it!=data.end(); ++it)
res<<std::hex<<std::setfill('0')<<std::setw(2)
<<(unsigned int)(unsigned char)*it;
return res.str();
}
inline std::string hexTxt(const std::string& data,
std::string::size_type len=20) {
std::stringstream res;
std::string::size_type pos(0);
@ -53,7 +61,7 @@ namespace crypto {
if (!data.size())
return "<empty>";
else if (data.find_first_not_of(VALID_CHARS)<data.size())
return hex(data);
return hexTxt(data);
else
return "\""+data+"\"";
}

@ -239,6 +239,21 @@ namespace cryptoki {
}
}
//----------------------------------------------------------------------------
ObjectList Session::find(const Attribute& a) {
AttributeList al;
al.push_back(a);
return find(al);
}
//----------------------------------------------------------------------------
ObjectList Session::find(const Attribute& a1, const Attribute& a2) {
AttributeList al;
al.push_back(a1);
al.push_back(a2);
return find(al);
}
//----------------------------------------------------------------------------
Object Session::create(const std::string& label, const openssl::X509& cert) {
AttributeList attrs;

@ -1002,6 +1002,11 @@ namespace cryptoki {
//! Get a list of matching objects.
ObjectList find(const AttributeList& attrs=AttributeList());
//! Get a list of matching objects.
ObjectList find(const Attribute& a);
//! Get a list of matching objects.
ObjectList find(const Attribute& a1, const Attribute& a2);
//! Create a new Certificate Object.
Object create(const std::string& label, const openssl::X509& cert);
//! Create a new PrivateKey Object.

@ -11,6 +11,7 @@
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include "openssl/bio.h"
#include "openssl/des.h"
#include "openssl/ssl.h"
#include <openssl/err.h>
#include <vector>
@ -21,6 +22,8 @@
#include <cstdio>
#include <cassert>
#include <iostream> //! @todo remove (debug only)
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API */
//@{
//! @defgroup openssllib OpenSSL C++ Library
@ -55,6 +58,13 @@ namespace openssl {
}
};
//----------------------------------------------------------------------------
class encryption_error: public openssl_error {
public:
encryption_error(const std::string& reason) throw():
openssl_error("encryption: "+reason) {
}
};
//----------------------------------------------------------------------------
class pkcs12_error: public openssl_error {
public:
pkcs12_error(const std::string& reason) throw():
@ -90,6 +100,13 @@ namespace openssl {
}
};
//----------------------------------------------------------------------------
class cannot_encrypt: public encryption_error {
public:
cannot_encrypt(std::string reason) throw():
encryption_error("cannot encrypt text: "+reason) {
}
};
//----------------------------------------------------------------------------
class allocation_failed: public x509_error {
public:
allocation_failed() throw():
@ -225,6 +242,193 @@ namespace openssl {
}
};
inline std::string desEnc(const std::string& txt, DES_cblock key1) {
std::string res(txt);
if (txt.size()%8!=0)
throw cannot_encrypt("text size must be a multiple of eight");
DES_key_schedule ks1;
DES_set_key_unchecked(&(DES_cblock&)key1, &ks1);
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) {
union {
DES_cblock array;
const char* text;
} in, out;
in.text = txt.begin().operator->()+pos;
out.text = res.begin().operator->()+pos;
DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_ENCRYPT);
}
return res;
}
inline std::string desDec(const std::string& txt, DES_cblock key1) {
std::string res(txt);
if (txt.size()%8!=0)
throw cannot_encrypt("text size must be a multiple of eight");
DES_key_schedule ks1;
DES_set_key_unchecked(&(DES_cblock&)key1, &ks1);
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) {
union {
DES_cblock array;
const char* text;
} in, out;
in.text = txt.begin().operator->()+pos;
out.text = res.begin().operator->()+pos;
DES_ecb_encrypt(&in.array, &out.array, &ks1, DES_DECRYPT);
}
return res;
}
class CBlock8 {
public:
CBlock8() {
_cb[0] = _cb[1] = _cb[2] = _cb[3] =
_cb[4] = _cb[5] = _cb[6] = _cb[7] = 0;
}
CBlock8(unsigned char c1, unsigned char c2, unsigned char c3,
unsigned char c4, unsigned char c5, unsigned char c6,
unsigned char c7, unsigned char c8) {
_cb[0] = c1;
_cb[1] = c2;
_cb[2] = c3;
_cb[3] = c4;
_cb[4] = c5;
_cb[5] = c6;
_cb[6] = c7;
_cb[7] = c8;
}
//! String must contain exactly 8 char.
CBlock8(const std::string& s) {
assert(s.size()==8);
_cb[0] = s[0];
_cb[1] = s[1];
_cb[2] = s[3];
_cb[3] = s[4];
_cb[4] = s[5];
_cb[5] = s[6];
_cb[6] = s[7];
_cb[7] = s[8];
}
operator DES_cblock&() {
return _cb;
}
operator DES_cblock*() {
return &_cb;
}
operator std::string() const {
return std::string((char*)_cb, 8);
}
private:
DES_cblock _cb;
};
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) {
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
std::string res(txt.size(), 0);
DES_key_schedule ks;
DES_set_key_unchecked(key, &ks);
DES_ncbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0],
txt.size(), &ks, ivec, DES_ENCRYPT);
return res;
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
inline std::string desCbcEnc(const std::string& txt, const CBlock8& key) {
CBlock8 ivec;
return desCbcEnc(txt, key, ivec);
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) {
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
std::string res(txt.size(), 0);
DES_key_schedule ks;
DES_set_key_unchecked(key, &ks);
DES_ncbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0],
txt.size(), &ks, ivec, DES_DECRYPT);
return res;
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
inline std::string desCbcDec(const std::string& txt, const CBlock8& key) {
CBlock8 ivec;
return desCbcDec(txt, key, ivec);
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
inline std::string des2edeCbcEnc(std::string txt,
CBlock8 key1, CBlock8 key2,
CBlock8 ivec = CBlock8()) {
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
std::string res(txt.size(), 0);
DES_key_schedule ks1, ks2;
DES_set_key_unchecked(key1, &ks1);
DES_set_key_unchecked(key2, &ks2);
DES_ede2_cbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0],
txt.size(), &ks1, &ks2, ivec, DES_ENCRYPT);
return res;
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
inline std::string des2edeCbcDec(std::string txt,
CBlock8 key1, CBlock8 key2,
CBlock8 ivec = CBlock8()) {
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
std::string res(txt.size(), 0);
DES_key_schedule ks1, ks2;
DES_set_key_unchecked(key1, &ks1);
DES_set_key_unchecked(key2, &ks2);
DES_ede2_cbc_encrypt((unsigned char*)&txt[0], (unsigned char*)&res[0],
txt.size(), &ks1, &ks2, ivec, DES_DECRYPT);
return res;
}
//! @todo untested
inline std::string des2ecbEnc(std::string txt,
CBlock8 key1, CBlock8 key2) {
std::string res;
if (txt.size()%8!=0)
throw cannot_encrypt("text size must be a multiple of eight");
DES_key_schedule ks1, ks2;
DES_set_key_unchecked(key1, &ks1);
DES_set_key_unchecked(key2, &ks2);
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) {
CBlock8 out, in(txt.substr(pos, 8));
DES_ecb2_encrypt(in, out, &ks1, &ks2, DES_ENCRYPT);
res+=out;
}
return res;
}
//! @todo untested
inline std::string des2ecbDec(std::string txt,
CBlock8 key1, CBlock8 key2) {
std::string res;
if (txt.size()%8!=0)
throw cannot_encrypt("text size must be a multiple of eight");
DES_key_schedule ks1, ks2;
DES_set_key_unchecked(key1, &ks1);
DES_set_key_unchecked(key2, &ks2);
for (std::string::size_type pos(0); pos<txt.size(); pos+=8) {
CBlock8 out, in(txt.substr(pos, 8));
DES_ecb2_encrypt(in, out, &ks1, &ks2, DES_DECRYPT);
res+=out;
}
return res;
}
//============================================================================
class X509 {
public:

@ -10,6 +10,25 @@
#ifndef PCSC_HXX
#define PCSC_HXX
#ifndef PCSC_LOG
//! Declare PCSC_LOG before #include in your code, if you want logging.
/*! PCSC_LOG passes its argument to a stream, so your definition must
behave so that the argument can be streamed.
Example, use std::log:
@code
#define PCSC_LOG(x) std::clog<<x<<" ("<<__PRETTY_FUNCTION__<<')'<<std::endl
#include <pcsc.hxx>
@endcode
Example, use qDebug():
@code
#define PCSC_LOG(x) qDebug()<<x
#include <pcsc.hxx>
@endcode */
#define PCSC_LOG(x) // if unset, do nothing
#endif
#include <cryptaux.hxx>
#include <string>
@ -221,6 +240,19 @@ namespace pcsc {
return transmit(claInsP1P2, lc, le);
}
//! Transmit data to reader.
/*! @note Take care: Stings may contain embedded @c 0. */
std::string transmit(char cla, char ins, char p1, char p2,
unsigned char le) {
std::string claInsP1P2;
claInsP1P2.push_back(cla);
claInsP1P2.push_back(ins);
claInsP1P2.push_back(p1);
claInsP1P2.push_back(p2);
assert(claInsP1P2.size()==4);
return transmit(claInsP1P2, std::string(), le);
}
//! Transmit data to reader.
/*! @note Take care: Stings may contain embedded @c 0. */
std::string transmit(char cla, char ins, char p1, char p2,
@ -262,10 +294,12 @@ namespace pcsc {
SCARD_IO_REQUEST rPci;
rPci.dwProtocol = pci()->dwProtocol;
rPci.cbPciLength = sizeof(rPci);
PCSC_LOG("SCardTransmit: "<<crypto::hex(in));
check(SCardTransmit(_id, &rPci,
(unsigned char*)in.c_str(), in.size(),
0, buff, &len),
"smartcard transmit message "+crypto::hex(in));
PCSC_LOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
return std::string((char*)buff, len);
}

Loading…
Cancel
Save