Crypt-HSM
view release on metacpan or search on metacpan
lib/Crypt/HSM.xs view on Meta::CPAN
av_push(get_av("Crypt::HSM::Encrypt::ISA", GV_ADD), SvREFCNT_inc(stream));
av_push(get_av("Crypt::HSM::Decrypt::ISA", GV_ADD), SvREFCNT_inc(stream));
av_push(get_av("Crypt::HSM::Digest::ISA" , GV_ADD), SvREFCNT_inc(stream));
av_push(get_av("Crypt::HSM::Sign::ISA" , GV_ADD), SvREFCNT_inc(stream));
av_push(get_av("Crypt::HSM::Verify::ISA" , GV_ADD), SvREFCNT_inc(stream));
SvREFCNT_dec(stream);
Crypt::HSM::Provider load(class, const char* path)
CODE:
void* handle;
CK_FUNCTION_LIST* funcs;
handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
if (!handle)
croak("Can not open library: %s", dlerror());
CK_C_GetFunctionList C_GetFunctionList = (CK_C_GetFunctionList) dlsym(handle, "C_GetFunctionList");
if (C_GetFunctionList == NULL)
croak("Symbol lookup failed");
CK_RV rc = C_GetFunctionList(&funcs);
if (rc != CKR_OK)
croak_with("Call to C_GetFunctionList failed", rc);
#if defined(USE_THREADS) || defined(__linux__)
CK_C_INITIALIZE_ARGS init_args = { NULL, NULL, NULL, NULL, CKF_OS_LOCKING_OK, NULL };
#else
CK_C_INITIALIZE_ARGS init_args = { NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, NULL };
#endif
rc = funcs->C_Initialize(&init_args);
if (rc != CKR_OK)
croak_with("Call to C_Initialize failed", rc);
RETVAL = (struct Provider*) PerlMemShared_calloc(1, sizeof(struct Provider));
refcount_init(&RETVAL->refcount, 1);
RETVAL->handle = handle;
RETVAL->funcs = funcs;
OUTPUT: RETVAL
MODULE = Crypt::HSM PACKAGE = Crypt::HSM::Provider
HV* info(Crypt::HSM::Provider self)
CODE:
CK_INFO info;
CK_RV result = self->funcs->C_GetInfo(&info);
if (result != CKR_OK)
croak_with("Couldn't get provider info", result);
RETVAL = newHV();
hv_stores(RETVAL, "cryptoki-version", version_to_sv(&info.cryptokiVersion));
hv_stores(RETVAL, "manufacturer-id", trimmed_value(info.manufacturerID, 32));
hv_stores(RETVAL, "flags", newRV_noinc((SV*)newHV()));
hv_stores(RETVAL, "library-description", trimmed_value(info.libraryDescription, 32));
hv_stores(RETVAL, "library-version", version_to_sv(&info.libraryVersion));
OUTPUT: RETVAL
void slots(Crypt::HSM::Provider self, CK_BBOOL tokenPresent = 1)
PPCODE:
CK_ULONG count, i;
CK_RV result = self->funcs->C_GetSlotList(tokenPresent, NULL, &count);
if ( result != CKR_OK )
croak_with("Couldn't get slots", result);
EXTEND(SP, (int)count);
CK_SLOT_ID_PTR slotList = safecalloc(count, sizeof(CK_SLOT_ID));
SAVEFREEPV(slotList);
result = self->funcs->C_GetSlotList(tokenPresent, slotList, &count);
if (result != CKR_OK)
croak_with("Couldn't get slots", result);
for(i = 0; i < count; i++)
mPUSHs(new_slot(self, slotList[i]));
SV* slot(Crypt::HSM::Provider self, CK_SLOT_ID slot)
CODE:
RETVAL = new_slot(self, slot);
OUTPUT: RETVAL
SV* wait_for_event(Crypt::HSM::Provider self, ...)
CODE:
CK_ULONG flags = 0;
int i;
for (i = 1; i < items; ++i)
flags |= get_flags(wait_flags, ST(i));
CK_SLOT_ID slot;
CK_RV result = self->funcs->C_WaitForSlotEvent(flags, &slot, NULL);
if (result == CKR_OK)
RETVAL = new_slot(self, slot);
else if (result == CKR_NO_EVENT)
RETVAL = &PL_sv_undef;
else
croak_with("Couldn't wait for slot event", result);
OUTPUT: RETVAL
MODULE = Crypt::HSM PACKAGE = Crypt::HSM::Slot
CK_SLOT_ID id(Crypt::HSM::Slot self)
CODE:
RETVAL = self->slot;
OUTPUT: RETVAL
HV* info(Crypt::HSM::Slot self)
CODE:
CK_SLOT_INFO info;
CK_RV result = slot_funcs(self)->C_GetSlotInfo(self->slot, &info);
if (result != CKR_OK)
croak_with("Couldn't get slot info", result);
RETVAL = newHV();
hv_stores(RETVAL, "description", trimmed_value(info.slotDescription, 64));
hv_stores(RETVAL, "manufacturer-id", trimmed_value(info.manufacturerID, 32));
hv_stores(RETVAL, "flags", reverse_flags(slot_flags, info.flags));
hv_stores(RETVAL, "hardware-version", version_to_sv(&info.hardwareVersion));
hv_stores(RETVAL, "firmware-version", version_to_sv(&info.firmwareVersion));
OUTPUT: RETVAL
HV* token_info(Crypt::HSM::Slot self)
CODE:
CK_TOKEN_INFO info;
CK_RV result = slot_funcs(self)->C_GetTokenInfo(self->slot, &info);
if (result != CKR_OK)
croak_with("Couldn't get token info", result);
RETVAL = newHV();
hv_stores(RETVAL, "label", trimmed_value(info.label, 32));
hv_stores(RETVAL, "manufacturer-id", trimmed_value(info.manufacturerID, 32));
hv_stores(RETVAL, "model", trimmed_value(info.model, 16));
hv_stores(RETVAL, "serial-number", trimmed_value(info.serialNumber, 16));
hv_stores(RETVAL, "flags", reverse_flags(token_flags, info.flags));
hv_stores(RETVAL, "max-session-count", newSVuv(info.ulMaxSessionCount));
hv_stores(RETVAL, "session-count", newSVuv(info.ulSessionCount));
hv_stores(RETVAL, "max-rw-session-count", newSVuv(info.ulMaxRwSessionCount));
hv_stores(RETVAL, "rw-session-count", newSVuv(info.ulRwSessionCount));
hv_stores(RETVAL, "max-pin-len", newSVuv(info.ulMaxPinLen));
hv_stores(RETVAL, "min-pin-len", newSVuv(info.ulMinPinLen));
hv_stores(RETVAL, "total-public-memory", newSVuv(info.ulTotalPublicMemory));
hv_stores(RETVAL, "free-public-memory", newSVuv(info.ulFreePublicMemory));
hv_stores(RETVAL, "total-private-memory", newSVuv(info.ulTotalPrivateMemory));
hv_stores(RETVAL, "free-private-memory", newSVuv(info.ulFreePrivateMemory));
hv_stores(RETVAL, "hardware-version", version_to_sv(&info.hardwareVersion));
hv_stores(RETVAL, "firmware-version", version_to_sv(&info.firmwareVersion));
hv_stores(RETVAL, "utc-time", trimmed_value(info.utcTime, 16));
OUTPUT: RETVAL
Crypt::HSM::Session open_session(Crypt::HSM::Slot self, ...)
CODE:
CK_NOTIFY Notify = NULL;
CK_SESSION_HANDLE handle;
CK_ULONG flags = CKF_SERIAL_SESSION;
ssize_t current = 1;
for (current = 1; current + 2 <= items; current += 2) {
CK_ULONG internal = map_get(session_flags, ST(current), "session flag");
if (SvTRUE(ST(current + 1)))
flags |= internal;
else
flags &= ~internal;
}
CK_RV result = slot_funcs(self)->C_OpenSession(self->slot, flags | CKF_SERIAL_SESSION, NULL, Notify, &handle);
if (result != CKR_OK)
croak_with("Could not open session", result);
RETVAL = PerlMemShared_calloc(1, sizeof(struct Session));
refcount_init(&RETVAL->refcount, 1);
RETVAL->slot = slot_refcount_increment(self);
RETVAL->handle = handle;
OUTPUT: RETVAL
void mechanisms(Crypt::HSM::Slot self)
PPCODE:
CK_ULONG length, i;
CK_RV result = slot_funcs(self)->C_GetMechanismList(self->slot, NULL, &length);
if (result != CKR_OK)
croak_with("Couldn't get mechanisms length", result);
CK_MECHANISM_TYPE* types = safecalloc(length, sizeof(CK_MECHANISM_TYPE));
SAVEFREEPV(types);
result = slot_funcs(self)->C_GetMechanismList(self->slot, types, &length);
if (result != CKR_OK)
croak_with("Couldn't get mechanisms", result);
for (i = 0; i < length; ++i)
mXPUSHs(new_mechanism(self, types[i]));
SV* mechanism(Crypt::HSM::Slot self, CK_MECHANISM_TYPE type)
CODE:
RETVAL = new_mechanism(self, type);
OUTPUT: RETVAL
void close_all_sessions(Crypt::HSM::Slot self)
CODE:
CK_RV result = slot_funcs(self)->C_CloseAllSessions(self->slot);
if (result != CKR_OK)
croak_with("Could not open session", result);
void init_token(Crypt::HSM::Slot self, SV* pin, SV* label)
CODE:
CK_BYTE label_buffer[32];
CK_ULONG pin_len, label_len;
CK_UTF8CHAR* pinPV = get_text(pin, &pin_len);
CK_UTF8CHAR* labelPV = get_text(label, &label_len);
memset(label_buffer, ' ', 32);
memcpy(label_buffer, labelPV, MIN(label_len, 32));
CK_RV result = slot_funcs(self)->C_InitToken(self->slot, pinPV, pin_len, label_buffer);
if (result != CKR_OK)
croak_with("Could not initialize token", result);
MODULE = Crypt::HSM PACKAGE = Crypt::HSM::Mechanism
SV* name(Crypt::HSM::Mechanism self)
CODE:
const entry* item = map_reverse_find(mechanisms, self->mechanism);
RETVAL = item ? newSVpvn(item->key, item->length) : newSV(0);
OUTPUT: RETVAL
Crypt::HSM::Mechanism::Info info(Crypt::HSM::Mechanism self)
CODE:
RETVAL = safemalloc(sizeof(CK_MECHANISM_INFO));
CK_RV result = slot_funcs(self->slot)->C_GetMechanismInfo(self->slot->slot, self->mechanism, RETVAL);
if (result != CKR_OK) {
Safefree(RETVAL);
croak_with("Couldn't get mechanism info", result);
}
OUTPUT: RETVAL
MODULE = Crypt::HSM PACKAGE = Crypt::HSM::Mechanism::Info
HV* hash(Crypt::HSM::Mechanism::Info self)
CODE:
RETVAL = newHV();
hv_stores(RETVAL, "min-key-size", newSVuv(self->ulMinKeySize));
hv_stores(RETVAL, "max-key-size", newSVuv(self->ulMaxKeySize));
hv_stores(RETVAL, "flags", reverse_flags(mechanism_flags, self->flags));
OUTPUT: RETVAL
bool has_flags(Crypt::HSM::Mechanism::Info self, ...)
CODE:
CK_ULONG flags = 0;
int i;
for (i = 1; i < items; ++i)
flags |= get_flags(mechanism_flags, ST(i));
RETVAL = (self->flags & flags) == flags;
OUTPUT: RETVAL
void flags(Crypt::HSM::Mechanism::Info self)
PPCODE:
CK_ULONG i;
for (i = 0; i < CHAR_BIT * sizeof(CK_ULONG); ++i) {
CK_ULONG right = 1ul << i;
if (self->flags & right)
mXPUSHs(entry_to_sv(map_reverse_find(mechanism_flags, right)));
}
CK_ULONG min_key_size(Crypt::HSM::Mechanism::Info self)
CODE:
RETVAL = self->ulMinKeySize;
OUTPUT: RETVAL
CK_ULONG max_key_size(Crypt::HSM::Mechanism::Info self)
CODE:
RETVAL = self->ulMaxKeySize;
OUTPUT: RETVAL
MODULE = Crypt::HSM PACKAGE = Crypt::HSM::Session PREFIX = session_
HV* info(Crypt::HSM::Session self)
CODE:
CK_SESSION_INFO info;
CK_RV result = session_funcs(self)->C_GetSessionInfo(self->handle, &info);
if (result != CKR_OK)
croak_with("Couldn't get session info", result);
RETVAL = newHV();
hv_stores(RETVAL, "slot-id", newSVuv(info.slotID));
hv_stores(RETVAL, "state", entry_to_sv(map_reverse_find(state_flags, info.state)));
hv_stores(RETVAL, "flags", reverse_flags(session_flags, info.flags));
hv_stores(RETVAL, "device-error", newSVuv(info.ulDeviceError));
OUTPUT: RETVAL
Crypt::HSM::Provider provider(Crypt::HSM::Session self)
CODE:
RETVAL = provider_refcount_increment(self->slot->provider);
OUTPUT: RETVAL
Crypt::HSM::Slot slot(Crypt::HSM::Session self)
CODE:
RETVAL = slot_refcount_increment(self->slot);
OUTPUT: RETVAL
void login(Crypt::HSM::Session self, CK_USER_TYPE type, SV* pin)
CODE:
CK_ULONG pin_len = 0;
CK_UTF8CHAR* pinPV = NULL;
if (SvOK(pin))
pinPV = get_text(pin, &pin_len);
CK_RV result = session_funcs(self)->C_Login(self->handle, type, pinPV, pin_len);
if (result != CKR_OK)
croak_with("Could not log in", result);
void logout(Crypt::HSM::Session self)
CODE:
CK_RV result = session_funcs(self)->C_Logout(self->handle);
if (result != CKR_OK)
croak_with("Could not log out", result);
void init_pin(Crypt::HSM::Session self, SV* pin)
CODE:
CK_ULONG pin_len = 0;
CK_UTF8CHAR* pinPV = NULL;
if (SvOK(pin))
pinPV = get_text(pin, &pin_len);
CK_RV result = session_funcs(self)->C_InitPIN(self->handle, pinPV, pin_len);
if (result != CKR_OK)
croak_with("Could not initialize pin", result);
void set_pin(Crypt::HSM::Session self, SV* old_pin, SV* new_pin)
CODE:
CK_ULONG old_pin_len = 0, new_pin_len = 0;
CK_UTF8CHAR* old_pinPV = NULL, *new_pinPV = NULL;
if (SvOK(old_pin))
old_pinPV = get_text(old_pin, &old_pin_len);
if (SvOK(new_pin))
new_pinPV = get_text(new_pin, &new_pin_len);
CK_RV result = session_funcs(self)->C_SetPIN(self->handle, old_pinPV, old_pin_len, new_pinPV, new_pin_len);
if (result != CKR_OK)
croak_with("Could not set pin", result);
SV* create_object(Crypt::HSM::Session self, Attributes template)
CODE:
CK_OBJECT_HANDLE handle;
CK_RV result = session_funcs(self)->C_CreateObject(self->handle, template.member, template.length, &handle);
if (result != CKR_OK)
croak_with("Could not create object", result);
RETVAL = new_object(self, handle);
OUTPUT: RETVAL
void find_objects(Crypt::HSM::Session self, Attributes attributes = empty)
PPCODE:
CK_RV result = session_funcs(self)->C_FindObjectsInit(self->handle, attributes.member, attributes.length);
if (result != CKR_OK)
croak_with("Could not find objects", result);
CK_ULONG actual = 0;
do {
CK_OBJECT_HANDLE current[16];
CK_ULONG iter;
CK_RV result = session_funcs(self)->C_FindObjects(self->handle, current, sizeof(current) / sizeof(*current), &actual);
if (result != CKR_OK) {
session_funcs(self)->C_FindObjectsFinal(self->handle);
croak_with("Could not find objects", result);
}
for (iter = 0; iter < actual; ++iter)
mXPUSHs(new_object(self, current[iter]));
} while (actual > 0);
session_funcs(self)->C_FindObjectsFinal(self->handle);
void generate_keypair(Crypt::HSM::Session self, CK_MECHANISM_TYPE mechanism_type, Attributes publicKeyTemplate, Attributes privateKeyTemplate, ...)
PPCODE:
CK_OBJECT_HANDLE publicKey;
CK_OBJECT_HANDLE privateKey;
CK_MECHANISM mechanism = mechanism_from_args(mechanism_type, 4);
CK_RV result = session_funcs(self)->C_GenerateKeyPair(self->handle, &mechanism, publicKeyTemplate.member, publicKeyTemplate.length, privateKeyTemplate.member, privateKeyTemplate.length, &publicKey, &privateKey);
if (result != CKR_OK)
croak_with("Could not create keypair", result);
mXPUSHs(new_object(self, publicKey));
mXPUSHs(new_object(self, privateKey));
SV* generate_key(Crypt::HSM::Session self, CK_MECHANISM_TYPE mechanism_type, Attributes keyTemplate = empty, ...)
CODE:
CK_MECHANISM mechanism = mechanism_from_args(mechanism_type, 3);
CK_OBJECT_HANDLE handle;
CK_RV result = session_funcs(self)->C_GenerateKey(self->handle, &mechanism, keyTemplate.member, keyTemplate.length, &handle);
if (result != CKR_OK)
croak_with("Could not create key", result);
RETVAL = new_object(self, handle);
OUTPUT: RETVAL
SV* encrypt(Crypt::HSM::Session self, CK_MECHANISM_TYPE mechanism_type, Crypt::HSM::Object key, SV* data, ...)
CODE:
CK_MECHANISM mechanism = mechanism_from_args(mechanism_type, 4);
CK_RV result = session_funcs(self)->C_EncryptInit(self->handle, &mechanism, key->handle);
if (result != CKR_OK)
croak_with("Couldn't initialize encryption", result);
CK_ULONG dataLen, encryptedDataLen;
CK_BYTE* dataPV = get_buffer(data, &dataLen);
result = session_funcs(self)->C_Encrypt(self->handle, dataPV, dataLen, NULL, &encryptedDataLen);
if (result != CKR_OK)
croak_with("Couldn't compute encrypted length", result);
RETVAL = newSV(encryptedDataLen);
SvPOK_only(RETVAL);
result = session_funcs(self)->C_Encrypt(self->handle, dataPV, dataLen, (CK_BYTE*)SvPVbyte_nolen(RETVAL), &encryptedDataLen);
if (result != CKR_OK) {
SvREFCNT_dec(RETVAL);
croak_with("Couldn't encrypt", result);
}
SvCUR(RETVAL) = encryptedDataLen;
OUTPUT: RETVAL
Crypt::HSM::Encrypt open_encrypt(Crypt::HSM::Session self, CK_MECHANISM_TYPE mechanism_type, Crypt::HSM::Object key, ...)
CODE:
CK_MECHANISM mechanism = mechanism_from_args(mechanism_type, 3);
CK_RV result = session_funcs(self)->C_EncryptInit(self->handle, &mechanism, key->handle);
if (result != CKR_OK)
croak_with("Couldn't initialize encryption", result);
RETVAL = open_stream(self, key->handle, CK_INVALID_HANDLE);
OUTPUT: RETVAL
SV* decrypt(Crypt::HSM::Session self, CK_MECHANISM_TYPE mechanism_type, Crypt::HSM::Object key, SV* data, ...)
CODE:
( run in 1.176 second using v1.01-cache-2.11-cpan-71847e10f99 )