now secure channel enabled
This commit is contained in:
@@ -30,7 +30,15 @@ namespace crypto {
|
|||||||
static const std::string VALID_CHARS
|
static const std::string VALID_CHARS
|
||||||
(LETTER_CHARS+NUMBER_CHARS+GRAFIC_CHARS+BLANK_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::string::size_type len=20) {
|
||||||
std::stringstream res;
|
std::stringstream res;
|
||||||
std::string::size_type pos(0);
|
std::string::size_type pos(0);
|
||||||
@@ -53,7 +61,7 @@ namespace crypto {
|
|||||||
if (!data.size())
|
if (!data.size())
|
||||||
return "<empty>";
|
return "<empty>";
|
||||||
else if (data.find_first_not_of(VALID_CHARS)<data.size())
|
else if (data.find_first_not_of(VALID_CHARS)<data.size())
|
||||||
return hex(data);
|
return hexTxt(data);
|
||||||
else
|
else
|
||||||
return "\""+data+"\"";
|
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) {
|
Object Session::create(const std::string& label, const openssl::X509& cert) {
|
||||||
AttributeList attrs;
|
AttributeList attrs;
|
||||||
|
@@ -1002,6 +1002,11 @@ namespace cryptoki {
|
|||||||
//! Get a list of matching objects.
|
//! Get a list of matching objects.
|
||||||
ObjectList find(const AttributeList& attrs=AttributeList());
|
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.
|
//! Create a new Certificate Object.
|
||||||
Object create(const std::string& label, const openssl::X509& cert);
|
Object create(const std::string& label, const openssl::X509& cert);
|
||||||
//! Create a new PrivateKey Object.
|
//! Create a new PrivateKey Object.
|
||||||
|
204
src/openssl.hxx
204
src/openssl.hxx
@@ -11,6 +11,7 @@
|
|||||||
#include <openssl/pkcs12.h>
|
#include <openssl/pkcs12.h>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
#include "openssl/bio.h"
|
#include "openssl/bio.h"
|
||||||
|
#include "openssl/des.h"
|
||||||
#include "openssl/ssl.h"
|
#include "openssl/ssl.h"
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -21,6 +22,8 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <iostream> //! @todo remove (debug only)
|
||||||
|
|
||||||
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API */
|
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API */
|
||||||
//@{
|
//@{
|
||||||
//! @defgroup openssllib OpenSSL C++ Library
|
//! @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 {
|
class pkcs12_error: public openssl_error {
|
||||||
public:
|
public:
|
||||||
pkcs12_error(const std::string& reason) throw():
|
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 {
|
class allocation_failed: public x509_error {
|
||||||
public:
|
public:
|
||||||
allocation_failed() throw():
|
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 {
|
class X509 {
|
||||||
public:
|
public:
|
||||||
|
34
src/pcsc.hxx
34
src/pcsc.hxx
@@ -10,6 +10,25 @@
|
|||||||
#ifndef PCSC_HXX
|
#ifndef PCSC_HXX
|
||||||
#define 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 <cryptaux.hxx>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -221,6 +240,19 @@ namespace pcsc {
|
|||||||
return transmit(claInsP1P2, lc, le);
|
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.
|
//! Transmit data to reader.
|
||||||
/*! @note Take care: Stings may contain embedded @c 0. */
|
/*! @note Take care: Stings may contain embedded @c 0. */
|
||||||
std::string transmit(char cla, char ins, char p1, char p2,
|
std::string transmit(char cla, char ins, char p1, char p2,
|
||||||
@@ -262,10 +294,12 @@ namespace pcsc {
|
|||||||
SCARD_IO_REQUEST rPci;
|
SCARD_IO_REQUEST rPci;
|
||||||
rPci.dwProtocol = pci()->dwProtocol;
|
rPci.dwProtocol = pci()->dwProtocol;
|
||||||
rPci.cbPciLength = sizeof(rPci);
|
rPci.cbPciLength = sizeof(rPci);
|
||||||
|
PCSC_LOG("SCardTransmit: "<<crypto::hex(in));
|
||||||
check(SCardTransmit(_id, &rPci,
|
check(SCardTransmit(_id, &rPci,
|
||||||
(unsigned char*)in.c_str(), in.size(),
|
(unsigned char*)in.c_str(), in.size(),
|
||||||
0, buff, &len),
|
0, buff, &len),
|
||||||
"smartcard transmit message "+crypto::hex(in));
|
"smartcard transmit message "+crypto::hex(in));
|
||||||
|
PCSC_LOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
|
||||||
return std::string((char*)buff, len);
|
return std::string((char*)buff, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user