#include "engine_sct.h" #include "CertificateList.h" #include "SlotList.h" #include "SecOpGuard.h" #include #include #include #ifdef U64 #undef U64 #endif #include #include #include #include #include #include #include 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(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( 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(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(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++; } }