mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-02-21 01:42:18 +00:00
Tidy up rhizome secret handling to improve reusability
This commit is contained in:
parent
cf6ecbc57d
commit
dc43b83c80
@ -1057,14 +1057,14 @@ int app_rhizome_add_file(int argc, const char *const *argv, const struct command
|
||||
return -1;
|
||||
cli_arg(argc, argv, o, "pin", &pin, NULL, "");
|
||||
cli_arg(argc, argv, o, "manifestpath", &manifestpath, NULL, "");
|
||||
if (cli_arg(argc, argv, o, "bsk", &bskhex, cli_optional_bundle_key, "") == -1)
|
||||
if (cli_arg(argc, argv, o, "bsk", &bskhex, cli_optional_bundle_key, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
sid_t authorSid;
|
||||
if (authorSidHex[0] && fromhexstr(authorSid.binary, authorSidHex, SID_SIZE) == -1)
|
||||
return WHYF("invalid author_sid: %s", authorSidHex);
|
||||
rhizome_bk_t bsk;
|
||||
if (bskhex[0] && fromhexstr(bsk.binary, bskhex, RHIZOME_BUNDLE_KEY_BYTES) == -1)
|
||||
if (bskhex && fromhexstr(bsk.binary, bskhex, RHIZOME_BUNDLE_KEY_BYTES) == -1)
|
||||
return WHYF("invalid bsk: %s", bskhex);
|
||||
|
||||
if (create_serval_instance_dir() == -1)
|
||||
@ -1097,7 +1097,7 @@ int app_rhizome_add_file(int argc, const char *const *argv, const struct command
|
||||
if (rhizome_stat_file(m, filepath))
|
||||
return -1;
|
||||
|
||||
if (rhizome_fill_manifest(m, filepath, *authorSidHex?&authorSid:NULL, &bsk))
|
||||
if (rhizome_fill_manifest(m, filepath, *authorSidHex?&authorSid:NULL, bskhex?&bsk:NULL))
|
||||
return -1;
|
||||
|
||||
/* Keep note as to whether we are supposed to be encrypting this file or not */
|
||||
@ -1250,7 +1250,7 @@ int app_rhizome_extract_manifest(int argc, const char *const *argv, const struct
|
||||
// fail if the manifest is invalid?
|
||||
}
|
||||
|
||||
rhizome_find_manifest_secret(m);
|
||||
rhizome_extract_privatekey(m, NULL);
|
||||
|
||||
const char *blob_service = rhizome_manifest_get(m, "service", NULL, 0);
|
||||
|
||||
|
@ -307,7 +307,6 @@ long long rhizome_bar_version(unsigned char *bar);
|
||||
unsigned long long rhizome_bar_bidprefix_ll(unsigned char *bar);
|
||||
int rhizome_list_manifests(const char *service, const char *sender_sid, const char *recipient_sid, int limit, int offset);
|
||||
int rhizome_retrieve_manifest(const char *manifestid, rhizome_manifest *m);
|
||||
int rhizome_find_manifest_secret(rhizome_manifest *m);
|
||||
|
||||
#define RHIZOME_DONTVERIFY 0
|
||||
#define RHIZOME_VERIFY 1
|
||||
@ -338,7 +337,7 @@ int rhizome_secret2bk(
|
||||
const unsigned char secret[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES]
|
||||
);
|
||||
unsigned char *rhizome_bundle_shared_secret(rhizome_manifest *m);
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m);
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m, rhizome_bk_t *bsk);
|
||||
int rhizome_sign_hash_with_key(rhizome_manifest *m,const unsigned char *sk,
|
||||
const unsigned char *pk,rhizome_signature *out);
|
||||
int rhizome_verify_bundle_privatekey(rhizome_manifest *m, const unsigned char *sk,
|
||||
|
106
rhizome_bundle.c
106
rhizome_bundle.c
@ -292,23 +292,6 @@ int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bu
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
/* Find the author and bundle secret */
|
||||
int rhizome_find_manifest_secret(rhizome_manifest *m)
|
||||
{
|
||||
int ret;
|
||||
if (is_sid_any(m->author)) {
|
||||
ret=rhizome_find_bundle_author(m);
|
||||
}else{
|
||||
// should we try this first, then fall back to searching the keyring?
|
||||
ret=rhizome_extract_privatekey(m);
|
||||
if (ret){
|
||||
INFOF("bundle author=%s is not in keyring -- ignored", alloca_tohex_sid(m->author));
|
||||
memset(m->author, 0, sizeof m->author);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rhizome_hash_file(rhizome_manifest *m,const char *filename,char *hash_out)
|
||||
{
|
||||
/* Gnarf! NaCl's crypto_hash() function needs the whole file passed in in one
|
||||
@ -730,81 +713,32 @@ int rhizome_fill_manifest(rhizome_manifest *m, const char *filepath, const sid_t
|
||||
if (id == NULL) {
|
||||
if (config.debug.rhizome) DEBUG("creating new bundle");
|
||||
if (rhizome_manifest_bind_id(m) == -1) {
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("Could not bind manifest to an ID");
|
||||
}
|
||||
} else {
|
||||
if (config.debug.rhizome) DEBUGF("modifying existing bundle bid=%s", id);
|
||||
// Modifying an existing bundle. If an author SID is supplied, we must ensure that it is valid,
|
||||
// ie, that identity has permission to alter the bundle. If no author SID is supplied but a BSK
|
||||
// is supplied, then use that to alter the bundle. Otherwise, search the keyring for an
|
||||
// identity with permission to alter the bundle.
|
||||
if (!is_sid_any(m->author)) {
|
||||
// Check that the given author has permission to alter the bundle, and extract the secret
|
||||
// bundle key if so.
|
||||
int result = rhizome_extract_privatekey(m);
|
||||
switch (result) {
|
||||
case -1:
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("error in rhizome_extract_privatekey()");
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (!rhizome_is_bk_none(bsk))
|
||||
break;
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("Manifest does not have BK field");
|
||||
case 2:
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("Author unknown");
|
||||
case 3:
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("Author does not have a Rhizome Secret");
|
||||
case 4:
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("Author does not have permission to modify manifest");
|
||||
default:
|
||||
rhizome_manifest_free(m);
|
||||
return WHYF("Unknown result from rhizome_extract_privatekey(): %d", result);
|
||||
}
|
||||
}
|
||||
if (!rhizome_is_bk_none(bsk)){
|
||||
if (config.debug.rhizome) DEBUGF("bskhex=%s", alloca_tohex(bsk->binary, RHIZOME_BUNDLE_KEY_BYTES));
|
||||
if (m->haveSecret) {
|
||||
// If a bundle secret key was supplied that does not match the secret key derived from the
|
||||
// author, then warn but carry on using the author's.
|
||||
if (memcmp(bsk, m->cryptoSignSecret, RHIZOME_BUNDLE_KEY_BYTES) != 0)
|
||||
WARNF("Supplied bundle secret key is invalid -- ignoring");
|
||||
} else {
|
||||
// The caller provided the bundle secret key, so ensure that it corresponds to the bundle's
|
||||
// public key (its bundle ID), otherwise it won't work.
|
||||
memcpy(m->cryptoSignSecret, bsk, RHIZOME_BUNDLE_KEY_BYTES);
|
||||
if (rhizome_verify_bundle_privatekey(m,m->cryptoSignSecret,
|
||||
m->cryptoSignPublic) == -1) {
|
||||
rhizome_manifest_free(m);
|
||||
return WHY("Incorrect BID secret key.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we still don't know the bundle secret or the author, then search for an author.
|
||||
if (!m->haveSecret && is_sid_any(m->author)) {
|
||||
if (config.debug.rhizome) DEBUG("bundle author not specified, searching keyring");
|
||||
int result = rhizome_find_bundle_author(m);
|
||||
if (result != 0) {
|
||||
rhizome_manifest_free(m);
|
||||
switch (result) {
|
||||
case -1:
|
||||
return WHY("error in rhizome_find_bundle_author()");
|
||||
case 4:
|
||||
return WHY("Manifest does not have BK field");
|
||||
case 1:
|
||||
return WHY("No author found");
|
||||
default:
|
||||
return WHYF("Unknown result from rhizome_find_bundle_author(): %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
// Modifying an existing bundle. Make sure we can find the bundle secret.
|
||||
int result = rhizome_extract_privatekey(m, bsk);
|
||||
switch (result) {
|
||||
case -1:
|
||||
return -1;
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
return WHY("bundle contains no BK field, and no bundle secret supplied");
|
||||
case 2:
|
||||
return WHY("Author unknown");
|
||||
case 3:
|
||||
return WHY("Author does not have a Rhizome Secret");
|
||||
case 4:
|
||||
return WHY("Author does not have permission to modify manifest");
|
||||
default:
|
||||
return WHYF("Unknown result from rhizome_extract_privatekey(): %d", result);
|
||||
}
|
||||
|
||||
// TODO assert that new version > old version?
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -203,35 +203,54 @@ int rhizome_find_secret(const unsigned char *authorSid, int *rs_len, const unsig
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
|
||||
*/
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m)
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m, rhizome_bk_t *bsk)
|
||||
{
|
||||
IN();
|
||||
unsigned char bkBytes[RHIZOME_BUNDLE_KEY_BYTES];
|
||||
char *bk = rhizome_manifest_get(m, "BK", NULL, 0);
|
||||
if (!bk) {
|
||||
if (config.debug.rhizome) DEBUG("bundle contains no BK field");
|
||||
|
||||
if (bk){
|
||||
int result;
|
||||
|
||||
if (fromhexstr(bkBytes, bk, RHIZOME_BUNDLE_KEY_BYTES) == -1)
|
||||
RETURN(WHYF("invalid BK field: %s", bk));
|
||||
|
||||
if (is_sid_any(m->author)) {
|
||||
result=rhizome_find_bundle_author(m);
|
||||
}else{
|
||||
int rs_len;
|
||||
const unsigned char *rs;
|
||||
result = rhizome_find_secret(m->author, &rs_len, &rs);
|
||||
if (result!=0)
|
||||
RETURN(result);
|
||||
|
||||
result = rhizome_bk2secret(m,m->cryptoSignPublic,rs,rs_len,
|
||||
bkBytes,m->cryptoSignSecret);
|
||||
}
|
||||
|
||||
if (result == 0){
|
||||
m->haveSecret=EXISTING_BUNDLE_ID;
|
||||
|
||||
if(bsk && !rhizome_is_bk_none(bsk)){
|
||||
// If a bundle secret key was supplied that does not match the secret key derived from the
|
||||
// author, then warn but carry on using the author's.
|
||||
if (memcmp(bsk, m->cryptoSignSecret, RHIZOME_BUNDLE_KEY_BYTES) != 0)
|
||||
WARNF("Supplied bundle secret key is invalid -- ignoring");
|
||||
}
|
||||
|
||||
}else{
|
||||
memset(m->cryptoSignSecret, 0, sizeof m->cryptoSignSecret);
|
||||
m->haveSecret=0;
|
||||
}
|
||||
|
||||
RETURN(result);
|
||||
}else if(bsk && !rhizome_is_bk_none(bsk)){
|
||||
memcpy(m->cryptoSignSecret, bsk, RHIZOME_BUNDLE_KEY_BYTES);
|
||||
RETURN(rhizome_verify_bundle_privatekey(m,m->cryptoSignSecret,
|
||||
m->cryptoSignPublic));
|
||||
}else{
|
||||
RETURN(1);
|
||||
}
|
||||
unsigned char bkBytes[RHIZOME_BUNDLE_KEY_BYTES];
|
||||
if (fromhexstr(bkBytes, bk, RHIZOME_BUNDLE_KEY_BYTES) == -1)
|
||||
RETURN(WHYF("invalid BK field: %s", bk));
|
||||
|
||||
int rs_len;
|
||||
const unsigned char *rs;
|
||||
int result = rhizome_find_secret(m->author, &rs_len, &rs);
|
||||
if (result != 0)
|
||||
return WHY("Error searching for Rhizome secret");
|
||||
|
||||
result = rhizome_bk2secret(m,m->cryptoSignPublic,rs,rs_len,
|
||||
bkBytes,m->cryptoSignSecret);
|
||||
|
||||
if (result == 0) {
|
||||
m->haveSecret=EXISTING_BUNDLE_ID;
|
||||
RETURN(0); // bingo
|
||||
}
|
||||
memset(m->cryptoSignSecret, 0, sizeof m->cryptoSignSecret);
|
||||
m->haveSecret=0;
|
||||
if (config.debug.rhizome) DEBUGF("result=%d", result);
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
/* Discover if the given manifest was created (signed) by any unlocked identity currently in the
|
||||
@ -343,7 +362,7 @@ int rhizome_sign_hash(rhizome_manifest *m,
|
||||
rhizome_signature *out)
|
||||
{
|
||||
IN();
|
||||
if (!m->haveSecret && rhizome_extract_privatekey(m))
|
||||
if (!m->haveSecret && rhizome_extract_privatekey(m, NULL))
|
||||
RETURN(WHY("Cannot find secret key to sign manifest data."));
|
||||
|
||||
RETURN(rhizome_sign_hash_with_key(m,m->cryptoSignSecret,m->cryptoSignPublic,out));
|
||||
@ -554,4 +573,3 @@ int rhizome_crypt_xor_block(unsigned char *buffer, int buffer_size, int64_t stre
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user