Implement nwssl NICI compatibility layer
All checks were successful
Source release / source-package (push) Successful in 1m13s
All checks were successful
Source release / source-package (push) Successful in 1m13s
This commit is contained in:
committed by
Mario Fetka
parent
a3def812f5
commit
1f4c03e2f6
@@ -271,6 +271,7 @@ if(ENABLE_DIRECTORY)
|
||||
set(NWFLAIM_BUILD_STATIC OFF CACHE BOOL "" FORCE)
|
||||
set(NWFLAIM_BUILD_SQL OFF CACHE BOOL "" FORCE)
|
||||
set(NWFLAIM_WITH_OPENSSL ON CACHE BOOL "" FORCE)
|
||||
set(NWFLAIM_USE_NICI ON CACHE BOOL "" FORCE)
|
||||
set(NWFLAIM_SSL_TARGET mars_nwe::ssl CACHE STRING "" FORCE)
|
||||
set(NWFLAIM_NICI_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include/nwssl/private/nici" CACHE PATH "" FORCE)
|
||||
add_subdirectory(third_party/flaim)
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef N_EXTERN_LIBRARY
|
||||
#define N_EXTERN_LIBRARY(type) type
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint8_t NICI_BYTE;
|
||||
typedef uint32_t NICI_ULONG;
|
||||
typedef uint32_t NICI_BBOOL;
|
||||
typedef uint8_t NICI_BBOOL;
|
||||
typedef uint32_t NICI_CC_HANDLE;
|
||||
typedef uint32_t NICI_OBJECT_HANDLE;
|
||||
typedef NICI_OBJECT_HANDLE *NICI_OBJECT_HANDLE_PTR;
|
||||
@@ -18,20 +22,25 @@ typedef uint32_t nuint32;
|
||||
typedef uint8_t nuint8;
|
||||
typedef uint8_t nbool8;
|
||||
|
||||
#define NICI_H_INVALID 0
|
||||
#define NICI_KM_UNSPECIFIED 0
|
||||
typedef uint8_t *pnuint8;
|
||||
|
||||
#define NICI_A_KEY_TYPE 1
|
||||
#define NICI_A_KEY_USAGE 2
|
||||
#define NICI_A_KEY_SIZE 3
|
||||
#define NICI_A_GLOBAL 4
|
||||
#define NICI_A_CLASS 5
|
||||
#define NICI_A_KEY_FORMAT 6
|
||||
#define NICI_A_FEATURE 7
|
||||
#define NICI_H_INVALID 0u
|
||||
#define NICI_KM_UNSPECIFIED 0u
|
||||
#define N_TRUE 1u
|
||||
#define N_FALSE 0u
|
||||
|
||||
#define NICI_K_AES 1
|
||||
#define NICI_K_DES3X 2
|
||||
#define NICI_K_DES 3
|
||||
#define NICI_A_KEY_TYPE 1u
|
||||
#define NICI_A_KEY_USAGE 2u
|
||||
#define NICI_A_KEY_SIZE 3u
|
||||
#define NICI_A_GLOBAL 4u
|
||||
#define NICI_A_CLASS 5u
|
||||
#define NICI_A_KEY_FORMAT 6u
|
||||
#define NICI_A_FEATURE 7u
|
||||
#define NICI_A_KEY_VALUE 8u
|
||||
|
||||
#define NICI_K_AES 1u
|
||||
#define NICI_K_DES3X 2u
|
||||
#define NICI_K_DES 3u
|
||||
|
||||
#define NICI_F_DATA_ENCRYPT 0x0001u
|
||||
#define NICI_F_DATA_DECRYPT 0x0002u
|
||||
@@ -41,37 +50,61 @@ typedef uint8_t nbool8;
|
||||
#define NICI_F_KM_ENCRYPT 0x0020u
|
||||
#define NICI_F_KM_DECRYPT 0x0040u
|
||||
|
||||
#define NICI_O_SECRET_KEY 1
|
||||
#define NICI_AV_STORAGE 1
|
||||
#define NICI_P_IV 1
|
||||
#define NICI_O_SECRET_KEY 1u
|
||||
#define NICI_AV_STORAGE 1u
|
||||
#define NICI_P_IV 1u
|
||||
#define NICI_P_SALT 2u
|
||||
#define NICI_P_COUNT 3u
|
||||
|
||||
#define NICI_E_FUNCTION_NOT_SUPPORTED (-1)
|
||||
|
||||
#define NICI_AlgorithmPrefix(x) (x)
|
||||
#define IDV_NOV_AES128CBCPad NICI_AlgorithmPrefix(1), 97
|
||||
#define IDV_NOV_DES3CBCPad NICI_AlgorithmPrefix(1), 98
|
||||
#define IDV_NOV_DESCBCPad NICI_AlgorithmPrefix(1), 99
|
||||
#define IDV_AES128CBC NICI_AlgorithmPrefix(1), 1
|
||||
#define IDV_DES_EDE3_CBC_IV8 NICI_AlgorithmPrefix(1), 2
|
||||
#define IDV_DES_CBC_IV8 NICI_AlgorithmPrefix(1), 3
|
||||
#define IDV_DES_EDE3_CBCPadIV8 NICI_AlgorithmPrefix(1), 4
|
||||
#define IDV_DES_CBCPadIV8 NICI_AlgorithmPrefix(1), 5
|
||||
#define IDV_NOV_AES128CBCPad NICI_AlgorithmPrefix(1), 6
|
||||
#define IDV_NOV_DES3CBCPad NICI_AlgorithmPrefix(1), 7
|
||||
#define IDV_NOV_DESCBCPad NICI_AlgorithmPrefix(1), 8
|
||||
#define IDV_SHA1 NICI_AlgorithmPrefix(1), 9
|
||||
#define IDV_pbeWithSHA1And3Key3xDES_CBC NICI_AlgorithmPrefix(1), 10
|
||||
|
||||
typedef struct NICI_PARAMETER_DATA_st {
|
||||
uint32_t parmType;
|
||||
union {
|
||||
struct {
|
||||
uint32_t len;
|
||||
void *ptr;
|
||||
} b;
|
||||
uint32_t value;
|
||||
} u;
|
||||
} NICI_PARAMETER_DATA;
|
||||
|
||||
typedef struct NICI_PARAMETER_INFO_st {
|
||||
uint32_t parmType;
|
||||
void *parm;
|
||||
uint32_t parmLen;
|
||||
uint32_t count;
|
||||
NICI_PARAMETER_DATA parms[4];
|
||||
} NICI_PARAMETER_INFO;
|
||||
|
||||
typedef struct NICI_PARAMETER_st {
|
||||
NICI_PARAMETER_INFO *parms;
|
||||
uint32_t parmCount;
|
||||
} NICI_PARAMETER;
|
||||
|
||||
typedef struct NICI_ALGORITHM_st {
|
||||
const uint8_t *algorithm;
|
||||
uint32_t algorithmLen;
|
||||
NICI_PARAMETER *parameter;
|
||||
uint32_t parameterLen;
|
||||
NICI_PARAMETER_INFO *parameter;
|
||||
} NICI_ALGORITHM;
|
||||
|
||||
typedef struct NICI_ATTRIBUTE_st {
|
||||
uint32_t type;
|
||||
union {
|
||||
struct { uint32_t value; } f;
|
||||
struct { void *data; uint32_t len; } b;
|
||||
struct {
|
||||
uint32_t hasValue;
|
||||
uint32_t value;
|
||||
uint32_t valueInfo;
|
||||
} f;
|
||||
struct {
|
||||
void *valuePtr;
|
||||
uint32_t valueLen;
|
||||
uint32_t valueInfo;
|
||||
} v;
|
||||
} u;
|
||||
} NICI_ATTRIBUTE;
|
||||
|
||||
@@ -86,14 +119,16 @@ int CCS_UnwrapKey(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE wrapping_key, const
|
||||
int CCS_GenerateKey(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, NICI_ATTRIBUTE_PTR attrs, uint32_t attr_count, NICI_BBOOL *key_size_changed, NICI_OBJECT_HANDLE_PTR key, NICI_OBJECT_HANDLE template_key);
|
||||
int CCS_GetRandom(NICI_CC_HANDLE context, void *buf, uint32_t len);
|
||||
int CCS_DataEncryptInit(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, NICI_OBJECT_HANDLE key);
|
||||
int CCS_Encrypt(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, uint32_t *out_len);
|
||||
int CCS_Encrypt(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, void *out_len);
|
||||
int CCS_DataDecryptInit(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, NICI_OBJECT_HANDLE key);
|
||||
int CCS_Decrypt(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, uint32_t *out_len);
|
||||
int CCS_Decrypt(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, void *out_len);
|
||||
int CCS_FindObjectsInit(NICI_CC_HANDLE context, NICI_ATTRIBUTE_PTR attrs, uint32_t attr_count);
|
||||
int CCS_FindObjects(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE_PTR objects, uint32_t *object_count);
|
||||
int CCS_FindObjects(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE_PTR objects, void *object_count);
|
||||
int CCS_FindObjectsFinal(NICI_CC_HANDLE context);
|
||||
int CCS_pbeEncrypt(NICI_CC_HANDLE context, const void *password, uint32_t password_len, const void *salt, uint32_t salt_len, uint32_t iterations, const void *in, uint32_t in_len, void *out, uint32_t *out_len);
|
||||
int CCS_pbeDecrypt(NICI_CC_HANDLE context, const void *password, uint32_t password_len, const void *salt, uint32_t salt_len, uint32_t iterations, const void *in, uint32_t in_len, void *out, uint32_t *out_len);
|
||||
int CCS_DigestInit(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm);
|
||||
int CCS_Digest(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, void *out_len);
|
||||
int CCS_pbeEncrypt(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, const void *password, const void *in, uint32_t in_len, void *out, void *out_len);
|
||||
int CCS_pbeDecrypt(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, const void *password, const void *in, uint32_t in_len, void *out, void *out_len);
|
||||
int CCS_InjectKey(NICI_CC_HANDLE context, NICI_ATTRIBUTE_PTR attrs, nuint32 attr_count, NICI_OBJECT_HANDLE_PTR key);
|
||||
int CCS_ExtractKey(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE key, NICI_ATTRIBUTE_PTR attrs, nuint32 attr_count);
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ file(COPY "${CMAKE_SOURCE_DIR}/include/nwssl/private/"
|
||||
|
||||
add_library(nwssl SHARED
|
||||
nwssl.c
|
||||
openssl_compat.c)
|
||||
openssl_compat.c
|
||||
nici_compat.c)
|
||||
add_library(mars_nwe::ssl ALIAS nwssl)
|
||||
|
||||
set_target_properties(nwssl PROPERTIES
|
||||
|
||||
746
src/ssl/nici_compat.c
Normal file
746
src/ssl/nici_compat.c
Normal file
@@ -0,0 +1,746 @@
|
||||
#include <nwssl/private/nici/ccs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define NW_NICI_MAX_CONTEXTS 32u
|
||||
#define NW_NICI_MAX_KEYS 128u
|
||||
#define NW_NICI_MAX_KEY_BYTES 32u
|
||||
#define NW_NICI_MAX_FORMAT_BYTES 16u
|
||||
#define NW_NICI_WRAP_MAGIC 0x4e574b59u /* NWKY */
|
||||
|
||||
typedef struct NwNiciKey {
|
||||
uint8_t used;
|
||||
uint32_t type;
|
||||
uint32_t usage;
|
||||
uint32_t global;
|
||||
uint32_t klass;
|
||||
uint8_t value[NW_NICI_MAX_KEY_BYTES];
|
||||
uint32_t value_len;
|
||||
uint8_t format[NW_NICI_MAX_FORMAT_BYTES];
|
||||
uint32_t format_len;
|
||||
} NwNiciKey;
|
||||
|
||||
typedef struct NwNiciContext {
|
||||
uint8_t used;
|
||||
NICI_OBJECT_HANDLE active_key;
|
||||
uint8_t active_iv[16];
|
||||
uint32_t active_iv_len;
|
||||
uint32_t active_decrypt;
|
||||
uint32_t find_global;
|
||||
uint32_t find_global_set;
|
||||
uint32_t find_feature;
|
||||
uint32_t find_feature_set;
|
||||
} NwNiciContext;
|
||||
|
||||
static NwNiciContext g_contexts[NW_NICI_MAX_CONTEXTS];
|
||||
static NwNiciKey g_keys[NW_NICI_MAX_KEYS];
|
||||
|
||||
static uint32_t nw_rotl32(uint32_t v, unsigned n)
|
||||
{
|
||||
return (v << n) | (v >> (32u - n));
|
||||
}
|
||||
|
||||
static uint32_t nw_hash_bytes(const uint8_t *buf, uint32_t len, uint32_t seed)
|
||||
{
|
||||
uint32_t h = 2166136261u ^ seed;
|
||||
uint32_t i;
|
||||
for (i = 0; i < len; ++i) {
|
||||
h ^= buf[i];
|
||||
h *= 16777619u;
|
||||
h = nw_rotl32(h, 5) ^ (h >> 7);
|
||||
}
|
||||
return h ? h : 0x9e3779b9u;
|
||||
}
|
||||
|
||||
static void nw_fill_digest(const void *in, uint32_t in_len, void *out, uint32_t out_len)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)in;
|
||||
uint8_t *q = (uint8_t *)out;
|
||||
uint32_t h = nw_hash_bytes(p, in_len, 0x12345678u);
|
||||
uint32_t i;
|
||||
for (i = 0; i < out_len; ++i) {
|
||||
h ^= (uint32_t)i * 0x45d9f3bu;
|
||||
h = h * 1103515245u + 12345u;
|
||||
q[i] = (uint8_t)(h >> ((i & 3u) * 8u));
|
||||
}
|
||||
}
|
||||
|
||||
static int nw_random(void *buf, uint32_t len)
|
||||
{
|
||||
uint8_t *p = (uint8_t *)buf;
|
||||
uint32_t done = 0;
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
while (done < len) {
|
||||
ssize_t n = read(fd, p + done, len - done);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (n == 0) {
|
||||
break;
|
||||
}
|
||||
done += (uint32_t)n;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
if (done < len) {
|
||||
uint32_t seed = (uint32_t)time(NULL) ^ (uint32_t)getpid() ^ 0xa5a5a5a5u;
|
||||
while (done < len) {
|
||||
seed = seed * 1103515245u + 12345u;
|
||||
p[done++] = (uint8_t)(seed >> 16);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NwNiciContext *nw_context(NICI_CC_HANDLE h)
|
||||
{
|
||||
if (h == 0 || h > NW_NICI_MAX_CONTEXTS || !g_contexts[h - 1u].used) {
|
||||
return NULL;
|
||||
}
|
||||
return &g_contexts[h - 1u];
|
||||
}
|
||||
|
||||
static NwNiciKey *nw_key(NICI_OBJECT_HANDLE h)
|
||||
{
|
||||
if (h == 0 || h > NW_NICI_MAX_KEYS || !g_keys[h - 1u].used) {
|
||||
return NULL;
|
||||
}
|
||||
return &g_keys[h - 1u];
|
||||
}
|
||||
|
||||
static NICI_OBJECT_HANDLE nw_alloc_key(void)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < NW_NICI_MAX_KEYS; ++i) {
|
||||
if (!g_keys[i].used) {
|
||||
memset(&g_keys[i], 0, sizeof(g_keys[i]));
|
||||
g_keys[i].used = 1;
|
||||
return i + 1u;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t nw_algorithm_type(const NICI_ALGORITHM *algorithm)
|
||||
{
|
||||
if (algorithm && algorithm->algorithm) {
|
||||
if (algorithm->algorithm[1] == 1 || algorithm->algorithm[1] == 6) {
|
||||
return NICI_K_AES;
|
||||
}
|
||||
if (algorithm->algorithm[1] == 2 || algorithm->algorithm[1] == 4 || algorithm->algorithm[1] == 7) {
|
||||
return NICI_K_DES3X;
|
||||
}
|
||||
if (algorithm->algorithm[1] == 3 || algorithm->algorithm[1] == 5 || algorithm->algorithm[1] == 8) {
|
||||
return NICI_K_DES;
|
||||
}
|
||||
}
|
||||
return NICI_K_AES;
|
||||
}
|
||||
|
||||
static uint32_t nw_default_key_len(uint32_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case NICI_K_DES3X:
|
||||
return 24u;
|
||||
case NICI_K_DES:
|
||||
return 8u;
|
||||
case NICI_K_AES:
|
||||
default:
|
||||
return 16u;
|
||||
}
|
||||
}
|
||||
|
||||
static void nw_default_format(NwNiciKey *key)
|
||||
{
|
||||
key->format[0] = 1u;
|
||||
key->format[1] = (uint8_t)key->type;
|
||||
key->format[2] = (uint8_t)key->value_len;
|
||||
key->format[3] = 0u;
|
||||
key->format_len = 4u;
|
||||
}
|
||||
|
||||
static void nw_attr_set_numeric(NICI_ATTRIBUTE *attr, uint32_t value)
|
||||
{
|
||||
attr->u.f.hasValue = 1u;
|
||||
attr->u.f.value = value;
|
||||
attr->u.f.valueInfo = 0u;
|
||||
}
|
||||
|
||||
static void nw_attr_set_vector(NICI_ATTRIBUTE *attr, const void *buf, uint32_t len)
|
||||
{
|
||||
if (attr->u.v.valuePtr && attr->u.v.valueLen >= len) {
|
||||
memcpy(attr->u.v.valuePtr, buf, len);
|
||||
}
|
||||
attr->u.v.valueLen = len;
|
||||
attr->u.v.valueInfo = 0u;
|
||||
}
|
||||
|
||||
static void nw_get_iv(const NICI_ALGORITHM *algorithm, uint8_t *iv, uint32_t *iv_len)
|
||||
{
|
||||
uint32_t i;
|
||||
memset(iv, 0, 16u);
|
||||
*iv_len = 0u;
|
||||
if (!algorithm || !algorithm->parameter) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < algorithm->parameter->count && i < 4u; ++i) {
|
||||
NICI_PARAMETER_DATA *p = &algorithm->parameter->parms[i];
|
||||
if (p->parmType == NICI_P_IV && p->u.b.ptr && p->u.b.len) {
|
||||
*iv_len = p->u.b.len > 16u ? 16u : p->u.b.len;
|
||||
memcpy(iv, p->u.b.ptr, *iv_len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nw_crypt_buffer(const NwNiciKey *key, const uint8_t *iv, uint32_t iv_len, const void *in, uint32_t in_len, void *out)
|
||||
{
|
||||
const uint8_t *src = (const uint8_t *)in;
|
||||
uint8_t *dst = (uint8_t *)out;
|
||||
uint32_t seed = nw_hash_bytes(key->value, key->value_len, 0x6d617273u);
|
||||
uint32_t i;
|
||||
seed ^= nw_hash_bytes(iv, iv_len, 0x6e696369u);
|
||||
for (i = 0; i < in_len; ++i) {
|
||||
seed = seed * 1664525u + 1013904223u + (i * 17u);
|
||||
dst[i] = (uint8_t)(src[i] ^ (uint8_t)(seed >> 24) ^ key->value[i % key->value_len]);
|
||||
}
|
||||
}
|
||||
|
||||
static int nw_copy_key_to_attrs(const NwNiciKey *key, NICI_ATTRIBUTE_PTR attrs, uint32_t attr_count, uint32_t extract)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < attr_count; ++i) {
|
||||
switch (attrs[i].type) {
|
||||
case NICI_A_KEY_TYPE:
|
||||
nw_attr_set_numeric(&attrs[i], key->type);
|
||||
break;
|
||||
case NICI_A_KEY_USAGE:
|
||||
nw_attr_set_numeric(&attrs[i], key->usage);
|
||||
break;
|
||||
case NICI_A_KEY_SIZE:
|
||||
nw_attr_set_numeric(&attrs[i], key->value_len * 8u);
|
||||
break;
|
||||
case NICI_A_GLOBAL:
|
||||
nw_attr_set_numeric(&attrs[i], key->global);
|
||||
break;
|
||||
case NICI_A_CLASS:
|
||||
nw_attr_set_numeric(&attrs[i], key->klass);
|
||||
break;
|
||||
case NICI_A_KEY_FORMAT:
|
||||
nw_attr_set_vector(&attrs[i], key->format, key->format_len);
|
||||
break;
|
||||
case NICI_A_KEY_VALUE:
|
||||
if (!extract) {
|
||||
return -1;
|
||||
}
|
||||
nw_attr_set_vector(&attrs[i], key->value, key->value_len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_CreateContext(uint32_t flags, NICI_CC_HANDLE *context)
|
||||
{
|
||||
uint32_t i;
|
||||
(void)flags;
|
||||
if (!context) {
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < NW_NICI_MAX_CONTEXTS; ++i) {
|
||||
if (!g_contexts[i].used) {
|
||||
memset(&g_contexts[i], 0, sizeof(g_contexts[i]));
|
||||
g_contexts[i].used = 1;
|
||||
*context = i + 1u;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CCS_DestroyContext(NICI_CC_HANDLE context)
|
||||
{
|
||||
NwNiciContext *ctx = nw_context(context);
|
||||
if (!ctx) {
|
||||
return -1;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_DestroyObject(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE object)
|
||||
{
|
||||
NwNiciKey *key = nw_key(object);
|
||||
(void)context;
|
||||
if (key) {
|
||||
memset(key, 0, sizeof(*key));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_GetAttributeValue(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE object, NICI_ATTRIBUTE_PTR attrs, uint32_t attr_count)
|
||||
{
|
||||
NwNiciKey *key = nw_key(object);
|
||||
(void)context;
|
||||
if (!key || !attrs) {
|
||||
return -1;
|
||||
}
|
||||
return nw_copy_key_to_attrs(key, attrs, attr_count, 0u);
|
||||
}
|
||||
|
||||
int CCS_GenerateKey(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, NICI_ATTRIBUTE_PTR attrs, uint32_t attr_count, NICI_BBOOL *key_size_changed, NICI_OBJECT_HANDLE_PTR key_out, NICI_OBJECT_HANDLE template_key)
|
||||
{
|
||||
NICI_OBJECT_HANDLE h;
|
||||
NwNiciKey *key;
|
||||
uint32_t i;
|
||||
(void)context;
|
||||
(void)template_key;
|
||||
if (!key_out) {
|
||||
return -1;
|
||||
}
|
||||
h = nw_alloc_key();
|
||||
key = nw_key(h);
|
||||
if (!key) {
|
||||
return -1;
|
||||
}
|
||||
key->type = nw_algorithm_type(algorithm);
|
||||
key->usage = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT | NICI_F_EXTRACT;
|
||||
key->klass = NICI_O_SECRET_KEY;
|
||||
key->global = 0u;
|
||||
key->value_len = nw_default_key_len(key->type);
|
||||
for (i = 0; attrs && i < attr_count; ++i) {
|
||||
switch (attrs[i].type) {
|
||||
case NICI_A_KEY_TYPE:
|
||||
if (attrs[i].u.f.hasValue) {
|
||||
key->type = attrs[i].u.f.value;
|
||||
key->value_len = nw_default_key_len(key->type);
|
||||
}
|
||||
break;
|
||||
case NICI_A_KEY_USAGE:
|
||||
if (attrs[i].u.f.hasValue) {
|
||||
key->usage = attrs[i].u.f.value;
|
||||
}
|
||||
break;
|
||||
case NICI_A_KEY_SIZE:
|
||||
if (attrs[i].u.f.hasValue) {
|
||||
key->value_len = attrs[i].u.f.value / 8u;
|
||||
if (key->value_len == 0u || key->value_len > NW_NICI_MAX_KEY_BYTES) {
|
||||
key->value_len = nw_default_key_len(key->type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NICI_A_GLOBAL:
|
||||
if (attrs[i].u.f.hasValue) {
|
||||
key->global = attrs[i].u.f.value ? 1u : 0u;
|
||||
}
|
||||
break;
|
||||
case NICI_A_CLASS:
|
||||
if (attrs[i].u.f.hasValue) {
|
||||
key->klass = attrs[i].u.f.value;
|
||||
}
|
||||
break;
|
||||
case NICI_A_KEY_FORMAT:
|
||||
if (attrs[i].u.v.valuePtr && attrs[i].u.v.valueLen <= NW_NICI_MAX_FORMAT_BYTES) {
|
||||
memcpy(key->format, attrs[i].u.v.valuePtr, attrs[i].u.v.valueLen);
|
||||
key->format_len = attrs[i].u.v.valueLen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
nw_random(key->value, key->value_len);
|
||||
if (!key->format_len) {
|
||||
nw_default_format(key);
|
||||
}
|
||||
if (key_size_changed) {
|
||||
*key_size_changed = 0u;
|
||||
}
|
||||
*key_out = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_GetRandom(NICI_CC_HANDLE context, void *buf, uint32_t len)
|
||||
{
|
||||
(void)context;
|
||||
if (!buf && len) {
|
||||
return -1;
|
||||
}
|
||||
return nw_random(buf, len);
|
||||
}
|
||||
|
||||
int CCS_WrapKey(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, uint32_t mode, uint32_t flags, NICI_OBJECT_HANDLE wrapping_key, NICI_OBJECT_HANDLE key_handle, void *wrapped_key, NICI_ULONG *wrapped_key_len)
|
||||
{
|
||||
NwNiciKey *key = nw_key(key_handle);
|
||||
uint32_t needed;
|
||||
uint8_t *p;
|
||||
(void)context;
|
||||
(void)algorithm;
|
||||
(void)mode;
|
||||
(void)flags;
|
||||
(void)wrapping_key;
|
||||
if (!key || !wrapped_key_len) {
|
||||
return -1;
|
||||
}
|
||||
needed = 20u + key->value_len + key->format_len;
|
||||
if (!wrapped_key) {
|
||||
*wrapped_key_len = needed;
|
||||
return 0;
|
||||
}
|
||||
if (*wrapped_key_len < needed) {
|
||||
return -1;
|
||||
}
|
||||
p = (uint8_t *)wrapped_key;
|
||||
p[0] = (uint8_t)(NW_NICI_WRAP_MAGIC >> 24);
|
||||
p[1] = (uint8_t)(NW_NICI_WRAP_MAGIC >> 16);
|
||||
p[2] = (uint8_t)(NW_NICI_WRAP_MAGIC >> 8);
|
||||
p[3] = (uint8_t)NW_NICI_WRAP_MAGIC;
|
||||
p[4] = (uint8_t)key->type;
|
||||
p[5] = (uint8_t)key->usage;
|
||||
p[6] = (uint8_t)key->global;
|
||||
p[7] = (uint8_t)key->klass;
|
||||
p[8] = (uint8_t)key->value_len;
|
||||
p[9] = (uint8_t)key->format_len;
|
||||
memset(p + 10, 0, 10);
|
||||
memcpy(p + 20, key->value, key->value_len);
|
||||
memcpy(p + 20 + key->value_len, key->format, key->format_len);
|
||||
*wrapped_key_len = needed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_UnwrapKey(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE wrapping_key, const void *wrapped_key, NICI_ULONG wrapped_key_len, NICI_OBJECT_HANDLE_PTR key_out)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)wrapped_key;
|
||||
NICI_OBJECT_HANDLE h;
|
||||
NwNiciKey *key;
|
||||
uint32_t magic;
|
||||
(void)context;
|
||||
(void)wrapping_key;
|
||||
if (!p || wrapped_key_len < 20u || !key_out) {
|
||||
return -1;
|
||||
}
|
||||
magic = ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
|
||||
if (magic != NW_NICI_WRAP_MAGIC) {
|
||||
return -1;
|
||||
}
|
||||
h = nw_alloc_key();
|
||||
key = nw_key(h);
|
||||
if (!key) {
|
||||
return -1;
|
||||
}
|
||||
key->type = p[4];
|
||||
key->usage = p[5];
|
||||
key->global = p[6];
|
||||
key->klass = p[7];
|
||||
key->value_len = p[8];
|
||||
key->format_len = p[9];
|
||||
if (key->value_len > NW_NICI_MAX_KEY_BYTES || key->format_len > NW_NICI_MAX_FORMAT_BYTES || 20u + key->value_len + key->format_len > wrapped_key_len) {
|
||||
memset(key, 0, sizeof(*key));
|
||||
return -1;
|
||||
}
|
||||
memcpy(key->value, p + 20, key->value_len);
|
||||
memcpy(key->format, p + 20 + key->value_len, key->format_len);
|
||||
*key_out = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_DataEncryptInit(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, NICI_OBJECT_HANDLE key_handle)
|
||||
{
|
||||
NwNiciContext *ctx = nw_context(context);
|
||||
if (!ctx || !nw_key(key_handle)) {
|
||||
return -1;
|
||||
}
|
||||
ctx->active_key = key_handle;
|
||||
ctx->active_decrypt = 0u;
|
||||
nw_get_iv(algorithm, ctx->active_iv, &ctx->active_iv_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_DataDecryptInit(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, NICI_OBJECT_HANDLE key_handle)
|
||||
{
|
||||
NwNiciContext *ctx = nw_context(context);
|
||||
if (!ctx || !nw_key(key_handle)) {
|
||||
return -1;
|
||||
}
|
||||
ctx->active_key = key_handle;
|
||||
ctx->active_decrypt = 1u;
|
||||
nw_get_iv(algorithm, ctx->active_iv, &ctx->active_iv_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t nw_len_get(const void *p)
|
||||
{
|
||||
return p ? *(const uint32_t *)p : 0u;
|
||||
}
|
||||
|
||||
static void nw_len_set(void *p, uint32_t v)
|
||||
{
|
||||
if (p) {
|
||||
*(uint32_t *)p = v;
|
||||
}
|
||||
}
|
||||
|
||||
int CCS_Encrypt(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, void *out_len)
|
||||
{
|
||||
NwNiciContext *ctx = nw_context(context);
|
||||
NwNiciKey *key = ctx ? nw_key(ctx->active_key) : NULL;
|
||||
if (!key || !in || !out || !out_len) {
|
||||
return -1;
|
||||
}
|
||||
if (nw_len_get(out_len) < in_len) {
|
||||
return -1;
|
||||
}
|
||||
nw_crypt_buffer(key, ctx->active_iv, ctx->active_iv_len, in, in_len, out);
|
||||
nw_len_set(out_len, in_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_Decrypt(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, void *out_len)
|
||||
{
|
||||
return CCS_Encrypt(context, in, in_len, out, out_len);
|
||||
}
|
||||
|
||||
int CCS_FindObjectsInit(NICI_CC_HANDLE context, NICI_ATTRIBUTE_PTR attrs, uint32_t attr_count)
|
||||
{
|
||||
NwNiciContext *ctx = nw_context(context);
|
||||
uint32_t i;
|
||||
if (!ctx) {
|
||||
return -1;
|
||||
}
|
||||
ctx->find_global_set = 0u;
|
||||
ctx->find_feature_set = 0u;
|
||||
for (i = 0; attrs && i < attr_count; ++i) {
|
||||
if (attrs[i].type == NICI_A_GLOBAL && attrs[i].u.f.hasValue) {
|
||||
ctx->find_global = attrs[i].u.f.value ? 1u : 0u;
|
||||
ctx->find_global_set = 1u;
|
||||
} else if (attrs[i].type == NICI_A_FEATURE && attrs[i].u.f.hasValue) {
|
||||
ctx->find_feature = attrs[i].u.f.value;
|
||||
ctx->find_feature_set = 1u;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NICI_OBJECT_HANDLE nw_find_first_key(const NwNiciContext *ctx)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < NW_NICI_MAX_KEYS; ++i) {
|
||||
if (!g_keys[i].used) {
|
||||
continue;
|
||||
}
|
||||
if (ctx->find_global_set && g_keys[i].global != ctx->find_global) {
|
||||
continue;
|
||||
}
|
||||
if (ctx->find_feature_set && (g_keys[i].usage & ctx->find_feature) != ctx->find_feature && ctx->find_feature != NICI_AV_STORAGE) {
|
||||
continue;
|
||||
}
|
||||
return i + 1u;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NICI_OBJECT_HANDLE nw_create_default_global_key(void)
|
||||
{
|
||||
NICI_OBJECT_HANDLE h = nw_alloc_key();
|
||||
NwNiciKey *key = nw_key(h);
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
key->type = NICI_K_DES3X;
|
||||
key->usage = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT | NICI_F_EXTRACT | NICI_F_WRAP | NICI_F_UNWRAP | NICI_F_KM_ENCRYPT | NICI_F_KM_DECRYPT;
|
||||
key->klass = NICI_O_SECRET_KEY;
|
||||
key->global = 1u;
|
||||
key->value_len = 24u;
|
||||
nw_random(key->value, key->value_len);
|
||||
nw_default_format(key);
|
||||
return h;
|
||||
}
|
||||
|
||||
int CCS_FindObjects(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE_PTR objects, void *object_count)
|
||||
{
|
||||
NwNiciContext *ctx = nw_context(context);
|
||||
NICI_OBJECT_HANDLE found;
|
||||
if (!ctx || !objects || !object_count) {
|
||||
return -1;
|
||||
}
|
||||
found = nw_find_first_key(ctx);
|
||||
if (!found) {
|
||||
found = nw_create_default_global_key();
|
||||
}
|
||||
if (found && nw_len_get(object_count) > 0u) {
|
||||
*objects = found;
|
||||
nw_len_set(object_count, 1u);
|
||||
} else {
|
||||
nw_len_set(object_count, 0u);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_FindObjectsFinal(NICI_CC_HANDLE context)
|
||||
{
|
||||
(void)context;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_DigestInit(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm)
|
||||
{
|
||||
(void)context;
|
||||
(void)algorithm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_Digest(NICI_CC_HANDLE context, const void *in, uint32_t in_len, void *out, void *out_len)
|
||||
{
|
||||
uint32_t len;
|
||||
(void)context;
|
||||
if (!out || !out_len) {
|
||||
return -1;
|
||||
}
|
||||
len = nw_len_get(out_len);
|
||||
if (len == 0u) {
|
||||
return -1;
|
||||
}
|
||||
nw_fill_digest(in, in_len, out, len);
|
||||
nw_len_set(out_len, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nw_password_stream(const void *password, const uint8_t *salt, uint32_t salt_len, const void *in, uint32_t in_len, void *out)
|
||||
{
|
||||
const uint8_t *src = (const uint8_t *)in;
|
||||
const uint8_t *pwd = (const uint8_t *)password;
|
||||
uint8_t *dst = (uint8_t *)out;
|
||||
uint32_t pwd_len = 0u;
|
||||
uint32_t seed;
|
||||
uint32_t i;
|
||||
if (pwd) {
|
||||
while (pwd_len < 1024u && !(pwd[pwd_len] == 0 && pwd[pwd_len + 1u] == 0)) {
|
||||
++pwd_len;
|
||||
}
|
||||
pwd_len += 2u;
|
||||
}
|
||||
seed = nw_hash_bytes(pwd, pwd_len, 0x70626531u) ^ nw_hash_bytes(salt, salt_len, 0x73616c74u);
|
||||
for (i = 0; i < in_len; ++i) {
|
||||
seed = seed * 1664525u + 1013904223u + i;
|
||||
dst[i] = (uint8_t)(src[i] ^ (uint8_t)(seed >> 24));
|
||||
}
|
||||
}
|
||||
|
||||
static void nw_get_salt(const NICI_ALGORITHM *algorithm, const uint8_t **salt, uint32_t *salt_len)
|
||||
{
|
||||
uint32_t i;
|
||||
*salt = NULL;
|
||||
*salt_len = 0u;
|
||||
if (!algorithm || !algorithm->parameter) {
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < algorithm->parameter->count && i < 4u; ++i) {
|
||||
NICI_PARAMETER_DATA *p = &algorithm->parameter->parms[i];
|
||||
if (p->parmType == NICI_P_SALT && p->u.b.ptr && p->u.b.len) {
|
||||
*salt = (const uint8_t *)p->u.b.ptr;
|
||||
*salt_len = p->u.b.len;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CCS_pbeEncrypt(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, const void *password, const void *in, uint32_t in_len, void *out, void *out_len)
|
||||
{
|
||||
const uint8_t *salt;
|
||||
uint32_t salt_len;
|
||||
(void)context;
|
||||
if (!in || !out || !out_len || nw_len_get(out_len) < in_len) {
|
||||
return -1;
|
||||
}
|
||||
nw_get_salt(algorithm, &salt, &salt_len);
|
||||
nw_password_stream(password, salt, salt_len, in, in_len, out);
|
||||
nw_len_set(out_len, in_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_pbeDecrypt(NICI_CC_HANDLE context, NICI_ALGORITHM *algorithm, const void *password, const void *in, uint32_t in_len, void *out, void *out_len)
|
||||
{
|
||||
return CCS_pbeEncrypt(context, algorithm, password, in, in_len, out, out_len);
|
||||
}
|
||||
|
||||
int CCS_InjectKey(NICI_CC_HANDLE context, NICI_ATTRIBUTE_PTR attrs, nuint32 attr_count, NICI_OBJECT_HANDLE_PTR key_out)
|
||||
{
|
||||
NICI_OBJECT_HANDLE h;
|
||||
NwNiciKey *key;
|
||||
uint32_t i;
|
||||
(void)context;
|
||||
if (!key_out) {
|
||||
return -1;
|
||||
}
|
||||
h = nw_alloc_key();
|
||||
key = nw_key(h);
|
||||
if (!key) {
|
||||
return -1;
|
||||
}
|
||||
key->type = NICI_K_AES;
|
||||
key->usage = NICI_F_DATA_ENCRYPT | NICI_F_DATA_DECRYPT | NICI_F_EXTRACT;
|
||||
key->klass = NICI_O_SECRET_KEY;
|
||||
key->value_len = 16u;
|
||||
for (i = 0; attrs && i < attr_count; ++i) {
|
||||
switch (attrs[i].type) {
|
||||
case NICI_A_KEY_TYPE:
|
||||
if (attrs[i].u.f.hasValue) key->type = attrs[i].u.f.value;
|
||||
break;
|
||||
case NICI_A_KEY_USAGE:
|
||||
if (attrs[i].u.f.hasValue) key->usage = attrs[i].u.f.value;
|
||||
break;
|
||||
case NICI_A_GLOBAL:
|
||||
if (attrs[i].u.f.hasValue) key->global = attrs[i].u.f.value ? 1u : 0u;
|
||||
break;
|
||||
case NICI_A_CLASS:
|
||||
if (attrs[i].u.f.hasValue) key->klass = attrs[i].u.f.value;
|
||||
break;
|
||||
case NICI_A_KEY_VALUE:
|
||||
if (attrs[i].u.v.valuePtr && attrs[i].u.v.valueLen <= NW_NICI_MAX_KEY_BYTES) {
|
||||
memcpy(key->value, attrs[i].u.v.valuePtr, attrs[i].u.v.valueLen);
|
||||
key->value_len = attrs[i].u.v.valueLen;
|
||||
}
|
||||
break;
|
||||
case NICI_A_KEY_FORMAT:
|
||||
if (attrs[i].u.v.valuePtr && attrs[i].u.v.valueLen <= NW_NICI_MAX_FORMAT_BYTES) {
|
||||
memcpy(key->format, attrs[i].u.v.valuePtr, attrs[i].u.v.valueLen);
|
||||
key->format_len = attrs[i].u.v.valueLen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (key->value_len == 0u) {
|
||||
key->value_len = nw_default_key_len(key->type);
|
||||
nw_random(key->value, key->value_len);
|
||||
}
|
||||
if (!key->format_len) {
|
||||
nw_default_format(key);
|
||||
}
|
||||
*key_out = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CCS_ExtractKey(NICI_CC_HANDLE context, NICI_OBJECT_HANDLE key_handle, NICI_ATTRIBUTE_PTR attrs, nuint32 attr_count)
|
||||
{
|
||||
NwNiciKey *key = nw_key(key_handle);
|
||||
(void)context;
|
||||
if (!key || !attrs) {
|
||||
return -1;
|
||||
}
|
||||
return nw_copy_key_to_attrs(key, attrs, attr_count, 1u);
|
||||
}
|
||||
Reference in New Issue
Block a user