|
|
|
|
|
|
|
#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->Release();
|
|
|
|
|
|
|
|
}
|
|
|
|
// 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++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|