A simple Qt based browser with no bullshit that supports PKCS#11 tokens (such as the SuisseID).
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
4.0 KiB

14 years ago
#include "engine_sct.h"
#include "CertificateList.h"
#include "SlotList.h"
#include "SecOpGuard.h"
#include <openssl/objects.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#ifdef U64
#undef U64
#endif
#include <actUtility.h>
#include <actITokenKey.h>
#include <actIToken.h>
#include <actISlot.h>
#include <actDebug.h>
#include <sstream>
#include <string>
CertificateList::CertificateList()
: m_num_certs(0)
, m_enum_list(NULL)
{
}
CertificateList::~CertificateList()
{
release_list();
}
void CertificateList::release_list()
{
if(m_enum_list == NULL) return;
enum_cert_s* cert_p = m_enum_list->certificate;
// Can only happen if someone tampered with the returned structure.
ACT_ASSERT(m_num_certs == m_enum_list->num_certs);
// No matter, we just use our value in any case.
for(int i=m_num_certs;i--;)
{
free((void *)cert_p[i].id);
free((void *)cert_p[i].name);
X509_free(cert_p[i].cert);
}
free(m_enum_list);
m_enum_list = NULL;
m_num_certs = 0;
}
void CertificateList::init(SlotList& slots)
{
cert_map_t cert_temp_map;
for(size_t i=slots.getNumSlots();i--;)
{
act::IToken* token = slots.getToken(i);
if(!token)
continue;
{
// Needs to be transacted
SecOpGuard guard(token);
// Iterate over the certificates on the token, adding them with empty ID
for(int j=token->GetCertificateNumber();j--;)
{
act::CertEntry ce(token->GetCertificate(j));
cert_tmp_s temp;
temp.slot_number = i;
cert_temp_map[ce.certblob] = temp;
}
// Iterate over the keys and insert their ID's into the corresponding certificates
for(int j=token->GetKeyNumber();j--;)
{
act::ITokenKey* key = dynamic_cast<act::ITokenKey*>(token->GetKey(j));
if(key == NULL)
continue;
act::Blob certblob(key->GetCertificate());
cert_map_t::iterator it = cert_temp_map.find(certblob);
// Sort key ID into the certificate data if found
if(it != cert_temp_map.end())
{
it->second.name = key->GetName();
it->second.id = key->GetID();
}
// What about keypairs without a certificate? We could add entries with no certs...?
}
}
token->Destroy();
}
// Now we have a map of all certificates. Those with IDs are connected to a keypair, those without
// are just stored on the card, probably CA certificates or somesuch.
m_num_certs = cert_temp_map.size();
ACT_ASSERT(m_enum_list == NULL);
// Allocate the needed memory to hold the structure heading plus the certificate pointers themselves
m_enum_list = reinterpret_cast<enum_certs_s*>(
malloc(sizeof(enum_certs_s) + m_num_certs * sizeof(enum_cert_s)));
// Bail out if we can't allocate.
if(!m_enum_list)
return;
m_enum_list->num_certs = m_num_certs;
enum_cert_s* cert_p = &m_enum_list->certificate[0];
// Now place the decoded certificates and key id's (if applicable) into a neat structure.
for(cert_map_t::const_iterator it = cert_temp_map.begin(); it != cert_temp_map.end();++it)
{
const act::Blob& certblob = it->first;
const unsigned char *cbp = &certblob[0];
cert_p->cert = d2i_X509(NULL, &cbp, certblob.size());
const cert_tmp_s& id_tmp = it->second;
cert_p->id = NULL;
if(!id_tmp.id.empty())
{
std::stringstream ss;
ss << "slot-" << id_tmp.slot_number << "-id-" << act::blob2hex(id_tmp.id);
std::string id_str(ss.str());
size_t len = id_str.length();
const char *src_p = id_str.c_str();
char *p = reinterpret_cast<char *>(malloc(len+1 * sizeof(char)));
if(p)
{
p[len]=0;
std::copy(src_p, src_p+len, p);
cert_p->id = (const char *)p;
}
}
cert_p->name = NULL;
if(!id_tmp.name.empty())
{
std::stringstream ss;
ss << "slot-" << id_tmp.slot_number << "-name-" << id_tmp.name;
std::string name_str(ss.str());
size_t len = name_str.length();
const char *src_p = name_str.c_str();
char *p = reinterpret_cast<char *>(malloc(len+1 * sizeof(char)));
if(p)
{
p[len]=0;
std::copy(src_p, src_p+len, p);
cert_p->name = (const char *)p;
}
}
cert_p++;
}
}