Tidy up rhizome secret handling to improve reusability

This commit is contained in:
Jeremy Lakeman 2013-01-03 12:14:13 +10:30
parent cf6ecbc57d
commit dc43b83c80
4 changed files with 69 additions and 118 deletions

View File

@ -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);

View File

@ -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,

View File

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

View File

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