int fwfile_add_meta_conf_str(const char *configtxt, int configtxt_len, struct archive *a, const unsigned char *signing_key) { struct archive_entry *entry; // If the user passed in a signing key, sign the meta.conf. if (signing_key) { unsigned char signature[crypto_sign_BYTES]; crypto_sign_detached(signature, NULL, (unsigned char *) configtxt, configtxt_len, signing_key); entry = archive_entry_new(); archive_entry_set_pathname(entry, "meta.conf.ed25519"); archive_entry_set_size(entry, sizeof(signature)); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_perm(entry, 0644); archive_write_header(a, entry); archive_write_data(a, signature, sizeof(signature)); archive_entry_free(entry); } // Add meta.conf entry = archive_entry_new(); archive_entry_set_pathname(entry, "meta.conf"); archive_entry_set_size(entry, configtxt_len); archive_entry_set_filetype(entry, AE_IFREG); archive_entry_set_perm(entry, 0644); archive_write_header(a, entry); archive_write_data(a, configtxt, configtxt_len); archive_entry_free(entry); return 0; }
int crypto_sign(unsigned char *sm, unsigned long long *smlen_p, const unsigned char *m, unsigned long long mlen, const unsigned char *sk) { unsigned long long siglen; memmove(sm + crypto_sign_ed25519_BYTES, m, mlen); /* LCOV_EXCL_START */ if (crypto_sign_detached(sm, &siglen, sm + crypto_sign_ed25519_BYTES, mlen, sk) != 0 || siglen != crypto_sign_ed25519_BYTES) { if (smlen_p != NULL) { *smlen_p = 0; } memset(sm, 0, mlen + crypto_sign_ed25519_BYTES); return -1; } /* LCOV_EXCL_STOP */ if (smlen_p != NULL) { *smlen_p = mlen + siglen; } return 0; }
SEXP R_sig_sign(SEXP msg, SEXP key) { if(LENGTH(key) != crypto_sign_SECRETKEYBYTES) Rf_error("Invalid key: must be exactly %d bytes", crypto_sign_SECRETKEYBYTES); SEXP res = allocVector(RAWSXP, crypto_sign_BYTES); if(crypto_sign_detached(RAW(res), NULL, RAW(msg), LENGTH(msg), RAW(key))) Rf_error("Failed to create signature"); return res; }
void RippleAddress::sign(uint256 const& message, Blob& retSignature) const { assert(vchData.size() == 64); const unsigned char *key = vchData.data(); retSignature.resize(crypto_sign_BYTES); crypto_sign_detached(&retSignature[0], NULL, (unsigned char*)message.begin(), message.size(), key); }
CWalletTx GetValidReceive(ZCJoinSplit& params, const libzcash::SpendingKey& sk, CAmount value, bool randomInputs) { CMutableTransaction mtx; mtx.nVersion = 2; // Enable JoinSplits mtx.vin.resize(2); if (randomInputs) { mtx.vin[0].prevout.hash = GetRandHash(); mtx.vin[1].prevout.hash = GetRandHash(); } else { mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); mtx.vin[1].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000002"); } mtx.vin[0].prevout.n = 0; mtx.vin[1].prevout.n = 0; // Generate an ephemeral keypair. uint256 joinSplitPubKey; unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); mtx.joinSplitPubKey = joinSplitPubKey; boost::array<libzcash::JSInput, 2> inputs = { libzcash::JSInput(), // dummy input libzcash::JSInput() // dummy input }; boost::array<libzcash::JSOutput, 2> outputs = { libzcash::JSOutput(sk.address(), value), libzcash::JSOutput(sk.address(), value) }; boost::array<libzcash::Note, 2> output_notes; // Prepare JoinSplits uint256 rt; JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, inputs, outputs, 2*value, 0, false}; mtx.vjoinsplit.push_back(jsdesc); // Empty output script. CScript scriptCode; CTransaction signTx(mtx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL); // Add the signature assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); CTransaction tx {mtx}; CWalletTx wtx {NULL, tx}; return wtx; }
int cpn_sign_sig(struct cpn_sign_sig *out, const struct cpn_sign_sk *key, uint8_t *data, size_t datalen) { memset(out, 0, sizeof(*out)); if (crypto_sign_detached(out->data, NULL, data, datalen, key->data) != 0) { cpn_log(LOG_LEVEL_ERROR, "Could not sign data"); return -1; } return 0; }
// Computes the signature of a message. int EdDSA::sign(unsigned char* msg, unsigned long long msglen, unsigned char* sig) { unsigned char pubKey[crypto_sign_PUBLICKEYBYTES]; unsigned char privKey[crypto_sign_SECRETKEYBYTES]; int check; check = crypto_sign_seed_keypair(pubKey, privKey, (const unsigned char*)this->keySeed); if (check != 0) { // Something went wrong deriving keys. return(0); } check = crypto_sign_detached(sig, NULL, msg, msglen, privKey); if (check != 0) { // Something went wrong signing the message. return(0); } return(crypto_sign_BYTES + msglen); }
int crypto_sign(unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen, const unsigned char *sk) { unsigned long long siglen; if (crypto_sign_detached(sm, &siglen, m, mlen, sk) != 0 || siglen > crypto_sign_ed25519_BYTES) { if (smlen != NULL) { *smlen = 0; } memset(sm, 0, mlen + crypto_sign_ed25519_BYTES); return -1; } memmove(sm + siglen, m, mlen); if (smlen != NULL) { *smlen = mlen + siglen; } return 0; }
CWalletTx GetValidSpend(ZCJoinSplit& params, const libzcash::SpendingKey& sk, const libzcash::Note& note, CAmount value) { CMutableTransaction mtx; mtx.vout.resize(2); mtx.vout[0].nValue = value; mtx.vout[1].nValue = 0; // Generate an ephemeral keypair. uint256 joinSplitPubKey; unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(joinSplitPubKey.begin(), joinSplitPrivKey); mtx.joinSplitPubKey = joinSplitPubKey; // Fake tree for the unused witness ZCIncrementalMerkleTree tree; libzcash::JSOutput dummyout; libzcash::JSInput dummyin; { if (note.value > value) { libzcash::SpendingKey dummykey = libzcash::SpendingKey::random(); libzcash::PaymentAddress dummyaddr = dummykey.address(); dummyout = libzcash::JSOutput(dummyaddr, note.value - value); } else if (note.value < value) { libzcash::SpendingKey dummykey = libzcash::SpendingKey::random(); libzcash::PaymentAddress dummyaddr = dummykey.address(); libzcash::Note dummynote(dummyaddr.a_pk, (value - note.value), uint256(), uint256()); tree.append(dummynote.cm()); dummyin = libzcash::JSInput(tree.witness(), dummynote, dummykey); } } tree.append(note.cm()); boost::array<libzcash::JSInput, 2> inputs = { libzcash::JSInput(tree.witness(), note, sk), dummyin }; boost::array<libzcash::JSOutput, 2> outputs = { dummyout, // dummy output libzcash::JSOutput() // dummy output }; boost::array<libzcash::Note, 2> output_notes; // Prepare JoinSplits uint256 rt = tree.root(); JSDescription jsdesc {params, mtx.joinSplitPubKey, rt, inputs, outputs, 0, value, false}; mtx.vjoinsplit.push_back(jsdesc); // Empty output script. CScript scriptCode; CTransaction signTx(mtx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL); // Add the signature assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); CTransaction tx {mtx}; CWalletTx wtx {NULL, tx}; return wtx; }
static int sign(const char *sk_file, const char *message_file, const char *sig_file, const char *comment, const char *trusted_comment, int hashed) { unsigned char global_sig[crypto_sign_BYTES]; SigStruct sig_struct; FILE *fp; SeckeyStruct *seckey_struct; unsigned char *message; unsigned char *sig_and_trusted_comment; size_t comment_len; size_t trusted_comment_len; size_t message_len; seckey_struct = seckey_load(sk_file); message = message_load(&message_len, message_file, hashed); if (hashed != 0) { memcpy(sig_struct.sig_alg, SIGALG_HASHED, sizeof sig_struct.sig_alg); } else { memcpy(sig_struct.sig_alg, SIGALG, sizeof sig_struct.sig_alg); } memcpy(sig_struct.keynum, seckey_struct->keynum_sk.keynum, sizeof sig_struct.keynum); crypto_sign_detached(sig_struct.sig, NULL, message, message_len, seckey_struct->keynum_sk.sk); free(message); if ((fp = fopen(sig_file, "w")) == NULL) { exit_err(sig_file); } comment_len = strlen(comment); assert(strrchr(comment, '\r') == NULL && strrchr(comment, '\n') == NULL); assert(COMMENTMAXBYTES > sizeof COMMENT_PREFIX); if (comment_len >= COMMENTMAXBYTES - sizeof COMMENT_PREFIX) { fprintf(stderr, "Warning: comment too long. " "This breaks compatibility with signify.\n"); } xfprintf(fp, "%s%s\n", COMMENT_PREFIX, comment); xfput_b64(fp, (unsigned char *) (void *) &sig_struct, sizeof sig_struct); xfprintf(fp, "%s%s\n", TRUSTED_COMMENT_PREFIX, trusted_comment); trusted_comment_len = strlen(trusted_comment); assert(strrchr(trusted_comment, '\r') == NULL && strrchr(trusted_comment, '\n') == NULL); if (trusted_comment_len >= TRUSTEDCOMMENTMAXBYTES - sizeof TRUSTED_COMMENT_PREFIX) { exit_msg("Trusted comment too long"); } sig_and_trusted_comment = xmalloc((sizeof sig_struct.sig) + trusted_comment_len); memcpy(sig_and_trusted_comment, sig_struct.sig, sizeof sig_struct.sig); memcpy(sig_and_trusted_comment + sizeof sig_struct.sig, trusted_comment, trusted_comment_len); crypto_sign_detached(global_sig, NULL, sig_and_trusted_comment, (sizeof sig_struct.sig) + trusted_comment_len, seckey_struct->keynum_sk.sk); sodium_free(seckey_struct); xfput_b64(fp, (unsigned char *) (void *) &global_sig, sizeof global_sig); free(sig_and_trusted_comment); xfclose(fp); return 0; }
void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t consensusBranchId) { tx.fOverwintered = insecure_rand() % 2; if (tx.fOverwintered) { if (insecure_rand() % 2) { tx.nVersionGroupId = SAPLING_VERSION_GROUP_ID; tx.nVersion = sapling_version_dist(rng); } else { tx.nVersionGroupId = OVERWINTER_VERSION_GROUP_ID; tx.nVersion = overwinter_version_dist(rng); } tx.nExpiryHeight = (insecure_rand() % 2) ? insecure_rand() : 0; } else { tx.nVersion = insecure_rand() & 0x7FFFFFFF; } tx.vin.clear(); tx.vout.clear(); tx.vShieldedSpend.clear(); tx.vShieldedOutput.clear(); tx.vjoinsplit.clear(); tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0; int ins = (insecure_rand() % 4) + 1; int outs = fSingle ? ins : (insecure_rand() % 4) + 1; int shielded_spends = (insecure_rand() % 4) + 1; int shielded_outs = (insecure_rand() % 4) + 1; int joinsplits = (insecure_rand() % 4); for (int in = 0; in < ins; in++) { tx.vin.push_back(CTxIn()); CTxIn &txin = tx.vin.back(); txin.prevout.hash = GetRandHash(); txin.prevout.n = insecure_rand() % 4; RandomScript(txin.scriptSig); txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1; } for (int out = 0; out < outs; out++) { tx.vout.push_back(CTxOut()); CTxOut &txout = tx.vout.back(); txout.nValue = insecure_rand() % 100000000; RandomScript(txout.scriptPubKey); } if (tx.nVersionGroupId == SAPLING_VERSION_GROUP_ID) { tx.valueBalance = insecure_rand() % 100000000; for (int spend = 0; spend < shielded_spends; spend++) { SpendDescription sdesc; sdesc.cv = GetRandHash(); sdesc.anchor = GetRandHash(); sdesc.nullifier = GetRandHash(); sdesc.rk = GetRandHash(); randombytes_buf(sdesc.zkproof.begin(), sdesc.zkproof.size()); tx.vShieldedSpend.push_back(sdesc); } for (int out = 0; out < shielded_outs; out++) { OutputDescription odesc; odesc.cv = GetRandHash(); odesc.cm = GetRandHash(); odesc.ephemeralKey = GetRandHash(); randombytes_buf(odesc.encCiphertext.begin(), odesc.encCiphertext.size()); randombytes_buf(odesc.outCiphertext.begin(), odesc.outCiphertext.size()); randombytes_buf(odesc.zkproof.begin(), odesc.zkproof.size()); tx.vShieldedOutput.push_back(odesc); } } if (tx.nVersion >= 2) { for (int js = 0; js < joinsplits; js++) { JSDescription jsdesc; if (insecure_rand() % 2 == 0) { jsdesc.vpub_old = insecure_rand() % 100000000; } else { jsdesc.vpub_new = insecure_rand() % 100000000; } jsdesc.anchor = GetRandHash(); jsdesc.nullifiers[0] = GetRandHash(); jsdesc.nullifiers[1] = GetRandHash(); jsdesc.ephemeralKey = GetRandHash(); jsdesc.randomSeed = GetRandHash(); randombytes_buf(jsdesc.ciphertexts[0].begin(), jsdesc.ciphertexts[0].size()); randombytes_buf(jsdesc.ciphertexts[1].begin(), jsdesc.ciphertexts[1].size()); if (tx.fOverwintered && tx.nVersion >= SAPLING_TX_VERSION) { libzcash::GrothProof zkproof; randombytes_buf(zkproof.begin(), zkproof.size()); jsdesc.proof = zkproof; } else { jsdesc.proof = libzcash::PHGRProof::random_invalid(); } jsdesc.macs[0] = GetRandHash(); jsdesc.macs[1] = GetRandHash(); tx.vjoinsplit.push_back(jsdesc); } unsigned char joinSplitPrivKey[crypto_sign_SECRETKEYBYTES]; crypto_sign_keypair(tx.joinSplitPubKey.begin(), joinSplitPrivKey); // Empty output script. CScript scriptCode; CTransaction signTx(tx); uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId); assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL, dataToBeSigned.begin(), 32, joinSplitPrivKey ) == 0); } }
int32_t mail_responder(uint32_t socket) { #ifdef DEBUG printf("Entering MAIL subroutine\n"); #endif /*DEBUG*/ //Allocate general variables //Allocate primary buffers and counters char source_account_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t source_account_length = 0; char source_domain_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t source_domain_length = 0; char dest_account_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t dest_account_length = 0; char dest_domain_buffer[ROUTING_FIELD_SIZE] = {0}; int32_t dest_domain_length = 0; uint32_t version = 0; uint32_t attachment_count = 0; uint64_t message_length = 0; uint64_t log_length = 0; //Generate unique file from current time and current FD //Get time with nanosecond resolution (or so they say) struct timespec time_for_file; clock_gettime(CLOCK_REALTIME, &time_for_file); //Mix time with FD and hash //We are hashing two ints and a long, so char meat_and_potatoes[24] = {0}; //memset(meat_and_potatoes, 0, sizeof(meat_and_potatoes)); memcpy(meat_and_potatoes, &time_for_file.tv_sec, sizeof(time_for_file.tv_sec)); memcpy(meat_and_potatoes+sizeof(time_for_file.tv_sec), &socket, sizeof(socket)); memcpy(meat_and_potatoes+sizeof(time_for_file.tv_sec)+sizeof(socket), &time_for_file.tv_nsec, sizeof(time_for_file.tv_nsec)); unsigned char hash[64]; //64 bytes because hash has a fixed size output crypto_generichash(hash, sizeof(hash), (const unsigned char *)meat_and_potatoes, sizeof(meat_and_potatoes),NULL, 0); //Get file ready to write //TODO needs to be /mail/user/unique_file_name char unique_file_name[129] = {0}; //char base64_username[341] = {0}; char unique_file_location[522] = {0}; //TODO Need to check if user is part of this domain. If not the file location should be some temporary storage. //unique_file_name_length is not currently used. Should be fine. uint32_t unique_file_name_length = base64_encode((char *)hash, sizeof(hash), unique_file_name, sizeof(unique_file_name), (char *)filesystem_safe_base64_string, 64); if (unique_file_name_length<=0) { perror("base64_encode. unique_file_name failed to be created"); print_to_log("base64_encode failed to create a unique_file_name.", LOG_ERR); return -1; } //uint32_t base64_username_length = base64_encode((char *)dest_account_buffer, strlen(dest_account_buffer), base64_username, strlen(base64_username), (char *)filesystem_safe_base64_string, 64); //Read primary routing and processing information //First read in fixed length fields if (read_n_bytes(socket, (unsigned char *)&version, 4)!=4) { perror("read_n_bytes version"); print_to_log("Read error while reading crypto type", LOG_ERR); return -1; } if (read_n_bytes(socket, (unsigned char *)&attachment_count, 4)!=4) { perror("read_n_bytes attachment_count"); print_to_log("Read error while reading attachment count", LOG_ERR); return -1; } if (read_n_bytes(socket, (unsigned char *)&log_length, 8)!=8) { perror("read_n_bytes log_length"); print_to_log("Read error while reading message length", LOG_ERR); return -1; } if (read_n_bytes(socket, (unsigned char *)&message_length, 8)!=8) { perror("read_n_bytes message_length"); print_to_log("Read error while reading message length", LOG_ERR); return -1; } //Read in account and domain info if ((dest_account_length=read_until(socket, (unsigned char *)dest_account_buffer, sizeof(dest_account_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading dest_account_buffer", LOG_ERR); return -1; } if (snprintf(unique_file_location, sizeof(unique_file_location), "%s%s%s%s", "/mail/", dest_account_buffer, "/" , unique_file_name)<0) { perror("snprintf"); print_to_log("snprintf failed to create a new file string. Cannot write message out",LOG_ERR); return -1; } write_to_file((char *)&version, 4, unique_file_location); version = be32toh(version); write_to_file((char *)&attachment_count, 4, unique_file_location); attachment_count = be32toh(attachment_count); write_to_file((char *)&log_length, 8, unique_file_location); log_length = be64toh(log_length); write_to_file((char *)&message_length, 8, unique_file_location); message_length = be64toh(message_length); #ifdef DEBUG printf("Writing mail to %s\n", unique_file_location); printf("Log length = %ld\n", log_length); printf("Version = %d\n", version); printf("Attachment count = %d\n", attachment_count); printf("Message length = %ld\n", message_length); #endif /*DEBUG*/ write_to_file(dest_account_buffer, dest_account_length, unique_file_location); #ifdef DEBUG printf("dest_account_length = %d\n", dest_account_length); #endif /*DEBUG*/ if ((dest_domain_length=read_until(socket, (unsigned char *)dest_domain_buffer, sizeof(dest_domain_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading dest_domain_buffer", LOG_ERR); return -1; } write_to_file(dest_domain_buffer, dest_domain_length, unique_file_location); #ifdef DEBUG printf("dest_domain_length = %d\n", dest_domain_length); #endif /*DEBUG*/ //Check if this is the destination if((strcmp(dest_domain_buffer, home_domain)!=0)&&(forward==0)) { //Send delivery failure, close connection, clean up and return. unsigned char signature_of_DELIVERYFAILURE[crypto_sign_BYTES] = {0}; unsigned char write_buffer[sizeof(network_crypto_version)+sizeof(server_public_key)+sizeof(signature_of_DELIVERYFAILURE)+2]; crypto_sign_detached(signature_of_DELIVERYFAILURE, NULL, signature_of_DELIVERYFAILURE, sizeof(signature_of_DELIVERYFAILURE), server_private_key); memcpy(write_buffer, &network_crypto_version, sizeof(network_crypto_version)); memcpy(write_buffer+sizeof(network_crypto_version), cmtp_reply_DELIVERYFAILURE, sizeof(cmtp_reply_DELIVERYFAILURE)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_DELIVERYFAILURE), &signature_of_DELIVERYFAILURE, sizeof(signature_of_DELIVERYFAILURE)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_DELIVERYFAILURE)+sizeof(signature_of_DELIVERYFAILURE), &termination_char, sizeof(termination_char)); write(socket, write_buffer, sizeof(write_buffer)); } if ((source_account_length=read_until(socket, (unsigned char *)source_account_buffer, sizeof(source_account_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading source_account_buffer", LOG_ERR); return -1; } write_to_file(source_account_buffer, source_account_length, unique_file_location); #ifdef DEBUG printf("source_account_length = %d\n", source_account_length); #endif /*DEBUG*/ if ((source_domain_length=read_until(socket, (unsigned char *)source_domain_buffer, sizeof(source_domain_buffer), '\0'))<0) { perror("read_until"); print_to_log("Read error while reading source_domain_buffer", LOG_ERR); return -1; } write_to_file(source_domain_buffer, source_domain_length, unique_file_location); #ifdef DEBUG printf("source_domain_length = %d\n", source_domain_length); #endif /*DEBUG*/ //This completes the read of the header //uint64_t numeric_message_length = be64toh(*(uint64_t*)(&(message_length[0]))); //uint64_t numeric_log_length = be64toh(*(uint64_t*)(&(log_length[0]))); char temp_byte[1] = {0}; //Read log for (uint64_t i = 0; i<log_length; i++) { if (read(socket, temp_byte, 1)<1) { print_to_log("read error while reading message body", LOG_ERR); perror("read"); return -1; } write_to_file(temp_byte, 1, unique_file_location); } //Read message body for (uint64_t i = 0; i<message_length; i++) { if (read(socket, temp_byte, 1)<1) { print_to_log("read error while reading message body", LOG_ERR); perror("read"); return -1; } write_to_file(temp_byte, 1, unique_file_location); } #ifdef DEBUG printf("Message body finished. Moving to attachment handling.\n"); #endif /*DEBUG*/ //Read for attachment //uint32_t numeric_attachment_count = be32toh(*(uint32_t*)(&(attachment_count[0]))); temp_byte[0] = 0; for (uint64_t i = 0; i<attachment_count; i++) { if (read(socket, temp_byte, 1)<1) { print_to_log("read error while reading message body", LOG_ERR); perror("read"); return -1; } write_to_file(temp_byte, 1, unique_file_location); } #ifdef DEBUG printf("Mail destin for %s\n", dest_domain_buffer); printf("Server domain is %s\n", home_domain); #endif /*DEBUG*/ //Destination cases if ((memcmp(dest_domain_buffer, home_domain, dest_domain_length)==0)&&(memcmp(dest_account_buffer,"",1))==0) { #ifdef DEBUG printf("Devlivered mail is for server. Begin processing.\n"); #endif /*DEBUG*/ print_to_log("Mail has arrived for the server. Processing.",LOG_INFO); //Destination is this domain and for the server } else if ((memcmp(dest_domain_buffer, home_domain, dest_domain_length)==0)) { #ifdef DEBUG printf("Devlivered mail is for a user on this domain. Store.\n"); #endif /*DEBUG*/ print_to_log("Mail has arrived for a user on this domain. Storing.",LOG_INFO); //Destination is for a user at this domain } else { #ifdef DEBUG printf("Devlivered mail is not destined for this domain. Forward to %s\n", dest_domain_buffer); #endif /*DEBUG*/ print_to_log("Mail has arrived for another domain. Forwarding.",LOG_INFO); forwardMessage(unique_file_location, dest_domain_buffer); //Destination is on the web. Forward message. } #ifdef DEBUG printf("Mail section complete. Returning to mail loop.\n"); #endif /*DEBUG*/ return 0; }
int32_t login_responder(uint32_t socket) { #ifdef DEBUG printf("Begin login_responder\n"); #endif /**/ char login_username_buffer[ROUTING_FIELD_SIZE] = {0}; //char login_command_buffer[THREAD_COMMAND_BUFFER_SIZE] = {0}; char xzibit_path_buffer[359] = {0}; //uint32_t i = 0; read_until(socket, (unsigned char *)login_username_buffer, sizeof(login_username_buffer), termination_char); // #ifdef DEBUG // printf("login_username_buffer looks like:\n"); // for (int j = 0; j<i;j++) // { // printf("%x : %c\n", login_username_buffer[j]); // } // #endif /*DEBUG*/ if (snprintf(xzibit_path_buffer, sizeof(xzibit_path_buffer), "%s%s%s%s%s", "/mail/", login_username_buffer, "/", login_username_buffer , ".xzibit")<0) { perror("snprintf"); print_to_log("snprintf error. Cannot check for user public key", LOG_ERR); } #ifdef DEBUG printf("Checking for user xzibit at %s\n", xzibit_path_buffer); #endif /*DEBUG*/ if (access(xzibit_path_buffer,R_OK)<0) { perror("access to user xzibit"); print_to_log("Cannot access user xzibit. User not valid", LOG_ERR); return -1; } else { //Read Xzibit to buffer int xzibit_fd = open(xzibit_path_buffer, O_RDONLY); struct stat xzibit_stats; fstat(xzibit_fd, &xzibit_stats); uint64_t xzibit_size = xzibit_stats.st_size; unsigned char * xzibit = calloc(1, xzibit_size); if(read(xzibit_fd, xzibit, xzibit_size)<0) { perror("Reading user xzibit has gone wrong!"); print_to_log("Reading user xzibit has gone wrong. Abort!", LOG_ERR); free(xzibit); return -1; } #ifdef DEBUG printf("Xzibit size = %ld\n", xzibit_size); #endif /*DEBUG*/ //Sign xzibit unsigned char * server_sign_of_xzibit = calloc(1, 64); if (crypto_sign_detached(server_sign_of_xzibit, NULL, xzibit, xzibit_size, server_private_key)!=0) { perror("crypto_sign_detached failed in login responder"); print_to_log("crypto_sign_detached failed in login responder", LOG_ERR); free(xzibit); free(server_sign_of_xzibit); return -1; } //Write it to the wire #ifdef DEBUG printf("Writing xzibit to the wire\n"); #endif /*DEBUG*/ if (write(socket, xzibit, xzibit_size)<0) { perror("Writing xzibit to the wire has failed"); print_to_log("Writing xzibit to the wire has failed", LOG_ERR); free(xzibit); free(server_sign_of_xzibit); return -1; } free(xzibit); #ifdef DEBUG printf("After writing xzibit\n"); #endif /*DEBUG*/ if (write(socket, server_sign_of_xzibit, 64)<0) { perror("Writing server_sign_of_xzibit to the wire has failed"); print_to_log("Writing server_sign_of_xzibit to the wire has failed", LOG_ERR); free(server_sign_of_xzibit); return -1; } free(server_sign_of_xzibit); #ifdef DEBUG printf("After writing signature\n"); #endif /*DEBUG*/ } return 0; }
int32_t keyrequest_responder(uint32_t socket) { //Read until null uint32_t i = 0; char base64_username[341] = {0}; char pub_key_path[358] = {0}; char user_keyrequest_buffer[ROUTING_FIELD_SIZE] = {0}; char domain_keyrequest_buffer[ROUTING_FIELD_SIZE] = {0}; unsigned char user_public_key[crypto_sign_ed25519_PUBLICKEYBYTES] = {0}; unsigned char signature_of_public_key[crypto_sign_BYTES] = {0}; unsigned char signature_of_KEYNOTAVAILABLE[crypto_sign_BYTES] = {0}; unsigned char write_buffer[sizeof(network_crypto_version)+sizeof(server_public_key)+sizeof(signature_of_public_key)+2]; //Read in username do { read(socket, user_keyrequest_buffer+i, 1); if (user_keyrequest_buffer[i]==-1) { #ifdef DEBUG printf("Negative return value in main read loop. Killing everything!\n"); return 0; #endif /*DEBUG*/ } i++; } while((i<sizeof(user_keyrequest_buffer))&&(user_keyrequest_buffer[i-1]!='\0')); if (memcmp(user_keyrequest_buffer, &termination_char, 1)==0) { crypto_sign_detached(signature_of_public_key, NULL, server_public_key, sizeof(server_public_key), server_private_key); //Wants server key. Reply and return. //Create single buffer memcpy(write_buffer, &network_crypto_version, sizeof(network_crypto_version)); memcpy(write_buffer+sizeof(network_crypto_version), server_public_key, sizeof(server_public_key)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(server_public_key), &termination_char, sizeof(termination_char)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(server_public_key)+sizeof(termination_char), signature_of_public_key, sizeof(signature_of_public_key)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(server_public_key)+sizeof(termination_char)+sizeof(signature_of_public_key), &termination_char, sizeof(termination_char)); write(socket, write_buffer, sizeof(write_buffer)); // write(socket, server_public_key, sizeof(server_public_key)); // write(socket, &termination_char, sizeof(termination_char)); // write(socket, signature_of_public_key, sizeof(signature_of_public_key)); // write(socket, &termination_char, sizeof(termination_char)); return 0; //Need to end here. Might need to functionize this code. } else { //uint32_t base64_username_length = base64_encode((char *)user_keyrequest_buffer, strlen(user_keyrequest_buffer), base64_username, strlen(base64_username), (char *)filesystem_safe_base64_string, 64); #ifdef DEBUG printf("Requested user = %s\n", user_keyrequest_buffer); #endif /*DEBUG*/ do { read(socket, domain_keyrequest_buffer+i, 1); i++; } while((i<sizeof(domain_keyrequest_buffer))&&(domain_keyrequest_buffer[i-1]!='\0')); if (memcmp(&domain_keyrequest_buffer, &home_domain, ROUTING_FIELD_SIZE)!=0) { //Keyrequest is for a different domain. Query that domain and relay key. } if (snprintf(pub_key_path, sizeof(pub_key_path), "%s%s%s", "/mail/", user_keyrequest_buffer, "/public.key")<0) { perror("snprintf"); print_to_log("snprintf error. Cannot check for user public key", LOG_ERR); } //Check for user's key in /mail/base64_username/public.key if (access(pub_key_path, R_OK)<0) { //User does not exist. Send error. perror("user access"); #ifdef DEBUG printf("Key not found at %s\n", pub_key_path); #endif /*DEBUG*/ print_to_log("Cannot access user public key. User does not exist.", LOG_ERR); //cmtp_reply_KEYNOTAVAILABLE includes the trailing null! crypto_sign_detached(signature_of_KEYNOTAVAILABLE, NULL, (const unsigned char *)cmtp_reply_KEYNOTAVAILABLE, sizeof(cmtp_reply_KEYNOTAVAILABLE), server_private_key); memcpy(write_buffer, &network_crypto_version, sizeof(network_crypto_version)); memcpy(write_buffer+sizeof(cmtp_reply_KEYNOTAVAILABLE), cmtp_reply_KEYNOTAVAILABLE, sizeof(cmtp_reply_KEYNOTAVAILABLE)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_KEYNOTAVAILABLE), &signature_of_KEYNOTAVAILABLE, sizeof(signature_of_KEYNOTAVAILABLE)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_KEYNOTAVAILABLE)+sizeof(signature_of_KEYNOTAVAILABLE), signature_of_public_key, sizeof(signature_of_public_key)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(cmtp_reply_KEYNOTAVAILABLE)+sizeof(signature_of_KEYNOTAVAILABLE)+sizeof(signature_of_public_key), &termination_char, sizeof(termination_char)); #ifdef DEBUG //print_buffer (cmtp_reply_KEYNOTAVAILABLE, 32, "Key not available message: ", 32, 1); //print_buffer (signature_of_public_key, 64, "Key not available signature: ", 64, 1); #endif /*DEBUG*/ write(socket, write_buffer, sizeof(write_buffer)); // write(socket, &network_crypto_version, sizeof(network_crypto_version)); // write(socket, cmtp_reply_KEYNOTAVAILABLE, sizeof(cmtp_reply_KEYNOTAVAILABLE)); // write(socket, signature_of_KEYNOTAVAILABLE, sizeof(signature_of_KEYNOTAVAILABLE)); // write(socket, &termination_char, sizeof(termination_char)); } else //Read public key and reply to request with it. { int32_t user_key_descriptor = open(pub_key_path, O_RDONLY); if (user_key_descriptor<0) { perror("open"); print_to_log("Cannot open user public key", LOG_ERR); } if (read(user_key_descriptor, user_public_key, sizeof(user_public_key))<0) { perror("read"); print_to_log("Error reading user public key", LOG_ERR); } //Sign key and store signature in signature_of_public_key crypto_sign_detached(signature_of_public_key, NULL, user_public_key, sizeof(user_public_key), server_private_key); //Send it all memcpy(write_buffer, &network_crypto_version, sizeof(network_crypto_version)); memcpy(write_buffer+sizeof(network_crypto_version), user_public_key, sizeof(user_public_key)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(user_public_key), &termination_char, sizeof(termination_char)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(user_public_key)+sizeof(termination_char), signature_of_public_key, sizeof(signature_of_public_key)); memcpy(write_buffer+sizeof(network_crypto_version)+sizeof(user_public_key)+sizeof(termination_char)+sizeof(signature_of_public_key), &termination_char, sizeof(termination_char)); #ifdef DEBUG //print_buffer (user_public_key, 32, "User public key: ", 32, 1); //print_buffer (signature_of_public_key, 64, "User public key signature: ", 64, 1); #endif /*DEBUG*/ write(socket, write_buffer, sizeof(write_buffer)); // write(socket, &network_crypto_version, sizeof(network_crypto_version)); // write(socket, user_public_key, sizeof(user_public_key)); // write(socket, &termination_char, sizeof(termination_char)); // write(socket, signature_of_public_key, sizeof(signature_of_public_key)); // write(socket, &termination_char, sizeof(termination_char)); printf("Sent %ld bytes\n", sizeof(network_crypto_version)+sizeof(user_public_key)+sizeof(termination_char)+sizeof(signature_of_public_key)+sizeof(termination_char)); } } //Clean buffers memset(user_keyrequest_buffer, 0, sizeof(user_keyrequest_buffer)); memset(base64_username, 0, sizeof(base64_username)); return 0; }
int proc_sign(const ts::wstrings_c & pars) { if (pars.size() < 3) return 0; ts::wstr_c arch = pars.get(1); ts::fix_path( arch, FNO_SIMPLIFY ); ts::wstr_c proc = pars.get(2); ts::fix_path( proc, FNO_SIMPLIFY ); if (!is_file_exists(arch.as_sptr())) { Print(FOREGROUND_RED, "arch file not found: %s\n", to_str(arch).cstr()); return 0; } if (!is_file_exists(proc.as_sptr())) { Print(FOREGROUND_RED, "proc file not found: %s\n", to_str(proc).cstr()); return 0; } ts::buf_c b; b.load_from_disk_file(arch); int archlen = b.size(); ts::md5_c md5; md5.update(b.data(), b.size()); md5.done(); ts::abp_c bp; b.load_from_disk_file(proc); bp.load(b.cstr()); ts::wstr_c procpath = ts::fn_get_path(proc); auto pa = [&]( ts::asptr p ) ->ts::wstr_c { return ts::fn_join(procpath, to_wstr(bp.get_string(p))); }; b.load_from_disk_file( pa(CONSTASTR("ver")) ); ts::str_c ver = b.cstr(); ver.replace_all('/','.').trim(); ts::str_c ss(CONSTASTR("ver=")); ss.append( ver ); ss.append(CONSTASTR("\r\nurl=")); ts::str_c path = bp.get_string(CONSTASTR("path")); path.replace_all(CONSTASTR("%ver%"), ver); path.replace_all(CONSTASTR("%https%"), CONSTASTR("https://")); path.replace_all(CONSTASTR("%http%"), CONSTASTR("http://")); path.appendcvt(ts::fn_get_name_with_ext(arch)); ss.append(path); ss.append(CONSTASTR("\r\nsize=")); ss.append_as_uint(archlen); ss.append(CONSTASTR("\r\nmd5=")); ss.append_as_hex(md5.result(), 16); unsigned char pk[crypto_sign_PUBLICKEYBYTES]; unsigned char sk[crypto_sign_SECRETKEYBYTES]; b.clear(); b.load_from_disk_file( pa(CONSTASTR("sk")) ); if (b.size() != crypto_sign_SECRETKEYBYTES) { rebuild: crypto_sign_keypair(pk, sk); FILE *f = _wfopen(pa(CONSTASTR("sk")), L"wb"); fwrite(sk, 1, sizeof(sk), f); fclose(f); ts::str_c spk; for(int i=0;i<crypto_sign_PUBLICKEYBYTES;++i) spk.append(CONSTASTR("0x")).append_as_hex(pk[i]).append(CONSTASTR(", ")); spk.trunc_length(2); f = _wfopen(pa(CONSTASTR("pk")), L"wb"); fwrite(spk.cstr(), 1, spk.get_length(), f); fclose(f); } else { memcpy(sk, b.data(), crypto_sign_SECRETKEYBYTES); crypto_sign_ed25519_sk_to_pk(pk, sk); b.load_from_disk_file( pa(CONSTASTR("pk")) ); ts::token<char> t(b.cstr(), ','); int n = 0; for(;t; ++t, ++n) { if (n >= sizeof(pk)) goto rebuild; ts::str_c nx(*t); nx.trim(); if (pk[n] != (byte)nx.as_uint()) goto rebuild; } if (n < sizeof(pk)) goto rebuild; } unsigned char sig[crypto_sign_BYTES]; unsigned long long siglen; crypto_sign_detached(sig,&siglen, (const byte *)ss.cstr(), ss.get_length(), sk); ss.append(CONSTASTR("\r\nsign=")); ss.append_as_hex(sig, (int)siglen); if (CONSTASTR("github") == bp.get_string(CONSTASTR("wiki"))) { ss.insert(0,CONSTASTR("[begin]\r\n")); ss.replace_all(CONSTASTR("\r\n"), CONSTASTR("`<br>\r\n`")); ss.replace_all(CONSTASTR("[begin]`"), CONSTASTR("[begin]")); ss.append(CONSTASTR("`<br>\r\n[end]<br>\r\n")); } FILE *f = _wfopen(pa(CONSTASTR("result")), L"wb"); fwrite(ss.cstr(), 1, ss.get_length(), f); fclose(f); return 0; }