diff --git a/meshms.c b/meshms.c index 2076658d..a7aa4c8b 100644 --- a/meshms.c +++ b/meshms.c @@ -23,190 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "log.h" #include "conf.h" -int meshms_generate_outgoing_bid(rhizome_manifest *m, - const unsigned char *sender_sid, - const char *recipient_sid_hex) -{ - // BIDprivate =SHA512(”moose”+recipientSID+RS+”anconal”+recipientSID+ ”capital gains tax”) - - const unsigned char *rs; - int rs_len; - if (rhizome_find_secret(sender_sid,&rs_len,&rs)) - return WHYF("Could not find rhizome secret for: '%s'", - alloca_tohex(sender_sid,SID_SIZE)); - return -1; - if (rs_len>256) rs_len=256; // limit to first 2048 bits of rhizome secret - if (rs_len<128) return WHYF("Rhizome secret too short"); - char *rs_hex=alloca_tohex(rs,rs_len); - - char secret[1024]; - unsigned char hash[crypto_hash_sha512_BYTES]; - snprintf(secret,1024,"moose%s%sanconal%scapital gains tax", - recipient_sid_hex,rs_hex,recipient_sid_hex); - crypto_hash_sha512(hash, (unsigned char *)secret, strlen(secret)); - - // The first 256 bits of the hash will be used as the private key of the BID. - bcopy(hash,m->cryptoSignSecret, - crypto_sign_edwards25519sha512batch_SECRETKEYBYTES); - if (crypto_sign_compute_public_key(m->cryptoSignSecret,m->cryptoSignPublic)) - return WHY("Could not compute BID"); - - // Clear out sensitive data - bzero(secret,1024); - bzero(rs_hex,strlen(rs_hex)); - bzero(hash,crypto_hash_sha512_BYTES); - - return 0; -} - - -int meshms_xor_obfuscated_sid(unsigned char *xor_sid, - const unsigned char *known_sid_secret, - const char *other_sid_hex) -{ - sid_t otherSid; - if (str_to_sid_t(&otherSid, other_sid_hex)==-1) - return WHY("Could not parse foreign SID"); - - unsigned char nm_bytes[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES]; - if (crypto_box_curve25519xsalsa20poly1305_beforenm(nm_bytes, - otherSid.binary, - known_sid_secret)) - return WHY("crypto_box_beforenm() failed"); - - char secret[strlen("Salt String 1")+crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES+strlen("Salt String 1")]; - unsigned char hash[crypto_hash_sha512_BYTES]; - int o=0,l; - l=strlen("Salt String 1"); - bcopy("Salt String 1",&secret[o],l); o+=l; - l=crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES; - bcopy(nm_bytes,&secret[o],l); o+=l; - l=strlen("Salt String 2"); - bcopy("Salt String 2",&secret[o],l); o+=l; - - // Hash secret to get sender obfuscation XOR string - crypto_hash_sha512(hash, (unsigned char *)secret, strlen(secret)); - - int i; - for(i=0;icontexts[cn]->identities[in] - // ->keypairs[kp]->public_key - - // 2. See if we are the recipient - if (!memcmp(recipient_sid.binary, - keyring->contexts[cn]->identities[in] - ->keypairs[kp]->public_key, - crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES)) - { - // We are the recipient -- so we can extract the sender - if (!meshms_xor_obfuscated_sid(ssender.binary, - keyring->contexts[cn]->identities[in] - ->keypairs[kp]->private_key, - recipient_hex)) - { - return rhizome_manifest_set_real_sender(m,ssender.binary); - } - - } - - // 1. See if we made the manifest - if (meshms_generate_outgoing_bid(m2, - keyring->contexts[cn]->identities[in] - ->keypairs[kp]->public_key, - recipient_hex)) - continue; - - if (!memcmp(m->cryptoSignPublic,m2->cryptoSignPublic, - crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES)) - { - // Bingo! We created this. - // Set the real sender in the manifest, and return - rhizome_manifest_free(m2); - return rhizome_manifest_set_real_sender(m, - keyring->contexts[cn] - ->identities[in] - ->keypairs[kp]->public_key); - } - } - rhizome_manifest_free(m2); - } - // Not found - return -1; -} - rhizome_manifest *meshms_find_or_create_manifestid (const char *sender_sid_hex,const char *recipient_sid_hex, int createP) { @@ -253,7 +69,8 @@ rhizome_manifest *meshms_find_or_create_manifestid rhizome_manifest_free(m); return NULL; } - if (meshms_generate_outgoing_bid(m,sender_sid.binary,recipient_sid_hex)) { + if (rhizome_obfuscated_manifest_generate_outgoing_bid + (m,sender_sid.binary,recipient_sid_hex)) { WHY("meshms_generate_outgoing_bid() failed"); rhizome_manifest_free(m); return NULL; @@ -269,7 +86,7 @@ rhizome_manifest *meshms_find_or_create_manifestid // 1. Set sender= and // 2. ssender= // This is done by the following function - if (meshms_set_obfuscated_sender(m,sender_sid_hex,recipient_sid_hex)) { + if (rhizome_manifest_set_obfuscated_sender(m,sender_sid_hex,recipient_sid_hex)) { WHY("meshms_set_obfuscated_sender() failed"); rhizome_manifest_free(m); return NULL; diff --git a/rhizome.h b/rhizome.h index 0e1a347c..e948c0bd 100644 --- a/rhizome.h +++ b/rhizome.h @@ -252,8 +252,17 @@ int rhizome_drop_stored_file(const char *id,int maximum_priority); int rhizome_manifest_priority(sqlite_retry_state *retry, const char *id); int rhizome_read_manifest_file(rhizome_manifest *m, const char *filename, int bufferPAndSize); int rhizome_hash_file(rhizome_manifest *m, const char *filename,char *hash_out); + int rhizome_manifest_set_real_sender(rhizome_manifest *m, const unsigned char *sid_binary); +int rhizome_obfuscated_manifest_generate_outgoing_bid +(rhizome_manifest *m, + const unsigned char *sender_sid, + const char *recipient_sid_hex); +int rhizome_manifest_set_obfuscated_sender(rhizome_manifest *m, + const char *sender_sid_to_obfuscate_hex, + const char *recipient_sid_hex); + char *rhizome_manifest_get(const rhizome_manifest *m, const char *var, char *out, int maxlen); long long rhizome_manifest_get_ll(rhizome_manifest *m, const char *var); int rhizome_manifest_set_ll(rhizome_manifest *m,char *var,long long value); diff --git a/rhizome_crypto.c b/rhizome_crypto.c index 9c6255dc..903facb5 100644 --- a/rhizome_crypto.c +++ b/rhizome_crypto.c @@ -588,6 +588,191 @@ int rhizome_crypt_xor_block(unsigned char *buffer, int buffer_size, int64_t stre return 0; } +int rhizome_manifest_xor_obfuscated_sid(unsigned char *xor_sid, + const unsigned char *known_sid_secret, + const char *other_sid_hex) +{ + sid_t otherSid; + if (str_to_sid_t(&otherSid, other_sid_hex)==-1) + return WHY("Could not parse foreign SID"); + + unsigned char nm_bytes[crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES]; + if (crypto_box_curve25519xsalsa20poly1305_beforenm(nm_bytes, + otherSid.binary, + known_sid_secret)) + return WHY("crypto_box_beforenm() failed"); + + char secret[strlen("Salt String 1")+crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES+strlen("Salt String 1")]; + unsigned char hash[crypto_hash_sha512_BYTES]; + int o=0,l; + l=strlen("Salt String 1"); + bcopy("Salt String 1",&secret[o],l); o+=l; + l=crypto_box_curve25519xsalsa20poly1305_BEFORENMBYTES; + bcopy(nm_bytes,&secret[o],l); o+=l; + l=strlen("Salt String 2"); + bcopy("Salt String 2",&secret[o],l); o+=l; + + // Hash secret to get sender obfuscation XOR string + crypto_hash_sha512(hash, (unsigned char *)secret, strlen(secret)); + + int i; + for(i=0;i256) rs_len=256; // limit to first 2048 bits of rhizome secret + if (rs_len<128) return WHYF("Rhizome secret too short"); + char *rs_hex=alloca_tohex(rs,rs_len); + + char secret[1024]; + unsigned char hash[crypto_hash_sha512_BYTES]; + snprintf(secret,1024,"moose%s%sanconal%scapital gains tax", + recipient_sid_hex,rs_hex,recipient_sid_hex); + crypto_hash_sha512(hash, (unsigned char *)secret, strlen(secret)); + + // The first 256 bits of the hash will be used as the private key of the BID. + bcopy(hash,m->cryptoSignSecret, + crypto_sign_edwards25519sha512batch_SECRETKEYBYTES); + if (crypto_sign_compute_public_key(m->cryptoSignSecret,m->cryptoSignPublic)) + return WHY("Could not compute BID"); + + // Clear out sensitive data + bzero(secret,1024); + bzero(rs_hex,strlen(rs_hex)); + bzero(hash,crypto_hash_sha512_BYTES); + + return 0; +} + +int manifest_recover_obfuscated_sender(rhizome_manifest *m) +{ + // There are two possiblities here: + // 1. We made the manifest, and are the real sender. + // 2. We are the named recipient, and can attempt to recover the + // real sender. + // The process of attempting to recover the real sender is different for each. + + { + // Get recipient + char *recipient_hex=rhizome_manifest_get(m, "recipient", NULL, 0); + // For each of our SIDs, see if we can reproduce the manifest ID + sid_t recipient_sid; + if (cf_opt_sid(&recipient_sid,recipient_hex)!=CFOK) + return WHYF("Unable to parse recipient sid from manifest"); + + sid_t ssender; + char *ssender_hex=rhizome_manifest_get(m, "ssender", NULL, 0); + if (!ssender_hex||(!ssender_hex[0])||cf_opt_sid(&ssender,ssender_hex)!=CFOK) + // missing or mal-formed ssender field, so cannot extract real sender. + // this is normal for non obfuscated sender bundles, so don't report an + // error. + return -1; + + int cn=0,in=0,kp=0; + rhizome_manifest *m2=rhizome_new_manifest(); + while (keyring_find_sid(keyring,&cn,&in,&kp,recipient_sid.binary)) + { + // SID is in keyring->contexts[cn]->identities[in] + // ->keypairs[kp]->public_key + + // 2. See if we are the recipient + if (!memcmp(recipient_sid.binary, + keyring->contexts[cn]->identities[in] + ->keypairs[kp]->public_key, + crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES)) + { + // We are the recipient -- so we can extract the sender + if (!rhizome_manifest_xor_obfuscated_sid(ssender.binary, + keyring->contexts[cn]->identities[in] + ->keypairs[kp]->private_key, + recipient_hex)) + { + return rhizome_manifest_set_real_sender(m,ssender.binary); + } + + } + + // 1. See if we made the manifest + if (rhizome_obfuscated_manifest_generate_outgoing_bid + (m2, + keyring->contexts[cn]->identities[in] + ->keypairs[kp]->public_key, + recipient_hex)) + continue; + + if (!memcmp(m->cryptoSignPublic,m2->cryptoSignPublic, + crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES)) + { + // Bingo! We created this. + // Set the real sender in the manifest, and return + rhizome_manifest_free(m2); + return rhizome_manifest_set_real_sender(m, + keyring->contexts[cn] + ->identities[in] + ->keypairs[kp]->public_key); + } + } + rhizome_manifest_free(m2); + } + // Not found + return -1; +} + int rhizome_derive_key(rhizome_manifest *m, rhizome_bk_t *bsk) { // don't do anything if the manifest isn't flagged as being encrypted @@ -598,6 +783,10 @@ int rhizome_derive_key(rhizome_manifest *m, rhizome_bk_t *bsk) char *sender = NULL; sid_t sender_sid, recipient_sid; + if (rhizome_manifest_get(m, "ssender", NULL, 0)) { + if (manifest_recover_obfuscated_sender(m)) + return WHYF("Sender SID is obfuscated, and we are not party to the bundle"); + } if (m->obfuscatedSenderP) { sender="obfuscated"; memcpy(m->realSender,sender_sid.binary,SID_SIZE);