132 lines
3.7 KiB
C
132 lines
3.7 KiB
C
/******************************************************************************
|
|
Custom Keystore Provider Example
|
|
|
|
Windows: compile with cl myKSP.c /LD /MD /link /out:myKSP.dll
|
|
Linux/mac: compile with gcc -fshort-wchar -fPIC -o myKSP.so -shared myKSP.c
|
|
|
|
******************************************************************************/
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#else
|
|
#define __stdcall
|
|
#endif
|
|
|
|
#define DEBUG 0
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sqltypes.h>
|
|
#include <sql.h>
|
|
#include <sqlext.h>
|
|
#include "msodbcsql.h"
|
|
|
|
int wcscmp_short(wchar_t *s1, wchar_t *s2) {
|
|
while(*s1 && *s2 && *s1 == *s2)
|
|
s1++, s2++;
|
|
return *s1 - *s2;
|
|
}
|
|
|
|
int __stdcall KeystoreInit(CEKEYSTORECONTEXT *ctx, errFunc *onError) {
|
|
if (DEBUG)
|
|
printf("KSP Init() function called\n");
|
|
return 1;
|
|
}
|
|
|
|
static unsigned char *g_encryptKey;
|
|
static unsigned int g_encryptKeyLen;
|
|
|
|
int __stdcall KeystoreWrite(CEKEYSTORECONTEXT *ctx, errFunc *onError, void *data, unsigned int len) {
|
|
if (DEBUG)
|
|
printf("KSP Write() function called (%d bytes)\n", len);
|
|
if (len) {
|
|
if (g_encryptKey)
|
|
free(g_encryptKey);
|
|
g_encryptKey = malloc(len);
|
|
if (!g_encryptKey) {
|
|
onError(ctx, L"Memory Allocation Error");
|
|
return 0;
|
|
}
|
|
memcpy(g_encryptKey, data, len);
|
|
g_encryptKeyLen = len;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// Very simple "encryption" scheme - rotating XOR with the key
|
|
int __stdcall KeystoreDecrypt(CEKEYSTORECONTEXT *ctx, errFunc *onError, const wchar_t *keyPath, const wchar_t *alg, unsigned char *ecek, unsigned short ecekLen, unsigned char **cekOut, unsigned short *cekLen) {
|
|
unsigned int i;
|
|
if (DEBUG)
|
|
printf("KSP Decrypt() function called (keypath=%S alg=%S ecekLen=%u)\n", keyPath, alg, ecekLen);
|
|
if (wcscmp_short(keyPath, L"TheOneAndOnlyKey")) {
|
|
onError(ctx, L"Invalid key path");
|
|
return 0;
|
|
}
|
|
if (wcscmp_short(alg, L"none")) {
|
|
onError(ctx, L"Invalid algorithm");
|
|
return 0;
|
|
}
|
|
if (!g_encryptKey) {
|
|
onError(ctx, L"Keystore provider not initialized with key");
|
|
return 0;
|
|
}
|
|
#ifndef _WIN32
|
|
*cekOut = malloc(ecekLen);
|
|
#else
|
|
*cekOut = LocalAlloc(LMEM_FIXED, ecekLen);
|
|
#endif
|
|
if (!*cekOut) {
|
|
onError(ctx, L"Memory Allocation Error");
|
|
return 0;
|
|
}
|
|
*cekLen = ecekLen;
|
|
for (i = 0; i < ecekLen; i++)
|
|
(*cekOut)[i] = ecek[i] ^ g_encryptKey[i % g_encryptKeyLen];
|
|
return 1;
|
|
}
|
|
|
|
// Note that in the provider interface, this function would be referenced via the CEKEYSTOREPROVIDER
|
|
// structure. However, that does not preclude keystore providers from exporting their own functions,
|
|
// as illustrated by this example where the encryption is performed via a separate function (with a
|
|
// different prototype than the one in the KSP interface.)
|
|
#ifdef _WIN32
|
|
__declspec(dllexport)
|
|
#endif
|
|
int KeystoreEncrypt(CEKEYSTORECONTEXT *ctx, errFunc *onError,
|
|
unsigned char *cek, unsigned short cekLen,
|
|
unsigned char **ecekOut, unsigned short *ecekLen) {
|
|
unsigned int i;
|
|
|
|
if (DEBUG)
|
|
printf("KSP Encrypt() function called (cekLen=%u)\n", cekLen);
|
|
if (!g_encryptKey) {
|
|
onError(ctx, L"Keystore provider not initialized with key");
|
|
return 0;
|
|
}
|
|
*ecekOut = malloc(cekLen);
|
|
if (!*ecekOut) {
|
|
onError(ctx, L"Memory Allocation Error");
|
|
return 0;
|
|
}
|
|
*ecekLen = cekLen;
|
|
for (i = 0; i < cekLen; i++)
|
|
(*ecekOut)[i] = cek[i] ^ g_encryptKey[i % g_encryptKeyLen];
|
|
return 1;
|
|
}
|
|
|
|
CEKEYSTOREPROVIDER MyCustomKSPName_desc = {
|
|
L"MyCustomKSPName",
|
|
KeystoreInit,
|
|
0,
|
|
KeystoreWrite,
|
|
KeystoreDecrypt,
|
|
0
|
|
};
|
|
|
|
#ifdef _WIN32
|
|
__declspec(dllexport)
|
|
#endif
|
|
CEKEYSTOREPROVIDER *CEKeystoreProvider[] = {
|
|
&MyCustomKSPName_desc,
|
|
0
|
|
}; |