Created
February 24, 2014 07:41
-
-
Save cmouse/9183485 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cstdlib> | |
#include <iomanip> | |
#include <boost/archive/iterators/base64_from_binary.hpp> | |
#include <boost/archive/iterators/insert_linebreaks.hpp> | |
#include <boost/archive/iterators/transform_width.hpp> | |
#include <boost/archive/iterators/ostream_iterator.hpp> | |
#include <sstream> | |
#include <string> | |
#include <string.h> | |
#include <p11-kit/p11-kit.h> | |
namespace bai=boost::archive::iterators; | |
int main(void) { | |
// we only use known modules | |
p11_kit_initialize_registered(); | |
CK_FUNCTION_LIST_PTR *modules = p11_kit_registered_modules(); | |
CK_FUNCTION_LIST_PTR module; | |
_CK_INFO info; | |
_CK_SLOT_INFO slotInfo; | |
_CK_TOKEN_INFO tokenInfo; | |
CK_SLOT_ID slotID; | |
// locate us a module which has a usable token | |
while((module = *modules)) { | |
unsigned long slots; | |
module->C_GetInfo(&info); | |
module->C_GetSlotList(1, NULL, &slots); | |
if (slots > 0) { | |
for(unsigned long i=0;i<slots;i++) { | |
module->C_GetSlotInfo(i, &slotInfo); | |
if ((slotInfo.flags & CKF_TOKEN_PRESENT) == CKF_TOKEN_PRESENT) { | |
module->C_GetTokenInfo(i, &tokenInfo); | |
if ((tokenInfo.flags & CKF_TOKEN_INITIALIZED) == CKF_TOKEN_INITIALIZED) { | |
slotID = i; | |
goto hasModule; | |
} | |
} | |
} | |
} | |
modules++; | |
} | |
// FIXME: Gotos are bad | |
hasModule: if (module == NULL) { | |
std::cout << "No module chosen" << std::endl; | |
return 1; | |
} | |
std::cout << "Chosen manufacturer: " << info.manufacturerID << std::endl; | |
// needs login? | |
CK_SESSION_HANDLE session; | |
std::cout << module->C_OpenSession(slotID, CKF_SERIAL_SESSION, 0, 0, &session) << std::endl; | |
if ((tokenInfo.flags & CKF_LOGIN_REQUIRED) == CKF_LOGIN_REQUIRED) { | |
// provide 1234 | |
unsigned char pin[] = "1234"; | |
std::cout << module->C_Login(session, CKU_USER, pin, 4) << std::endl; | |
} | |
unsigned long mechs; | |
module->C_GetMechanismList(slotID, NULL, &mechs); | |
CK_MECHANISM_TYPE *mechTypes = new CK_MECHANISM_TYPE[mechs]; | |
module->C_GetMechanismList(slotID, mechTypes, &mechs); | |
for(unsigned long i=0;i<mechs;i++) { | |
_CK_MECHANISM_INFO mechInfo; | |
module->C_GetMechanismInfo(slotID, mechTypes[i], &mechInfo); | |
std::cout << "Mechanism type " << std::hex << mechTypes[i] << " key size " << std::dec << mechInfo.ulMinKeySize << "-" << mechInfo.ulMaxKeySize << " flags " << std::hex << mechInfo.flags << std::endl; | |
} | |
// try usign mech RSA_SHA1 | |
CK_MECHANISM mech; | |
mech.mechanism = CKM_SHA256_RSA_PKCS; | |
mech.pParameter = 0; | |
mech.ulParameterLen = 0; | |
unsigned long objects; | |
// need key object | |
CK_OBJECT_HANDLE object; | |
CK_ATTRIBUTE attr[5]; | |
attr[0].type = CKA_SIGN; | |
char value = CK_TRUE; | |
attr[0].pValue = &value; | |
attr[0].ulValueLen = 1; | |
attr[1].type = CKA_LABEL; | |
attr[1].pValue = const_cast<char*>("test"); | |
attr[1].ulValueLen = 4; | |
module->C_FindObjectsInit(session, attr, 2); | |
module->C_FindObjects(session, &object, 1, &objects); | |
module->C_FindObjectsFinal(session); | |
unsigned char data[] = "A quick brown fox jumped over the lazy fox"; | |
unsigned long datalen = sizeof(data); | |
unsigned char digest[4096]; | |
unsigned long digestlen = sizeof(digest); | |
std::cout << module->C_SignInit(session, &mech, object) << std::endl; | |
std::cout << module->C_Sign(session, data, datalen, digest, &digestlen) << std::endl; | |
// try verify signature | |
attr[0].type = CKA_VERIFY; | |
attr[0].pValue = &value; | |
attr[0].ulValueLen = 1; | |
module->C_FindObjectsInit(session, attr, 1); | |
module->C_FindObjects(session, &object, 1, &objects); | |
module->C_FindObjectsFinal(session); | |
std::cout << module->C_VerifyInit(session, &mech, object) << std::endl; | |
std::cout << module->C_Verify(session, data, datalen, digest, digestlen) << std::endl; | |
// locate public key and try export it to some reasonable format | |
attr[0].type = CKA_CLASS; | |
unsigned long value2 = CKO_PUBLIC_KEY; | |
attr[0].pValue = &value2; | |
attr[0].ulValueLen = sizeof(value2); | |
module->C_FindObjectsInit(session, attr, 1); | |
module->C_FindObjects(session, &object, 1, &objects); | |
module->C_FindObjectsFinal(session); | |
attr[0].type = CKA_MODULUS; | |
attr[0].pValue = new unsigned char[4096]; | |
attr[0].ulValueLen = 4096; | |
attr[1].type = CKA_MODULUS_BITS; | |
attr[1].pValue = new unsigned char[4096]; | |
attr[1].ulValueLen = 4096; | |
attr[2].type = CKA_PUBLIC_EXPONENT; | |
attr[2].pValue = new unsigned char[4096]; | |
attr[2].ulValueLen = 4096; | |
// try to get more attributes | |
module->C_GetAttributeValue(session, object, attr, 3); | |
// print props | |
CK_BYTE_PTR pModulus, pExponent; | |
pModulus = (CK_BYTE_PTR)attr[0].pValue; | |
pExponent = (CK_BYTE_PTR)attr[1].pValue; | |
unsigned char buffer[8196] = {0}; | |
size_t bs = 0; | |
// | |
typedef | |
bai::base64_from_binary< | |
bai::transform_width< | |
char*, | |
6, | |
8 | |
> | |
> | |
base64_text; | |
unsigned int keytag = 0; | |
buffer[0] = static_cast<unsigned char>(attr[2].ulValueLen); | |
memcpy(buffer+1,pExponent,attr[1].ulValueLen); | |
bs = 1 + attr[2].ulValueLen; | |
memcpy(buffer+bs,pModulus,attr[0].ulValueLen); | |
bs += attr[0].ulValueLen; | |
for(size_t i = 0; i < bs; i++) | |
keytag += (i & 1) ? buffer[i] : buffer[i] << 8; | |
keytag += (keytag >> 16) & 0xFFFF; | |
keytag = keytag & 0xFFFF; | |
std::stringstream os; | |
std::copy(base64_text(buffer), base64_text(buffer + bs), bai::ostream_iterator<char>(os)); | |
std::cout << "example.com IN DNSKEY 256 3 8 " << os.str() << std::endl; | |
mech.mechanism = CKM_SHA256; | |
module->C_DigestInit(session, &mech); | |
module->C_DigestUpdate(session, (unsigned char*)("example.com"), 11); | |
module->C_DigestUpdate(session, buffer, bs); | |
digestlen = sizeof digest; | |
module->C_DigestFinal(session, digest, &digestlen); | |
// print out DS | |
os.str(""); | |
std::copy(base64_text(digest), base64_text(digest + digestlen), bai::ostream_iterator<char>(os)); | |
std::cout << "example.com IN DS " << std::dec << keytag << " 5 2 " << os.str() << std::endl; | |
p11_kit_finalize_registered(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
$ ./pkcs11
p11-kit: 'id >= BASE_SLOT_ID && id - BASE_SLOT_ID < gl.tokens->num' not true at lookup_slot_inlock
Chosen manufacturer: SoftHSM
0
0
Mechanism type 0 key size 512-4096 flags 10000
Mechanism type 1 key size 512-4096 flags 2b00
Mechanism type 3 key size 512-4096 flags 2800
Mechanism type 210 key size 0-0 flags 400
Mechanism type 240 key size 0-0 flags 400
Mechanism type 220 key size 0-0 flags 400
Mechanism type 250 key size 0-0 flags 400
Mechanism type 260 key size 0-0 flags 400
Mechanism type 270 key size 0-0 flags 400
Mechanism type 5 key size 512-4096 flags 2800
Mechanism type 8 key size 512-4096 flags 2800
Mechanism type 6 key size 512-4096 flags 2800
Mechanism type 40 key size 512-4096 flags 2800
Mechanism type 41 key size 512-4096 flags 2800
Mechanism type 42 key size 512-4096 flags 2800
0
0
0
0
example.com IN DNSKEY 256 3 8 AwAIALr5KjkipReknEJAITSBaVhTF/+IF3wXWiAebAHmRctNUY5K/8T4owLFREFLMUNSy4oKEnIt5QL9BHVDuokuNqVs7rmwu2ZVARnuROXYrveaCV+M2lG6RaeUD7nIYFBIIBJb8orWZX0mWnJlghoU64QH7LpUnNgaSDFm+ib7p1aQMuG3BBlMl6on7nNg8gf3CYimRpdTlwaQ5aV5ixV2Fi+lZsR7jbsAXyBGuP2kEQkjPk+KKxDVeB6FKwMT+yYuF9PLg2itpRG6gfyZYJ8lkt5hUDwXmXHKdrH2AN9zFa0jfMfT+wGBX0qh0YzK9gx7BG03CjxplC0vYn7INpwUtes
example.com IN DS 53490 5 2 dHhrhVFaNqg62f/wL7UrBcJcsT1ROj/eLUqUnwpEchs