From ab0dcb92158c38a8d51316016bd5c58d12292aa1 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Fri, 14 Feb 2014 13:00:39 -0500 Subject: [PATCH 1/7] allow signing to create new keys when no SID given --- plugins/serval-dna/crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/serval-dna/crypto.c b/plugins/serval-dna/crypto.c index 1d5f513..1a2b66c 100644 --- a/plugins/serval-dna/crypto.c +++ b/plugins/serval-dna/crypto.c @@ -179,7 +179,7 @@ int cmd_serval_sign(const char *sid_str, stowSid(packedSid,0,sid_str); } - if (keyring_path) { + if (keyring_path || !sid_len) { CHECK_ERR(serval_init_keyring(sid_str ? packedSid : NULL, sid_str ? SID_SIZE : 0, keyring_path, From 6a1bb0977d0765213a7bbf51ae7378de81d897ba Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Fri, 14 Feb 2014 15:33:33 -0500 Subject: [PATCH 2/7] improve readability of crypto.c --- plugins/serval-dna/crypto.c | 698 ++++++++++++++++++++---------------- 1 file changed, 394 insertions(+), 304 deletions(-) diff --git a/plugins/serval-dna/crypto.c b/plugins/serval-dna/crypto.c index 1a2b66c..6efbfd1 100644 --- a/plugins/serval-dna/crypto.c +++ b/plugins/serval-dna/crypto.c @@ -26,7 +26,7 @@ * You should have received a copy of the GNU General Public License * along with Commotion. If not, see . * - * ===================================================================================== + * ============================================================================ */ #include @@ -48,29 +48,47 @@ #include "serval-dna.h" -extern struct subscriber *my_subscriber; +/* libserval global for the primary keyring */ extern keyring_file *keyring; -char *serval_path = NULL; +/* + * libserval global identifying the subscriber corresponding + * to the primary identity in the primary keyring + */ +extern struct subscriber *my_subscriber; +/* file path for the serval state/conf/keyring directory */ +char *serval_path = NULL; + +/* used to store error messages to pass in response to client commands */ co_obj_t *err_msg = NULL; -static int serval_create_signature(unsigned char *key, +/* Private */ + +static int +serval_create_signature(unsigned char *key, const unsigned char *msg, const size_t msg_len, unsigned char *sig_buffer, - const size_t sig_size) { - + const size_t sig_size) +{ unsigned long long sig_length = SIGNATURE_BYTES; - CHECK(sig_size >= msg_len + SIGNATURE_BYTES,"Signature buffer too small"); + CHECK(sig_size >= msg_len + SIGNATURE_BYTES, "Signature buffer too small"); unsigned char hash[crypto_hash_sha512_BYTES]; - crypto_hash_sha512(hash, msg, msg_len); // create sha512 hash of message, which will then be signed - memcpy(sig_buffer,msg,msg_len); - - if (crypto_create_signature(key, hash, crypto_hash_sha512_BYTES, &sig_buffer[msg_len], &sig_length) != 0) // create signature of message hash, append it to end of message + // create sha512 hash of message, which will then be signed + crypto_hash_sha512(hash, msg, msg_len); + memcpy(sig_buffer, msg, msg_len); + + // create signature of message hash, append it to end of message + int sig_ret = crypto_create_signature(key, + hash, + crypto_hash_sha512_BYTES, + &sig_buffer[msg_len], + &sig_length); + if (sig_ret != 0) return 0; return 1; @@ -78,40 +96,165 @@ static int serval_create_signature(unsigned char *key, return 0; } -static int serval_extract_sas(unsigned char **key, int *key_len, keyring_file *_keyring, unsigned char *_sid) { - *key=keyring_find_sas_private(_keyring, _sid, NULL); // get SAS key associated with our SID - CHECK_ERR(*key,"Failed to fetch SAS key"); - if (key_len) *key_len = crypto_sign_edwards25519sha512batch_SECRETKEYBYTES; +static int +serval_extract_sas(unsigned char **key, + int *key_len, + keyring_file *_keyring, + unsigned char *_sid) +{ + // get SAS key associated with our SID + *key = keyring_find_sas_private(_keyring, _sid, NULL); + CHECK_ERR(*key, "Failed to fetch SAS key"); + + if (key_len) *key_len = crypto_sign_edwards25519sha512batch_SECRETKEYBYTES; return 1; error: return 0; } -int serval_open_keyring(const char *keyring_path, - const size_t keyring_len, - keyring_file **_keyring) { +static int +keyring_send_sas_request_client(struct subscriber *subscriber) +{ + int ret = 0; + unsigned char *srcsid[SID_SIZE] = {0}; + time_ms_t now = gettime_ms(); + + CHECK_ERR(overlay_mdp_getmyaddr(0, (sid_t *)srcsid) == 0, "Could not get local address"); + + if (subscriber->sas_valid) + return 1; + + CHECK_ERR(now >= subscriber->sas_last_request + 100, "Too soon to ask for SAS mapping again"); + + CHECK_ERR(my_subscriber, "Couldn't request SAS (I don't know who I am)"); + + DEBUG("Requesting SAS mapping for SID=%s", alloca_tohex_sid(subscriber->sid)); + + int client_port = 32768 + (random() & 32767); + CHECK_ERR(overlay_mdp_bind((sid_t *)my_subscriber->sid, client_port) == 0, + "Failed to bind to client socket"); + /* request mapping (send request auth-crypted). */ + overlay_mdp_frame mdp; + memset(&mdp, 0, sizeof(mdp)); + + mdp.packetTypeAndFlags = MDP_TX; + mdp.out.queue = OQ_MESH_MANAGEMENT; + memmove(mdp.out.dst.sid, subscriber->sid, SID_SIZE); + mdp.out.dst.port = MDP_PORT_KEYMAPREQUEST; + mdp.out.src.port = client_port; + memmove(mdp.out.src.sid, srcsid, SID_SIZE); + mdp.out.payload_length = 1; + mdp.out.payload[0] = KEYTYPE_CRYPTOSIGN; + + int sent = overlay_mdp_send(&mdp, 0, 0); + if (sent) { + DEBUG("Failed to send SAS resolution request: %d", sent); + CHECK_ERR(mdp.packetTypeAndFlags != MDP_ERROR, "MDP Server error #%d: '%s'", mdp.error.error, mdp.error.message); + } + + time_ms_t timeout = now + 5000; + + while(now < timeout) { + time_ms_t timeout_ms = timeout - gettime_ms(); + int result = overlay_mdp_client_poll(timeout_ms); + + if (result > 0) { + int ttl = -1; + if (overlay_mdp_recv(&mdp, client_port, &ttl) == 0) { + int found = 0; + switch(mdp.packetTypeAndFlags & MDP_TYPE_MASK) { + case MDP_ERROR: + ERROR("overlay_mdp_recv: %s (code %d)", mdp.error.message, mdp.error.error); + break; + case MDP_TX: + DEBUG("Received SAS mapping response"); + found = 1; + break; + default: + DEBUG("overlay_mdp_recv: Unexpected MDP frame type 0x%x", mdp.packetTypeAndFlags); + break; + } + if (found) + break; + } + } + now = gettime_ms(); + if (servalShutdown) + break; + } + + unsigned keytype = mdp.out.payload[0]; + + CHECK_ERR(keytype == KEYTYPE_CRYPTOSIGN, "Ignoring SID:SAS mapping with unsupported key type %u", keytype); + + CHECK_ERR(mdp.out.payload_length >= 1 + SAS_SIZE, + "Truncated key mapping announcement? payload_length: %d", + mdp.out.payload_length); + + unsigned char *plain = (unsigned char*)calloc(mdp.out.payload_length,sizeof(unsigned char)); + unsigned long long plain_len = 0; + unsigned char *sas_public = &mdp.out.payload[1]; + unsigned char *compactsignature = &mdp.out.payload[SAS_SIZE + 1]; + + /* reconstitute signed SID for verification */ + unsigned char signature[SID_SIZE + crypto_sign_edwards25519sha512batch_BYTES]; + memmove(&signature[0], &compactsignature[0], 64); + memmove(&signature[64], &mdp.out.src.sid[0], SID_SIZE); + + int sign_ret = crypto_sign_edwards25519sha512batch_open(plain, + &plain_len, + signature, + SID_SIZE + crypto_sign_edwards25519sha512batch_BYTES, + sas_public); + CHECK_ERR(sign_ret == 0, "SID:SAS mapping verification signature does not verify"); + + /* These next two tests should never be able to fail, but let's just check anyway. */ + CHECK_ERR(plain_len == SID_SIZE, "SID:SAS mapping signed block is wrong length"); + CHECK_ERR(memcmp(plain, mdp.out.src.sid, SID_SIZE) == 0, "SID:SAS mapping signed block is for wrong SID"); + + memmove(subscriber->sas_public, sas_public, SAS_SIZE); + subscriber->sas_valid = 1; + subscriber->sas_last_request = now; + ret = 1; + + error: + if (plain) + free(plain); + return ret; +} + +/* Public */ + +int +serval_open_keyring(const char *keyring_path, + const size_t keyring_len, + keyring_file **_keyring) +{ char keyring_path_str[PATH_MAX] = {0}; - if (keyring_path == NULL || keyring_len == 0) { // if no keyring specified, use default keyring - strcpy(keyring_path_str,serval_path); + if (keyring_path == NULL || keyring_len == 0) { + // if no keyring specified, use default keyring + strcpy(keyring_path_str, serval_path); if (serval_path[strlen(serval_path) - 1] != '/') - strcat(keyring_path_str,"/"); - strcat(keyring_path_str,"serval.keyring"); + strcat(keyring_path_str, "/"); + strcat(keyring_path_str, "serval.keyring"); // Fetching SAS keys requires setting the SERVALINSTANCE_PATH environment variable - CHECK_ERR(setenv("SERVALINSTANCE_PATH",serval_path,1) == 0,"Failed to set SERVALINSTANCE_PATH env variable"); - } - else { // otherwise, use specified keyring (NOTE: if keyring does not exist, it will be created) - CHECK(keyring_len < PATH_MAX,"Keyring length too long"); - strncpy(keyring_path_str,keyring_path,keyring_len); + CHECK_ERR(setenv("SERVALINSTANCE_PATH", serval_path, 1) == 0, + "Failed to set SERVALINSTANCE_PATH env variable"); + } else { + // otherwise, use specified keyring (NOTE: if keyring does not exist, it will be created) + CHECK(keyring_len < PATH_MAX, "Keyring length too long"); + strncpy(keyring_path_str, keyring_path, keyring_len); keyring_path_str[keyring_len] = '\0'; } - CHECK_ERR((*_keyring = keyring_open(keyring_path_str)),"Failed to open specified keyring file"); + *_keyring = keyring_open(keyring_path_str); + CHECK_ERR(*_keyring, "Failed to open specified keyring file"); if (keyring_enter_pin(*_keyring, KEYRING_PIN) <= 0) { - /* put initial identity in if we don't have any visible */ - CHECK_ERR(keyring_seed(*_keyring) == 0,"Failed to seed keyring"); + // put initial identity in if we don't have any visible + CHECK_ERR(keyring_seed(*_keyring) == 0, "Failed to seed keyring"); } return 1; @@ -119,270 +262,194 @@ int serval_open_keyring(const char *keyring_path, return 0; } -int serval_init_keyring(unsigned char *sid, - const size_t sid_len, - const char *keyring_path, - const size_t keyring_len, - keyring_file **_keyring, - unsigned char **key, - int *key_len) { +int +serval_init_keyring(unsigned char *sid, + const size_t sid_len, + const char *keyring_path, + const size_t keyring_len, + keyring_file **_keyring, + unsigned char **key, + int *key_len) +{ keyring_identity *new_ident; - unsigned char *_sid = sid; - if (sid) CHECK(sid_len == SID_SIZE,"Invalid SID"); + if (sid) + CHECK(sid_len == SID_SIZE, "Invalid SID"); - CHECK_ERR(serval_open_keyring(keyring_path,keyring_len,_keyring),"Failed to open keyring"); + CHECK_ERR(serval_open_keyring(keyring_path, keyring_len, _keyring), + "Failed to open keyring"); - if (!sid) { - //create new sid - int c; - for(c = 0; c < (*_keyring)->context_count; c++) { // cycle through the keyring contexts until we find one with room for another identity - new_ident = keyring_create_identity(*_keyring,(*_keyring)->contexts[c], KEYRING_PIN); // create new Serval identity + if (!sid) { //create new sid + // cycle through the keyring contexts until we find one with room for another identity + for(int c = 0; c < (*_keyring)->context_count; c++) { + // create new Serval identity + new_ident = keyring_create_identity(*_keyring, + (*_keyring)->contexts[c], + KEYRING_PIN); if (new_ident) break; } - CHECK_ERR(new_ident,"failed to create new SID"); + CHECK_ERR(new_ident, "Failed to create new SID"); - CHECK_ERR(keyring_commit(*_keyring) == 0,"Failed to save new SID into keyring"); // need to commit keyring or else new identity won't be saved (needs permissions) + // need to commit keyring or else new identity won't be saved (needs permissions) + CHECK_ERR(keyring_commit(*_keyring) == 0, "Failed to save new SID into keyring"); _sid = new_ident->subscriber->sid; } if (key) - CHECK(serval_extract_sas(key,key_len, *_keyring, _sid),"Failed to fetch SAS key"); + CHECK(serval_extract_sas(key, key_len, *_keyring, _sid), "Failed to fetch SAS key"); return 1; error: return 0; } -int cmd_serval_sign(const char *sid_str, - const size_t sid_len, - const unsigned char *msg, - const size_t msg_len, - char *sig_str_buf, - const size_t sig_str_size, - const char *keyring_path, - const size_t keyring_len) { - +int +cmd_serval_sign(const char *sid_str, + const size_t sid_len, + const unsigned char *msg, + const size_t msg_len, + char *sig_str_buf, + const size_t sig_str_size, + const char *keyring_path, + const size_t keyring_len) +{ int ret = 0; unsigned char signed_msg[msg_len + SIGNATURE_BYTES]; keyring_file *_keyring = NULL; unsigned char *key = NULL; unsigned char packedSid[SID_SIZE] = {0}; - CHECK(sig_str_size >= 2*SIGNATURE_BYTES + 1,"Signature buffer too small"); + CHECK(sig_str_size >= (2 * SIGNATURE_BYTES) + 1, "Signature buffer too small"); if (sid_str) { - CHECK_ERR(sid_len == 2*SID_SIZE && str_is_subscriber_id(sid_str) == 1,"Invalid SID"); - stowSid(packedSid,0,sid_str); + CHECK_ERR(sid_len == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, + "Invalid SID"); + stowSid(packedSid, 0, sid_str); } if (keyring_path || !sid_len) { CHECK_ERR(serval_init_keyring(sid_str ? packedSid : NULL, - sid_str ? SID_SIZE : 0, - keyring_path, - keyring_len, - &_keyring, - &key, - NULL), "Failed to initialize Serval keyring"); + sid_str ? SID_SIZE : 0, + keyring_path, + keyring_len, + &_keyring, + &key, + NULL), + "Failed to initialize Serval keyring"); } else { - CHECK_ERR(serval_extract_sas(&key,NULL,keyring,packedSid),"Failed to fetch SAS key"); + CHECK_ERR(serval_extract_sas(&key, NULL, keyring, packedSid), + "Failed to fetch SAS key"); } - CHECK_ERR(serval_create_signature(key, msg, msg_len, signed_msg, SIGNATURE_BYTES + msg_len),"Failed to create signature"); + CHECK_ERR(serval_create_signature(key, + msg, + msg_len, + signed_msg, + SIGNATURE_BYTES + msg_len), + "Failed to create signature"); - strncpy(sig_str_buf,alloca_tohex(signed_msg + msg_len,SIGNATURE_BYTES),2*SIGNATURE_BYTES); - sig_str_buf[2*SIGNATURE_BYTES] = '\0'; + strncpy(sig_str_buf, alloca_tohex(signed_msg + msg_len, SIGNATURE_BYTES), 2 * SIGNATURE_BYTES); + sig_str_buf[2 * SIGNATURE_BYTES] = '\0'; ret = 1; error: - if (_keyring) keyring_free(_keyring); + if (_keyring) + keyring_free(_keyring); return ret; } -static int keyring_send_sas_request_client(struct subscriber *subscriber){ - int sent, client_port, found = 0, ret = 0; - int siglen=SID_SIZE+crypto_sign_edwards25519sha512batch_BYTES; - unsigned char *srcsid[SID_SIZE] = {0}, *plain = NULL; - unsigned char signature[siglen]; - time_ms_t now = gettime_ms(); - - CHECK_ERR(overlay_mdp_getmyaddr(0,(sid_t *)srcsid) == 0,"Could not get local address"); - - if (subscriber->sas_valid) - return 1; - - CHECK_ERR(now >= subscriber->sas_last_request + 100,"Too soon to ask for SAS mapping again"); - - CHECK_ERR(my_subscriber,"couldn't request SAS (I don't know who I am)"); - - DEBUG("Requesting SAS mapping for SID=%s", alloca_tohex_sid(subscriber->sid)); - - CHECK_ERR(overlay_mdp_bind((sid_t *)my_subscriber->sid,(client_port=32768+(random()&32767))) == 0,"Failed to bind to client socket"); - -/* request mapping (send request auth-crypted). */ - overlay_mdp_frame mdp; - memset(&mdp,0,sizeof(mdp)); - - mdp.packetTypeAndFlags=MDP_TX; - mdp.out.queue=OQ_MESH_MANAGEMENT; - memmove(mdp.out.dst.sid,subscriber->sid,SID_SIZE); - mdp.out.dst.port=MDP_PORT_KEYMAPREQUEST; - mdp.out.src.port=client_port; - memmove(mdp.out.src.sid,srcsid,SID_SIZE); - mdp.out.payload_length=1; - mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN; - - sent = overlay_mdp_send(&mdp, 0,0); - if (sent) { - DEBUG("Failed to send SAS resolution request: %d", sent); - CHECK_ERR(mdp.packetTypeAndFlags != MDP_ERROR,"MDP Server error #%d: '%s'",mdp.error.error,mdp.error.message); - } - - time_ms_t timeout = now + 5000; - - while(now0) { - int ttl=-1; - if (overlay_mdp_recv(&mdp, client_port, &ttl)==0) { - switch(mdp.packetTypeAndFlags&MDP_TYPE_MASK) { - case MDP_ERROR: - ERROR("overlay_mdp_recv: %s (code %d)", mdp.error.message, mdp.error.error); - break; - case MDP_TX: - { - DEBUG("Received SAS mapping response"); - found = 1; - break; - } - break; - default: - DEBUG("overlay_mdp_recv: Unexpected MDP frame type 0x%x", mdp.packetTypeAndFlags); - break; - } - if (found) break; - } - } - now=gettime_ms(); - if (servalShutdown) - break; - } - - unsigned keytype = mdp.out.payload[0]; - - CHECK_ERR(keytype == KEYTYPE_CRYPTOSIGN,"Ignoring SID:SAS mapping with unsupported key type %u", keytype); - - CHECK_ERR(mdp.out.payload_length >= 1 + SAS_SIZE,"Truncated key mapping announcement? payload_length: %d", mdp.out.payload_length); - - plain = (unsigned char*)calloc(mdp.out.payload_length,sizeof(unsigned char)); - unsigned long long plain_len=0; - unsigned char *sas_public=&mdp.out.payload[1]; - unsigned char *compactsignature = &mdp.out.payload[1+SAS_SIZE]; - - /* reconstitute signed SID for verification */ - memmove(&signature[0],&compactsignature[0],64); - memmove(&signature[64],&mdp.out.src.sid[0],SID_SIZE); - - int r=crypto_sign_edwards25519sha512batch_open(plain,&plain_len, - signature,siglen, - sas_public); - CHECK_ERR(r == 0,"SID:SAS mapping verification signature does not verify"); - - /* These next two tests should never be able to fail, but let's just check anyway. */ - CHECK_ERR(plain_len == SID_SIZE,"SID:SAS mapping signed block is wrong length"); - CHECK_ERR(memcmp(plain, mdp.out.src.sid, SID_SIZE) == 0,"SID:SAS mapping signed block is for wrong SID"); - - memmove(subscriber->sas_public, sas_public, SAS_SIZE); - subscriber->sas_valid=1; - subscriber->sas_last_request=now; - ret = 1; - -error: - if (plain) free(plain); - return ret; -} - -int cmd_serval_verify(const char *sas_key, - const size_t sas_key_len, - const unsigned char *msg, - const size_t msg_len, - const char *sig, - const size_t sig_len) { +int +cmd_serval_verify(const char *sas_key, + const size_t sas_key_len, + const unsigned char *msg, + const size_t msg_len, + const char *sig, + const size_t sig_len) +{ int verdict = 0; unsigned char bin_sig[SIGNATURE_BYTES]; unsigned char bin_sas[SAS_SIZE]; - CHECK_ERR(sig_len == 2*SIGNATURE_BYTES,"Invalid signature"); - CHECK_ERR(sas_key_len == 2*SAS_SIZE,"Invalid SAS key"); + CHECK_ERR(sig_len == 2 * SIGNATURE_BYTES, "Invalid signature"); + CHECK_ERR(sas_key_len == 2 * SAS_SIZE, "Invalid SAS key"); // convert signature from hex to binary - CHECK_ERR(fromhexstr(bin_sig,sig,SIGNATURE_BYTES) == 0,"Invalid signature"); - CHECK_ERR(fromhexstr(bin_sas,sas_key,SAS_SIZE) == 0,"Invalid SAS key"); + CHECK_ERR(fromhexstr(bin_sig, sig, SIGNATURE_BYTES) == 0, "Invalid signature"); + CHECK_ERR(fromhexstr(bin_sas, sas_key, SAS_SIZE) == 0, "Invalid SAS key"); - DEBUG("Message to verify:\n%s",msg); + DEBUG("Message to verify:\n%s", msg); unsigned char hash[crypto_hash_sha512_BYTES]; - crypto_hash_sha512(hash,msg,msg_len); - - if (crypto_verify_signature(bin_sas, hash, crypto_hash_sha512_BYTES, - &bin_sig[0], SIGNATURE_BYTES) == 0) + crypto_hash_sha512(hash, msg, msg_len); + + int sig_ret = crypto_verify_signature(bin_sas, + hash, + crypto_hash_sha512_BYTES, + &bin_sig[0], + SIGNATURE_BYTES); + if (sig_ret == 0) verdict = 1; // successfully verified error: return verdict; } -int serval_verify_client(const char *sid_str, - const size_t sid_len, - const unsigned char *msg, - const size_t msg_len, - const char *sig, - const size_t sig_len, - const char *keyring_path, - const size_t keyring_len) { +int +serval_verify_client(const char *sid_str, + const size_t sid_len, + const unsigned char *msg, + const size_t msg_len, + const char *sig, + const size_t sig_len, + const char *keyring_path, + const size_t keyring_len) +{ + CHECK(sid_len == 2 * SID_SIZE, "Invalid SID length"); + CHECK(sig_len == 2 * SIGNATURE_BYTES, "Invalid signature length"); + + CHECK(str_is_subscriber_id(sid_str) != 0, "Invalid SID"); - int verdict = 0; - char sas_str[2*SAS_SIZE+1] = {0}; unsigned char packedSid[SID_SIZE] = {0}; - - CHECK(sid_len == 2*SID_SIZE,"Invalid SID length"); - CHECK(sig_len == 2*SIGNATURE_BYTES,"Invalid signature length"); - - CHECK(str_is_subscriber_id(sid_str) != 0,"Invalid SID"); - stowSid(packedSid,0,sid_str); - - CHECK(serval_init_keyring(packedSid, - SID_SIZE, - keyring_path, - keyring_len, - &keyring, - NULL, - NULL), "Failed to initialize Serval keyring"); + stowSid(packedSid, 0, sid_str); + + int init_ret = serval_init_keyring(packedSid, + SID_SIZE,keyring_path, + keyring_len, + &keyring, + NULL, + NULL); + CHECK(init_ret, "Failed to initialize Serval keyring"); struct subscriber *sub = find_subscriber(packedSid, SID_SIZE, 1); // get Serval identity described by given SID - CHECK(sub,"Failed to fetch Serval subscriber"); + CHECK(sub, "Failed to fetch Serval subscriber"); - CHECK(keyring_send_sas_request_client(sub),"SAS request failed"); + CHECK(keyring_send_sas_request_client(sub), "SAS request failed"); - CHECK(sub->sas_valid,"Could not validate the signing key!"); - CHECK(sub->sas_public[0],"Could not validate the signing key!"); - CHECK(tohex(sas_str,sub->sas_public,SAS_SIZE),"Failed to convert signing key"); + CHECK(sub->sas_valid, "Could not validate the signing key!"); + CHECK(sub->sas_public[0], "Could not validate the signing key!"); - verdict = cmd_serval_verify(sas_str,2*SAS_SIZE, - msg,msg_len,sig,sig_len); + char sas_str[2*SAS_SIZE+1] = {0}; + CHECK(tohex(sas_str,sub->sas_public,SAS_SIZE), "Failed to convert signing key"); + + return cmd_serval_verify(sas_str, + 2 * SAS_SIZE, + msg, + msg_len, + sig, + sig_len); error: - return verdict; + return 0; } -int serval_crypto_register(void) { +int +serval_crypto_register(void) +{ /** name: serval-crypto * param[0] - param[3]: (co_str?_t) */ @@ -390,20 +457,29 @@ int serval_crypto_register(void) { const char name[] = "serval-crypto", usage[] = "serval-crypto sign [] [--keyring=]\n" "serval-crypto verify ", - desc[] = "Serval-crypto utilizes Serval's crypto API to:\n" - " * Sign any arbitrary text using a Serval key. If no Serval key ID (SID) is given,\n" - " a new key will be created on the default Serval keyring.\n" - " * Verify any arbitrary text, a signature, and a Serval signing key (SAS), and will\n" - " determine if the signature is valid."; - - CHECK(co_cmd_register(name,sizeof(name),usage,sizeof(usage),desc,sizeof(desc),serval_crypto_handler),"Failed to register commands"); + desc[] = "Serval-crypto utilizes Serval's crypto API to:\n" + " * Sign any arbitrary text using a Serval key. If no Serval key ID (SID) is given,\n" + " a new key will be created on the default Serval keyring.\n" + " * Verify any arbitrary text, a signature, and a Serval signing key (SAS), and will\n" + " determine if the signature is valid."; + + int reg_ret = co_cmd_register(name, + sizeof(name), + usage, + sizeof(usage), + desc, + sizeof(desc), + serval_crypto_handler); + CHECK(reg_ret, "Failed to register commands"); return 1; error: return 0; } -int olsrd_mdp_register(void) { +int +olsrd_mdp_register(void) +{ /** * name: mdp-init * param[0] : (co_str8_t) @@ -411,14 +487,16 @@ int olsrd_mdp_register(void) { */ const char name[] = "mdp-init"; - CHECK(co_cmd_register(name,sizeof(name),"",1,"",1,olsrd_mdp_init),"Failed to register command"); + CHECK(co_cmd_register(name, sizeof(name), "", 1, "", 1, olsrd_mdp_init), "Failed to register command"); return 1; error: return 0; } -int olsrd_mdp_sign_register(void) { +int +olsrd_mdp_sign_register(void) +{ /** * name: mdp-sign * param[0] : key (co_bin8_t) @@ -427,68 +505,73 @@ int olsrd_mdp_sign_register(void) { const char name[] = "mdp-sign"; - CHECK(co_cmd_register(name,sizeof(name),"",1,"",1,olsrd_mdp_sign),"Failed to register command"); + CHECK(co_cmd_register(name, sizeof(name), "", 1, "", 1, olsrd_mdp_sign), "Failed to register command"); return 1; error: return 0; } -int serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) { +int +serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) +{ CLEAR_ERR(); - int list_len = co_list_length(params), keypath = 0; + int list_len = co_list_length(params); + int keypath = 0; - CHECK_ERR(IS_LIST(params) && list_len >= 2,"Invalid params"); + CHECK_ERR(IS_LIST(params) && list_len >= 2, "Invalid params"); - if (!strncmp("--keyring=",co_obj_data_ptr(co_list_get_last(params)),10)) { + if (!strncmp("--keyring=", co_obj_data_ptr(co_list_get_last(params)), 10)) { keypath = 1; --list_len; } - if (co_str_cmp_str(co_list_element(params,0),"sign") == 0) { + if (co_str_cmp_str(co_list_element(params, 0), "sign") == 0) { - CHECK_ERR(list_len == 2 || list_len == 3,"Invalid arguments"); - char sig_buf[2*SIGNATURE_BYTES + 1] = {0}; + CHECK_ERR(list_len == 2 || list_len == 3, "Invalid arguments"); + char sig_buf[(2 * SIGNATURE_BYTES) + 1] = {0}; if (list_len == 3) { - CHECK_ERR(cmd_serval_sign(_LIST_ELEMENT(params,1), - co_str_len(co_list_element(params,1)) - 1, - (unsigned char*)_LIST_ELEMENT(params,2), - co_str_len(co_list_element(params,2)) - 1, - sig_buf, - 2*SIGNATURE_BYTES + 1, - keypath ? _LIST_ELEMENT(params,3) + 10 : NULL, // strlen("--length=") == 10 - keypath ? co_str_len(co_list_element(params,3)) - 11 : 0),"Failed to create signature"); + int sign_ret = cmd_serval_sign(_LIST_ELEMENT(params, 1), + co_str_len(co_list_element(params, 1)) - 1, + (unsigned char*)_LIST_ELEMENT(params, 2), + co_str_len(co_list_element(params, 2)) - 1, + sig_buf, + (2 * SIGNATURE_BYTES) + 1, + keypath ? _LIST_ELEMENT(params, 3) + 10 : NULL, // strlen("--length=") == 10 + keypath ? co_str_len(co_list_element(params, 3)) - 11 : 0); + CHECK_ERR(sign_ret, "Failed to create signature"); } else if (list_len == 2) { - CHECK_ERR(cmd_serval_sign(NULL, - 0, - (unsigned char*)_LIST_ELEMENT(params,1), - co_str_len(co_list_element(params,1)) - 1, - sig_buf, - 2*SIGNATURE_BYTES + 1, - keypath ? _LIST_ELEMENT(params,2) + 10 : NULL, // strlen("--length=") == 10 - keypath ? co_str_len(co_list_element(params,2)) - 11 : 0),"Failed to create signature"); + int sign_ret = cmd_serval_sign(NULL, + 0, + (unsigned char*)_LIST_ELEMENT(params, 1), + co_str_len(co_list_element(params, 1)) - 1, + sig_buf, + (2 * SIGNATURE_BYTES) + 1, + keypath ? _LIST_ELEMENT(params, 2) + 10 : NULL, // strlen("--length=") == 10 + keypath ? co_str_len(co_list_element(params, 2)) - 11 : 0); + CHECK_ERR(sign_ret, "Failed to create signature"); } - CMD_OUTPUT("result",co_str8_create(sig_buf,2*SIGNATURE_BYTES+1,0)); + CMD_OUTPUT("result", co_str8_create(sig_buf, (2 * SIGNATURE_BYTES) + 1, 0)); - } else if (co_str_cmp_str(co_list_element(params,0),"verify") == 0) { + } else if (co_str_cmp_str(co_list_element(params, 0), "verify") == 0) { - CHECK_ERR(!keypath,"Keyring option not available for verification"); - CHECK_ERR(list_len == 4,"Invalid arguments"); - int verdict = cmd_serval_verify(_LIST_ELEMENT(params,1), - co_str_len(co_list_element(params,1)) - 1, - (unsigned char*)_LIST_ELEMENT(params,3), - co_str_len(co_list_element(params,3)) - 1, - _LIST_ELEMENT(params,2), - co_str_len(co_list_element(params,2)) - 1); -// keypath ? _LIST_ELEMENT(params,4) + 10 : NULL, // strlen("--length=") == 10 -// keypath ? co_str_len(co_list_element(params,4)) - 10 : 0); + CHECK_ERR(!keypath, "Keyring option not available for verification"); + CHECK_ERR(list_len == 4, "Invalid arguments"); + int verdict = cmd_serval_verify(_LIST_ELEMENT(params, 1), + co_str_len(co_list_element(params, 1)) - 1, + (unsigned char*)_LIST_ELEMENT(params, 3), + co_str_len(co_list_element(params, 3)) - 1, + _LIST_ELEMENT(params, 2), + co_str_len(co_list_element(params, 2)) - 1); +// keypath ? _LIST_ELEMENT(params,4) + 10 : NULL, // strlen("--length=") == 10 +// keypath ? co_str_len(co_list_element(params,4)) - 10 : 0); if (verdict == 1) { DEBUG("signature verified"); - CMD_OUTPUT("result",co_bool_create(true,0)); // successfully verified + CMD_OUTPUT("result", co_bool_create(true, 0)); // successfully verified } else if (verdict == 0) { DEBUG("signature NOT verified"); - CMD_OUTPUT("result",co_bool_create(false,0)); + CMD_OUTPUT("result", co_bool_create(false, 0)); } } @@ -499,57 +582,64 @@ int serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) { return 0; } -int olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) { - keyring_file *mdp_keyring = NULL; - unsigned char *mdp_key = NULL; - int mdp_key_len = 0; - unsigned char packedSid[SID_SIZE] = {0}; +int +olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) +{ + CHECK(IS_LIST(params) && co_list_length(params) == 2, "Invalid params"); - CHECK(IS_LIST(params) && co_list_length(params) == 2,"Invalid params"); + size_t sid_len = co_str_len(co_list_element(params, 1)); + char *sid_str = _LIST_ELEMENT(params, 1); - size_t sid_len = co_str_len(co_list_element(params,1)); - char *sid_str = _LIST_ELEMENT(params,1); + CHECK(sid_len == (2 * SID_SIZE) + 1 && str_is_subscriber_id(sid_str) == 1, "Invalid SID"); - CHECK(sid_len == 2*SID_SIZE + 1 && str_is_subscriber_id(sid_str) == 1,"Invalid SID"); - stowSid(packedSid,0,sid_str); + unsigned char packedSid[SID_SIZE] = {0}; + stowSid(packedSid, 0, sid_str); - CHECK(serval_init_keyring(packedSid, - SID_SIZE, - _LIST_ELEMENT(params,0), - co_str_len(co_list_element(params,0)), - &mdp_keyring, - &mdp_key, - &mdp_key_len), "Failed to initialize Serval keyring"); + keyring_file *mdp_keyring = NULL; + unsigned char *mdp_key = NULL; + int mdp_key_len = 0; + int init_ret = serval_init_keyring(packedSid, + SID_SIZE, + _LIST_ELEMENT(params, 0), + co_str_len(co_list_element(params, 0)), + &mdp_keyring, + &mdp_key, + &mdp_key_len); + CHECK(init_ret, "Failed to initialize Serval keyring"); - CMD_OUTPUT("key",co_bin8_create((char*)mdp_key,mdp_key_len,0)); + CMD_OUTPUT("key", co_bin8_create((char*)mdp_key, mdp_key_len, 0)); return 1; error: return 0; } -int olsrd_mdp_sign(co_obj_t *self, co_obj_t **output, co_obj_t *params) { - int msg_len = 0, ret = 0, sig_buf_len; - unsigned char *msg = NULL, *sig_buf = NULL; +int +olsrd_mdp_sign(co_obj_t *self, co_obj_t **output, co_obj_t *params) +{ + int ret = 0; + unsigned char *msg = NULL; /** skipping some error checking for performance reasons */ -// CHECK(IS_LIST(params) && co_list_length(params) == 2,"Invalid params"); +// CHECK(IS_LIST(params) && co_list_length(params) == 2, "Invalid params"); - msg_len = co_obj_data((char**)&msg,co_list_element(params,1)); - sig_buf_len = SIGNATURE_BYTES + msg_len + 1; - sig_buf = calloc(sig_buf_len,sizeof(unsigned char)); + int msg_len = co_obj_data((char**)&msg, co_list_element(params, 1)); + int sig_buf_len = SIGNATURE_BYTES + msg_len + 1; + unsigned char *sig_buf = calloc(sig_buf_len, sizeof(unsigned char)); - CHECK(serval_create_signature((unsigned char*)_LIST_ELEMENT(params,0), - msg, - msg_len, - sig_buf, - sig_buf_len),"Failed to sign OLSRd packet"); + int sign_ret = serval_create_signature((unsigned char*)_LIST_ELEMENT(params, 0), + msg, + msg_len, + sig_buf, + sig_buf_len); + CHECK(sign_ret, "Failed to sign OLSRd packet"); - CMD_OUTPUT("sig",co_bin8_create((char*)(sig_buf+msg_len),SIGNATURE_BYTES,0)); + CMD_OUTPUT("sig", co_bin8_create((char*)(sig_buf + msg_len), SIGNATURE_BYTES, 0)); ret = 1; error: - if (sig_buf) free(sig_buf); + if (sig_buf) + free(sig_buf); return ret; } From 2e190812bd546abbf965ac1131061039b207af5a Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Tue, 18 Feb 2014 13:15:16 -0500 Subject: [PATCH 3/7] overhauled crypto functionality, now using contexts --- plugins/serval-dna/crypto.c | 355 ++++++++++++----------------- plugins/serval-dna/crypto.h | 64 +++--- plugins/serval-dna/serval-client.c | 192 +++++++++------- plugins/serval-dna/serval-dna.c | 15 +- 4 files changed, 300 insertions(+), 326 deletions(-) diff --git a/plugins/serval-dna/crypto.c b/plugins/serval-dna/crypto.c index 6efbfd1..75faf1e 100644 --- a/plugins/serval-dna/crypto.c +++ b/plugins/serval-dna/crypto.c @@ -66,27 +66,20 @@ co_obj_t *err_msg = NULL; /* Private */ static int -serval_create_signature(unsigned char *key, - const unsigned char *msg, - const size_t msg_len, - unsigned char *sig_buffer, - const size_t sig_size) +serval_create_signature(svl_crypto_ctx *ctx) { + CHECK(ctx && ctx->sas_private[0] && ctx->msg && ctx->msg_len,"Invalid ctx"); unsigned long long sig_length = SIGNATURE_BYTES; - - CHECK(sig_size >= msg_len + SIGNATURE_BYTES, "Signature buffer too small"); - unsigned char hash[crypto_hash_sha512_BYTES]; // create sha512 hash of message, which will then be signed - crypto_hash_sha512(hash, msg, msg_len); - memcpy(sig_buffer, msg, msg_len); + crypto_hash_sha512(hash, ctx->msg, ctx->msg_len); // create signature of message hash, append it to end of message - int sig_ret = crypto_create_signature(key, - hash, - crypto_hash_sha512_BYTES, - &sig_buffer[msg_len], + int sig_ret = crypto_create_signature(ctx->sas_private, + hash, + crypto_hash_sha512_BYTES, + ctx->signature, &sig_length); if (sig_ret != 0) return 0; @@ -97,21 +90,21 @@ serval_create_signature(unsigned char *key, } static int -serval_extract_sas(unsigned char **key, - int *key_len, - keyring_file *_keyring, - unsigned char *_sid) +serval_extract_sas(svl_crypto_ctx *ctx) { + CHECK(ctx,"Invalid ctx"); // get SAS key associated with our SID - *key = keyring_find_sas_private(_keyring, _sid, NULL); - CHECK_ERR(*key, "Failed to fetch SAS key"); - - if (key_len) *key_len = crypto_sign_edwards25519sha512batch_SECRETKEYBYTES; - return 1; + unsigned char *sas_public = NULL; + unsigned char *sas_private = keyring_find_sas_private(ctx->keyring_file, ctx->sid, &sas_public); + CHECK(sas_private && sas_public,"Failed to fetch SAS private key"); + memcpy(ctx->sas_private, sas_private, crypto_sign_PUBLICKEYBYTES); + memcpy(ctx->sas_public, sas_public, crypto_sign_SECRETKEYBYTES); + return 1; error: - return 0; + return 0; } +/* Used by serval-client */ static int keyring_send_sas_request_client(struct subscriber *subscriber) { @@ -226,15 +219,34 @@ keyring_send_sas_request_client(struct subscriber *subscriber) /* Public */ +svl_crypto_ctx * +svl_crypto_ctx_new(void) +{ + svl_crypto_ctx *ctx = h_calloc(1,sizeof(svl_crypto_ctx)); + CHECK_MEM(ctx); + return ctx; +error: + return NULL; +} + +void +svl_crypto_ctx_free(svl_crypto_ctx *ctx) +{ + if (!ctx) + return; + if (ctx->keyring_file) + keyring_free(ctx->keyring_file); + h_free(ctx); +} + int -serval_open_keyring(const char *keyring_path, - const size_t keyring_len, - keyring_file **_keyring) +serval_open_keyring(svl_crypto_ctx *ctx) { - char keyring_path_str[PATH_MAX] = {0}; - - if (keyring_path == NULL || keyring_len == 0) { + CHECK_ERR(ctx,"Invalid ctx"); + if (ctx->keyring_len == 0) { // if no keyring specified, use default keyring + CHECK(serval_path,"Default Serval path not initialized"); + char keyring_path_str[PATH_MAX] = {0}; strcpy(keyring_path_str, serval_path); if (serval_path[strlen(serval_path) - 1] != '/') strcat(keyring_path_str, "/"); @@ -242,19 +254,21 @@ serval_open_keyring(const char *keyring_path, // Fetching SAS keys requires setting the SERVALINSTANCE_PATH environment variable CHECK_ERR(setenv("SERVALINSTANCE_PATH", serval_path, 1) == 0, "Failed to set SERVALINSTANCE_PATH env variable"); + ctx->keyring_len = strlen(keyring_path_str); + ctx->keyring_path = h_malloc(ctx->keyring_len + 1); + strcpy(ctx->keyring_path,keyring_path_str); + hattach(ctx->keyring_path,ctx); } else { // otherwise, use specified keyring (NOTE: if keyring does not exist, it will be created) - CHECK(keyring_len < PATH_MAX, "Keyring length too long"); - strncpy(keyring_path_str, keyring_path, keyring_len); - keyring_path_str[keyring_len] = '\0'; + CHECK(ctx->keyring_len < PATH_MAX, "Keyring length too long"); } - *_keyring = keyring_open(keyring_path_str); - CHECK_ERR(*_keyring, "Failed to open specified keyring file"); + ctx->keyring_file = keyring_open(ctx->keyring_path); + CHECK_ERR(ctx->keyring_file, "Failed to open specified keyring file"); - if (keyring_enter_pin(*_keyring, KEYRING_PIN) <= 0) { + if (keyring_enter_pin(ctx->keyring_file, KEYRING_PIN) <= 0) { // put initial identity in if we don't have any visible - CHECK_ERR(keyring_seed(*_keyring) == 0, "Failed to seed keyring"); + CHECK_ERR(keyring_seed(ctx->keyring_file) == 0, "Failed to seed keyring"); } return 1; @@ -263,29 +277,20 @@ serval_open_keyring(const char *keyring_path, } int -serval_init_keyring(unsigned char *sid, - const size_t sid_len, - const char *keyring_path, - const size_t keyring_len, - keyring_file **_keyring, - unsigned char **key, - int *key_len) +serval_init_keyring(svl_crypto_ctx *ctx) { keyring_identity *new_ident; - unsigned char *_sid = sid; - if (sid) - CHECK(sid_len == SID_SIZE, "Invalid SID"); + CHECK_ERR(ctx && ctx->keyring_path && ctx->keyring_len,"Invalid ctx"); - CHECK_ERR(serval_open_keyring(keyring_path, keyring_len, _keyring), - "Failed to open keyring"); + CHECK_ERR(serval_open_keyring(ctx), "Failed to open keyring"); - if (!sid) { //create new sid + if (!ctx->sid[0]) { //create new sid // cycle through the keyring contexts until we find one with room for another identity - for(int c = 0; c < (*_keyring)->context_count; c++) { + for(int c = 0; c < (ctx->keyring_file)->context_count; c++) { // create new Serval identity - new_ident = keyring_create_identity(*_keyring, - (*_keyring)->contexts[c], + new_ident = keyring_create_identity(ctx->keyring_file, + (ctx->keyring_file)->contexts[c], KEYRING_PIN); if (new_ident) break; @@ -293,13 +298,12 @@ serval_init_keyring(unsigned char *sid, CHECK_ERR(new_ident, "Failed to create new SID"); // need to commit keyring or else new identity won't be saved (needs permissions) - CHECK_ERR(keyring_commit(*_keyring) == 0, "Failed to save new SID into keyring"); + CHECK_ERR(keyring_commit(ctx->keyring_file) == 0, "Failed to save new SID into keyring"); - _sid = new_ident->subscriber->sid; + memcpy(ctx->sid,new_ident->subscriber->sid,SID_SIZE); } - if (key) - CHECK(serval_extract_sas(key, key_len, *_keyring, _sid), "Failed to fetch SAS key"); + CHECK(serval_extract_sas(ctx), "Failed to fetch SAS keys"); return 1; error: @@ -307,89 +311,44 @@ serval_init_keyring(unsigned char *sid, } int -cmd_serval_sign(const char *sid_str, - const size_t sid_len, - const unsigned char *msg, - const size_t msg_len, - char *sig_str_buf, - const size_t sig_str_size, - const char *keyring_path, - const size_t keyring_len) +cmd_serval_sign(svl_crypto_ctx *ctx) { - int ret = 0; - unsigned char signed_msg[msg_len + SIGNATURE_BYTES]; - keyring_file *_keyring = NULL; - unsigned char *key = NULL; - unsigned char packedSid[SID_SIZE] = {0}; - - CHECK(sig_str_size >= (2 * SIGNATURE_BYTES) + 1, "Signature buffer too small"); + CHECK_ERR(ctx,"Invalid ctx"); - if (sid_str) { - CHECK_ERR(sid_len == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, - "Invalid SID"); - stowSid(packedSid, 0, sid_str); - } - - if (keyring_path || !sid_len) { - CHECK_ERR(serval_init_keyring(sid_str ? packedSid : NULL, - sid_str ? SID_SIZE : 0, - keyring_path, - keyring_len, - &_keyring, - &key, - NULL), + /* If a non-default keyring path is given, and/or no SID is set, + * we need to initialize the keyring */ + if (ctx->keyring_path || !ctx->sid[0]) { + CHECK_ERR(serval_init_keyring(ctx), "Failed to initialize Serval keyring"); } else { - CHECK_ERR(serval_extract_sas(&key, NULL, keyring, packedSid), - "Failed to fetch SAS key"); + // or just use the default keyring + CHECK_ERR(serval_extract_sas(ctx), + "Failed to fetch SAS keys"); } - CHECK_ERR(serval_create_signature(key, - msg, - msg_len, - signed_msg, - SIGNATURE_BYTES + msg_len), - "Failed to create signature"); + CHECK_ERR(serval_create_signature(ctx),"Failed to create signature"); - strncpy(sig_str_buf, alloca_tohex(signed_msg + msg_len, SIGNATURE_BYTES), 2 * SIGNATURE_BYTES); - sig_str_buf[2 * SIGNATURE_BYTES] = '\0'; - - ret = 1; + return 1; error: - if (_keyring) - keyring_free(_keyring); - return ret; + return 0; } int -cmd_serval_verify(const char *sas_key, - const size_t sas_key_len, - const unsigned char *msg, - const size_t msg_len, - const char *sig, - const size_t sig_len) +cmd_serval_verify(svl_crypto_ctx *ctx) { int verdict = 0; - unsigned char bin_sig[SIGNATURE_BYTES]; - unsigned char bin_sas[SAS_SIZE]; - - CHECK_ERR(sig_len == 2 * SIGNATURE_BYTES, "Invalid signature"); - CHECK_ERR(sas_key_len == 2 * SAS_SIZE, "Invalid SAS key"); - - // convert signature from hex to binary - CHECK_ERR(fromhexstr(bin_sig, sig, SIGNATURE_BYTES) == 0, "Invalid signature"); - CHECK_ERR(fromhexstr(bin_sas, sas_key, SAS_SIZE) == 0, "Invalid SAS key"); + CHECK_ERR(ctx && ctx->msg && ctx->signature[0] && ctx->sas_public[0],"Invalid ctx"); - DEBUG("Message to verify:\n%s", msg); + DEBUG("Message to verify:\n%s", ctx->msg); unsigned char hash[crypto_hash_sha512_BYTES]; - crypto_hash_sha512(hash, msg, msg_len); + crypto_hash_sha512(hash, ctx->msg, ctx->msg_len); - int sig_ret = crypto_verify_signature(bin_sas, + int sig_ret = crypto_verify_signature(ctx->sas_public, hash, crypto_hash_sha512_BYTES, - &bin_sig[0], + ctx->signature, SIGNATURE_BYTES); if (sig_ret == 0) verdict = 1; // successfully verified @@ -398,33 +357,16 @@ cmd_serval_verify(const char *sas_key, return verdict; } +/* Used by serval-client */ int -serval_verify_client(const char *sid_str, - const size_t sid_len, - const unsigned char *msg, - const size_t msg_len, - const char *sig, - const size_t sig_len, - const char *keyring_path, - const size_t keyring_len) +serval_verify_client(svl_crypto_ctx *ctx) { - CHECK(sid_len == 2 * SID_SIZE, "Invalid SID length"); - CHECK(sig_len == 2 * SIGNATURE_BYTES, "Invalid signature length"); + CHECK(ctx && ctx->sid[0] && ctx->msg && ctx->signature[0] && ctx->keyring_path, + "Invalid ctx"); - CHECK(str_is_subscriber_id(sid_str) != 0, "Invalid SID"); - - unsigned char packedSid[SID_SIZE] = {0}; - stowSid(packedSid, 0, sid_str); - - int init_ret = serval_init_keyring(packedSid, - SID_SIZE,keyring_path, - keyring_len, - &keyring, - NULL, - NULL); - CHECK(init_ret, "Failed to initialize Serval keyring"); + CHECK(serval_init_keyring(ctx), "Failed to initialize Serval keyring"); - struct subscriber *sub = find_subscriber(packedSid, SID_SIZE, 1); // get Serval identity described by given SID + struct subscriber *sub = find_subscriber(ctx->sid, SID_SIZE, 1); // get Serval identity described by given SID CHECK(sub, "Failed to fetch Serval subscriber"); @@ -433,16 +375,9 @@ serval_verify_client(const char *sid_str, CHECK(sub->sas_valid, "Could not validate the signing key!"); CHECK(sub->sas_public[0], "Could not validate the signing key!"); - char sas_str[2*SAS_SIZE+1] = {0}; - CHECK(tohex(sas_str,sub->sas_public,SAS_SIZE), "Failed to convert signing key"); - - return cmd_serval_verify(sas_str, - 2 * SAS_SIZE, - msg, - msg_len, - sig, - sig_len); + memcpy(ctx->sas_public,sub->sas_public,crypto_sign_PUBLICKEYBYTES); + return cmd_serval_verify(ctx); error: return 0; } @@ -482,8 +417,8 @@ olsrd_mdp_register(void) { /** * name: mdp-init - * param[0] : (co_str8_t) - * param[1] : (co_str16_t) + * param[0] : (co_str16_t) + * param[1] : (co_str8_t) */ const char name[] = "mdp-init"; @@ -517,6 +452,7 @@ serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) { CLEAR_ERR(); + svl_crypto_ctx *ctx = NULL; int list_len = co_list_length(params); int keypath = 0; @@ -527,45 +463,56 @@ serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) --list_len; } + ctx = svl_crypto_ctx_new(); + if (co_str_cmp_str(co_list_element(params, 0), "sign") == 0) { CHECK_ERR(list_len == 2 || list_len == 3, "Invalid arguments"); char sig_buf[(2 * SIGNATURE_BYTES) + 1] = {0}; + if (list_len == 3) { - int sign_ret = cmd_serval_sign(_LIST_ELEMENT(params, 1), - co_str_len(co_list_element(params, 1)) - 1, - (unsigned char*)_LIST_ELEMENT(params, 2), - co_str_len(co_list_element(params, 2)) - 1, - sig_buf, - (2 * SIGNATURE_BYTES) + 1, - keypath ? _LIST_ELEMENT(params, 3) + 10 : NULL, // strlen("--length=") == 10 - keypath ? co_str_len(co_list_element(params, 3)) - 11 : 0); - CHECK_ERR(sign_ret, "Failed to create signature"); + char *sid_str = _LIST_ELEMENT(params, 1); + size_t sid_len = co_str_len(co_list_element(params, 1)) - 1; + CHECK_ERR(sid_len == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, + "Invalid SID"); + stowSid(ctx->sid, 0, sid_str); + ctx->msg = (unsigned char*)_LIST_ELEMENT(params, 2); + ctx->msg_len = co_str_len(co_list_element(params, 2)) - 1; + if (keypath) { + ctx->keyring_path = _LIST_ELEMENT(params, 3) + 10; + ctx->keyring_len = co_str_len(co_list_element(params, 3)) - 11; + CHECK_ERR(ctx->keyring_len < PATH_MAX,"Keyring path too long"); + } + } else if (list_len == 2) { - int sign_ret = cmd_serval_sign(NULL, - 0, - (unsigned char*)_LIST_ELEMENT(params, 1), - co_str_len(co_list_element(params, 1)) - 1, - sig_buf, - (2 * SIGNATURE_BYTES) + 1, - keypath ? _LIST_ELEMENT(params, 2) + 10 : NULL, // strlen("--length=") == 10 - keypath ? co_str_len(co_list_element(params, 2)) - 11 : 0); - CHECK_ERR(sign_ret, "Failed to create signature"); + + ctx->msg = (unsigned char*)_LIST_ELEMENT(params, 1); + ctx->msg_len = co_str_len(co_list_element(params, 1)) - 1; + if (keypath) { + ctx->keyring_path = _LIST_ELEMENT(params, 2) + 10; + ctx->keyring_len = co_str_len(co_list_element(params, 2)) - 11; + CHECK_ERR(ctx->keyring_len < PATH_MAX,"Keyring path too long"); + } + } + CHECK_ERR(cmd_serval_sign(ctx), "Failed to create signature"); + + // convert ctx->signature to hex: + strncpy(sig_buf, alloca_tohex(ctx->signature, SIGNATURE_BYTES), 2 * SIGNATURE_BYTES); + sig_buf[2 * SIGNATURE_BYTES] = '\0'; CMD_OUTPUT("result", co_str8_create(sig_buf, (2 * SIGNATURE_BYTES) + 1, 0)); } else if (co_str_cmp_str(co_list_element(params, 0), "verify") == 0) { CHECK_ERR(!keypath, "Keyring option not available for verification"); CHECK_ERR(list_len == 4, "Invalid arguments"); - int verdict = cmd_serval_verify(_LIST_ELEMENT(params, 1), - co_str_len(co_list_element(params, 1)) - 1, - (unsigned char*)_LIST_ELEMENT(params, 3), - co_str_len(co_list_element(params, 3)) - 1, - _LIST_ELEMENT(params, 2), - co_str_len(co_list_element(params, 2)) - 1); -// keypath ? _LIST_ELEMENT(params,4) + 10 : NULL, // strlen("--length=") == 10 -// keypath ? co_str_len(co_list_element(params,4)) - 10 : 0); + // convert SAS and signature from hex to bin + CHECK_ERR(fromhexstr(ctx->signature, _LIST_ELEMENT(params, 2), SIGNATURE_BYTES) == 0, "Invalid signature"); + CHECK_ERR(fromhexstr(ctx->sas_public, _LIST_ELEMENT(params, 1), crypto_sign_PUBLICKEYBYTES) == 0, "Invalid SAS key"); + ctx->msg = (unsigned char*)_LIST_ELEMENT(params, 3); + ctx->msg_len = co_str_len(co_list_element(params, 3)) - 1; + + int verdict = cmd_serval_verify(ctx); if (verdict == 1) { DEBUG("signature verified"); CMD_OUTPUT("result", co_bool_create(true, 0)); // successfully verified @@ -579,12 +526,15 @@ serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) return 1; error: INS_ERROR(); + if (ctx) + svl_crypto_ctx_free(ctx); return 0; } int olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) { + svl_crypto_ctx *ctx = NULL; CHECK(IS_LIST(params) && co_list_length(params) == 2, "Invalid params"); size_t sid_len = co_str_len(co_list_element(params, 1)); @@ -592,25 +542,22 @@ olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) CHECK(sid_len == (2 * SID_SIZE) + 1 && str_is_subscriber_id(sid_str) == 1, "Invalid SID"); - unsigned char packedSid[SID_SIZE] = {0}; - stowSid(packedSid, 0, sid_str); + ctx = svl_crypto_ctx_new(); + + stowSid(ctx->sid, 0, sid_str); - keyring_file *mdp_keyring = NULL; - unsigned char *mdp_key = NULL; - int mdp_key_len = 0; - int init_ret = serval_init_keyring(packedSid, - SID_SIZE, - _LIST_ELEMENT(params, 0), - co_str_len(co_list_element(params, 0)), - &mdp_keyring, - &mdp_key, - &mdp_key_len); - CHECK(init_ret, "Failed to initialize Serval keyring"); + ctx->keyring_path = _LIST_ELEMENT(params, 0); + ctx->keyring_len = co_str_len(co_list_element(params, 0)) - 1; + CHECK_ERR(ctx->keyring_len < PATH_MAX,"Keyring path too long"); - CMD_OUTPUT("key", co_bin8_create((char*)mdp_key, mdp_key_len, 0)); + CHECK(serval_init_keyring(ctx), "Failed to initialize Serval keyring"); + + CMD_OUTPUT("key", co_bin8_create((char*)ctx->sas_private, crypto_sign_SECRETKEYBYTES, 0)); return 1; error: + if (ctx) + svl_crypto_ctx_free(ctx); return 0; } @@ -618,28 +565,22 @@ int olsrd_mdp_sign(co_obj_t *self, co_obj_t **output, co_obj_t *params) { int ret = 0; - unsigned char *msg = NULL; + svl_crypto_ctx *ctx = svl_crypto_ctx_new(); /** skipping some error checking for performance reasons */ // CHECK(IS_LIST(params) && co_list_length(params) == 2, "Invalid params"); - int msg_len = co_obj_data((char**)&msg, co_list_element(params, 1)); - int sig_buf_len = SIGNATURE_BYTES + msg_len + 1; - unsigned char *sig_buf = calloc(sig_buf_len, sizeof(unsigned char)); + ctx->msg_len = co_obj_data((char**)&ctx->msg, co_list_element(params, 1)); + + memcpy(ctx->sas_private,_LIST_ELEMENT(params, 0),crypto_sign_SECRETKEYBYTES); - int sign_ret = serval_create_signature((unsigned char*)_LIST_ELEMENT(params, 0), - msg, - msg_len, - sig_buf, - sig_buf_len); - CHECK(sign_ret, "Failed to sign OLSRd packet"); + CHECK(serval_create_signature(ctx), "Failed to sign OLSRd packet"); - CMD_OUTPUT("sig", co_bin8_create((char*)(sig_buf + msg_len), SIGNATURE_BYTES, 0)); + CMD_OUTPUT("sig", co_bin8_create((char*)ctx->signature, SIGNATURE_BYTES, 0)); ret = 1; error: - if (sig_buf) - free(sig_buf); + svl_crypto_ctx_free(ctx); return ret; } diff --git a/plugins/serval-dna/crypto.h b/plugins/serval-dna/crypto.h index 07a503b..a92b42d 100644 --- a/plugins/serval-dna/crypto.h +++ b/plugins/serval-dna/crypto.h @@ -38,6 +38,25 @@ #define KEYRING_PIN NULL #define BUF_SIZE 1024 +#define crypto_sign_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES +#define crypto_sign_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_SECRETKEYBYTES +#define SIGNATURE_BYTES crypto_sign_edwards25519sha512batch_BYTES + +struct svl_crypto_ctx { + char *keyring_path; + size_t keyring_len; + keyring_file *keyring_file; + unsigned char sid[SID_SIZE]; // SID public key + unsigned char sas_public[crypto_sign_PUBLICKEYBYTES]; // SAS public key + unsigned char sas_private[crypto_sign_SECRETKEYBYTES]; // SAS private key + unsigned char signature[SIGNATURE_BYTES]; + unsigned char *msg; // byte array used to create signature + size_t msg_len; +}; +typedef struct svl_crypto_ctx svl_crypto_ctx; + +svl_crypto_ctx *svl_crypto_ctx_new(void); +void svl_crypto_ctx_free(svl_crypto_ctx *ctx); int serval_crypto_register(void); @@ -51,41 +70,14 @@ int olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params); int olsrd_mdp_sign(co_obj_t *self, co_obj_t **output, co_obj_t *params); -int serval_open_keyring(const char *keyring_path, - const size_t keyring_len, - keyring_file **_keyring); - -int serval_init_keyring(unsigned char *sid, - const size_t sid_len, - const char *keyring_path, - const size_t keyring_len, - keyring_file **_keyring, - unsigned char **key, - int *key_len); - -int cmd_serval_sign(const char *sid_str, - const size_t sid_len, - const unsigned char *msg, - const size_t msg_len, - char *sig_str_buf, - const size_t sig_str_size, - const char *keyring_path, - const size_t keyring_len); - -int cmd_serval_verify(const char *sas_key, - const size_t sas_key_len, - const unsigned char *msg, - const size_t msg_len, - const char *sig, - const size_t sig_len); - -int serval_verify_client(const char *sid_str, - const size_t sid_len, - const unsigned char *msg, - const size_t msg_len, - const char *sig, - const size_t sig_len, - const char *keyring_path, - const size_t keyring_len); +int serval_open_keyring(svl_crypto_ctx *ctx); + +int serval_init_keyring(svl_crypto_ctx *ctx); + +int cmd_serval_sign(svl_crypto_ctx *ctx); + +int cmd_serval_verify(svl_crypto_ctx *ctx); + +int serval_verify_client(svl_crypto_ctx *ctx); #endif \ No newline at end of file diff --git a/plugins/serval-dna/serval-client.c b/plugins/serval-dna/serval-client.c index bfd473a..27139bf 100644 --- a/plugins/serval-dna/serval-client.c +++ b/plugins/serval-dna/serval-client.c @@ -57,7 +57,7 @@ typedef enum { SERVAL_SIGN = 0, SERVAL_VERIFY = 1, SERVAL_CRYPTO = 2 -} serval_cmd; +} serval_client_cmd; #define _DECLARE_SERVAL(F) extern int F(const struct cli_parsed *parsed, void *context); _DECLARE_SERVAL(commandline_usage); @@ -204,7 +204,7 @@ static struct cli_schema command_line_options[]={ {NULL,{NULL}} }; -static int print_usage(serval_cmd cmd) { +static int print_usage(serval_client_cmd cmd) { printf("Serval client\n"); printf("Usage:\n"); if (cmd == SERVAL_SIGN || cmd == SERVAL_CRYPTO) { @@ -218,75 +218,116 @@ static int print_usage(serval_cmd cmd) { return 1; } +static int serval_cmd(int argc, char *argv[]) { + struct cli_parsed parsed; + int result = cli_parse(argc, (const char*const*)argv, command_line_options, &parsed); + switch (result) { + case 0: + // Do not run the command if the configuration does not load ok. + if (((parsed.commands[parsed.cmdi].flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1) { + if (cli_invoke(&parsed, NULL) == 0) { + return 0; + } + } + break; + case 1: + case 2: + // Load configuration so that log messages can get out. + cf_reload_permissive(); + // NOWHENCE(HINTF("Run \"%s help\" for more information.", argv0 ? argv0 : "servald")); + break; + default: + // Load configuration so that log error messages can get out. + cf_reload_permissive(); + break; + } + return 1; +} + int main(int argc, char *argv[]) { - int ret = 1, opt = 0, opt_index = 0, keypath = 0; - char keyring_path[PATH_MAX] = {0}; - char *keyring_opt = NULL; - static const char *opt_string = "k:h"; + int ret = 1, opt = 0, opt_index = 0; +// char *keyring_opt = NULL; +// static const char *opt_string = "k:h"; + static const char *opt_string = "h"; + svl_crypto_ctx *ctx = svl_crypto_ctx_new(); + CHECK_MEM(ctx); static struct option long_opts[] = { - {"keyring", required_argument, NULL, 'k'}, +// {"keyring", required_argument, NULL, 'k'}, {"help", no_argument, NULL, 'h'} }; - opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); +// opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); - while(opt != -1) { - switch(opt) { - case 'k': - keyring_opt = optarg; - break; - case 'h': - default: - print_usage(SERVAL_CRYPTO); - return 0; - break; - } - opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); +// while(opt != -1) { +// switch(opt) { +// case 'k': +// keyring_opt = optarg; +// break; +// case 'h': +// default: + if (getopt_long(argc, argv, opt_string, long_opts, &opt_index) != -1) { + // TODO +// serval_cmd(1,["help"]); +// print_usage(SERVAL_CRYPTO); + if (opt == 'h') + return 0; + return 1; } +// break; +// } +// opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); +// } - if (keyring_opt) { - CHECK(strlen(keyring_opt) < PATH_MAX,"keyring path too long"); - strcpy(keyring_path,keyring_opt); - } else { - strcpy(keyring_path,DEFAULT_SERVAL_PATH); - strcpy(keyring_path,"/"); - strcpy(keyring_path,"serval.keyring"); - } +// if (keyring_opt) { +// CHECK(strlen(keyring_opt) < PATH_MAX,"keyring path too long"); +// strcpy(keyring_path,keyring_opt); +// } else { +// strcpy(keyring_path,DEFAULT_SERVAL_PATH); +// strcpy(keyring_path,"/"); +// strcpy(keyring_path,"serval.keyring"); +// } +// ctx->keyring_len = strlen(keyring_path); +// ctx->keyring_path = h_malloc(ctx->keyring_len + 1); +// strcpy(ctx->keyring_path,keyring_path); +// hattach(ctx->keyring_path,ctx); // Run the Serval command + if (!strncmp("--keyring=",argv[argc-1],10)) { + CHECK(strlen(argv[argc-1] + 10) < PATH_MAX,"keyring path too long"); + ctx->keyring_path = argv[argc-1] + 10; + argc--; + } else { + // add default path to ctx->keyring_path + ctx->keyring_path = h_malloc(strlen(DEFAULT_SERVAL_PATH) + strlen("/serval.keyring")); + hattach(ctx->keyring_path,ctx); + strcpy(ctx->keyring_path,DEFAULT_SERVAL_PATH); + strcat(ctx->keyring_path,"/serval.keyring"); + } + ctx->keyring_len = strlen(ctx->keyring_path); + if (!strcmp(argv[optind],"sign")) { - if (argc - optind <= 2 || argc - optind >= 4) { + if (argc - optind < 2 || argc - optind > 3) { print_usage(SERVAL_SIGN); goto error; } char sig_buf[2*SIGNATURE_BYTES + 1] = {0}; - if (!strncmp("--keyring=",argv[argc-1],10)) { - keypath = 1; - argc--; - } - char keyring_path[PATH_MAX] = {0}; - FORM_SERVAL_INSTANCE_PATH(keyring_path, "serval.keyring"); if (argc - optind == 3) { - CHECK(cmd_serval_sign(argv[optind+1], - strlen(argv[optind+1]), - (unsigned char*)argv[optind+2], - strlen(argv[optind+2]), - sig_buf, - 2*SIGNATURE_BYTES + 1, - keypath ? argv[optind+3] + 10 : keyring_path, // strlen("--length=") == 10 - keypath ? strlen(argv[optind+3] + 10) : strlen(keyring_path)),"Failed to create signature"); + char *sid_str = argv[optind+1]; + CHECK(strlen(sid_str) == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, + "Invalid SID"); + stowSid(ctx->sid, 0, sid_str); + ctx->msg = (unsigned char*)argv[optind+2]; + ctx->msg_len = strlen(argv[optind+2]); } else if (argc - optind == 2) { - CHECK(cmd_serval_sign(NULL, - 0, - (unsigned char*)argv[optind+1], - strlen(argv[optind+1]), - sig_buf, - 2*SIGNATURE_BYTES + 1, - keypath ? argv[optind+2] + 10 : keyring_path, // strlen("--length=") == 10 - keypath ? strlen(argv[optind+2] + 10) : strlen(keyring_path)),"Failed to create signature"); + ctx->msg = (unsigned char*)argv[optind+1]; + ctx->msg_len = strlen(argv[optind+1]); } + CHECK(cmd_serval_sign(ctx), "Failed to create signature"); + // convert ctx->signature to hex: + strncpy(sig_buf, alloca_tohex(ctx->signature, SIGNATURE_BYTES), 2 * SIGNATURE_BYTES); + sig_buf[2 * SIGNATURE_BYTES] = '\0'; printf("%s\n",sig_buf); } else if (!strcmp(argv[optind],"verify")) { @@ -294,42 +335,29 @@ int main(int argc, char *argv[]) { print_usage(SERVAL_VERIFY); goto error; } - int verdict = serval_verify_client(argv[optind+1], - strlen(argv[optind+1]), - (unsigned char*)argv[optind+3], - strlen(argv[optind+3]), - argv[optind+2], - strlen(argv[optind+2]), - keyring_path, - strlen(keyring_path)); + char *sid_str = argv[optind+1]; + CHECK(strlen(sid_str) == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, + "Invalid SID"); + stowSid(ctx->sid, 0, sid_str); + CHECK(fromhexstr(ctx->signature, argv[optind+2], SIGNATURE_BYTES) == 0, "Invalid signature"); + ctx->msg = (unsigned char*)argv[optind+3]; + ctx->msg_len = strlen(argv[optind+3]); + int verdict = serval_verify_client(ctx); +// int verdict = serval_verify_client(argv[optind+1], +// strlen(argv[optind+1]), +// (unsigned char*)argv[optind+3], +// strlen(argv[optind+3]), +// argv[optind+2], +// strlen(argv[optind+2]), +// keyring_path, +// strlen(keyring_path)); if (verdict == 1) printf("Message verified!\n"); else printf("Message NOT verified!\n"); } else { // Serval built-in commands - struct cli_parsed parsed; - int result = cli_parse(argc - optind, (const char*const*)(argv + optind), command_line_options, &parsed); - switch (result) { - case 0: - // Do not run the command if the configuration does not load ok. - if (((parsed.commands[parsed.cmdi].flags & CLIFLAG_PERMISSIVE_CONFIG) ? cf_reload_permissive() : cf_reload()) != -1) { - if (cli_invoke(&parsed, NULL) == 0) { - ret = 0; - } - } - break; - case 1: - case 2: - // Load configuration so that log messages can get out. - cf_reload_permissive(); - // NOWHENCE(HINTF("Run \"%s help\" for more information.", argv0 ? argv0 : "servald")); - break; - default: - // Load configuration so that log error messages can get out. - cf_reload_permissive(); - break; - } + ret = serval_cmd(argc - optind, argv + optind); } /* clean up after ourselves */ @@ -337,5 +365,7 @@ int main(int argc, char *argv[]) { rhizome_close_db(); error: + if (ctx) + svl_crypto_ctx_free(ctx); return ret; } diff --git a/plugins/serval-dna/serval-dna.c b/plugins/serval-dna/serval-dna.c index 766d1b8..d148519 100644 --- a/plugins/serval-dna/serval-dna.c +++ b/plugins/serval-dna/serval-dna.c @@ -395,6 +395,7 @@ static int serval_load_config(void) { int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) { char *enabled = NULL; + svl_crypto_ctx *ctx = NULL; co_profile_get_str(co_profile_global(),&enabled,"servald",sizeof("servald")); if (strcmp(enabled,"disabled") == 0) return 1; @@ -403,7 +404,9 @@ int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) { srandomdev(); CHECK(serval_load_config(),"Failed to load Serval config parameters"); - CHECK(serval_open_keyring(NULL,0,&keyring),"Failed to open keyring"); + ctx = svl_crypto_ctx_new(); + CHECK(serval_open_keyring(ctx),"Failed to open keyring"); + keyring = ctx->keyring_file; if (!serval_registered) { // CHECK(serval_register(),"Failed to register Serval commands"); @@ -433,6 +436,8 @@ int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) { return 1; error: + if (ctx) + svl_crypto_ctx_free(ctx); return 0; } @@ -488,6 +493,8 @@ static int serval_daemon_register(void) { } int serval_daemon_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) { + svl_crypto_ctx *ctx = NULL; + CLEAR_ERR(); CHECK_ERR(IS_LIST(params) && co_list_length(params) == 1,"Invalid parameters"); @@ -500,13 +507,17 @@ int serval_daemon_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) { CHECK_ERR(co_plugin_shutdown(NULL,NULL,NULL),"Failed to stop daemon"); } else*/ if (co_str_cmp_str(co_list_element(params,0),"reload") == 0) { keyring_free(keyring); - CHECK_ERR(serval_open_keyring(NULL,0,&keyring),"Failed to open keyring"); + ctx = svl_crypto_ctx_new(); + CHECK_ERR(serval_open_keyring(ctx),"Failed to open keyring"); + keyring = ctx->keyring_file; } CMD_OUTPUT("result",co_str8_create("success",sizeof("success"),0)); return 1; error: + if (ctx) + svl_crypto_ctx_free(ctx); INS_ERROR(); return 0; } \ No newline at end of file From 09fdf5fb796c9b898a8d85d616377ed32fa51775 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Tue, 18 Feb 2014 14:15:28 -0500 Subject: [PATCH 4/7] minor fixes/cleaup for serval plugin --- plugins/serval-dna/crypto.c | 5 +-- plugins/serval-dna/serval-client.c | 50 +++++------------------------- 2 files changed, 10 insertions(+), 45 deletions(-) diff --git a/plugins/serval-dna/crypto.c b/plugins/serval-dna/crypto.c index 75faf1e..c100937 100644 --- a/plugins/serval-dna/crypto.c +++ b/plugins/serval-dna/crypto.c @@ -97,8 +97,8 @@ serval_extract_sas(svl_crypto_ctx *ctx) unsigned char *sas_public = NULL; unsigned char *sas_private = keyring_find_sas_private(ctx->keyring_file, ctx->sid, &sas_public); CHECK(sas_private && sas_public,"Failed to fetch SAS private key"); - memcpy(ctx->sas_private, sas_private, crypto_sign_PUBLICKEYBYTES); - memcpy(ctx->sas_public, sas_public, crypto_sign_SECRETKEYBYTES); + memcpy(ctx->sas_private, sas_private, crypto_sign_SECRETKEYBYTES); + memcpy(ctx->sas_public, sas_public, crypto_sign_PUBLICKEYBYTES); return 1; error: return 0; @@ -322,6 +322,7 @@ cmd_serval_sign(svl_crypto_ctx *ctx) "Failed to initialize Serval keyring"); } else { // or just use the default keyring + ctx->keyring_file = keyring; // serval global CHECK_ERR(serval_extract_sas(ctx), "Failed to fetch SAS keys"); } diff --git a/plugins/serval-dna/serval-client.c b/plugins/serval-dna/serval-client.c index 27139bf..0d27aea 100644 --- a/plugins/serval-dna/serval-client.c +++ b/plugins/serval-dna/serval-client.c @@ -246,51 +246,22 @@ static int serval_cmd(int argc, char *argv[]) { int main(int argc, char *argv[]) { int ret = 1, opt = 0, opt_index = 0; -// char *keyring_opt = NULL; -// static const char *opt_string = "k:h"; static const char *opt_string = "h"; svl_crypto_ctx *ctx = svl_crypto_ctx_new(); CHECK_MEM(ctx); static struct option long_opts[] = { -// {"keyring", required_argument, NULL, 'k'}, {"help", no_argument, NULL, 'h'} }; -// opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); - -// while(opt != -1) { -// switch(opt) { -// case 'k': -// keyring_opt = optarg; -// break; -// case 'h': -// default: - if (getopt_long(argc, argv, opt_string, long_opts, &opt_index) != -1) { + if ((opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index)) != -1) { // TODO -// serval_cmd(1,["help"]); -// print_usage(SERVAL_CRYPTO); - if (opt == 'h') - return 0; - return 1; + char *asd[] = {"help"}; + serval_cmd(1,asd); + if (opt == 'h') + return 0; + return 1; } -// break; -// } -// opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); -// } - -// if (keyring_opt) { -// CHECK(strlen(keyring_opt) < PATH_MAX,"keyring path too long"); -// strcpy(keyring_path,keyring_opt); -// } else { -// strcpy(keyring_path,DEFAULT_SERVAL_PATH); -// strcpy(keyring_path,"/"); -// strcpy(keyring_path,"serval.keyring"); -// } -// ctx->keyring_len = strlen(keyring_path); -// ctx->keyring_path = h_malloc(ctx->keyring_len + 1); -// strcpy(ctx->keyring_path,keyring_path); -// hattach(ctx->keyring_path,ctx); // Run the Serval command @@ -343,14 +314,6 @@ int main(int argc, char *argv[]) { ctx->msg = (unsigned char*)argv[optind+3]; ctx->msg_len = strlen(argv[optind+3]); int verdict = serval_verify_client(ctx); -// int verdict = serval_verify_client(argv[optind+1], -// strlen(argv[optind+1]), -// (unsigned char*)argv[optind+3], -// strlen(argv[optind+3]), -// argv[optind+2], -// strlen(argv[optind+2]), -// keyring_path, -// strlen(keyring_path)); if (verdict == 1) printf("Message verified!\n"); else @@ -364,6 +327,7 @@ int main(int argc, char *argv[]) { overlay_mdp_client_done(); rhizome_close_db(); + ret = 0; error: if (ctx) svl_crypto_ctx_free(ctx); From ace4fec076e8c8336e213f8cf70fbbd869456940 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Tue, 18 Feb 2014 14:23:33 -0500 Subject: [PATCH 5/7] add more info to crypto command responses --- plugins/serval-dna/crypto.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/serval-dna/crypto.c b/plugins/serval-dna/crypto.c index c100937..c3f63f1 100644 --- a/plugins/serval-dna/crypto.c +++ b/plugins/serval-dna/crypto.c @@ -469,7 +469,6 @@ serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) if (co_str_cmp_str(co_list_element(params, 0), "sign") == 0) { CHECK_ERR(list_len == 2 || list_len == 3, "Invalid arguments"); - char sig_buf[(2 * SIGNATURE_BYTES) + 1] = {0}; if (list_len == 3) { char *sid_str = _LIST_ELEMENT(params, 1); @@ -498,10 +497,16 @@ serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) } CHECK_ERR(cmd_serval_sign(ctx), "Failed to create signature"); - // convert ctx->signature to hex: - strncpy(sig_buf, alloca_tohex(ctx->signature, SIGNATURE_BYTES), 2 * SIGNATURE_BYTES); - sig_buf[2 * SIGNATURE_BYTES] = '\0'; - CMD_OUTPUT("result", co_str8_create(sig_buf, (2 * SIGNATURE_BYTES) + 1, 0)); + // convert ctx->signature, ctx->sas_public, and ctx->sid to hex: + char sid_str[(2 * SID_SIZE) + 1] = {0}; + strncpy(sid_str, alloca_tohex(ctx->sid, SID_SIZE), 2 * SID_SIZE); + char sas_str[(2 * crypto_sign_PUBLICKEYBYTES) + 1] = {0}; + strncpy(sas_str, alloca_tohex(ctx->sas_public, crypto_sign_PUBLICKEYBYTES), 2 * crypto_sign_PUBLICKEYBYTES); + char sig_str[(2 * SIGNATURE_BYTES) + 1] = {0}; + strncpy(sig_str, alloca_tohex(ctx->signature, SIGNATURE_BYTES), 2 * SIGNATURE_BYTES); + CMD_OUTPUT("SID", co_str8_create(sid_str, (2 * SID_SIZE) + 1, 0)); + CMD_OUTPUT("SAS", co_str8_create(sas_str, (2 * crypto_sign_PUBLICKEYBYTES) + 1, 0)); + CMD_OUTPUT("signature", co_str8_create(sig_str, (2 * SIGNATURE_BYTES) + 1, 0)); } else if (co_str_cmp_str(co_list_element(params, 0), "verify") == 0) { @@ -517,9 +522,11 @@ serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) if (verdict == 1) { DEBUG("signature verified"); CMD_OUTPUT("result", co_bool_create(true, 0)); // successfully verified + CMD_OUTPUT("verified",co_str8_create("true",sizeof("true"),0)); } else if (verdict == 0) { DEBUG("signature NOT verified"); CMD_OUTPUT("result", co_bool_create(false, 0)); + CMD_OUTPUT("verified",co_str8_create("false",sizeof("false"),0)); } } From 3c5b825e8481d0fb94a98c7b338a47c9165ced57 Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Tue, 18 Feb 2014 14:27:17 -0500 Subject: [PATCH 6/7] keyring doesnt need to be set when signing --- plugins/serval-dna/crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/serval-dna/crypto.c b/plugins/serval-dna/crypto.c index c3f63f1..4a9547d 100644 --- a/plugins/serval-dna/crypto.c +++ b/plugins/serval-dna/crypto.c @@ -281,7 +281,7 @@ serval_init_keyring(svl_crypto_ctx *ctx) { keyring_identity *new_ident; - CHECK_ERR(ctx && ctx->keyring_path && ctx->keyring_len,"Invalid ctx"); + CHECK_ERR(ctx,"Invalid ctx"); CHECK_ERR(serval_open_keyring(ctx), "Failed to open keyring"); From d0a16e81c50c35d18458eba76011aebae3845f4d Mon Sep 17 00:00:00 2001 From: Dan Staples Date: Tue, 18 Feb 2014 15:10:19 -0500 Subject: [PATCH 7/7] got rid of getopt; fixed specifying keyring when verifying --- plugins/serval-dna/serval-client.c | 62 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/plugins/serval-dna/serval-client.c b/plugins/serval-dna/serval-client.c index 0d27aea..068997a 100644 --- a/plugins/serval-dna/serval-client.c +++ b/plugins/serval-dna/serval-client.c @@ -31,7 +31,6 @@ #include #include -#include #include #include #include @@ -245,23 +244,10 @@ static int serval_cmd(int argc, char *argv[]) { } int main(int argc, char *argv[]) { - int ret = 1, opt = 0, opt_index = 0; - static const char *opt_string = "h"; + int ret = 1; + char *instance_path = NULL; svl_crypto_ctx *ctx = svl_crypto_ctx_new(); CHECK_MEM(ctx); - - static struct option long_opts[] = { - {"help", no_argument, NULL, 'h'} - }; - - if ((opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index)) != -1) { - // TODO - char *asd[] = {"help"}; - serval_cmd(1,asd); - if (opt == 'h') - return 0; - return 1; - } // Run the Serval command @@ -278,22 +264,24 @@ int main(int argc, char *argv[]) { } ctx->keyring_len = strlen(ctx->keyring_path); - if (!strcmp(argv[optind],"sign")) { - if (argc - optind < 2 || argc - optind > 3) { + argc--; + argv++; + if (!strcmp(argv[0],"sign")) { + if (argc < 2 || argc > 3) { print_usage(SERVAL_SIGN); goto error; } char sig_buf[2*SIGNATURE_BYTES + 1] = {0}; - if (argc - optind == 3) { - char *sid_str = argv[optind+1]; + if (argc == 3) { + char *sid_str = argv[1]; CHECK(strlen(sid_str) == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, "Invalid SID"); stowSid(ctx->sid, 0, sid_str); - ctx->msg = (unsigned char*)argv[optind+2]; - ctx->msg_len = strlen(argv[optind+2]); - } else if (argc - optind == 2) { - ctx->msg = (unsigned char*)argv[optind+1]; - ctx->msg_len = strlen(argv[optind+1]); + ctx->msg = (unsigned char*)argv[2]; + ctx->msg_len = strlen(argv[2]); + } else if (argc == 2) { + ctx->msg = (unsigned char*)argv[1]; + ctx->msg_len = strlen(argv[1]); } CHECK(cmd_serval_sign(ctx), "Failed to create signature"); // convert ctx->signature to hex: @@ -301,18 +289,26 @@ int main(int argc, char *argv[]) { sig_buf[2 * SIGNATURE_BYTES] = '\0'; printf("%s\n",sig_buf); - } else if (!strcmp(argv[optind],"verify")) { - if (argc - optind != 4) { + } else if (!strcmp(argv[0],"verify")) { + if (argc != 4) { print_usage(SERVAL_VERIFY); goto error; } - char *sid_str = argv[optind+1]; + + // Set SERVALINSTANCE_PATH environment variable + char *last_slash = strrchr(ctx->keyring_path,(int)'/'); + instance_path = calloc(last_slash - ctx->keyring_path + 1,sizeof(char)); + strncpy(instance_path,ctx->keyring_path,last_slash - ctx->keyring_path); + CHECK(setenv("SERVALINSTANCE_PATH", instance_path, 1) == 0, + "Failed to set SERVALINSTANCE_PATH env variable"); + + char *sid_str = argv[1]; CHECK(strlen(sid_str) == (2 * SID_SIZE) && str_is_subscriber_id(sid_str) == 1, "Invalid SID"); stowSid(ctx->sid, 0, sid_str); - CHECK(fromhexstr(ctx->signature, argv[optind+2], SIGNATURE_BYTES) == 0, "Invalid signature"); - ctx->msg = (unsigned char*)argv[optind+3]; - ctx->msg_len = strlen(argv[optind+3]); + CHECK(fromhexstr(ctx->signature, argv[2], SIGNATURE_BYTES) == 0, "Invalid signature"); + ctx->msg = (unsigned char*)argv[3]; + ctx->msg_len = strlen(argv[3]); int verdict = serval_verify_client(ctx); if (verdict == 1) printf("Message verified!\n"); @@ -320,7 +316,7 @@ int main(int argc, char *argv[]) { printf("Message NOT verified!\n"); } else { // Serval built-in commands - ret = serval_cmd(argc - optind, argv + optind); + ret = serval_cmd(argc, argv); } /* clean up after ourselves */ @@ -329,6 +325,8 @@ int main(int argc, char *argv[]) { ret = 0; error: + if (instance_path) + free(instance_path); if (ctx) svl_crypto_ctx_free(ctx); return ret;