mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-24 07:16:43 +00:00
Issue #17, overhaul manifest author crypto logic
Add test case for new feature of the "rhizome add" command: if the author SID is not specified (empty arg) then it searches the keyring for the author. Removed "authorSid" argument from several functions that also take a struct rhizome_manifest * arg, since the author, if known, is now supplied in the struct. Improve return value handling and refactored some rhizome crypto code.
This commit is contained in:
parent
f4d0b7a16a
commit
3f1f495d68
@ -1042,29 +1042,75 @@ int app_rhizome_add_file(int argc, const char *const *argv, struct command_line_
|
||||
if (rhizome_manifest_get(m, "id", NULL, 0) == NULL) {
|
||||
if (rhizome_manifest_bind_id(m) == -1) {
|
||||
rhizome_manifest_free(m);
|
||||
m = NULL;
|
||||
return WHY("Could not bind manifest to an ID");
|
||||
}
|
||||
} else if (bskhex[0]) {
|
||||
/* Modifying an existing bundle. If the caller provides the bundle secret key, then ensure that
|
||||
it corresponds to the bundle's public key (its bundle ID), otherwise the caller cannot modify
|
||||
the bundle. */
|
||||
} else {
|
||||
// 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 (bskhex[0])
|
||||
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 (bskhex[0]) {
|
||||
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) == -1) {
|
||||
rhizome_manifest_free(m);
|
||||
m = NULL;
|
||||
return WHY("Incorrect BID secret key.");
|
||||
}
|
||||
} else if (!authorSidHex[0]) {
|
||||
/* In order to modify an existing bundle, the author must be known. */
|
||||
}
|
||||
}
|
||||
// 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)) {
|
||||
int result = rhizome_find_bundle_author(m);
|
||||
if (result != 0) {
|
||||
rhizome_manifest_free(m);
|
||||
m = NULL;
|
||||
return WHY("Author SID not specified");
|
||||
} else if (rhizome_extract_privatekey(m, authorSid) == -1) {
|
||||
/* Only the original author can modify an existing bundle. */
|
||||
rhizome_manifest_free(m);
|
||||
m = NULL;
|
||||
return WHY("Could not extract BID secret key. Does the manifest have a BK?");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int encryptP = 0; // TODO Determine here whether payload is to be encrypted.
|
||||
if (rhizome_manifest_bind_file(m, filepath, encryptP)) {
|
||||
|
@ -50,7 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
get - 8 bit variable value
|
||||
|
||||
*/
|
||||
#define SID_SIZE 32
|
||||
#define SID_SIZE 32 // == crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES
|
||||
#define SAS_SIZE 32 // == crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES
|
||||
#define DID_MINSIZE 5
|
||||
#define DID_MAXSIZE 32
|
||||
|
@ -157,9 +157,7 @@ int rhizome_manifest_bind_id(rhizome_manifest *m_in)
|
||||
manifests on receiver nodes works easily. We might implement something that strips the id
|
||||
variable out of the manifest when sending it, or some other scheme to avoid sending all the
|
||||
extra bytes. */
|
||||
char id[RHIZOME_MANIFEST_ID_STRLEN + 1];
|
||||
rhizome_bytes_to_hex_upper(m_in->cryptoSignPublic, id, RHIZOME_MANIFEST_ID_BYTES);
|
||||
rhizome_manifest_set(m_in, "id", id);
|
||||
rhizome_manifest_set(m_in, "id", alloca_tohex_bid(m_in->cryptoSignPublic));
|
||||
if (!is_sid_any(m_in->author)) {
|
||||
/* Set the BK using the provided authorship information.
|
||||
Serval Security Framework defines BK as being:
|
||||
|
@ -234,7 +234,7 @@ int rhizome_add_manifest(rhizome_manifest *m_in,int ttl);
|
||||
|
||||
void rhizome_bytes_to_hex_upper(unsigned const char *in, char *out, int byteCount);
|
||||
int rhizome_find_privatekey(rhizome_manifest *m);
|
||||
rhizome_signature *rhizome_sign_hash(rhizome_manifest *m, const unsigned char *authorSid);
|
||||
int rhizome_sign_hash(rhizome_manifest *m, rhizome_signature *out);
|
||||
|
||||
__RHIZOME_INLINE int sqlite_code_ok(int code)
|
||||
{
|
||||
@ -299,9 +299,9 @@ int rhizome_bk_xor(const unsigned char *authorSid, // binary
|
||||
unsigned char bkin[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES],
|
||||
unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES]);
|
||||
unsigned char *rhizome_bundle_shared_secret(rhizome_manifest *m);
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m, const unsigned char *authorSid);
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m);
|
||||
int rhizome_verify_bundle_privatekey(rhizome_manifest *m);
|
||||
int rhizome_is_self_signed(rhizome_manifest *m);
|
||||
int rhizome_find_bundle_author(rhizome_manifest *m);
|
||||
int rhizome_queue_ignore_manifest(rhizome_manifest *m,
|
||||
struct sockaddr_in *peerip,int timeout);
|
||||
int rhizome_ignore_manifest_check(rhizome_manifest *m,
|
||||
|
@ -570,22 +570,17 @@ int rhizome_manifest_pack_variables(rhizome_manifest *m)
|
||||
*/
|
||||
int rhizome_manifest_selfsign(rhizome_manifest *m)
|
||||
{
|
||||
if (!m->haveSecret) return WHY("Need private key to sign manifest");
|
||||
rhizome_signature *sig = rhizome_sign_hash(m, m->cryptoSignSecret);
|
||||
if (!sig) return WHY("rhizome_sign_hash() failed.");
|
||||
|
||||
if (!m->haveSecret)
|
||||
return WHY("Need private key to sign manifest");
|
||||
rhizome_signature sig;
|
||||
if (rhizome_sign_hash(m, &sig) == -1)
|
||||
return WHY("rhizome_sign_hash() failed");
|
||||
/* Append signature to end of manifest data */
|
||||
if (sig->signatureLength+m->manifest_bytes>MAX_MANIFEST_BYTES) {
|
||||
free(sig);
|
||||
return WHY("Manifest plus signatures is too long.");
|
||||
}
|
||||
|
||||
bcopy(&sig->signature[0],&m->manifestdata[m->manifest_bytes],sig->signatureLength);
|
||||
|
||||
m->manifest_bytes+=sig->signatureLength;
|
||||
if (sig.signatureLength + m->manifest_bytes > MAX_MANIFEST_BYTES)
|
||||
return WHY("Manifest plus signatures is too long");
|
||||
bcopy(&sig.signature[0], &m->manifestdata[m->manifest_bytes], sig.signatureLength);
|
||||
m->manifest_bytes += sig.signatureLength;
|
||||
m->manifest_all_bytes = m->manifest_bytes;
|
||||
|
||||
free(sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
239
rhizome_crypto.c
239
rhizome_crypto.c
@ -38,34 +38,20 @@ int rhizome_manifest_createid(rhizome_manifest *m)
|
||||
return WHY("Failed to create keypair for manifest ID.");
|
||||
}
|
||||
|
||||
/*
|
||||
Return -1 if an error occurs.
|
||||
Return 0 if the author's private key is located and the XOR is performed successfully.
|
||||
Return 1 if the author's identity is not in the keyring.
|
||||
Return 2 if the author's identity is in the keyring but has no rhizome secret.
|
||||
/* Given a Rhizome Secret (RS) and bundle ID (BID), XOR a bundle key 'bkin' (private or public) with
|
||||
* RS##BID.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int rhizome_bk_xor(const unsigned char *authorSid, // binary
|
||||
static void rhizome_bk_xor_rs(
|
||||
const unsigned char *rs,
|
||||
size_t rs_len,
|
||||
unsigned char bid[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES],
|
||||
unsigned char bkin[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES],
|
||||
unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES])
|
||||
unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES]
|
||||
)
|
||||
{
|
||||
IN();
|
||||
if (crypto_sign_edwards25519sha512batch_SECRETKEYBYTES > crypto_hash_sha512_BYTES)
|
||||
{ RETURN(WHY("BK needs to be longer than it can be")); }
|
||||
int cn=0,in=0,kp=0;
|
||||
if (!keyring_find_sid(keyring,&cn,&in,&kp,authorSid)) {
|
||||
if (debug & DEBUG_RHIZOME) DEBUG("identity not in keyring");
|
||||
{ RETURN(1); }
|
||||
}
|
||||
kp = keyring_identity_find_keytype(keyring, cn, in, KEYTYPE_RHIZOME);
|
||||
if (kp == -1) {
|
||||
if (debug & DEBUG_RHIZOME) DEBUG("identity has no Rhizome Secret");
|
||||
RETURN(2);
|
||||
}
|
||||
int rs_len=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key_len;
|
||||
if (rs_len<16||rs_len>1024)
|
||||
{ RETURN(WHYF("invalid Rhizome Secret: length=%d", rs_len)); }
|
||||
unsigned char *rs=keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key;
|
||||
int combined_len = rs_len + crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES;
|
||||
unsigned char buffer[combined_len];
|
||||
bcopy(&rs[0], &buffer[0], rs_len);
|
||||
@ -75,86 +61,164 @@ int rhizome_bk_xor(const unsigned char *authorSid, // binary
|
||||
int i;
|
||||
for(i = 0; i != crypto_sign_edwards25519sha512batch_SECRETKEYBYTES; ++i)
|
||||
bkout[i] = bkin[i] ^ hash[i];
|
||||
bzero(&buffer[0],combined_len);
|
||||
bzero(&hash[0],crypto_hash_sha512_BYTES);
|
||||
RETURN(0);
|
||||
bzero(buffer, combined_len);
|
||||
bzero(hash, sizeof hash);
|
||||
OUT();
|
||||
}
|
||||
|
||||
/* See if the manifest has a BK entry, and if so, use it to obtain the
|
||||
private key for the BID. Decoding BK's relies on the provision of
|
||||
the appropriate SID.
|
||||
|
||||
Return 0 if the private key was extracted, 1 if not. Return -1 if an error occurs.
|
||||
|
||||
XXX Note that this function is not able to verify that the private key
|
||||
is correct, as there is no exposed API in NaCl for calculating the
|
||||
public key from a cryptosign private key. We thus have to trust that
|
||||
the supplied SID is correct.
|
||||
|
||||
/* Given the SID of a bundle's author and the bundle ID, XOR a bundle key (private or public) with
|
||||
* RS##BID where RS is the rhizome secret of the bundle's author, and BID is the bundle's public key
|
||||
* (aka the Bundle ID).
|
||||
*
|
||||
* This will convert a manifest BK field into the bundle's private key, or vice versa.
|
||||
*
|
||||
* Returns -1 if an error occurs.
|
||||
* Returns 0 if the author's private key is located and the XOR is performed successfully.
|
||||
* Returns 2 if the author's identity is not in the keyring.
|
||||
* Returns 3 if the author's identity is in the keyring but has no rhizome secret.
|
||||
*
|
||||
* Looks up the SID in the keyring, and if it is present and has a valid-looking RS, calls
|
||||
* rhizome_bk_xor_rs() to perform the XOR.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m, const unsigned char *authorSid)
|
||||
int rhizome_bk_xor(const unsigned char *authorSid, // binary
|
||||
unsigned char bid[crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES],
|
||||
unsigned char bkin[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES],
|
||||
unsigned char bkout[crypto_sign_edwards25519sha512batch_SECRETKEYBYTES])
|
||||
{
|
||||
if (crypto_sign_edwards25519sha512batch_SECRETKEYBYTES > crypto_hash_sha512_BYTES)
|
||||
return WHY("BK needs to be longer than it can be");
|
||||
int cn=0,in=0,kp=0;
|
||||
if (!keyring_find_sid(keyring,&cn,&in,&kp,authorSid)) {
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("identity sid=%s is not in keyring", alloca_tohex_sid(authorSid));
|
||||
return 2;
|
||||
}
|
||||
kp = keyring_identity_find_keytype(keyring, cn, in, KEYTYPE_RHIZOME);
|
||||
if (kp == -1) {
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("identity sid=%s has no Rhizome Secret", alloca_tohex_sid(authorSid));
|
||||
return 3;
|
||||
}
|
||||
int rs_len = keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key_len;
|
||||
if (rs_len < 16 || rs_len > 1024)
|
||||
return WHYF("identity sid=%s has invalid Rhizome Secret: length=%d", alloca_tohex_sid(authorSid), rs_len);
|
||||
const unsigned char *rs = keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key;
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("using identity sid=%s", alloca_tohex_sid(authorSid));
|
||||
rhizome_bk_xor_rs(rs, rs_len, bid, bkin, bkout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See if the manifest has a BK entry, and if so, use it to obtain the private key for the BID. The
|
||||
* manifest's 'author' field must contain the (binary) SID of the purported author of the bundle,
|
||||
* which is used to look up the author's rhizome secret in the keyring.
|
||||
*
|
||||
* Returns 0 if a valid private key was extracted, with the private key in the manifest
|
||||
* 'cryptoSignSecret' field and the 'haveSecret' field set to 1.
|
||||
*
|
||||
* Returns 1 if the manifest does not have a BK field.
|
||||
*
|
||||
* Returns 2 if the author is not found in the keyring (not unlocked?) -- this return code from
|
||||
* rhizome_bk_xor().
|
||||
*
|
||||
* Returns 3 if the author is found in the keyring but has no rhizome secret -- this return code
|
||||
* from rhizome_bk_xor().
|
||||
*
|
||||
* Returns 4 if the author is found in the keyring and has a rhizome secret but the private bundle
|
||||
* key formed using it does not verify.
|
||||
*
|
||||
* Returns -1 on error.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int rhizome_extract_privatekey(rhizome_manifest *m)
|
||||
{
|
||||
IN();
|
||||
char *bk = rhizome_manifest_get(m, "BK", NULL, 0);
|
||||
if (!bk) { RETURN(WHY("missing BK field")); }
|
||||
if (!bk)
|
||||
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)); }
|
||||
switch (rhizome_bk_xor(authorSid, m->cryptoSignPublic, bkBytes, m->cryptoSignSecret)) {
|
||||
case -1:
|
||||
RETURN(WHY("rhizome_bk_xor() failed"));
|
||||
case 0:
|
||||
RETURN(rhizome_verify_bundle_privatekey(m));
|
||||
RETURN(WHYF("invalid BK field: %s", bk));
|
||||
int result = rhizome_bk_xor(m->author, m->cryptoSignPublic, bkBytes, m->cryptoSignSecret);
|
||||
if (result == 0) {
|
||||
int verified = rhizome_verify_bundle_privatekey(m);
|
||||
if (verified == 0)
|
||||
RETURN(0); // bingo
|
||||
if (verified == -1)
|
||||
result = WHY("rhizome_bk_xor() failed");
|
||||
else {
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("identity sid=%s is not the author of bundle with BK=%s", alloca_tohex_sid(m->author), bk);
|
||||
result = 3;
|
||||
}
|
||||
RETURN(WHYF("Rhizome secret for %s not found. (Have you unlocked the identity?)", alloca_tohex_sid(authorSid)));
|
||||
}
|
||||
memset(m->cryptoSignSecret, 0, sizeof m->cryptoSignSecret);
|
||||
RETURN(result);
|
||||
}
|
||||
|
||||
/*
|
||||
Test to see if the given manifest was created (signed) by any unlocked identity currently in the
|
||||
keyring.
|
||||
- Returns -1 if an error occurs, eg, the manifest contains an invalid BK field.
|
||||
- Return 0 if the manifest's BK field was produced by any currently unlocked SID.
|
||||
- Returns 1 if the manifest has no BK field.
|
||||
- Returns 2 otherwise.
|
||||
Currently unused; was called from rhizome_list_manifests() to compute the now-defunct
|
||||
".selfsigned" column, but that made the Rhizome List view too slow in the Serval Mesh app.
|
||||
See issue servalproject/serval-dna#17.
|
||||
@author Andrew Bettison <andrew@servalproject.com>
|
||||
/* Discover if the given manifest was created (signed) by any unlocked identity currently in the
|
||||
* keyring.
|
||||
*
|
||||
* Returns 0 if an identity is found with permission to alter the bundle, after setting the manifest
|
||||
* 'author' field to the SID of the identity and the manifest 'cryptoSignSecret' field to the bundle
|
||||
* secret key and the 'haveSecret' field to 1.
|
||||
*
|
||||
* Returns 1 if no identity in the keyring is the author of this bundle.
|
||||
*
|
||||
* Returns 4 if the manifest has no BK field.
|
||||
*
|
||||
* Returns -1 if an error occurs, eg, the manifest contains an invalid BK field.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
int rhizome_is_self_signed(rhizome_manifest *m)
|
||||
int rhizome_find_bundle_author(rhizome_manifest *m)
|
||||
{
|
||||
IN();
|
||||
char *bk = rhizome_manifest_get(m, "BK", NULL, 0);
|
||||
if (!bk) {
|
||||
if (debug & DEBUG_RHIZOME) DEBUGF("missing BK field");
|
||||
RETURN(1);
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("missing BK field");
|
||||
RETURN(4);
|
||||
}
|
||||
unsigned char bkBytes[RHIZOME_BUNDLE_KEY_BYTES];
|
||||
if (fromhexstr(bkBytes, bk, RHIZOME_BUNDLE_KEY_BYTES) == -1)
|
||||
{ RETURN(WHYF("invalid BK field: %s", bk)); }
|
||||
RETURN(WHYF("invalid BK field: %s", bk));
|
||||
int cn = 0, in = 0, kp = 0;
|
||||
for (; keyring_next_identity(keyring, &cn, &in, &kp); ++kp) {
|
||||
const unsigned char *authorSid = keyring->contexts[cn]->identities[in]->keypairs[kp]->public_key;
|
||||
//if (debug & DEBUG_RHIZOME) DEBUGF("identity %s", alloca_tohex(authorSid, SID_SIZE));
|
||||
//if (debug & DEBUG_RHIZOME) DEBUGF("try author identity sid=%s", alloca_tohex(authorSid, SID_SIZE));
|
||||
int rkp = keyring_identity_find_keytype(keyring, cn, in, KEYTYPE_RHIZOME);
|
||||
if (rkp != -1) {
|
||||
switch (rhizome_bk_xor(authorSid, m->cryptoSignPublic, bkBytes, m->cryptoSignSecret)) {
|
||||
case -1:
|
||||
RETURN(WHY("rhizome_bk_xor() failed"));
|
||||
case 0:
|
||||
if (rhizome_verify_bundle_privatekey(m) == 0)
|
||||
int rs_len = keyring->contexts[cn]->identities[in]->keypairs[rkp]->private_key_len;
|
||||
if (rs_len < 16 || rs_len > 1024)
|
||||
RETURN(WHYF("invalid Rhizome Secret: length=%d", rs_len));
|
||||
const unsigned char *rs = keyring->contexts[cn]->identities[in]->keypairs[rkp]->private_key;
|
||||
rhizome_bk_xor_rs(rs, rs_len, m->cryptoSignPublic, bkBytes, m->cryptoSignSecret);
|
||||
int verified = rhizome_verify_bundle_privatekey(m);
|
||||
if (verified == 0) {
|
||||
memcpy(m->author, authorSid, sizeof m->author);
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUGF("found bundle author sid=%s", alloca_tohex_sid(m->author));
|
||||
RETURN(0); // bingo
|
||||
break;
|
||||
}
|
||||
memset(m->cryptoSignSecret, 0, sizeof m->cryptoSignSecret);
|
||||
if (verified == -1)
|
||||
RETURN(WHY("rhizome_verify_bundle_privatekey() failed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
RETURN(2); // not self signed
|
||||
if (debug & DEBUG_RHIZOME)
|
||||
DEBUG("bundle author not found");
|
||||
RETURN(1);
|
||||
}
|
||||
|
||||
/* Verify the validity of the manifest's sccret key.
|
||||
Return 0 if valid, 1 if not. Return -1 if an error occurs.
|
||||
XXX This is a pretty ugly way to do it, but NaCl offers no API to
|
||||
do this cleanly.
|
||||
/* Verify the validity of the manifest's secret key, ie, is the given manifest's 'cryptoSignSecret'
|
||||
* field actually the secret key corresponding to the public key in 'cryptoSignPublic'?
|
||||
* Return 0 if valid, 1 if not. Return -1 if an error occurs.
|
||||
*
|
||||
* XXX This is a pretty ugly way to do it, but NaCl offers no API to do this cleanly.
|
||||
*/
|
||||
int rhizome_verify_bundle_privatekey(rhizome_manifest *m)
|
||||
{
|
||||
@ -194,33 +258,22 @@ int rhizome_verify_bundle_privatekey(rhizome_manifest *m)
|
||||
#endif //!ge25519
|
||||
}
|
||||
|
||||
rhizome_signature *rhizome_sign_hash(rhizome_manifest *m, const unsigned char *authorSid)
|
||||
int rhizome_sign_hash(rhizome_manifest *m, rhizome_signature *out)
|
||||
{
|
||||
IN();
|
||||
unsigned char *hash = m->manifesthash;
|
||||
unsigned char *publicKeyBytes = m->cryptoSignPublic;
|
||||
|
||||
if (!m->haveSecret && rhizome_extract_privatekey(m, authorSid)) {
|
||||
WHY("Cannot find secret key to sign manifest data.");
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
if (!m->haveSecret && rhizome_extract_privatekey(m))
|
||||
RETURN(WHY("Cannot find secret key to sign manifest data."));
|
||||
/* Signature is formed by running crypto_sign_edwards25519sha512batch() on the
|
||||
hash of the manifest. The signature actually contains the hash, so to save
|
||||
space we cut the hash out of the signature. */
|
||||
unsigned char signatureBuffer[crypto_sign_edwards25519sha512batch_BYTES + crypto_hash_sha512_BYTES];
|
||||
unsigned long long sigLen = 0;
|
||||
int mLen = crypto_hash_sha512_BYTES;
|
||||
|
||||
int r=crypto_sign_edwards25519sha512batch(signatureBuffer,&sigLen,
|
||||
&hash[0],mLen,m->cryptoSignSecret);
|
||||
if (r) {
|
||||
WHY("crypto_sign() failed.");
|
||||
RETURN(NULL);
|
||||
}
|
||||
|
||||
rhizome_signature *out=calloc(sizeof(rhizome_signature),1);
|
||||
|
||||
int r = crypto_sign_edwards25519sha512batch(signatureBuffer, &sigLen, &hash[0], mLen, m->cryptoSignSecret);
|
||||
if (r)
|
||||
RETURN(WHY("crypto_sign_edwards25519sha512batch() failed."));
|
||||
/* Here we use knowledge of the internal structure of the signature block
|
||||
to remove the hash, since that is implicitly transported, thus reducing the
|
||||
actual signature size down to 64 bytes.
|
||||
@ -229,10 +282,8 @@ rhizome_signature *rhizome_sign_hash(rhizome_manifest *m, const unsigned char *a
|
||||
bcopy(&signatureBuffer[96], &out->signature[33], 32);
|
||||
bcopy(&publicKeyBytes[0], &out->signature[65], crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES);
|
||||
out->signatureLength = 65 + crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES;
|
||||
|
||||
out->signature[0] = out->signatureLength;
|
||||
|
||||
RETURN(out);
|
||||
RETURN(0);
|
||||
}
|
||||
|
||||
typedef struct manifest_signature_block_cache {
|
||||
|
6
serval.h
6
serval.h
@ -914,9 +914,9 @@ void dump_stack();
|
||||
_this_call.totals=&_aggregate_stats; \
|
||||
fd_func_enter(&_this_call);
|
||||
|
||||
#define OUT() fd_func_exit(&_this_call);
|
||||
#define RETURN(X) { OUT() return(X); }
|
||||
#define RETURNNULL { OUT() return(NULL); }
|
||||
#define OUT() fd_func_exit(&_this_call)
|
||||
#define RETURN(X) do { OUT(); return (X); } while (0);
|
||||
#define RETURNNULL do { OUT(); return (NULL); } while (0);
|
||||
|
||||
|
||||
|
||||
|
@ -366,6 +366,19 @@ test_AddUpdateNewVersion() {
|
||||
assert_rhizome_list file1_2@$SIDB1 file2@$SIDB1
|
||||
}
|
||||
|
||||
doc_AddUpdateDiscoverAuthor="Add new payload to manifest with author discovery"
|
||||
setup_AddUpdateDiscoverAuthor() {
|
||||
setup_AddUpdateNewVersion
|
||||
}
|
||||
test_AddUpdateDiscoverAuthor() {
|
||||
tfw_cat -v file1_2.manifest
|
||||
executeOk_servald rhizome add file '' '' file1_2 file1_2.manifest "$file1_secret"
|
||||
tfw_cat --stderr
|
||||
# Rhizome store contents have new payload.
|
||||
executeOk_servald rhizome list ''
|
||||
assert_rhizome_list file1_2@$SIDB1 file2@$SIDB1
|
||||
}
|
||||
|
||||
doc_AddUpdateNoAuthor="Cannot add new payload to authorless manifest"
|
||||
setup_AddUpdateNoAuthor() {
|
||||
setup_AddUpdateNewVersion
|
||||
|
Loading…
Reference in New Issue
Block a user