Skip to content

Instantly share code, notes, and snippets.

@cmouse
Created February 24, 2014 07:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmouse/9183485 to your computer and use it in GitHub Desktop.
Save cmouse/9183485 to your computer and use it in GitHub Desktop.
#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;
}
@cmouse
Copy link
Author

cmouse commented Feb 24, 2014

$ ./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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment