int rhizome_manifest_check_sanity(rhizome_manifest *m_in) { /* Ensure manifest meets basic sanity checks. */ const char *service = rhizome_manifest_get(m_in, "service", NULL, 0); const char *sender = rhizome_manifest_get(m_in, "sender", NULL, 0); const char *recipient = rhizome_manifest_get(m_in, "recipient", NULL, 0); if (service == NULL || !service[0]) return WHY("Manifest missing 'service' field"); if (rhizome_manifest_get_ll(m_in, "date") == -1) return WHY("Manifest missing 'date' field"); if (strcasecmp(service, RHIZOME_SERVICE_FILE) == 0) { const char *name = rhizome_manifest_get(m_in, "name", NULL, 0); if (name == NULL) return WHY("Manifest missing 'name' field"); } else if (strcasecmp(service, RHIZOME_SERVICE_MESHMS) == 0) { if (sender == NULL || !sender[0]) return WHY("MeshMS Manifest missing 'sender' field"); if (!str_is_subscriber_id(sender)) return WHYF("MeshMS Manifest contains invalid 'sender' field: %s", sender); if (recipient == NULL || !recipient[0]) return WHY("MeshMS Manifest missing 'recipient' field"); if (!str_is_subscriber_id(recipient)) return WHYF("MeshMS Manifest contains invalid 'recipient' field: %s", recipient); } else { return WHY("Invalid service type"); } if (debug & DEBUG_RHIZOME) DEBUGF("sender='%s'", sender ? sender : "(null)"); /* passes all sanity checks */ 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}; 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); CHECK(sid_len == 2*SID_SIZE + 1 && str_is_subscriber_id(sid_str) == 1,"Invalid SID"); 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"); CMD_OUTPUT("key",co_bin8_create((char*)mdp_key,mdp_key_len,0)); return 1; error: 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)); char *sid_str = _LIST_ELEMENT(params, 1); CHECK(sid_len == (2 * SID_SIZE) + 1 && str_is_subscriber_id(sid_str) == 1, "Invalid SID"); ctx = svl_crypto_ctx_new(); stowSid(ctx->sid, 0, sid_str); 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"); 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; }
void handle_reply_line(const char *bufp, size_t len) { if (!dna_helper_started) { if (len == 8 && strncmp(bufp, "STARTED\n", 8) == 0) { if (config.debug.dnahelper) DEBUGF("DNAHELPER got STARTED ACK"); dna_helper_started = 1; // Start sending request if there is one pending. if (request_bufptr) { sched_requests.poll.fd = dna_helper_stdin; watch(&sched_requests); } } else { WHYF("DNAHELPER malformed start ACK %s", alloca_toprint(-1, bufp, len)); dna_helper_kill(); } } else if (awaiting_reply) { if (len == 5 && strncmp(bufp, "DONE\n", 5) == 0) { if (config.debug.dnahelper) DEBUG("DNAHELPER reply DONE"); unschedule(&sched_timeout); awaiting_reply = 0; } else { char sidhex[SID_STRLEN + 1]; char did[DID_MAXSIZE + 1]; char name[64]; char uri[512]; const char *replyend = NULL; if (!parseDnaReply(bufp, len, sidhex, did, name, uri, &replyend)) WHYF("DNAHELPER reply %s invalid -- ignored", alloca_toprint(-1, bufp, len)); else if (uri[0] == '\0') WHYF("DNAHELPER reply %s contains empty URI -- ignored", alloca_toprint(-1, bufp, len)); else if (!str_is_uri(uri)) WHYF("DNAHELPER reply %s contains invalid URI -- ignored", alloca_toprint(-1, bufp, len)); else if (sidhex[0] == '\0') WHYF("DNAHELPER reply %s contains empty token -- ignored", alloca_toprint(-1, bufp, len)); else if (!str_is_subscriber_id(sidhex)) WHYF("DNAHELPER reply %s contains invalid token -- ignored", alloca_toprint(-1, bufp, len)); else if (strncmp(sidhex, request_buffer, SID_STRLEN) != 0) WHYF("DNAHELPER reply %s contains mismatched token -- ignored", alloca_toprint(-1, bufp, len)); else if (did[0] == '\0') WHYF("DNAHELPER reply %s contains empty DID -- ignored", alloca_toprint(-1, bufp, len)); else if (!str_is_did(did)) WHYF("DNAHELPER reply %s contains invalid DID -- ignored", alloca_toprint(-1, bufp, len)); else if (strcmp(did, request_did) != 0) WHYF("DNAHELPER reply %s contains mismatched DID -- ignored", alloca_toprint(-1, bufp, len)); else if (*replyend != '\n') WHYF("DNAHELPER reply %s contains spurious trailing chars -- ignored", alloca_toprint(-1, bufp, len)); else { if (config.debug.dnahelper) DEBUGF("DNAHELPER reply %s", alloca_toprint(-1, bufp, len)); overlay_mdp_dnalookup_reply(request_source, request_port, my_subscriber, uri, did, name); } } } else { WARNF("DNAHELPER spurious output %s -- ignored", alloca_toprint(-1, bufp, len)); } }
int cf_opt_sid(sid_t *sidp, const char *text) { if (strcasecmp(text, "broadcast")==0){ *sidp = SID_BROADCAST; return CFOK; } if (!str_is_subscriber_id(text)) return CFINVALID; int r = str_to_sid_t(sidp, text); assert(r != -1); return CFOK; }
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"); 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) { 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"); } else { 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"); 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); return ret; }
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 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"); struct subscriber *sub = find_subscriber(packedSid, SID_SIZE, 1); // get Serval identity described by given SID CHECK(sub,"Failed to fetch Serval subscriber"); 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"); verdict = cmd_serval_verify(sas_str,2*SAS_SIZE, msg,msg_len,sig,sig_len); error: return verdict; }
int serval_sign(const char *sid, const size_t sid_len, const unsigned char *msg, const size_t msg_len, char *sig_buffer, const size_t sig_size, const char *keyringName, const size_t keyring_len) { keyring_identity *new_ident; char keyringFile[1024]; assert(msg_len); if (sid) assert(sid_len == 2*SID_SIZE); if (keyringName == NULL || keyring_len == 0) { FORM_SERVAL_INSTANCE_PATH(keyringFile, "serval.keyring"); // if no keyring specified, use default keyring } else { // otherwise, use specified keyring (NOTE: if keyring does not exist, it will be created) strncpy(keyringFile,keyringName,keyring_len); keyringFile[keyring_len] = '\0'; } keyring = keyring_open(keyringFile); keyring_enter_pin(keyring, KEYRING_PIN); // unlocks Serval keyring for using identities (also initializes global default identity my_subscriber) 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 (new_ident) break; } if (!new_ident) { fprintf(stderr, "failed to create new SID\n"); return 1; } if (keyring_commit(keyring)) { // need to commit keyring or else new identity won't be saved (needs root permissions) fprintf(stderr, "Failed to save new SID into keyring...make sure you are running as root!\n"); return 1; } sid = alloca_tohex_sid(new_ident->subscriber->sid); // convert SID from binary to hex } else { if (!str_is_subscriber_id(sid)) { fprintf(stderr,"Invalid SID\n"); return 1; } } unsigned char packedSid[SID_SIZE]; stowSid(packedSid,0,sid); unsigned char *key=keyring_find_sas_private(keyring, packedSid, NULL); // get SAS key associated with our SID if (!key) return 1; unsigned char hash[crypto_hash_sha512_BYTES]; unsigned long long sig_length = SIGNATURE_BYTES; crypto_hash_sha512(hash, msg, msg_len); // create sha512 hash of message, which will then be signed unsigned char signed_msg[msg_len + sig_length]; memcpy(signed_msg,msg,msg_len); int ret = crypto_create_signature(key, hash, crypto_hash_sha512_BYTES, &signed_msg[msg_len], &sig_length); // create signature of message hash, append it to end of message if (!ret) { //success printf("%s\n", alloca_tohex(signed_msg + msg_len, sig_length)); printf("%s\n",sid); if (sig_size > 0) { if (sig_size >= 2*sig_length + 1) { strncpy(sig_buffer,alloca_tohex(signed_msg + msg_len,sig_length),2*sig_length); sig_buffer[2*sig_length] = '\0'; } else fprintf(stderr,"Insufficient signature buffer size\n"); } } keyring_free(keyring); return ret; }
int cli_optional_sid(const char *arg) { return !arg[0] || str_is_subscriber_id(arg); }
int 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; CHECK_ERR(IS_LIST(params) && list_len >= 2, "Invalid params"); if (!strncmp("--keyring=", co_obj_data_ptr(co_list_get_last(params)), 10)) { keypath = 1; --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"); if (list_len == 3) { 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) { 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, 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) { CHECK_ERR(!keypath, "Keyring option not available for verification"); CHECK_ERR(list_len == 4, "Invalid arguments"); // 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 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)); } } error: INS_ERROR(); if (ctx) svl_crypto_ctx_free(ctx); return 1; }