|
|
@ -49,11 +49,13 @@
|
|
|
|
#include <sxt/base64.h>
|
|
|
|
#include <sxt/base64.h>
|
|
|
|
|
|
|
|
|
|
|
|
/* locals */
|
|
|
|
/* locals */
|
|
|
|
static int sxt_key_export_priv_ed25519(const sxtkey_t *key, const char *pass, sxtsafebuffer_t **bin);
|
|
|
|
static int sxtkey_export_priv_ed25519(const sxtkey_t *key, const char *pass, sxtsafebuffer_t **bin);
|
|
|
|
static int sxt_public_ed25519_2sb(const sxtkey_t *key, sxtsafebuffer_t **buf);
|
|
|
|
static int sxt_public_ed25519_2sb(const sxtkey_t *key, sxtsafebuffer_t **buf);
|
|
|
|
static int sxt_public_ed25519_2rdb(const sxtkey_t *key, sxtrdb_t **out);
|
|
|
|
static int sxt_public_ed25519_2rdb(const sxtkey_t *key, sxtrdb_t **out);
|
|
|
|
|
|
|
|
static int _sxtkey_check_fmtrawbuf(const char *buffer);
|
|
|
|
|
|
|
|
static int _sxtkey_privkey_decrypt(sxtrdb_t *privkey, sxtrdb_t *kdfopt, const char *passkey);
|
|
|
|
|
|
|
|
|
|
|
|
int sxt_key_generate(sxtkey_t *key, int type, int opt)
|
|
|
|
int sxtkey_generate(sxtkey_t *key, int type, int opt)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
|
|
|
@ -96,7 +98,7 @@ int sxt_key_generate(sxtkey_t *key, int type, int opt)
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sxtkey_t *sxt_key_alloc(void)
|
|
|
|
sxtkey_t *sxtkey_alloc(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sxtkey_t *key = malloc(sizeof(sxtkey_t));
|
|
|
|
sxtkey_t *key = malloc(sizeof(sxtkey_t));
|
|
|
|
|
|
|
|
|
|
|
@ -105,7 +107,7 @@ sxtkey_t *sxt_key_alloc(void)
|
|
|
|
return key;
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void sxt_key_burn(sxtkey_t *key)
|
|
|
|
void sxtkey_burn(sxtkey_t *key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!key) return;
|
|
|
|
if(!key) return;
|
|
|
|
|
|
|
|
|
|
|
@ -126,7 +128,7 @@ void sxt_key_burn(sxtkey_t *key)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void sxt_key_free(sxtkey_t *key)
|
|
|
|
void sxtkey_free(sxtkey_t *key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!key) return;
|
|
|
|
if(!key) return;
|
|
|
|
|
|
|
|
|
|
|
@ -144,7 +146,7 @@ void sxt_key_free(sxtkey_t *key)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *sxt_key_name(int type)
|
|
|
|
const char *sxtkey_name(int type)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
switch(type) {
|
|
|
|
switch(type) {
|
|
|
|
case PPKP_ED25519:
|
|
|
|
case PPKP_ED25519:
|
|
|
@ -155,7 +157,7 @@ const char *sxt_key_name(int type)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t sxt_key_type_fname(const char *name)
|
|
|
|
uint8_t sxtkey_type_fname(const char *name)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!name) return 0;
|
|
|
|
if(!name) return 0;
|
|
|
|
|
|
|
|
|
|
|
@ -163,25 +165,25 @@ uint8_t sxt_key_type_fname(const char *name)
|
|
|
|
else return 0;
|
|
|
|
else return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sxt_key_public(const sxtkey_t *key)
|
|
|
|
int sxtkey_public(const sxtkey_t *key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!key) return 0;
|
|
|
|
if(!key) return 0;
|
|
|
|
|
|
|
|
|
|
|
|
return (key->flags & SXT_PPKP_PUBLIC) == SXT_PPKP_PUBLIC;
|
|
|
|
return (key->flags & SXT_PPKP_PUBLIC) == SXT_PPKP_PUBLIC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sxt_key_private(const sxtkey_t *key)
|
|
|
|
int sxtkey_private(const sxtkey_t *key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!key) return 0;
|
|
|
|
if(!key) return 0;
|
|
|
|
|
|
|
|
|
|
|
|
return (key->flags & SXT_PPKP_PRIVATE) == SXT_PPKP_PRIVATE;
|
|
|
|
return (key->flags & SXT_PPKP_PRIVATE) == SXT_PPKP_PRIVATE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sxt_key_assign_hash(sxtkey_t *key, uint64_t hash)
|
|
|
|
int sxtkey_assign_hash(sxtkey_t *key, uint64_t hash)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
if(!sxt_key_private(key)) return SXT_EINVAL;
|
|
|
|
if(!sxtkey_private(key)) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
if(key->hash) return SXT_EKEY;
|
|
|
|
if(key->hash) return SXT_EKEY;
|
|
|
|
else key->hash = hash;
|
|
|
|
else key->hash = hash;
|
|
|
@ -189,7 +191,7 @@ int sxt_key_assign_hash(sxtkey_t *key, uint64_t hash)
|
|
|
|
return SXT_SUCCESS;
|
|
|
|
return SXT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint64_t sxt_key_hash(const sxtkey_t *key)
|
|
|
|
uint64_t sxtkey_hash(const sxtkey_t *key)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!key) return 0;
|
|
|
|
if(!key) return 0;
|
|
|
|
|
|
|
|
|
|
|
@ -197,31 +199,31 @@ uint64_t sxt_key_hash(const sxtkey_t *key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* will duplicate a key depends on it's kind */
|
|
|
|
/* will duplicate a key depends on it's kind */
|
|
|
|
int sxt_key_dup(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
int sxtkey_dup(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int r = SXT_EKEY;
|
|
|
|
int r = SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
if(sxt_key_public(key)) return sxt_key_dup_public(key, dest);
|
|
|
|
if(sxtkey_public(key)) return sxtkey_dup_public(key, dest);
|
|
|
|
else if(sxt_key_private(key)) return sxt_key_dup_private(key, dest);
|
|
|
|
else if(sxtkey_private(key)) return sxtkey_dup_private(key, dest);
|
|
|
|
else return sxt_key_dup_private(key, dest);
|
|
|
|
else return sxtkey_dup_private(key, dest);
|
|
|
|
|
|
|
|
|
|
|
|
/* never riched */
|
|
|
|
/* never riched */
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* will duplicate public key, if key was private or pair - it becomes public */
|
|
|
|
/* will duplicate public key, if key was private or pair - it becomes public */
|
|
|
|
int sxt_key_dup_public(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
int sxtkey_dup_public(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sxtkey_t *nkey = NULL;
|
|
|
|
sxtkey_t *nkey = NULL;
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
if(!sxt_key_private(key)) return SXT_EKEY;
|
|
|
|
if(!sxtkey_private(key)) return SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
if(!(nkey = sxt_key_alloc())) return SXT_ENOMEM;
|
|
|
|
if(!(nkey = sxtkey_alloc())) return SXT_ENOMEM;
|
|
|
|
else nkey->flags = 0;
|
|
|
|
else nkey->flags = 0;
|
|
|
|
|
|
|
|
|
|
|
|
switch(key->type) {
|
|
|
|
switch(key->type) {
|
|
|
@ -248,7 +250,7 @@ int sxt_key_dup_public(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
memcpy(nkey->privkey, key->privkey, ED25519_SK_LEN);
|
|
|
|
memcpy(nkey->privkey, key->privkey, ED25519_SK_LEN);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default: /* don't now about it */
|
|
|
|
default: /* don't now about it */
|
|
|
|
sxt_key_free(nkey);
|
|
|
|
sxtkey_free(nkey);
|
|
|
|
return SXT_EKEY;
|
|
|
|
return SXT_EKEY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -263,12 +265,12 @@ int sxt_key_dup_public(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
__failed:
|
|
|
|
sxt_key_free(nkey);
|
|
|
|
sxtkey_free(nkey);
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* will duplicate private key, if key public error will returns */
|
|
|
|
/* will duplicate private key, if key public error will returns */
|
|
|
|
int sxt_key_dup_private(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
int sxtkey_dup_private(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sxtkey_t *nkey = NULL;
|
|
|
|
sxtkey_t *nkey = NULL;
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
@ -276,7 +278,7 @@ int sxt_key_dup_private(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
//if(sxt_key_public(key)) return SXT_EKEY; /* cannot duplicate private key from public */
|
|
|
|
//if(sxt_key_public(key)) return SXT_EKEY; /* cannot duplicate private key from public */
|
|
|
|
|
|
|
|
|
|
|
|
if(!(nkey = sxt_key_alloc())) return SXT_ENOMEM;
|
|
|
|
if(!(nkey = sxtkey_alloc())) return SXT_ENOMEM;
|
|
|
|
else nkey->flags = 0;
|
|
|
|
else nkey->flags = 0;
|
|
|
|
|
|
|
|
|
|
|
|
switch(key->type) {
|
|
|
|
switch(key->type) {
|
|
|
@ -303,7 +305,7 @@ int sxt_key_dup_private(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
memcpy(nkey->privkey, key->privkey, ED25519_SK_LEN);
|
|
|
|
memcpy(nkey->privkey, key->privkey, ED25519_SK_LEN);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default: /* don't now about it */
|
|
|
|
default: /* don't now about it */
|
|
|
|
sxt_key_free(nkey);
|
|
|
|
sxtkey_free(nkey);
|
|
|
|
return SXT_EKEY;
|
|
|
|
return SXT_EKEY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -318,16 +320,538 @@ int sxt_key_dup_private(const sxtkey_t *key, sxtkey_t **dest)
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
__failed:
|
|
|
|
sxt_key_free(nkey);
|
|
|
|
sxtkey_free(nkey);
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
int sxtkey_import_priv_file(const char *file, const char *passkey,
|
|
|
|
#define dbg_mark printf("%s:%d\n", __FUNCTION__, __LINE__)
|
|
|
|
int (*ask_passkey)(char *pkbuf, size_t length, int confirm, void *priv),
|
|
|
|
#endif
|
|
|
|
void *priv, sxtkey_t **ik)
|
|
|
|
int sxt_key_export_priv_file(const sxtkey_t *key, const char *file, const char *passkey,
|
|
|
|
{
|
|
|
|
int (*ask_passkey)(char *pkbuf, size_t length, int confirm, void *priv),
|
|
|
|
FILE *stream = NULL;
|
|
|
|
void *priv)
|
|
|
|
char *rawfbuf = NULL, *tbuf, *tebuf, *tuple = NULL, *b64pk = NULL;
|
|
|
|
|
|
|
|
struct stat stbuf;
|
|
|
|
|
|
|
|
uint8_t keytype = 0;
|
|
|
|
|
|
|
|
int r = SXT_SUCCESS, tc = 0, tcc = 0, len;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*ik = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check input file */
|
|
|
|
|
|
|
|
if(!file) return SXT_EINVAL;
|
|
|
|
|
|
|
|
if(stat(file, &stbuf) != 0) return SXT_EIO;
|
|
|
|
|
|
|
|
else if(!S_ISREG(stbuf.st_mode)) return SXT_EINVAL;
|
|
|
|
|
|
|
|
if(stbuf.st_size >= SXT_PPKP_MAXCSIZE) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if((stream = fopen(file, "r")) == NULL) return SXT_EIO;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(rawfbuf = malloc(stbuf.st_size + sizeof(char)))) goto __failed;
|
|
|
|
|
|
|
|
else rawfbuf[stbuf.st_size + sizeof(char)] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(fread(rawfbuf, stbuf.st_size + sizeof(char), 1, stream) != 1) {
|
|
|
|
|
|
|
|
r = SXT_EIO;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check general format */
|
|
|
|
|
|
|
|
r = _sxtkey_check_fmtrawbuf(rawfbuf);
|
|
|
|
|
|
|
|
if(r != SXT_SUCCESS) goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* now we need to get a keytype and decode b64blob */
|
|
|
|
|
|
|
|
for(tbuf = rawfbuf, tc = 0, tcc = 0, tebuf = NULL; *tbuf != '\0'; tbuf++) {
|
|
|
|
|
|
|
|
switch(tcc) {
|
|
|
|
|
|
|
|
case 0: /* just entering */
|
|
|
|
|
|
|
|
if(*tbuf == '(') tcc++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* first e.g. key type plain text description */
|
|
|
|
|
|
|
|
if(!tebuf) tebuf = tbuf;
|
|
|
|
|
|
|
|
else if(tebuf && *tbuf == ' ') {
|
|
|
|
|
|
|
|
if(!tebuf) goto __failed;
|
|
|
|
|
|
|
|
len = (tbuf - tebuf) + sizeof(char);
|
|
|
|
|
|
|
|
if(!(tuple = malloc(len))) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
} else memset(tuple, 0, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check keytype */
|
|
|
|
|
|
|
|
memcpy(tuple, tebuf, len - sizeof(char));
|
|
|
|
|
|
|
|
keytype = sxtkey_type_fname(tuple);
|
|
|
|
|
|
|
|
free(tuple);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(keytype == 0) {
|
|
|
|
|
|
|
|
r = SXT_EKEY; /* unsupported key type */
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* going further */
|
|
|
|
|
|
|
|
tebuf = NULL;
|
|
|
|
|
|
|
|
tcc++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: /* private key contents */
|
|
|
|
|
|
|
|
if(!tebuf && *tbuf != ' ') tebuf = tbuf;
|
|
|
|
|
|
|
|
else if(tebuf && *tbuf == ' ') {
|
|
|
|
|
|
|
|
len = (tbuf - tebuf) + sizeof(char);
|
|
|
|
|
|
|
|
/* check format */
|
|
|
|
|
|
|
|
if(*tebuf != '"') tc = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
if(!tc && tebuf[len - 2] != '"') tc = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
len -= 2;
|
|
|
|
|
|
|
|
if(tc || len <= 0) { r = tc; goto __failed; }
|
|
|
|
|
|
|
|
tebuf++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(tuple = malloc(len))) { r = SXT_ENOMEM; goto __failed; }
|
|
|
|
|
|
|
|
else memset(tuple, 0, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(tuple, tebuf, len - sizeof(char));
|
|
|
|
|
|
|
|
b64pk = tuple;
|
|
|
|
|
|
|
|
tuple = tebuf = NULL;
|
|
|
|
|
|
|
|
tcc++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
if(*tbuf == ')') tcc++;
|
|
|
|
|
|
|
|
else if(*tbuf != ' ') {
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(tcc < 3) {
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT; goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = sxtkey_privkey_import_fbase64blob(b64pk, keytype, ask_passkey, priv, ik);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
if(stream) fclose(stream);
|
|
|
|
|
|
|
|
if(rawfbuf) free(rawfbuf);
|
|
|
|
|
|
|
|
if(b64pk) free(b64pk);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sxtkey_privkey_import_rdbuf(sxtrdb_t *buf, uint8_t keytype,
|
|
|
|
|
|
|
|
int (*ask_passkey)(char *pkbuf, size_t length,
|
|
|
|
|
|
|
|
int confirm, void *priv),
|
|
|
|
|
|
|
|
void *priv, sxtkey_t **ik)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
uint8_t flags = 0, chk = 0;
|
|
|
|
|
|
|
|
char *passkey = NULL;
|
|
|
|
|
|
|
|
sxtrdb_t *kdfopt = NULL, *ctrl_pubkey = NULL, *privkey = NULL;
|
|
|
|
|
|
|
|
sxtrdb_t *ed25519_pubbuf = NULL, *ed25519_privbuf = NULL;
|
|
|
|
|
|
|
|
sxtkey_t *key = NULL;
|
|
|
|
|
|
|
|
char *keyname = NULL, *ciphername = NULL, *kdfname = NULL, *magic = NULL;
|
|
|
|
|
|
|
|
uint64_t hash = 0;
|
|
|
|
|
|
|
|
uint32_t r1 = 0, r2 = 0;
|
|
|
|
|
|
|
|
int r = SXT_SUCCESS, decrypt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!buf) return SXT_EINVAL;
|
|
|
|
|
|
|
|
if(!sxtrdb_length(buf)) return SXT_EINVAL;
|
|
|
|
|
|
|
|
if(keytype == 0) return SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = sxtrdb_escan(buf, "sbsssRRR", &magic, &flags, &keyname, &ciphername, &kdfname,
|
|
|
|
|
|
|
|
&kdfopt, &ctrl_pubkey, &privkey);
|
|
|
|
|
|
|
|
if(r != SXT_SUCCESS) goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(strcmp(PPKP_MAGIC, magic)) { /* magic should be right */
|
|
|
|
|
|
|
|
__eekey:
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(strcmp(sxtkey_name(keytype), keyname)) goto __eekey;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check for auth function */
|
|
|
|
|
|
|
|
if(flags & SXT_PPKP_ENCRYPT) decrypt++;
|
|
|
|
|
|
|
|
if(decrypt && !ask_passkey) {
|
|
|
|
|
|
|
|
r = SXT_EAUTH;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(keytype) {
|
|
|
|
|
|
|
|
case PPKP_ED25519:
|
|
|
|
|
|
|
|
/* check for encryption details */
|
|
|
|
|
|
|
|
if(decrypt) {
|
|
|
|
|
|
|
|
if(strcmp(ciphername, "aes128-cbc") || strcmp(kdfname, "bcrypt")) {
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get passkey */
|
|
|
|
|
|
|
|
passkey = malloc(64*sizeof(char));
|
|
|
|
|
|
|
|
if(!passkey) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
r = ask_passkey(passkey, 63, 0, priv);
|
|
|
|
|
|
|
|
if(r != SXT_SUCCESS) { /* FIXME: might be return SXT_EAUTH here ? */
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* decrypt it */
|
|
|
|
|
|
|
|
r = _sxtkey_privkey_decrypt(privkey, kdfopt, passkey);
|
|
|
|
|
|
|
|
if(r != SXT_SUCCESS) goto __failed;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* nil expected */
|
|
|
|
|
|
|
|
if(strcmp(ciphername, "nil") || strcmp(kdfname, "nil")) {
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* here we have privkey decrypted */
|
|
|
|
|
|
|
|
r = sxtrdb_escan(privkey, "ddRRqb", &r1, &r2, &ed25519_pubbuf, &ed25519_privbuf, &hash, &chk);
|
|
|
|
|
|
|
|
if(r != SXT_SUCCESS) {
|
|
|
|
|
|
|
|
hash = 0;
|
|
|
|
|
|
|
|
chk = 0;
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* control check for random numbers */
|
|
|
|
|
|
|
|
if(r1 != r2) goto __invalid;
|
|
|
|
|
|
|
|
/* control check of public keys */
|
|
|
|
|
|
|
|
if(sxtrdb_cmp(ctrl_pubkey, ed25519_privbuf)) {
|
|
|
|
|
|
|
|
__invalid:
|
|
|
|
|
|
|
|
sxtrdb_free(ed25519_pubbuf);
|
|
|
|
|
|
|
|
sxtrdb_free(ed25519_privbuf);
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* alloc a key and copy data */
|
|
|
|
|
|
|
|
if(!(key = sxtkey_alloc())) {
|
|
|
|
|
|
|
|
__enomem:
|
|
|
|
|
|
|
|
sxtrdb_free(ed25519_pubbuf);
|
|
|
|
|
|
|
|
sxtrdb_free(ed25519_privbuf);
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* allocate space */
|
|
|
|
|
|
|
|
if(!(key->pubkey = malloc(ED25519_PK_LEN)) ||
|
|
|
|
|
|
|
|
!(key->privkey = malloc(ED25519_SK_LEN))) {
|
|
|
|
|
|
|
|
if(key->pubkey) free(key->pubkey);
|
|
|
|
|
|
|
|
if(key->privkey) free(key->privkey);
|
|
|
|
|
|
|
|
sxtkey_free(key);
|
|
|
|
|
|
|
|
goto __enomem;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy and set all required data */
|
|
|
|
|
|
|
|
memcpy(key->pubkey, sxtrdb_rdata(ed25519_pubbuf), ED25519_PK_LEN);
|
|
|
|
|
|
|
|
memcpy(key->privkey, sxtrdb_rdata(ed25519_privbuf), ED25519_SK_LEN);
|
|
|
|
|
|
|
|
/* free it */
|
|
|
|
|
|
|
|
sxtrdb_free(ed25519_pubbuf);
|
|
|
|
|
|
|
|
sxtrdb_free(ed25519_privbuf);
|
|
|
|
|
|
|
|
key->type = keytype;
|
|
|
|
|
|
|
|
key->hash = hash;
|
|
|
|
|
|
|
|
key->flags = SXT_PPKP_PRIVATE;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* and the rest */
|
|
|
|
|
|
|
|
*ik = key;
|
|
|
|
|
|
|
|
r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* unsupported key type ... */
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
/* free temproary stuff */
|
|
|
|
|
|
|
|
if(magic) free(magic);
|
|
|
|
|
|
|
|
if(keyname) free(keyname);
|
|
|
|
|
|
|
|
if(ciphername) free(ciphername);
|
|
|
|
|
|
|
|
if(kdfname) free(kdfname);
|
|
|
|
|
|
|
|
if(passkey) {
|
|
|
|
|
|
|
|
memset(passkey, 0, 64);
|
|
|
|
|
|
|
|
free(passkey);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(kdfopt) sxtrdb_free(kdfopt);
|
|
|
|
|
|
|
|
if(ctrl_pubkey) sxtrdb_free(ctrl_pubkey);
|
|
|
|
|
|
|
|
if(privkey) sxtrdb_free(privkey);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sxtkey_privkey_import_fbase64blob(const char *b64pk, uint8_t keytype,
|
|
|
|
|
|
|
|
int (*ask_passkey)(char *pkbuf, size_t length,
|
|
|
|
|
|
|
|
int confirm, void *priv),
|
|
|
|
|
|
|
|
void *priv, sxtkey_t **ik)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
sxtrdb_t *fullkeybuf = NULL;
|
|
|
|
|
|
|
|
char *decoded = NULL;
|
|
|
|
|
|
|
|
int len, r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!b64pk) return SXT_EINVAL;
|
|
|
|
|
|
|
|
else len = strlen(b64pk);
|
|
|
|
|
|
|
|
if(keytype == 0) return SXT_EKEY;
|
|
|
|
|
|
|
|
if(!len) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(decoded = malloc(len + sizeof(char)))) return SXT_ENOMEM;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* decode */
|
|
|
|
|
|
|
|
len = sxt_b64decode_in(b64pk, len, decoded, len);
|
|
|
|
|
|
|
|
if(!len) {
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* allocate a buffer and insert raw data */
|
|
|
|
|
|
|
|
if(!(fullkeybuf = sxtrdb_new())) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
} else sxtrdb_setflags(fullkeybuf, SXTRDB_BURN);
|
|
|
|
|
|
|
|
sxtrdb_write_raw_head(fullkeybuf, decoded, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = sxtkey_privkey_import_rdbuf(fullkeybuf, keytype, ask_passkey, priv, ik);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
if(decoded) {
|
|
|
|
|
|
|
|
memset(decoded, 0, len);
|
|
|
|
|
|
|
|
free(decoded);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fullkeybuf) sxtrdb_free(fullkeybuf);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sxtkey_pubkey_import_fbase64blob(const char *b64b, uint8_t keytype,
|
|
|
|
|
|
|
|
uint64_t ctrl_hash, sxtkey_t **ik)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
sxtkey_t *key = NULL;
|
|
|
|
|
|
|
|
sxtrdb_t *keybuf = NULL;
|
|
|
|
|
|
|
|
char *blob = NULL, *ed25519pk = NULL;
|
|
|
|
|
|
|
|
uint64_t hash;
|
|
|
|
|
|
|
|
int len, r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!b64b) return SXT_EINVAL;
|
|
|
|
|
|
|
|
if(!sxtkey_name(keytype)) return SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ok, first decode */
|
|
|
|
|
|
|
|
len = strlen(b64b) + sizeof(char);
|
|
|
|
|
|
|
|
if(!(blob = malloc(len))) return SXT_ENOMEM;
|
|
|
|
|
|
|
|
else memset(blob, 0, len);
|
|
|
|
|
|
|
|
len = sxt_b64decode_in(b64b, len - 1, blob, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(keybuf = sxtrdb_new())) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch(keytype) {
|
|
|
|
|
|
|
|
case PPKP_ED25519:
|
|
|
|
|
|
|
|
if(!(ed25519pk = malloc(ED25519_PK_LEN))) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* <pubkey><hash> */
|
|
|
|
|
|
|
|
sxtrdb_write_raw(keybuf, blob, len);
|
|
|
|
|
|
|
|
sxtrdb_escan(keybuf, "pq", ED25519_PK_LEN, ed25519pk, &hash);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(hash != ctrl_hash) {
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(key = sxtkey_alloc())) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM; goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
key->type = keytype;
|
|
|
|
|
|
|
|
if(!(key->pubkey = malloc(ED25519_PK_LEN))) {
|
|
|
|
|
|
|
|
sxtkey_free(key);
|
|
|
|
|
|
|
|
r = SXT_ENOMEM; goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
key->hash = hash;
|
|
|
|
|
|
|
|
key->flags = SXT_PPKP_PUBLIC;
|
|
|
|
|
|
|
|
memcpy(key->pubkey, ed25519pk, ED25519_PK_LEN);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
*ik = key;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: r = SXT_EKEYFMT; break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
if(blob) free(blob);
|
|
|
|
|
|
|
|
if(keybuf) sxtrdb_free(keybuf);
|
|
|
|
|
|
|
|
if(ed25519pk) free(ed25519pk);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sxtkey_import_public_file(const char *file, sxtkey_t **ik)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
FILE *stream = NULL;
|
|
|
|
|
|
|
|
char *rawfbuf = NULL, *tbuf, *tebuf, *tuple = NULL, *b64pk = NULL;
|
|
|
|
|
|
|
|
sxtrdb_t *chbuf = NULL;
|
|
|
|
|
|
|
|
int tc = 0, tcc = 0, len;
|
|
|
|
|
|
|
|
struct stat stbuf;
|
|
|
|
|
|
|
|
int r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
uint64_t ctrl_hash;
|
|
|
|
|
|
|
|
uint8_t keytype = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*ik = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!file) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(stat(file, &stbuf) != 0) return SXT_EIO;
|
|
|
|
|
|
|
|
else if(!S_ISREG(stbuf.st_mode)) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(stbuf.st_size >= SXT_PPKP_MAXCSIZE) return SXT_EINVAL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if((stream = fopen(file, "r")) == NULL) return SXT_EIO;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(rawfbuf = malloc(stbuf.st_size + sizeof(char)))) goto __failed;
|
|
|
|
|
|
|
|
else rawfbuf[stbuf.st_size + sizeof(char)] = '\0';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(fread(rawfbuf, stbuf.st_size + sizeof(char), 1, stream) != 1) {
|
|
|
|
|
|
|
|
r = SXT_EIO;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check general format */
|
|
|
|
|
|
|
|
r = _sxtkey_check_fmtrawbuf(rawfbuf);
|
|
|
|
|
|
|
|
if(r != SXT_SUCCESS) goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ok, now we can parse it, avoid to use libsexpr here,
|
|
|
|
|
|
|
|
* to make sxt inpedendent as possible */
|
|
|
|
|
|
|
|
for(tbuf = rawfbuf, tc = 0, tcc = 0, tebuf = NULL; *tbuf != '\0'; tbuf++) {
|
|
|
|
|
|
|
|
switch(tcc) {
|
|
|
|
|
|
|
|
case 0: /* just entering */
|
|
|
|
|
|
|
|
if(*tbuf == '(') tcc++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1: /* first e.g. key type plain text description */
|
|
|
|
|
|
|
|
if(!tebuf) tebuf = tbuf;
|
|
|
|
|
|
|
|
else if(tebuf && *tbuf == ' ') {
|
|
|
|
|
|
|
|
if(!tebuf) goto __failed;
|
|
|
|
|
|
|
|
len = (tbuf - tebuf) + sizeof(char);
|
|
|
|
|
|
|
|
if(!(tuple = malloc(len))) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
} else memset(tuple, 0, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check keytype */
|
|
|
|
|
|
|
|
memcpy(tuple, tebuf, len - sizeof(char));
|
|
|
|
|
|
|
|
keytype = sxtkey_type_fname(tuple);
|
|
|
|
|
|
|
|
free(tuple);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(keytype == 0) {
|
|
|
|
|
|
|
|
r = SXT_EKEY; /* unsupported key type */
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* going further */
|
|
|
|
|
|
|
|
tebuf = NULL;
|
|
|
|
|
|
|
|
tcc++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2: /* public sign keyword */
|
|
|
|
|
|
|
|
if(!tebuf && *tbuf != ' ') tebuf = tbuf;
|
|
|
|
|
|
|
|
else if(tebuf && *tbuf == ' ') {
|
|
|
|
|
|
|
|
if(*tebuf != '\'') { /* invalid format */
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* get tuple */
|
|
|
|
|
|
|
|
len = (tbuf - tebuf) + sizeof(char);
|
|
|
|
|
|
|
|
if(!(tuple = malloc(len))) {
|
|
|
|
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
} else memset(tuple, 0, len);
|
|
|
|
|
|
|
|
memcpy(tuple, tebuf, len - sizeof(char));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(strcmp(tuple, "'public")) tc = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
else tc = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
free(tuple);
|
|
|
|
|
|
|
|
if(tc) {
|
|
|
|
|
|
|
|
r = tc;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
tebuf = NULL;
|
|
|
|
|
|
|
|
tcc++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: /* key contents */
|
|
|
|
|
|
|
|
if(!tebuf && *tbuf != ' ') tebuf = tbuf;
|
|
|
|
|
|
|
|
else if(tebuf && *tbuf == ' ') {
|
|
|
|
|
|
|
|
len = (tbuf - tebuf) + sizeof(char);
|
|
|
|
|
|
|
|
/* check format */
|
|
|
|
|
|
|
|
if(*tebuf != '"') tc = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
if(!tc && tebuf[len - 2] != '"') tc = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
len -= 2;
|
|
|
|
|
|
|
|
if(tc || len <= 0) { r = tc; goto __failed; }
|
|
|
|
|
|
|
|
tebuf++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!(tuple = malloc(len))) { r = SXT_ENOMEM; goto __failed; }
|
|
|
|
|
|
|
|
else memset(tuple, 0, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(tuple, tebuf, len - sizeof(char));
|
|
|
|
|
|
|
|
b64pk = tuple;
|
|
|
|
|
|
|
|
tuple = tebuf = NULL;
|
|
|
|
|
|
|
|
tcc++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4: /* base64 encoded hash to verify contents */
|
|
|
|
|
|
|
|
if(!tebuf && *tbuf == '"') tebuf = tbuf;
|
|
|
|
|
|
|
|
else if(tebuf && *tbuf == '"') {
|
|
|
|
|
|
|
|
tebuf++;
|
|
|
|
|
|
|
|
len = (tbuf - tebuf) + sizeof(char);
|
|
|
|
|
|
|
|
if(len <= 1) tc = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(tc) {r = tc; goto __failed;}
|
|
|
|
|
|
|
|
if(!(tuple = malloc(len))) { r = SXT_ENOMEM; goto __failed; }
|
|
|
|
|
|
|
|
else memset(tuple, 0, len);
|
|
|
|
|
|
|
|
memcpy(tuple, tebuf, len - 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* decode hash */
|
|
|
|
|
|
|
|
tebuf = NULL;
|
|
|
|
|
|
|
|
if(!(tebuf = malloc(len))) {
|
|
|
|
|
|
|
|
free(tuple);
|
|
|
|
|
|
|
|
r = SXT_ENOMEM; goto __failed;
|
|
|
|
|
|
|
|
} else memset(tebuf, 0, len);
|
|
|
|
|
|
|
|
len = sxt_b64decode_in(tuple, len, tebuf, len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
free(tuple);
|
|
|
|
|
|
|
|
if(!(chbuf = sxtrdb_new())) {
|
|
|
|
|
|
|
|
free(tebuf);
|
|
|
|
|
|
|
|
r = SXT_ENOMEM; goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sxtrdb_write_raw(chbuf, tebuf, len);
|
|
|
|
|
|
|
|
sxtrdb_read_u64(chbuf, &ctrl_hash);
|
|
|
|
|
|
|
|
sxtrdb_free(chbuf);
|
|
|
|
|
|
|
|
free(tebuf);
|
|
|
|
|
|
|
|
tebuf = tuple = NULL;
|
|
|
|
|
|
|
|
tcc++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
|
|
|
|
if(*tbuf == ')') tcc++;
|
|
|
|
|
|
|
|
else if(*tbuf != ' ') {
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ok check fmt last time */
|
|
|
|
|
|
|
|
if(tcc < 6) {
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT; goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* import from base64 encoded blob */
|
|
|
|
|
|
|
|
r = sxtkey_pubkey_import_fbase64blob(b64pk, keytype, ctrl_hash, ik);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
if(stream) fclose(stream);
|
|
|
|
|
|
|
|
if(rawfbuf) free(rawfbuf);
|
|
|
|
|
|
|
|
if(b64pk) free(b64pk);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sxtkey_export_priv_file(const sxtkey_t *key, const char *file, const char *passkey,
|
|
|
|
|
|
|
|
int (*ask_passkey)(char *pkbuf, size_t length, int confirm, void *priv),
|
|
|
|
|
|
|
|
void *priv)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FILE *out = NULL;
|
|
|
|
FILE *out = NULL;
|
|
|
|
char *pass = NULL;
|
|
|
|
char *pass = NULL;
|
|
|
@ -335,7 +859,7 @@ int sxt_key_export_priv_file(const sxtkey_t *key, const char *file, const char *
|
|
|
|
int r = 0;
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!sxt_key_private(key)) return SXT_EKEY;
|
|
|
|
if(!sxtkey_private(key)) return SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
if((out = fopen(file, "wb")) == NULL) return SXT_EIO;
|
|
|
|
if((out = fopen(file, "wb")) == NULL) return SXT_EIO;
|
|
|
|
|
|
|
|
|
|
|
@ -353,7 +877,7 @@ int sxt_key_export_priv_file(const sxtkey_t *key, const char *file, const char *
|
|
|
|
/* ok, get the base64 encoded data for the key */
|
|
|
|
/* ok, get the base64 encoded data for the key */
|
|
|
|
switch(key->type) {
|
|
|
|
switch(key->type) {
|
|
|
|
case PPKP_ED25519:
|
|
|
|
case PPKP_ED25519:
|
|
|
|
r = sxt_key_export_priv_ed25519(key, pass, &bin);
|
|
|
|
r = sxtkey_export_priv_ed25519(key, pass, &bin);
|
|
|
|
if(!bin) goto __failed;
|
|
|
|
if(!bin) goto __failed;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
@ -362,7 +886,7 @@ int sxt_key_export_priv_file(const sxtkey_t *key, const char *file, const char *
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* sxt key container as follows: (<key-type> "<base64 encoded content of the key>")\n */
|
|
|
|
/* sxt key container as follows: (<key-type> "<base64 encoded content of the key>")\n */
|
|
|
|
fprintf(out, "(%s \"%s\")\n", sxt_key_name(key->type), (char *)sxtsafebuffer_getdata(bin));
|
|
|
|
fprintf(out, "(%s \"%s\")\n", sxtkey_name(key->type), (char *)sxtsafebuffer_getdata(bin));
|
|
|
|
|
|
|
|
|
|
|
|
sxtsafebuffer_destroy(bin);
|
|
|
|
sxtsafebuffer_destroy(bin);
|
|
|
|
|
|
|
|
|
|
|
@ -376,7 +900,7 @@ int sxt_key_export_priv_file(const sxtkey_t *key, const char *file, const char *
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int sxt_key_publickey2blob_whash(const sxtkey_t *key, sxtsafebuffer_t **o)
|
|
|
|
static int sxtkey_publickey2blob_whash(const sxtkey_t *key, sxtsafebuffer_t **o)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sxtsafebuffer_t *buf = NULL, *pk = NULL;
|
|
|
|
sxtsafebuffer_t *buf = NULL, *pk = NULL;
|
|
|
|
sxtrdb_t *b = NULL;
|
|
|
|
sxtrdb_t *b = NULL;
|
|
|
@ -414,7 +938,7 @@ static int sxt_key_publickey2blob_whash(const sxtkey_t *key, sxtsafebuffer_t **o
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int sxt_key_hash2blob(const sxtkey_t *key, sxtsafebuffer_t **o)
|
|
|
|
static int sxtkey_hash2blob(const sxtkey_t *key, sxtsafebuffer_t **o)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
sxtsafebuffer_t *buf = NULL;
|
|
|
|
sxtsafebuffer_t *buf = NULL;
|
|
|
|
sxtrdb_t *b = NULL;
|
|
|
|
sxtrdb_t *b = NULL;
|
|
|
@ -439,7 +963,7 @@ static int sxt_key_hash2blob(const sxtkey_t *key, sxtsafebuffer_t **o)
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sxt_key_export_public_file(const sxtkey_t *key, const char *file)
|
|
|
|
int sxtkey_export_public_file(const sxtkey_t *key, const char *file)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
FILE *out = NULL;
|
|
|
|
FILE *out = NULL;
|
|
|
|
sxtsafebuffer_t *hashbuf = NULL, *pubkeybuf = NULL;
|
|
|
|
sxtsafebuffer_t *hashbuf = NULL, *pubkeybuf = NULL;
|
|
|
@ -448,7 +972,7 @@ int sxt_key_export_public_file(const sxtkey_t *key, const char *file)
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!key) return SXT_EINVAL;
|
|
|
|
if(!sxt_key_public(key)) return SXT_EKEY;
|
|
|
|
if(!sxtkey_public(key)) return SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
if((out = fopen(file, "wb")) == NULL) return SXT_EIO;
|
|
|
|
if((out = fopen(file, "wb")) == NULL) return SXT_EIO;
|
|
|
|
|
|
|
|
|
|
|
@ -459,10 +983,10 @@ int sxt_key_export_public_file(const sxtkey_t *key, const char *file)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* get a public key with hash blob */
|
|
|
|
/* get a public key with hash blob */
|
|
|
|
if((r = sxt_key_publickey2blob_whash(key, &pubkey_sb)) != SXT_SUCCESS) goto __failed;
|
|
|
|
if((r = sxtkey_publickey2blob_whash(key, &pubkey_sb)) != SXT_SUCCESS) goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
/* get key hash blob */
|
|
|
|
/* get key hash blob */
|
|
|
|
if((r = sxt_key_hash2blob(key, &hash_sb)) != SXT_SUCCESS) goto __failed;
|
|
|
|
if((r = sxtkey_hash2blob(key, &hash_sb)) != SXT_SUCCESS) goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
/* allocate buffers for base64 encoded data */
|
|
|
|
/* allocate buffers for base64 encoded data */
|
|
|
|
if(!(pubkeybuf = sxtsafebuffer_new(sxt_rawlen2b64len(sxtsafebuffer_length(pubkey_sb))))) {
|
|
|
|
if(!(pubkeybuf = sxtsafebuffer_new(sxt_rawlen2b64len(sxtsafebuffer_length(pubkey_sb))))) {
|
|
|
@ -491,7 +1015,7 @@ int sxt_key_export_public_file(const sxtkey_t *key, const char *file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* output this */
|
|
|
|
/* output this */
|
|
|
|
fprintf(out, "(%s 'public \"%s\" \"%s\")\n", sxt_key_name(key->type), pckey, pchash);
|
|
|
|
fprintf(out, "(%s 'public \"%s\" \"%s\")\n", sxtkey_name(key->type), pckey, pchash);
|
|
|
|
|
|
|
|
|
|
|
|
/* free all stuff */
|
|
|
|
/* free all stuff */
|
|
|
|
sxtsafebuffer_freecstr(pckey);
|
|
|
|
sxtsafebuffer_freecstr(pckey);
|
|
|
@ -507,7 +1031,7 @@ int sxt_key_export_public_file(const sxtkey_t *key, const char *file)
|
|
|
|
return r;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int sxt_key_export_priv_ed25519(const sxtkey_t *key, const char *pass, sxtsafebuffer_t **bin)
|
|
|
|
static int sxtkey_export_priv_ed25519(const sxtkey_t *key, const char *pass, sxtsafebuffer_t **bin)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
int r = 0;
|
|
|
|
sxtsafebuffer_t *b64 = NULL, *pubkey_sb = NULL;
|
|
|
|
sxtsafebuffer_t *b64 = NULL, *pubkey_sb = NULL;
|
|
|
@ -584,7 +1108,7 @@ static int sxt_key_export_priv_ed25519(const sxtkey_t *key, const char *pass, sx
|
|
|
|
sxtsafebuffer_destroy(salt);
|
|
|
|
sxtsafebuffer_destroy(salt);
|
|
|
|
goto __enomem1;
|
|
|
|
goto __enomem1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sxtrdb_print(kdfopts, "pd", 16, sxtsafebuffer_getdata(salt), (uint32_t)32);
|
|
|
|
sxtrdb_print(kdfopts, "Pd", 16, sxtsafebuffer_getdata(salt), (uint32_t)32);
|
|
|
|
|
|
|
|
|
|
|
|
/* ok, now we need to get a padding, just to be sure to be aligned for the
|
|
|
|
/* ok, now we need to get a padding, just to be sure to be aligned for the
|
|
|
|
cipher block size */
|
|
|
|
cipher block size */
|
|
|
@ -629,7 +1153,7 @@ static int sxt_key_export_priv_ed25519(const sxtkey_t *key, const char *pass, sx
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
r = SXT_ENOMEM;
|
|
|
|
goto __failed;
|
|
|
|
goto __failed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sxtrdb_print(kdfopts, "pd", 3, "nil", (uint32_t)0);
|
|
|
|
sxtrdb_print(kdfopts, "Pd", 3, "nil", (uint32_t)0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* there are a time to print all required content to the buffer */
|
|
|
|
/* there are a time to print all required content to the buffer */
|
|
|
@ -639,7 +1163,7 @@ static int sxt_key_export_priv_ed25519(const sxtkey_t *key, const char *pass, sx
|
|
|
|
* <private-key-data>
|
|
|
|
* <private-key-data>
|
|
|
|
* according to the documentation
|
|
|
|
* according to the documentation
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
sxtrdb_print(keybuf, "sbsssppp", PPKP_MAGIC, flags, "ppkp-ed25519",
|
|
|
|
sxtrdb_print(keybuf, "sbsssPPP", PPKP_MAGIC, flags, "ppkp-ed25519",
|
|
|
|
pass ? "aes128-cbc" : "nil", pass ? "bcrypt" : "nil",
|
|
|
|
pass ? "aes128-cbc" : "nil", pass ? "bcrypt" : "nil",
|
|
|
|
sxtrdb_length(kdfopts), sxtrdb_rdata(kdfopts),
|
|
|
|
sxtrdb_length(kdfopts), sxtrdb_rdata(kdfopts),
|
|
|
|
sxtsafebuffer_length(pubkey_sb), sxtsafebuffer_getdata(pubkey_sb),
|
|
|
|
sxtsafebuffer_length(pubkey_sb), sxtsafebuffer_getdata(pubkey_sb),
|
|
|
@ -711,3 +1235,89 @@ static int sxt_public_ed25519_2rdb(const sxtkey_t *key, sxtrdb_t **out)
|
|
|
|
return SXT_SUCCESS;
|
|
|
|
return SXT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int _sxtkey_check_fmtrawbuf(const char *buffer)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
char *tbuf;
|
|
|
|
|
|
|
|
int r = SXT_SUCCESS, tc = 0, tcc = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* currently only own container supported,
|
|
|
|
|
|
|
|
* let's checkout format:
|
|
|
|
|
|
|
|
* = () and ""
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
for(tbuf = (char *)buffer; *tbuf != '\0'; tbuf++) {
|
|
|
|
|
|
|
|
switch(*tbuf) {
|
|
|
|
|
|
|
|
case '(': tc++; break;
|
|
|
|
|
|
|
|
case ')': tc--; break;
|
|
|
|
|
|
|
|
case '"':
|
|
|
|
|
|
|
|
if(!tc) {
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
} else tcc++;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break; /* just ignore */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = SXT_EKEYFMT;
|
|
|
|
|
|
|
|
if(tc) goto __failed;
|
|
|
|
|
|
|
|
if(tcc%2) goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int _sxtkey_privkey_decrypt(sxtrdb_t *privkey, sxtrdb_t *kdfopt,
|
|
|
|
|
|
|
|
const char *passkey)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int r = SXT_SUCCESS;
|
|
|
|
|
|
|
|
sxtrdb_t *salt = NULL;
|
|
|
|
|
|
|
|
sxt_cipher_t *cipher = sxt_cipher_get("aes128-cbc");
|
|
|
|
|
|
|
|
uint32_t rounds, keystub_len;
|
|
|
|
|
|
|
|
uint8_t keystub[128];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* default check */
|
|
|
|
|
|
|
|
if(!privkey || !kdfopt) return SXT_EINVAL;
|
|
|
|
|
|
|
|
if(!passkey) return SXT_EAUTH;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* cipher */
|
|
|
|
|
|
|
|
if(!(cipher = sxt_cipher_get("aes128-cbc"))) return SXT_EKEY;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* get salt and rounds */
|
|
|
|
|
|
|
|
if((r = sxtrdb_escan(kdfopt, "Rd", &salt, &rounds)) != SXT_SUCCESS)
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* check blob length and cipher block size */
|
|
|
|
|
|
|
|
if(sxtrdb_length(privkey) % cipher->blksize != 0) {
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* bcrypt */
|
|
|
|
|
|
|
|
keystub_len = cipher->keysize/8 + cipher->blksize;
|
|
|
|
|
|
|
|
if(keystub_len > sizeof(keystub)) {
|
|
|
|
|
|
|
|
r = SXT_EKEY;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(bcrypt_pbkdf(passkey, strlen(passkey), sxtrdb_rdata(salt), sxtrdb_length(salt),
|
|
|
|
|
|
|
|
keystub, keystub_len, rounds) < 0) {
|
|
|
|
|
|
|
|
memset(keystub, 0, keystub_len);
|
|
|
|
|
|
|
|
r = SXT_EAUTH;
|
|
|
|
|
|
|
|
goto __failed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* set decrypt key and decrypt */
|
|
|
|
|
|
|
|
cipher->f->set_decrypt_key(cipher, keystub, keystub + cipher->keysize/8);
|
|
|
|
|
|
|
|
cipher->f->decrypt(cipher, sxtrdb_rdata(privkey), sxtrdb_rdata(privkey),
|
|
|
|
|
|
|
|
sxtrdb_length(privkey));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* free/burn unused data */
|
|
|
|
|
|
|
|
memset(keystub, 0, keystub_len);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__failed:
|
|
|
|
|
|
|
|
if(cipher) sxt_cipher_free(cipher);
|
|
|
|
|
|
|
|
if(salt) sxtrdb_free(salt);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|