|
/***************************************************************************
|
|
begin : Wed Mar 16 2005
|
|
copyright : (C) 2005-2010 by Martin Preuss
|
|
email : martin@libchipcard.de
|
|
|
|
***************************************************************************
|
|
* Please see toplevel file COPYING for license details *
|
|
***************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#define DISABLE_DEBUGLOG
|
|
|
|
|
|
#include "ctfile_p.h"
|
|
#include "i18n_l.h"
|
|
#include <gwenhywfar/ctf_context_be.h>
|
|
#include <gwenhywfar/misc.h>
|
|
#include <gwenhywfar/debug.h>
|
|
#include <gwenhywfar/padd.h>
|
|
#include <gwenhywfar/cryptkeyrsa.h>
|
|
#include <gwenhywfar/text.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
GWEN_INHERIT(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE)
|
|
|
|
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__OpenFile(GWEN_CRYPT_TOKEN *ct, int wr, uint32_t gid) {
|
|
int fd;
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_FSLOCK_RESULT lres;
|
|
const char *fname;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
fname = GWEN_Crypt_Token_GetTokenName(ct);
|
|
if (!fname) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "No name of the crypt token set - maybe you need to set the key file as token name? Cannot lock token.");
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
|
|
lct->lock=GWEN_FSLock_new(fname,
|
|
GWEN_FSLock_TypeFile);
|
|
lres=GWEN_FSLock_Lock(lct->lock, 10000, gid);
|
|
if (lres!=GWEN_FSLock_ResultOk) {
|
|
GWEN_FSLock_free(lct->lock);
|
|
lct->lock=0;
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Could not lock file");
|
|
if (lres==GWEN_FSLock_ResultUserAbort)
|
|
return GWEN_ERROR_USER_ABORTED;
|
|
else
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
else {
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Keyfile [%s] locked.",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
}
|
|
|
|
if (wr) {
|
|
/* write file */
|
|
fd=open(GWEN_Crypt_Token_GetTokenName(ct),
|
|
O_RDWR|O_CREAT
|
|
#ifdef OS_WIN32
|
|
| O_BINARY
|
|
#endif
|
|
,
|
|
S_IRUSR|S_IWUSR | lct->keyfile_mode);
|
|
}
|
|
else {
|
|
/* Remember the access permissions when opening the file */
|
|
struct stat statbuffer;
|
|
if (!stat(GWEN_Crypt_Token_GetTokenName(ct), &statbuffer)) {
|
|
/* Save the access mode, but masked by the bit masks for
|
|
user/group/other permissions */
|
|
lct->keyfile_mode =
|
|
statbuffer.st_mode & (S_IRWXU
|
|
#ifndef OS_WIN32
|
|
| S_IRWXG | S_IRWXO
|
|
#endif
|
|
);
|
|
}
|
|
else {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"stat(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
|
|
GWEN_FSLock_Unlock(lct->lock);
|
|
GWEN_FSLock_free(lct->lock);
|
|
lct->lock=0;
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Keyfile [%s] unlocked.",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
|
|
/* and open the file */
|
|
fd=open(GWEN_Crypt_Token_GetTokenName(ct),
|
|
O_RDONLY
|
|
#ifdef OS_WIN32
|
|
| O_BINARY
|
|
#endif
|
|
);
|
|
}
|
|
|
|
if (fd==-1) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"open(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
GWEN_FSLock_Unlock(lct->lock);
|
|
GWEN_FSLock_free(lct->lock);
|
|
lct->lock=0;
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Keyfile [%s] unlocked.",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
|
|
lct->fd=fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__CloseFile(GWEN_CRYPT_TOKEN *ct, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_FSLOCK_RESULT lres;
|
|
struct stat st;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
if (lct->fd==-1) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Keyfile \"%s\"not open",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
return GWEN_ERROR_INTERNAL;
|
|
}
|
|
|
|
if (close(lct->fd)) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "close(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct), strerror(errno));
|
|
lct->fd=-1;
|
|
GWEN_FSLock_Unlock(lct->lock);
|
|
GWEN_FSLock_free(lct->lock);
|
|
lct->lock=0;
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Keyfile [%s] unlocked.",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
lct->fd=-1;
|
|
|
|
lres=GWEN_FSLock_Unlock(lct->lock);
|
|
if (lres!=GWEN_FSLock_ResultOk) {
|
|
DBG_WARN(GWEN_LOGDOMAIN, "Error removing lock from \"%s\": %d",
|
|
GWEN_Crypt_Token_GetTokenName(ct), lres);
|
|
}
|
|
GWEN_FSLock_free(lct->lock);
|
|
lct->lock=0;
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Keyfile [%s] unlocked.",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
|
|
/* get times */
|
|
if (stat(GWEN_Crypt_Token_GetTokenName(ct), &st)) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"stat(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
|
|
#ifndef OS_WIN32
|
|
if (st.st_mode & 0007) {
|
|
DBG_WARN(GWEN_LOGDOMAIN,
|
|
"WARNING: Your keyfile \"%s\" is accessible by every user on your computer!\n"
|
|
"Nobody but you should have access to the file. You \n"
|
|
"should probably change this with \"chmod 600 %s\"",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Warning,
|
|
"WARNING: Your keyfile is accessible ny every user on your computer!\n"
|
|
"Nobody but you should have access to the file.");
|
|
}
|
|
#endif
|
|
lct->mtime=st.st_mtime;
|
|
lct->ctime=st.st_ctime;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__Read(GWEN_CRYPT_TOKEN *ct, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
assert(lct->readFn);
|
|
if (lseek(lct->fd, 0, SEEK_SET)==-1) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "lseek(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
return lct->readFn(ct, lct->fd, gid);
|
|
}
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__Write(GWEN_CRYPT_TOKEN *ct, int cr, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
if (lct->writeFn==0) {
|
|
DBG_WARN(GWEN_LOGDOMAIN,
|
|
"No write function in crypt token type \"%s\"",
|
|
GWEN_Crypt_Token_GetTypeName(ct));
|
|
return GWEN_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
if (lseek(lct->fd, 0, SEEK_SET)==-1) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "lseek(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
return lct->writeFn(ct, lct->fd, cr, gid);
|
|
}
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__ReadFile(GWEN_CRYPT_TOKEN *ct, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* clear context list, it will be reloaded */
|
|
GWEN_Crypt_Token_Context_List_Clear(lct->contextList);
|
|
|
|
/* open file */
|
|
rv=GWEN_Crypt_TokenFile__OpenFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Could not open keyfile for reading (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* read file */
|
|
rv=GWEN_Crypt_TokenFile__Read(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Error reading keyfile");
|
|
GWEN_Crypt_TokenFile__CloseFile(ct, gid);
|
|
return rv;
|
|
}
|
|
|
|
/* close file */
|
|
rv=GWEN_Crypt_TokenFile__CloseFile(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Could not close keyfile");
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__WriteFile(GWEN_CRYPT_TOKEN *ct, int cr, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* open file */
|
|
rv=GWEN_Crypt_TokenFile__OpenFile(ct, 1, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN,
|
|
"Could not open keyfile for writing (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* write file */
|
|
rv=GWEN_Crypt_TokenFile__Write(ct, cr, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Error writing keyfile");
|
|
GWEN_Crypt_TokenFile__CloseFile(ct, gid);
|
|
return rv;
|
|
}
|
|
|
|
/* close file */
|
|
rv=GWEN_Crypt_TokenFile__CloseFile(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Could not close keyfile");
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWEN_Crypt_TokenFile__ReloadIfNeeded(GWEN_CRYPT_TOKEN *ct, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
struct stat st;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
if (stat(GWEN_Crypt_Token_GetTokenName(ct), &st)) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"stat(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
return -1;
|
|
}
|
|
if (lct->mtime!=st.st_mtime ||
|
|
lct->ctime!=st.st_ctime) {
|
|
int rv;
|
|
|
|
/* file has changed, reload it */
|
|
DBG_NOTICE(GWEN_LOGDOMAIN,
|
|
"Keyfile changed externally, reloading it");
|
|
/* read file */
|
|
rv=GWEN_Crypt_TokenFile__ReadFile(ct, gid);
|
|
if (rv) {
|
|
DBG_WARN(GWEN_LOGDOMAIN, "Error reloading keyfile");
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
DBG_NOTICE(GWEN_LOGDOMAIN, "Keyfile unchanged, not reloading");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void GWEN_Crypt_TokenFile_AddContext(GWEN_CRYPT_TOKEN *ct, GWEN_CRYPT_TOKEN_CONTEXT *ctx) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* make sure the context is a file context */
|
|
assert(GWEN_CTF_Context_IsOfThisType(ctx));
|
|
GWEN_Crypt_Token_Context_List_Add(ctx, lct->contextList);
|
|
}
|
|
|
|
|
|
|
|
GWEN_CRYPT_TOKEN_CONTEXT *GWEN_Crypt_TokenFile_GetContext(GWEN_CRYPT_TOKEN *ct, int idx) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (idx==0)
|
|
return ctx;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
idx--;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
GWEN_CRYPT_TOKEN_FILE_READ_FN GWEN_Crypt_TokenFile_SetReadFn(GWEN_CRYPT_TOKEN *ct,
|
|
GWEN_CRYPT_TOKEN_FILE_READ_FN f) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_FILE_READ_FN of;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
of=lct->readFn;
|
|
lct->readFn=f;
|
|
|
|
return of;
|
|
}
|
|
|
|
|
|
|
|
GWEN_CRYPT_TOKEN_FILE_WRITE_FN GWEN_Crypt_TokenFile_SetWriteFn(GWEN_CRYPT_TOKEN *ct,
|
|
GWEN_CRYPT_TOKEN_FILE_WRITE_FN f) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_FILE_WRITE_FN of;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
of=lct->writeFn;
|
|
lct->writeFn=f;
|
|
|
|
return of;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB GWEN_Crypt_TokenFile_Create(GWEN_CRYPT_TOKEN *ct, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
struct stat st;
|
|
int fd;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
if (!GWEN_Crypt_Token_GetTokenName(ct)) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "No medium name given");
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
if (stat(GWEN_Crypt_Token_GetTokenName(ct), &st)) {
|
|
if (errno!=ENOENT) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"Error trying to access key file \"%s\": %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
}
|
|
else {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"Keyfile \"%s\" already exists, will not create it",
|
|
GWEN_Crypt_Token_GetTokenName(ct));
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
|
|
/* create file */
|
|
fd=open(GWEN_Crypt_Token_GetTokenName(ct),
|
|
O_RDWR | O_CREAT | O_EXCL
|
|
#ifdef OS_WIN32
|
|
| O_BINARY
|
|
#endif
|
|
,
|
|
S_IRUSR|S_IWUSR);
|
|
|
|
|
|
if (fd==-1) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"open(%s): %s",
|
|
GWEN_Crypt_Token_GetTokenName(ct),
|
|
strerror(errno));
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
|
|
close(fd);
|
|
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 1, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here");
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB GWEN_Crypt_TokenFile_Open(GWEN_CRYPT_TOKEN *ct, GWEN_UNUSED int admin, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
rv=GWEN_Crypt_TokenFile__ReadFile(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here");
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB GWEN_Crypt_TokenFile_Close(GWEN_CRYPT_TOKEN *ct, int abandon, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
if (!abandon)
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
else
|
|
rv=0;
|
|
|
|
/* free/reset all data */
|
|
GWEN_Crypt_Token_Context_List_Clear(lct->contextList);
|
|
lct->mtime=0;
|
|
lct->ctime=0;
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB GWEN_Crypt_TokenFile__GetKeyIdList(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t *pIdList,
|
|
uint32_t *pCount,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int i;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* count keys */
|
|
i=0;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
i+=GWEN_CRYPT_TOKEN_CONTEXT_KEYS;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
}
|
|
|
|
/* if no buffer given just return number of keys */
|
|
if (pIdList==NULL) {
|
|
*pCount=i;
|
|
return 0;
|
|
}
|
|
|
|
if (*pCount<i) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Buffer too small");
|
|
return GWEN_ERROR_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
*pCount=i;
|
|
i=0;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
int j;
|
|
|
|
for (j=1; j<=GWEN_CRYPT_TOKEN_CONTEXT_KEYS; j++)
|
|
*(pIdList++)=(i<<16)+j;
|
|
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
const GWEN_CRYPT_TOKEN_KEYINFO* GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__GetKeyInfo(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t id,
|
|
uint32_t flags,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
int i;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return NULL;
|
|
}
|
|
|
|
i=id>>16;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (context out of range)", id);
|
|
return NULL;
|
|
}
|
|
|
|
switch(id & 0xffff) {
|
|
case 1:
|
|
ki=GWEN_CTF_Context_GetLocalSignKeyInfo(ctx);
|
|
break;
|
|
case 2:
|
|
ki=GWEN_CTF_Context_GetLocalCryptKeyInfo(ctx);
|
|
break;
|
|
case 3:
|
|
ki=GWEN_CTF_Context_GetRemoteSignKeyInfo(ctx);
|
|
break;
|
|
case 4:
|
|
ki=GWEN_CTF_Context_GetRemoteCryptKeyInfo(ctx);
|
|
break;
|
|
case 5:
|
|
ki=GWEN_CTF_Context_GetLocalAuthKeyInfo(ctx);
|
|
break;
|
|
case 6:
|
|
ki=GWEN_CTF_Context_GetRemoteAuthKeyInfo(ctx);
|
|
break;
|
|
case 7:
|
|
ki=GWEN_CTF_Context_GetTempLocalSignKeyInfo(ctx);
|
|
break;
|
|
default:
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (key id out of range)", id);
|
|
return NULL;
|
|
}
|
|
|
|
if (ki==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key info stored for key %d", id);
|
|
return NULL;
|
|
}
|
|
|
|
return ki;
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__SetKeyInfo(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t id,
|
|
const GWEN_CRYPT_TOKEN_KEYINFO *ki,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int i;
|
|
int rv;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *nki;
|
|
GWEN_CRYPT_KEY *key;
|
|
uint32_t flags;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
flags=GWEN_Crypt_Token_KeyInfo_GetFlags(ki);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
i=id>>16;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (context out of range)", id);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
nki=GWEN_Crypt_Token_KeyInfo_dup(ki);
|
|
assert(nki);
|
|
switch(id & 0xffff) {
|
|
case 1:
|
|
GWEN_CTF_Context_SetLocalSignKeyInfo(ctx, nki);
|
|
key=GWEN_CTF_Context_GetLocalSignKey(ctx);
|
|
break;
|
|
case 2:
|
|
GWEN_CTF_Context_SetLocalCryptKeyInfo(ctx, nki);
|
|
key=GWEN_CTF_Context_GetLocalCryptKey(ctx);
|
|
break;
|
|
case 3:
|
|
GWEN_CTF_Context_SetRemoteSignKeyInfo(ctx, nki);
|
|
key=GWEN_CTF_Context_GetRemoteSignKey(ctx);
|
|
break;
|
|
case 4:
|
|
GWEN_CTF_Context_SetRemoteCryptKeyInfo(ctx, nki);
|
|
key=GWEN_CTF_Context_GetRemoteCryptKey(ctx);
|
|
break;
|
|
case 5:
|
|
GWEN_CTF_Context_SetLocalAuthKeyInfo(ctx, nki);
|
|
key=GWEN_CTF_Context_GetLocalAuthKey(ctx);
|
|
break;
|
|
case 6:
|
|
GWEN_CTF_Context_SetRemoteAuthKeyInfo(ctx, nki);
|
|
key=GWEN_CTF_Context_GetRemoteAuthKey(ctx);
|
|
break;
|
|
default:
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (key id out of range)", id);
|
|
GWEN_Crypt_Token_KeyInfo_free(nki);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* replace key if modulus and exponent are given */
|
|
if ((flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS) &&
|
|
(flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT) &&
|
|
id!=1 && /* don't change local keys */
|
|
id!=2 &&
|
|
id!=5) {
|
|
GWEN_CRYPT_KEY *nkey;
|
|
|
|
nkey=GWEN_Crypt_KeyRsa_fromModExp(GWEN_Crypt_Token_KeyInfo_GetKeySize(ki),
|
|
GWEN_Crypt_Token_KeyInfo_GetModulusData(ki),
|
|
GWEN_Crypt_Token_KeyInfo_GetModulusLen(ki),
|
|
GWEN_Crypt_Token_KeyInfo_GetExponentData(ki),
|
|
GWEN_Crypt_Token_KeyInfo_GetExponentLen(ki));
|
|
assert(nkey);
|
|
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER)
|
|
GWEN_Crypt_Key_SetKeyNumber(nkey, GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ki));
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION)
|
|
GWEN_Crypt_Key_SetKeyVersion(nkey, GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki));
|
|
|
|
/* replace public key */
|
|
switch(id & 0xffff) {
|
|
case 3: /* remote sign key */
|
|
GWEN_CTF_Context_SetRemoteSignKey(ctx, nkey);
|
|
break;
|
|
case 4: /* remote crypt key */
|
|
GWEN_CTF_Context_SetRemoteCryptKey(ctx, nkey);
|
|
break;
|
|
case 6: /* remote auth key */
|
|
GWEN_CTF_Context_SetRemoteAuthKey(ctx, nkey);
|
|
break;
|
|
default:
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"Can't set modulus and exponent for private key");
|
|
GWEN_Crypt_Key_free(nkey);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Public key replaced"));
|
|
}
|
|
else {
|
|
if (key) {
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER)
|
|
GWEN_Crypt_Key_SetKeyNumber(key, GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ki));
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION)
|
|
GWEN_Crypt_Key_SetKeyVersion(key, GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki));
|
|
}
|
|
}
|
|
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Unable to write file");
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Unable to write key file"));
|
|
return rv;
|
|
}
|
|
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Key file saved"));
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__SetKeyInfo(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t id,
|
|
const GWEN_CRYPT_TOKEN_KEYINFO *ski,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int i;
|
|
int rv;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
GWEN_CRYPT_KEY *key;
|
|
uint32_t flags;
|
|
uint32_t nflags;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
flags=GWEN_Crypt_Token_KeyInfo_GetFlags(ski);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
i=id>>16;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (context out of range)", id);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
switch(id & 0xffff) {
|
|
case 1:
|
|
ki=GWEN_CTF_Context_GetLocalSignKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetLocalSignKey(ctx);
|
|
break;
|
|
case 2:
|
|
ki=GWEN_CTF_Context_GetLocalCryptKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetLocalCryptKey(ctx);
|
|
break;
|
|
case 3:
|
|
ki=GWEN_CTF_Context_GetRemoteSignKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetRemoteSignKey(ctx);
|
|
break;
|
|
case 4:
|
|
ki=GWEN_CTF_Context_GetRemoteCryptKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetRemoteCryptKey(ctx);
|
|
break;
|
|
case 5:
|
|
ki=GWEN_CTF_Context_GetLocalAuthKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetLocalAuthKey(ctx);
|
|
break;
|
|
case 6:
|
|
ki=GWEN_CTF_Context_GetRemoteAuthKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetRemoteAuthKey(ctx);
|
|
break;
|
|
case 7:
|
|
ki=GWEN_CTF_Context_GetTempLocalSignKeyInfo(ctx);
|
|
key=GWEN_CTF_Context_GetTempLocalSignKey(ctx);
|
|
break;
|
|
default:
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (key id out of range)", id);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
assert(ki);
|
|
|
|
nflags=GWEN_Crypt_Token_KeyInfo_GetFlags(ki);
|
|
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASSTATUS) {
|
|
/* ignore for now */
|
|
}
|
|
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS) {
|
|
nflags&=~GWEN_CRYPT_TOKEN_KEYFLAGS_ACTIONMASK;
|
|
nflags|=(flags & GWEN_CRYPT_TOKEN_KEYFLAGS_ACTIONMASK);
|
|
}
|
|
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION) {
|
|
uint32_t i=GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ski);
|
|
GWEN_Crypt_Token_KeyInfo_SetKeyVersion(ki, i);
|
|
nflags|=GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION;
|
|
if (key)
|
|
GWEN_Crypt_Key_SetKeyVersion(key, GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ski));
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Setting key version");
|
|
}
|
|
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER) {
|
|
uint32_t i=GWEN_Crypt_Token_KeyInfo_GetSignCounter(ski);
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, i);
|
|
nflags|=GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER;
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Setting signature counter");
|
|
}
|
|
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER) {
|
|
uint32_t i=GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ski);
|
|
GWEN_Crypt_Token_KeyInfo_SetKeyNumber(ki, i);
|
|
nflags|=GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER;
|
|
if (key)
|
|
GWEN_Crypt_Key_SetKeyNumber(key, GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ski));
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Setting key number");
|
|
}
|
|
|
|
/* replace key if modulus and exponent are given */
|
|
if ((flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS) &&
|
|
(flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT) &&
|
|
id!=1 && /* don't change local keys */
|
|
id!=2 &&
|
|
id!=5 &&
|
|
id!=7) {
|
|
GWEN_CRYPT_KEY *nkey;
|
|
|
|
GWEN_Crypt_Token_KeyInfo_SetKeySize(ki, GWEN_Crypt_Token_KeyInfo_GetKeySize(ski));
|
|
GWEN_Crypt_Token_KeyInfo_SetModulus(ki,
|
|
GWEN_Crypt_Token_KeyInfo_GetModulusData(ski),
|
|
GWEN_Crypt_Token_KeyInfo_GetModulusLen(ski));
|
|
nflags|=GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS;
|
|
GWEN_Crypt_Token_KeyInfo_SetExponent(ki,
|
|
GWEN_Crypt_Token_KeyInfo_GetExponentData(ski),
|
|
GWEN_Crypt_Token_KeyInfo_GetExponentLen(ski));
|
|
nflags|=GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT;
|
|
nkey=GWEN_Crypt_KeyRsa_fromModExp(GWEN_Crypt_Token_KeyInfo_GetKeySize(ski),
|
|
GWEN_Crypt_Token_KeyInfo_GetModulusData(ski),
|
|
GWEN_Crypt_Token_KeyInfo_GetModulusLen(ski),
|
|
GWEN_Crypt_Token_KeyInfo_GetExponentData(ski),
|
|
GWEN_Crypt_Token_KeyInfo_GetExponentLen(ski));
|
|
assert(nkey);
|
|
|
|
if (nflags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER)
|
|
GWEN_Crypt_Key_SetKeyNumber(nkey, GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ki));
|
|
if (nflags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION)
|
|
GWEN_Crypt_Key_SetKeyVersion(nkey, GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki));
|
|
|
|
/* replace public key */
|
|
switch(id & 0xffff) {
|
|
case 3: /* remote sign key */
|
|
GWEN_CTF_Context_SetRemoteSignKey(ctx, nkey);
|
|
break;
|
|
case 4: /* remote crypt key */
|
|
GWEN_CTF_Context_SetRemoteCryptKey(ctx, nkey);
|
|
break;
|
|
case 6: /* remote auth key */
|
|
GWEN_CTF_Context_SetRemoteAuthKey(ctx, nkey);
|
|
break;
|
|
default:
|
|
DBG_ERROR(GWEN_LOGDOMAIN,
|
|
"Can't set modulus and exponent for private key");
|
|
GWEN_Crypt_Key_free(nkey);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Public key replaced"));
|
|
}
|
|
else {
|
|
if (key) {
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER)
|
|
GWEN_Crypt_Key_SetKeyNumber(key, GWEN_Crypt_Token_KeyInfo_GetKeyNumber(ki));
|
|
if (flags & GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION)
|
|
GWEN_Crypt_Key_SetKeyVersion(key, GWEN_Crypt_Token_KeyInfo_GetKeyVersion(ki));
|
|
}
|
|
}
|
|
|
|
GWEN_Crypt_Token_KeyInfo_SetFlags(ki, nflags);
|
|
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Unable to write file");
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Unable to write key file"));
|
|
return rv;
|
|
}
|
|
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Key file saved"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__ActivateKey(GWEN_CRYPT_TOKEN *ct, uint32_t id, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int rv;
|
|
int i;
|
|
uint32_t keyNum;
|
|
uint8_t kbuf[GWEN_CRYPT_KEYRSA_MAX_KEYLENGTH];
|
|
uint32_t klen;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *cki=NULL;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
GWEN_CRYPT_KEY *key;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
keyNum=id & 0xffff;
|
|
|
|
i=id>>16;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (context out of range)", id);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
key=GWEN_CTF_Context_GetTempLocalSignKey(ctx);
|
|
if (key==NULL) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "No temporary local sign key.");
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
key=GWEN_Crypt_KeyRsa_dup(key);
|
|
|
|
/* set key */
|
|
if (keyNum==1)
|
|
cki=GWEN_CTF_Context_GetLocalSignKeyInfo(ctx);
|
|
else if (keyNum==6)
|
|
cki=GWEN_CTF_Context_GetLocalAuthKeyInfo(ctx);
|
|
else {
|
|
GWEN_Gui_ProgressLog2(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Invalid key id %02x"), id);
|
|
GWEN_Crypt_Key_free(key);
|
|
return GWEN_ERROR_NO_DATA;
|
|
}
|
|
if (cki==NULL) {
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("No key info found"));
|
|
GWEN_Crypt_Key_free(key);
|
|
return GWEN_ERROR_NO_DATA;
|
|
}
|
|
|
|
/* update key info for the key */
|
|
ki=GWEN_Crypt_Token_KeyInfo_dup(cki);
|
|
assert(ki);
|
|
|
|
/* get modulus */
|
|
klen=sizeof(kbuf);
|
|
rv=GWEN_Crypt_KeyRsa_GetModulus(key, kbuf, &klen);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No modulus for key");
|
|
GWEN_Crypt_Token_KeyInfo_free(ki);
|
|
GWEN_Crypt_Key_free(key);
|
|
return rv;
|
|
}
|
|
GWEN_Crypt_Token_KeyInfo_SetModulus(ki, kbuf, klen);
|
|
|
|
/* get exponent */
|
|
klen=sizeof(kbuf);
|
|
rv=GWEN_Crypt_KeyRsa_GetExponent(key, kbuf, &klen);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No exponent for key");
|
|
GWEN_Crypt_Token_KeyInfo_free(ki);
|
|
GWEN_Crypt_Key_free(key);
|
|
return rv;
|
|
}
|
|
GWEN_Crypt_Token_KeyInfo_SetExponent(ki, kbuf, klen);
|
|
GWEN_Crypt_Token_KeyInfo_SetKeyNumber(ki, GWEN_Crypt_Key_GetKeyNumber(key));
|
|
GWEN_Crypt_Token_KeyInfo_SetKeyVersion(ki, GWEN_Crypt_Key_GetKeyVersion(key));
|
|
|
|
if (keyNum==1) {
|
|
if (GWEN_Crypt_Token_GetModes(ct) & GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN) {
|
|
DBG_DEBUG(GWEN_LOGDOMAIN, "Adding mode \"direct sign\" to key");
|
|
GWEN_Crypt_KeyRsa_AddFlags(key, GWEN_CRYPT_KEYRSA_FLAGS_DIRECTSIGN);
|
|
}
|
|
GWEN_CTF_Context_SetLocalSignKey(ctx, key);
|
|
GWEN_Crypt_Token_KeyInfo_AddFlags(ki,
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANVERIFY |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANSIGN);
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, 1);
|
|
GWEN_CTF_Context_SetLocalSignKeyInfo(ctx, ki);
|
|
}
|
|
else if (keyNum==6) {
|
|
if (GWEN_Crypt_Token_GetModes(ct) & GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN) {
|
|
DBG_DEBUG(GWEN_LOGDOMAIN, "Adding mode \"direct sign\" to key");
|
|
GWEN_Crypt_KeyRsa_AddFlags(key, GWEN_CRYPT_KEYRSA_FLAGS_DIRECTSIGN);
|
|
}
|
|
GWEN_CTF_Context_SetLocalAuthKey(ctx, key);
|
|
GWEN_Crypt_Token_KeyInfo_AddFlags(ki,
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANVERIFY |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANSIGN);
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, 1);
|
|
GWEN_CTF_Context_SetLocalAuthKeyInfo(ctx, ki);
|
|
}
|
|
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Unable to write file");
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Unable to write key file"));
|
|
return rv;
|
|
}
|
|
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Key file saved"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__GetContextIdList(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t *pIdList,
|
|
uint32_t *pCount,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int i;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* count keys */
|
|
i=0;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
i++;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
}
|
|
|
|
/* store number of entries */
|
|
*pCount=i;
|
|
|
|
/* if no buffer given just return number of keys */
|
|
if (pIdList==NULL)
|
|
return 0;
|
|
|
|
if (*pCount<i) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Buffer too small");
|
|
return GWEN_ERROR_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
i=1;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
*(pIdList++)=i;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
const GWEN_CRYPT_TOKEN_CONTEXT* GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__GetContext(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t id,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return NULL;
|
|
}
|
|
|
|
if (id==0) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Invalid context id 0");
|
|
return NULL;
|
|
}
|
|
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (GWEN_Crypt_Token_Context_GetId(ctx)==id)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No context by id [%x] known", id);
|
|
return NULL;
|
|
}
|
|
|
|
return ctx;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__SetContext(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t id,
|
|
const GWEN_CRYPT_TOKEN_CONTEXT *nctx,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int rv;
|
|
const char *s;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
if (id==0) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Invalid context id 0");
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (GWEN_Crypt_Token_Context_GetId(ctx)==id)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No context by id [%x] known", id);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* copy user data from context */
|
|
s=GWEN_Crypt_Token_Context_GetServiceId(nctx);
|
|
GWEN_Crypt_Token_Context_SetServiceId(ctx, s);
|
|
s=GWEN_Crypt_Token_Context_GetUserId(nctx);
|
|
GWEN_Crypt_Token_Context_SetUserId(ctx, s);
|
|
s=GWEN_Crypt_Token_Context_GetUserName(nctx);
|
|
GWEN_Crypt_Token_Context_SetUserName(ctx, s);
|
|
s=GWEN_Crypt_Token_Context_GetPeerId(nctx);
|
|
GWEN_Crypt_Token_Context_SetPeerId(ctx, s);
|
|
s=GWEN_Crypt_Token_Context_GetAddress(nctx);
|
|
GWEN_Crypt_Token_Context_SetAddress(ctx, s);
|
|
GWEN_Crypt_Token_Context_SetPort(ctx, GWEN_Crypt_Token_Context_GetPort(nctx));
|
|
s=GWEN_Crypt_Token_Context_GetSystemId(nctx);
|
|
GWEN_Crypt_Token_Context_SetSystemId(ctx, s);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
GWEN_CRYPT_KEY *GWEN_Crypt_TokenFile__GetKey(GWEN_CRYPT_TOKEN *ct, uint32_t id, uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int i;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return NULL;
|
|
}
|
|
|
|
i=id>>16;
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (context out of range)", id);
|
|
return NULL;
|
|
}
|
|
|
|
switch(id & 0xffff) {
|
|
case 1:
|
|
return GWEN_CTF_Context_GetLocalSignKey(ctx);
|
|
case 2:
|
|
return GWEN_CTF_Context_GetLocalCryptKey(ctx);
|
|
case 3:
|
|
return GWEN_CTF_Context_GetRemoteSignKey(ctx);
|
|
case 4:
|
|
return GWEN_CTF_Context_GetRemoteCryptKey(ctx);
|
|
case 5:
|
|
return GWEN_CTF_Context_GetLocalAuthKey(ctx);
|
|
case 6:
|
|
return GWEN_CTF_Context_GetRemoteAuthKey(ctx);
|
|
default:
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No key by id [%x] known (key id out of range)", id);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__Sign(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t keyId,
|
|
GWEN_CRYPT_PADDALGO *a,
|
|
const uint8_t *pInData,
|
|
uint32_t inLen,
|
|
uint8_t *pSignatureData,
|
|
uint32_t *pSignatureLen,
|
|
uint32_t *pSeqCounter,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
GWEN_CRYPT_KEY *k;
|
|
int keyNum;
|
|
GWEN_BUFFER *srcBuf;
|
|
int i;
|
|
int rv;
|
|
GWEN_CRYPT_PADDALGOID aid;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Signing with key %d", keyId);
|
|
aid=GWEN_Crypt_PaddAlgo_GetId(a);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* get context */
|
|
i=(keyId>>16);
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
if (ctx==NULL) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Token has no context");
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Checking token %d (i==%d)",
|
|
GWEN_Crypt_Token_Context_GetId(ctx), i);
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No context by id [%x] known", (keyId>>16) & 0xffff);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* get key */
|
|
keyNum=keyId & 0xffff;
|
|
if (keyNum!=1 && keyNum!=5) {
|
|
/* neither localSignKey nor localAuthKey */
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Bad key for signing (%x)", keyId);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
k=GWEN_Crypt_TokenFile__GetKey(ct, keyId, gid);
|
|
if (k==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Key not found");
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* copy to a buffer for padding */
|
|
srcBuf=GWEN_Buffer_new(0, inLen, 0, 0);
|
|
|
|
if (aid==GWEN_Crypt_PaddAlgoId_Pkcs1_Pss_Sha256) {
|
|
const GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
int nbits;
|
|
const uint8_t *modPtr;
|
|
uint32_t modLen;
|
|
GWEN_MDIGEST *md;
|
|
|
|
switch(keyId & 0xffff) {
|
|
case 1:
|
|
ki=GWEN_CTF_Context_GetLocalSignKeyInfo(ctx);
|
|
break;
|
|
case 5:
|
|
ki=GWEN_CTF_Context_GetLocalAuthKeyInfo(ctx);
|
|
break;
|
|
default:
|
|
ki=NULL;
|
|
}
|
|
|
|
if (ki==NULL) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "No information for key %d", keyNum);
|
|
GWEN_Buffer_free(srcBuf);
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
/* calculate real number of bits */
|
|
modPtr=GWEN_Crypt_Token_KeyInfo_GetModulusData(ki);
|
|
modLen=GWEN_Crypt_Token_KeyInfo_GetModulusLen(ki);
|
|
nbits=modLen*8;
|
|
while(modLen && *modPtr==0) {
|
|
nbits-=8;
|
|
modLen--;
|
|
modPtr++;
|
|
}
|
|
if (modLen) {
|
|
uint8_t b=*modPtr;
|
|
int i;
|
|
uint8_t mask=0x80;
|
|
|
|
for (i=0; i<8; i++) {
|
|
if (b & mask)
|
|
break;
|
|
nbits--;
|
|
mask>>=1;
|
|
}
|
|
}
|
|
|
|
if (nbits==0) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Empty modulus");
|
|
GWEN_Buffer_free(srcBuf);
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
md=GWEN_MDigest_Sha256_new();
|
|
GWEN_Buffer_AllocRoom(srcBuf, modLen);
|
|
|
|
rv=GWEN_Padd_AddPkcs1Pss((uint8_t*) GWEN_Buffer_GetStart(srcBuf),
|
|
GWEN_Buffer_GetMaxUnsegmentedWrite(srcBuf),
|
|
nbits,
|
|
pInData, inLen,
|
|
inLen,
|
|
md);
|
|
GWEN_MDigest_free(md);
|
|
if (rv<0) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(srcBuf);
|
|
return rv;
|
|
}
|
|
|
|
GWEN_Buffer_IncrementPos(srcBuf, rv);
|
|
GWEN_Buffer_AdjustUsedBytes(srcBuf);
|
|
}
|
|
else {
|
|
GWEN_Buffer_AppendBytes(srcBuf, (const char*)pInData, inLen);
|
|
|
|
/* padd according to given algo */
|
|
rv=GWEN_Padd_ApplyPaddAlgo(a, srcBuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(srcBuf);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
/* sign with key */
|
|
rv=GWEN_Crypt_Key_Sign(k,
|
|
(const uint8_t*)GWEN_Buffer_GetStart(srcBuf),
|
|
GWEN_Buffer_GetUsedBytes(srcBuf),
|
|
pSignatureData,
|
|
pSignatureLen);
|
|
GWEN_Buffer_free(srcBuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
if (pSeqCounter) {
|
|
GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
|
|
/* signature sequence counter is to be incremented */
|
|
switch(keyId & 0xffff) {
|
|
case 1:
|
|
ki=GWEN_CTF_Context_GetLocalSignKeyInfo(ctx);
|
|
break;
|
|
case 5:
|
|
ki=GWEN_CTF_Context_GetLocalAuthKeyInfo(ctx);
|
|
break;
|
|
default:
|
|
ki=NULL;
|
|
}
|
|
if (ki &&
|
|
(GWEN_Crypt_Token_KeyInfo_GetFlags(ki) & GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER)) {
|
|
unsigned int seq;
|
|
|
|
seq=GWEN_Crypt_Token_KeyInfo_GetSignCounter(ki);
|
|
*pSeqCounter=seq;
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, ++seq);
|
|
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Unable to write file");
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
DBG_WARN(GWEN_LOGDOMAIN, "No sign counter for key %04x", keyId);
|
|
*pSeqCounter=0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__Verify(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t keyId,
|
|
GWEN_CRYPT_PADDALGO *a,
|
|
const uint8_t *pInData,
|
|
uint32_t inLen,
|
|
const uint8_t *pSignatureData,
|
|
uint32_t signatureLen,
|
|
uint32_t seqCounter,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
GWEN_CRYPT_KEY *k;
|
|
int keyNum;
|
|
int i;
|
|
int rv;
|
|
GWEN_CRYPT_PADDALGOID aid;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Verifying with key %d", keyId);
|
|
|
|
aid=GWEN_Crypt_PaddAlgo_GetId(a);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* get context */
|
|
i=(keyId>>16);
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No context by id [%x] known", (keyId>>16) & 0xffff);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* get key */
|
|
keyNum=keyId & 0xffff;
|
|
if (keyNum!=1 && keyNum!=3 && keyNum!=6) {
|
|
/* neither remoteSignKey nor remoteAuthKey */
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Bad key for verifying (%x)", keyId);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
k=GWEN_Crypt_TokenFile__GetKey(ct, keyId, gid);
|
|
if (k==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Key not found");
|
|
return GWEN_ERROR_NO_KEY;
|
|
}
|
|
|
|
if (aid==GWEN_Crypt_PaddAlgoId_Iso9796_2 ||
|
|
aid==GWEN_Crypt_PaddAlgoId_Pkcs1_2 ||
|
|
aid==GWEN_Crypt_PaddAlgoId_Pkcs1_Pss_Sha256) {
|
|
GWEN_BUFFER *tbuf;
|
|
uint32_t l;
|
|
|
|
/* these algos add random numbers, we must use encrypt fn here and
|
|
* compare the decrypted and unpadded data with the source data */
|
|
tbuf=GWEN_Buffer_new(0, signatureLen+16, 0, 0);
|
|
l=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf);
|
|
rv=GWEN_Crypt_Key_Encipher(k,
|
|
pSignatureData, signatureLen,
|
|
(uint8_t*)GWEN_Buffer_GetStart(tbuf),
|
|
&l);
|
|
if (rv<0) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(tbuf);
|
|
return rv;
|
|
}
|
|
GWEN_Buffer_IncrementPos(tbuf, l);
|
|
GWEN_Buffer_AdjustUsedBytes(tbuf);
|
|
|
|
if (aid==GWEN_Crypt_PaddAlgoId_Pkcs1_Pss_Sha256) {
|
|
const GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
int nbits;
|
|
const uint8_t *modPtr;
|
|
uint32_t modLen;
|
|
GWEN_MDIGEST *md;
|
|
|
|
if (keyNum==3)
|
|
ki=GWEN_CTF_Context_GetRemoteSignKeyInfo(ctx);
|
|
else
|
|
ki=GWEN_CTF_Context_GetRemoteAuthKeyInfo(ctx);
|
|
if (ki==NULL) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "No information for key %d", keyNum);
|
|
GWEN_Buffer_free(tbuf);
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
/* calculate real number of bits */
|
|
modPtr=GWEN_Crypt_Token_KeyInfo_GetModulusData(ki);
|
|
modLen=GWEN_Crypt_Token_KeyInfo_GetModulusLen(ki);
|
|
nbits=modLen*8;
|
|
while(modLen && *modPtr==0) {
|
|
nbits-=8;
|
|
modLen--;
|
|
modPtr++;
|
|
}
|
|
if (modLen) {
|
|
uint8_t b=*modPtr;
|
|
int i;
|
|
uint8_t mask=0x80;
|
|
|
|
for (i=0; i<8; i++) {
|
|
if (b & mask)
|
|
break;
|
|
nbits--;
|
|
mask>>=1;
|
|
}
|
|
}
|
|
|
|
if (nbits==0) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Empty modulus");
|
|
GWEN_Buffer_free(tbuf);
|
|
return GWEN_ERROR_GENERIC;
|
|
}
|
|
|
|
md=GWEN_MDigest_Sha256_new();
|
|
rv=GWEN_Padd_VerifyPkcs1Pss((const uint8_t*) GWEN_Buffer_GetStart(tbuf),
|
|
GWEN_Buffer_GetUsedBytes(tbuf),
|
|
nbits,
|
|
pInData, inLen,
|
|
inLen,
|
|
md);
|
|
GWEN_MDigest_free(md);
|
|
if (rv<0) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(tbuf);
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
rv=GWEN_Padd_UnapplyPaddAlgo(a, tbuf);
|
|
if (rv<0) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(tbuf);
|
|
return rv;
|
|
}
|
|
l=GWEN_Buffer_GetUsedBytes(tbuf);
|
|
|
|
if (l!=inLen) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Signature length doesn't match");
|
|
GWEN_Buffer_free(tbuf);
|
|
return GWEN_ERROR_VERIFY;
|
|
}
|
|
if (memcmp(pInData, GWEN_Buffer_GetStart(tbuf), l)!=0) {
|
|
DBG_ERROR(GWEN_LOGDOMAIN, "Signature doesn't match:");
|
|
GWEN_Buffer_free(tbuf);
|
|
return GWEN_ERROR_VERIFY;
|
|
}
|
|
}
|
|
GWEN_Buffer_free(tbuf);
|
|
}
|
|
else {
|
|
GWEN_BUFFER *srcBuf;
|
|
|
|
/* copy to a buffer for padding */
|
|
srcBuf=GWEN_Buffer_new(0, inLen, 0, 0);
|
|
GWEN_Buffer_AppendBytes(srcBuf, (const char*)pInData, inLen);
|
|
|
|
/* padd according to given algo */
|
|
rv=GWEN_Padd_ApplyPaddAlgo(a, srcBuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(srcBuf);
|
|
return rv;
|
|
}
|
|
|
|
/* verify with key */
|
|
rv=GWEN_Crypt_Key_Verify(k,
|
|
(const uint8_t*)GWEN_Buffer_GetStart(srcBuf),
|
|
GWEN_Buffer_GetUsedBytes(srcBuf),
|
|
pSignatureData,
|
|
signatureLen);
|
|
GWEN_Buffer_free(srcBuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
if (seqCounter) {
|
|
GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
|
|
/* signature sequence counter is to be checked */
|
|
if (keyNum==3)
|
|
ki=GWEN_CTF_Context_GetRemoteSignKeyInfo(ctx);
|
|
else
|
|
ki=GWEN_CTF_Context_GetRemoteAuthKeyInfo(ctx);
|
|
if (ki &&
|
|
(GWEN_Crypt_Token_KeyInfo_GetFlags(ki) & GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER)) {
|
|
unsigned int seq;
|
|
|
|
seq=GWEN_Crypt_Token_KeyInfo_GetSignCounter(ki);
|
|
|
|
if (seq>=seqCounter) {
|
|
DBG_WARN(GWEN_LOGDOMAIN, "Bad remote sequence counter (possibly replay attack!)");
|
|
return GWEN_ERROR_VERIFY;
|
|
}
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, seqCounter);
|
|
|
|
/* write file */
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Unable to write file");
|
|
return rv;
|
|
}
|
|
}
|
|
else {
|
|
DBG_WARN(GWEN_LOGDOMAIN, "No sign counter for key %04x", keyId);
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__Encipher(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t keyId,
|
|
GWEN_CRYPT_PADDALGO *a,
|
|
const uint8_t *pInData,
|
|
uint32_t inLen,
|
|
uint8_t *pOutData,
|
|
uint32_t *pOutLen,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
GWEN_CRYPT_KEY *k;
|
|
int keyNum;
|
|
GWEN_BUFFER *srcBuf;
|
|
int i;
|
|
int rv;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Enciphering with key %d", keyId);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* get context */
|
|
i=(keyId>>16);
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No context by id [%x] known", (keyId>>16) & 0xffff);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* get key */
|
|
keyNum=keyId & 0xffff;
|
|
if (keyNum!=2 && keyNum!=4) {
|
|
/* not remoteCryptKey */
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Bad key for encrypting (%x)", keyId);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
k=GWEN_Crypt_TokenFile__GetKey(ct, keyId, gid);
|
|
if (k==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Key %d not found", keyId);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* copy to a buffer for padding */
|
|
srcBuf=GWEN_Buffer_new(0, inLen, 0, 0);
|
|
GWEN_Buffer_AppendBytes(srcBuf, (const char*)pInData, inLen);
|
|
GWEN_Buffer_Rewind(srcBuf);
|
|
|
|
/* padd according to given algo */
|
|
rv=GWEN_Padd_ApplyPaddAlgo(a, srcBuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(srcBuf);
|
|
return rv;
|
|
}
|
|
|
|
/* encipher with key */
|
|
rv=GWEN_Crypt_Key_Encipher(k,
|
|
(const uint8_t*)GWEN_Buffer_GetStart(srcBuf),
|
|
GWEN_Buffer_GetUsedBytes(srcBuf),
|
|
pOutData,
|
|
pOutLen);
|
|
GWEN_Buffer_free(srcBuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__Decipher(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t keyId,
|
|
GWEN_CRYPT_PADDALGO *a,
|
|
const uint8_t *pInData,
|
|
uint32_t inLen,
|
|
uint8_t *pOutData,
|
|
uint32_t *pOutLen,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
GWEN_CRYPT_KEY *k;
|
|
int keyNum;
|
|
GWEN_BUFFER *tbuf;
|
|
int i;
|
|
int rv;
|
|
uint32_t l;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Deciphering with key %d", keyId);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
/* get context */
|
|
i=(keyId>>16);
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
if (ctx==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No context by id [%x] known", (keyId>>16) & 0xffff);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* get key */
|
|
keyNum=keyId & 0xffff;
|
|
if (keyNum!=2 && keyNum!=4) {
|
|
/* not localCryptKey */
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Bad key for decrypting (%x)", keyId);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
k=GWEN_Crypt_TokenFile__GetKey(ct, keyId, gid);
|
|
if (k==NULL) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Key not found");
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* decipher with key */
|
|
tbuf=GWEN_Buffer_new(0, inLen+16, 0, 1);
|
|
l=GWEN_Buffer_GetMaxUnsegmentedWrite(tbuf);
|
|
rv=GWEN_Crypt_Key_Decipher(k,
|
|
pInData, inLen,
|
|
(uint8_t*)GWEN_Buffer_GetStart(tbuf), &l);
|
|
if (rv<0) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(tbuf);
|
|
return rv;
|
|
}
|
|
GWEN_Buffer_IncrementPos(tbuf, l);
|
|
GWEN_Buffer_AdjustUsedBytes(tbuf);
|
|
|
|
/* unpadd according to given algo */
|
|
rv=GWEN_Padd_UnapplyPaddAlgo(a, tbuf);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(tbuf);
|
|
return rv;
|
|
}
|
|
|
|
/* copy resulting data to given buffer */
|
|
l=GWEN_Buffer_GetUsedBytes(tbuf);
|
|
if (l>*pOutLen) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Buffer_free(tbuf);
|
|
return GWEN_ERROR_BUFFER_OVERFLOW;
|
|
}
|
|
memmove(pOutData, GWEN_Buffer_GetStart(tbuf), l);
|
|
*pOutLen=l;
|
|
GWEN_Buffer_free(tbuf);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB
|
|
GWEN_Crypt_TokenFile__GenerateKey(GWEN_CRYPT_TOKEN *ct,
|
|
uint32_t keyId,
|
|
const GWEN_CRYPT_CRYPTALGO *a,
|
|
uint32_t gid) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
GWEN_CRYPT_KEY *pubKey;
|
|
GWEN_CRYPT_KEY *secKey;
|
|
int rv;
|
|
uint32_t keyNum;
|
|
GWEN_CRYPT_TOKEN_CONTEXT *ctx;
|
|
int i;
|
|
uint8_t kbuf[GWEN_CRYPT_KEYRSA_MAX_KEYLENGTH];
|
|
uint32_t klen;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *cki;
|
|
GWEN_CRYPT_TOKEN_KEYINFO *ki;
|
|
|
|
assert(ct);
|
|
lct=GWEN_INHERIT_GETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct);
|
|
assert(lct);
|
|
|
|
/* reload if needed */
|
|
rv=GWEN_Crypt_TokenFile__ReloadIfNeeded(ct, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
keyNum=keyId & 0xffff;
|
|
|
|
/* check key id */
|
|
if (keyNum!=1 && keyNum!=2 && keyNum!=5 && keyNum!=7) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Can only generate local keys.");
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Can only generate local keys."));
|
|
return GWEN_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* check for algo */
|
|
if (GWEN_Crypt_CryptAlgo_GetId(a)!=GWEN_Crypt_CryptAlgoId_Rsa) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Only RSA keys supported.");
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Only RSA keys supported."));
|
|
return GWEN_ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
/* get context */
|
|
i=(keyId>>16);
|
|
ctx=GWEN_Crypt_Token_Context_List_First(lct->contextList);
|
|
while(ctx) {
|
|
if (i==0)
|
|
break;
|
|
ctx=GWEN_Crypt_Token_Context_List_Next(ctx);
|
|
i--;
|
|
}
|
|
|
|
/* generate key pair */
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Creating key pair using %d bytes", GWEN_Crypt_CryptAlgo_GetChunkSize(a));
|
|
rv=GWEN_Crypt_KeyRsa_GeneratePair(GWEN_Crypt_CryptAlgo_GetChunkSize(a),
|
|
(GWEN_Crypt_Token_GetModes(ct) &
|
|
GWEN_CRYPT_TOKEN_MODE_EXP_65537)?1:0,
|
|
&pubKey,
|
|
&secKey);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Could not generate key"));
|
|
return rv;
|
|
}
|
|
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Key generated"));
|
|
|
|
/* set key */
|
|
if (keyNum==1)
|
|
cki=GWEN_CTF_Context_GetLocalSignKeyInfo(ctx);
|
|
else if (keyNum==2)
|
|
cki=GWEN_CTF_Context_GetLocalCryptKeyInfo(ctx);
|
|
else if (keyNum==5)
|
|
cki=GWEN_CTF_Context_GetLocalAuthKeyInfo(ctx);
|
|
else if (keyNum==7)
|
|
cki=GWEN_CTF_Context_GetTempLocalSignKeyInfo(ctx);
|
|
else
|
|
cki=NULL;
|
|
|
|
if (cki==NULL) {
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("No key info found"));
|
|
return GWEN_ERROR_NO_DATA;
|
|
}
|
|
|
|
/* update key info for the key */
|
|
ki=GWEN_Crypt_Token_KeyInfo_dup(cki);
|
|
assert(ki);
|
|
|
|
/* get modulus */
|
|
klen=sizeof(kbuf);
|
|
rv=GWEN_Crypt_KeyRsa_GetModulus(pubKey, kbuf, &klen);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No modulus for key");
|
|
GWEN_Crypt_Token_KeyInfo_free(ki);
|
|
GWEN_Crypt_Key_free(pubKey);
|
|
return rv;
|
|
}
|
|
GWEN_Crypt_Token_KeyInfo_SetModulus(ki, kbuf, klen);
|
|
|
|
/* get exponent */
|
|
klen=sizeof(kbuf);
|
|
rv=GWEN_Crypt_KeyRsa_GetExponent(pubKey, kbuf, &klen);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "No exponent for key");
|
|
GWEN_Crypt_Token_KeyInfo_free(ki);
|
|
GWEN_Crypt_Key_free(pubKey);
|
|
return rv;
|
|
}
|
|
GWEN_Crypt_Token_KeyInfo_SetExponent(ki, kbuf, klen);
|
|
GWEN_Crypt_Token_KeyInfo_SetKeyNumber(ki, GWEN_Crypt_Key_GetKeyNumber(pubKey));
|
|
GWEN_Crypt_Token_KeyInfo_SetKeyVersion(ki, GWEN_Crypt_Key_GetKeyVersion(pubKey));
|
|
|
|
if (keyNum==1) {
|
|
if (GWEN_Crypt_Token_GetModes(ct) & GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN) {
|
|
DBG_DEBUG(GWEN_LOGDOMAIN, "Adding mode \"direct sign\" to key");
|
|
GWEN_Crypt_KeyRsa_AddFlags(secKey, GWEN_CRYPT_KEYRSA_FLAGS_DIRECTSIGN);
|
|
}
|
|
GWEN_CTF_Context_SetLocalSignKey(ctx, secKey);
|
|
GWEN_Crypt_Token_KeyInfo_AddFlags(ki,
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANVERIFY |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANSIGN);
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, 1);
|
|
GWEN_CTF_Context_SetLocalSignKeyInfo(ctx, ki);
|
|
}
|
|
else if (keyNum==2) {
|
|
GWEN_CTF_Context_SetLocalCryptKey(ctx, secKey);
|
|
GWEN_Crypt_Token_KeyInfo_AddFlags(ki,
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANENCIPHER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANDECIPHER);
|
|
GWEN_CTF_Context_SetLocalCryptKeyInfo(ctx, ki);
|
|
}
|
|
else if (keyNum==5) {
|
|
if (GWEN_Crypt_Token_GetModes(ct) & GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN) {
|
|
DBG_DEBUG(GWEN_LOGDOMAIN, "Adding mode \"direct sign\" to key");
|
|
GWEN_Crypt_KeyRsa_AddFlags(secKey, GWEN_CRYPT_KEYRSA_FLAGS_DIRECTSIGN);
|
|
}
|
|
GWEN_CTF_Context_SetLocalAuthKey(ctx, secKey);
|
|
GWEN_Crypt_Token_KeyInfo_AddFlags(ki,
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANVERIFY |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANSIGN);
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, 1);
|
|
GWEN_CTF_Context_SetLocalAuthKeyInfo(ctx, ki);
|
|
}
|
|
else if (keyNum==7) {
|
|
if (GWEN_Crypt_Token_GetModes(ct) & GWEN_CRYPT_TOKEN_MODE_DIRECT_SIGN) {
|
|
DBG_DEBUG(GWEN_LOGDOMAIN, "Adding mode \"direct sign\" to key");
|
|
GWEN_Crypt_KeyRsa_AddFlags(secKey, GWEN_CRYPT_KEYRSA_FLAGS_DIRECTSIGN);
|
|
}
|
|
GWEN_CTF_Context_SetTempLocalSignKey(ctx, secKey);
|
|
GWEN_Crypt_Token_KeyInfo_AddFlags(ki,
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASMODULUS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASEXPONENT |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYNUMBER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASKEYVERSION |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASSIGNCOUNTER |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_HASACTIONFLAGS |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANVERIFY |
|
|
GWEN_CRYPT_TOKEN_KEYFLAGS_CANSIGN);
|
|
GWEN_Crypt_Token_KeyInfo_SetSignCounter(ki, 1);
|
|
GWEN_CTF_Context_SetTempLocalSignKeyInfo(ctx, ki);
|
|
}
|
|
|
|
/* the public key is not used */
|
|
GWEN_Crypt_Key_free(pubKey);
|
|
|
|
rv=GWEN_Crypt_TokenFile__WriteFile(ct, 0, gid);
|
|
if (rv) {
|
|
DBG_INFO(GWEN_LOGDOMAIN, "Unable to write file");
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Error,
|
|
I18N("Unable to write key file"));
|
|
return rv;
|
|
}
|
|
|
|
GWEN_Gui_ProgressLog(gid, GWEN_LoggerLevel_Notice,
|
|
I18N("Key generated and set"));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GWENHYWFAR_CB
|
|
void GWEN_Crypt_TokenFile_freeData(GWEN_UNUSED void *bp, void *p) {
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
|
|
lct=(GWEN_CRYPT_TOKEN_FILE*) p;
|
|
GWEN_Crypt_Token_Context_List_free(lct->contextList);
|
|
|
|
GWEN_FREE_OBJECT(lct);
|
|
}
|
|
|
|
|
|
|
|
GWEN_CRYPT_TOKEN *GWEN_Crypt_TokenFile_new(const char *typeName,
|
|
const char *tokenName) {
|
|
GWEN_CRYPT_TOKEN *ct;
|
|
GWEN_CRYPT_TOKEN_FILE *lct;
|
|
|
|
ct=GWEN_Crypt_Token_new(GWEN_Crypt_Token_Device_File, typeName, tokenName);
|
|
assert(ct);
|
|
|
|
GWEN_NEW_OBJECT(GWEN_CRYPT_TOKEN_FILE, lct);
|
|
lct->contextList=GWEN_Crypt_Token_Context_List_new();
|
|
GWEN_INHERIT_SETDATA(GWEN_CRYPT_TOKEN, GWEN_CRYPT_TOKEN_FILE, ct, lct,
|
|
GWEN_Crypt_TokenFile_freeData);
|
|
GWEN_Crypt_Token_SetOpenFn(ct, GWEN_Crypt_TokenFile_Open);
|
|
GWEN_Crypt_Token_SetCreateFn(ct, GWEN_Crypt_TokenFile_Create);
|
|
GWEN_Crypt_Token_SetCloseFn(ct, GWEN_Crypt_TokenFile_Close);
|
|
GWEN_Crypt_Token_SetGetKeyIdListFn(ct, GWEN_Crypt_TokenFile__GetKeyIdList);
|
|
GWEN_Crypt_Token_SetGetKeyInfoFn(ct, GWEN_Crypt_TokenFile__GetKeyInfo);
|
|
GWEN_Crypt_Token_SetSetKeyInfoFn(ct, GWEN_Crypt_TokenFile__SetKeyInfo);
|
|
GWEN_Crypt_Token_SetGetContextIdListFn(ct, GWEN_Crypt_TokenFile__GetContextIdList);
|
|
GWEN_Crypt_Token_SetGetContextFn(ct, GWEN_Crypt_TokenFile__GetContext);
|
|
GWEN_Crypt_Token_SetSetContextFn(ct, GWEN_Crypt_TokenFile__SetContext);
|
|
GWEN_Crypt_Token_SetSignFn(ct, GWEN_Crypt_TokenFile__Sign);
|
|
GWEN_Crypt_Token_SetVerifyFn(ct, GWEN_Crypt_TokenFile__Verify);
|
|
GWEN_Crypt_Token_SetEncipherFn(ct, GWEN_Crypt_TokenFile__Encipher);
|
|
GWEN_Crypt_Token_SetDecipherFn(ct, GWEN_Crypt_TokenFile__Decipher);
|
|
GWEN_Crypt_Token_SetGenerateKeyFn(ct, GWEN_Crypt_TokenFile__GenerateKey);
|
|
GWEN_Crypt_Token_SetActivateKeyFn(ct, GWEN_Crypt_TokenFile__ActivateKey);
|
|
|
|
return ct;
|
|
}
|
|
|
|
|
|
|
|
|
|
|