php-sqlsrv/test/functional/setup/myKSP.c
2017-09-01 16:10:42 -07:00

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
};