int validate_crypto_write(unsigned char *buffer, UNUSED(uint64_t length)) { unsigned char *block; unsigned char *ciphertextpadded; unsigned char nonce[crypto_box_NONCEBYTES]; unsigned char lengthpacked[40]; unsigned char lengthbox[40] = {0}; uint64_t unpackedlen; uint64_t packetnonce; uint64_t ciphertextlen; uint64_t blocklen; /* unpack nonce and check it's validity */ packetnonce = uint64_unpack(buffer + 8); /* nonce is prefixed with 16-byte string "splonbox-client" */ memcpy(nonce, "splonebox-server", 16); memcpy(nonce + 16, buffer + 8, 8); memcpy(lengthbox + 16, buffer + 16, 24); if (crypto_box_open_afternm(lengthpacked, lengthbox, 40, nonce, cc.clientshortservershort)) { return (-1); } unpackedlen = uint64_unpack(lengthpacked + 32); ciphertextlen = unpackedlen - 24; blocklen = unpackedlen - 40; block = MALLOC_ARRAY(ciphertextlen, unsigned char); ciphertextpadded = CALLOC(ciphertextlen, unsigned char); if (block == NULL || ciphertextpadded == NULL) return (-1); memcpy(ciphertextpadded + 16, buffer + 40, blocklen); uint64_pack(nonce + 16, packetnonce + 2); if (crypto_box_open_afternm(block, ciphertextpadded, ciphertextlen, nonce, cc.clientshortservershort)) { FREE(block); FREE(ciphertextpadded); return (-1); } FREE(block); FREE(ciphertextpadded); return (0); }
/* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, uint8_t *encrypted, uint32_t length, uint8_t *plain) { if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) return -1; uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES]; uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, enc_key) == -1) return -1; /* If decryption is successful the first crypto_box_ZEROBYTES of the message will be zero. * Apparently memcmp should not be used so we do this instead: */ if (crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) return -1; /* Unpad the plain message. */ memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; }
int main(void) { unsigned char k[crypto_box_BEFORENMBYTES]; int i; int ret; if (crypto_box_open(m, c, 163, nonce, alicepk, bobsk) == 0) { for (i = 32; i < 163; ++i) { printf(",0x%02x", (unsigned int)m[i]); if (i % 8 == 7) printf("\n"); } printf("\n"); } ret = crypto_box_open(m, c, 163, nonce, small_order_p, bobsk); assert(ret == -1); memset(m, 0, sizeof m); ret = crypto_box_beforenm(k, alicepk, bobsk); assert(ret == 0); if (crypto_box_open_afternm(m, c, 163, nonce, k) == 0) { for (i = 32; i < 163; ++i) { printf(",0x%02x", (unsigned int)m[i]); if (i % 8 == 7) printf("\n"); } printf("\n"); } return 0; }
static int _handle_client_message (struct curvecpr_server *server, struct curvecpr_session *s, void *priv, const struct curvecpr_packet_client_message *p, const unsigned char *buf, size_t num) { const struct curvecpr_server_cf *cf = &server->cf; unsigned char nonce[24]; unsigned char data[1120]; crypto_uint64 unpacked_nonce = curvecpr_bytes_unpack_uint64(p->nonce); if (unpacked_nonce <= s->their_session_nonce) return -EINVAL; curvecpr_bytes_copy(nonce, "CurveCP-client-M", 16); curvecpr_bytes_copy(nonce + 16, p->nonce, 8); curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, buf, num); if (crypto_box_open_afternm(data, data, num + 16, nonce, s->my_session_their_session_key)) return -EINVAL; s->their_session_nonce = unpacked_nonce; curvecpr_session_set_priv(s, priv); if (cf->ops.recv(server, s, data + 32, num - 16)) return -EINVAL; return 0; }
static int proto_decode(sigma_proto *instance, uint8_t* input, uint8_t* output, size_t len) { if (len < crypto_box_ZEROBYTES) { fprintf(stderr, "Short packet received: %u\n", (unsigned) len); errno = EINVAL; return -1; } sigma_proto_nacl* inst = (sigma_proto_nacl*) instance; int i, taioldest = 0; for (i = 0; i < rxtaiacount; i ++) { if (memcmp(input, inst->rxtaialog[i], noncelength) == 0) { fprintf(stderr, "Timestamp reuse detected, possible replay attack (packet length %u)\n", (unsigned) len); errno = EINVAL; return -1; } if (i != 0 && memcmp(inst->rxtaialog[i], inst->rxtaialog[taioldest], noncelength) < 0) taioldest = i; } if (memcmp(input, inst->rxtaialog[taioldest], noncelength) < 0) { fprintf(stderr, "Timestamp older than our oldest known timestamp, possible replay attack (packet length %u)\n", (unsigned) len); errno = EINVAL; return -1; } uint8_t tempbufferout[len]; memcpy(inst->decnonce + nonceoffset, input, noncelength); bzero(input, crypto_box_BOXZEROBYTES); int result = crypto_box_open_afternm( tempbufferout, input, len, inst->decnonce, inst->precomp ); if (result) { fprintf(stderr, "Decryption failed (length %u, given result %i)\n", (unsigned) len, result); errno = EINVAL; return -1; } len -= crypto_box_ZEROBYTES; memcpy(output, tempbufferout + crypto_box_ZEROBYTES, len); memcpy(inst->rxtaialog[taioldest], inst->decnonce + nonceoffset, noncelength); return len; }
int zmq::curve_client_t::decode (msg_t *msg_) { zmq_assert (state == connected); if (msg_->size () < 33) { errno = EPROTO; return -1; } const uint8_t *message = static_cast <uint8_t *> (msg_->data ()); if (memcmp (message, "\x07MESSAGE", 8)) { errno = EPROTO; return -1; } uint8_t message_nonce [crypto_box_NONCEBYTES]; memcpy (message_nonce, "CurveZMQMESSAGES", 16); memcpy (message_nonce + 16, message + 8, 8); const size_t clen = crypto_box_BOXZEROBYTES + (msg_->size () - 16); uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (clen)); alloc_assert (message_plaintext); uint8_t *message_box = static_cast <uint8_t *> (malloc (clen)); alloc_assert (message_box); memset (message_box, 0, crypto_box_BOXZEROBYTES); memcpy (message_box + crypto_box_BOXZEROBYTES, message + 16, msg_->size () - 16); int rc = crypto_box_open_afternm (message_plaintext, message_box, clen, message_nonce, cn_precom); if (rc == 0) { rc = msg_->close (); zmq_assert (rc == 0); rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); zmq_assert (rc == 0); const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; if (flags & 0x01) msg_->set_flags (msg_t::more); memcpy (msg_->data (), message_plaintext + crypto_box_ZEROBYTES + 1, msg_->size ()); } else errno = EPROTO; free (message_plaintext); free (message_box); return rc; }
int zmq::curve_client_t::process_ready (const uint8_t *msg_data, size_t msg_size) { if (msg_size < 30) { session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_MALFORMED_COMMAND_READY); errno = EPROTO; return -1; } const size_t clen = (msg_size - 14) + crypto_box_BOXZEROBYTES; uint8_t ready_nonce[crypto_box_NONCEBYTES]; uint8_t *ready_plaintext = static_cast<uint8_t *> (malloc (crypto_box_ZEROBYTES + clen)); alloc_assert (ready_plaintext); uint8_t *ready_box = static_cast<uint8_t *> (malloc (crypto_box_BOXZEROBYTES + 16 + clen)); alloc_assert (ready_box); memset (ready_box, 0, crypto_box_BOXZEROBYTES); memcpy (ready_box + crypto_box_BOXZEROBYTES, msg_data + 14, clen - crypto_box_BOXZEROBYTES); memcpy (ready_nonce, "CurveZMQREADY---", 16); memcpy (ready_nonce + 16, msg_data + 6, 8); cn_peer_nonce = get_uint64 (msg_data + 6); int rc = crypto_box_open_afternm (ready_plaintext, ready_box, clen, ready_nonce, cn_precom); free (ready_box); if (rc != 0) { session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_CRYPTOGRAPHIC); errno = EPROTO; return -1; } rc = parse_metadata (ready_plaintext + crypto_box_ZEROBYTES, clen - crypto_box_ZEROBYTES); free (ready_plaintext); if (rc == 0) state = connected; else { session->get_socket ()->event_handshake_failed_protocol ( session->get_endpoint (), ZMQ_PROTOCOL_ERROR_ZMTP_INVALID_METADATA); errno = EPROTO; } return rc; }
static nif_term_t salt_box_open_afternm(nif_heap_t *hp, int argc, const nif_term_t argv[]) { /* salt_box_open_afternm(Cipher_text, Nonce, Context) -> {ok, Plain_text} | forged_or_garbled. */ nif_bin_t ct; nif_bin_t nc; nif_bin_t bn; nif_bin_t pt; nif_term_t raw; nif_term_t sub; nif_term_t tag; if (argc != 3) return (BADARG); /* Unpack arguments ensuring they're suitably typed. */ if (! enif_inspect_iolist_as_binary(hp, argv[0], &ct)) return (BADARG); if (! enif_inspect_binary(hp, argv[1], &nc)) return (BADARG); if (! enif_inspect_binary(hp, argv[2], &bn)) return (BADARG); /* Check constraints on size and zero prefixing. */ if (ct.size < crypto_box_BOXZEROBYTES || ct.size > SALT_MAX_MESSAGE_SIZE) return (BADARG); if (memcmp((const void *)ct.data, &salt_box_boxzerobytes[0], crypto_box_BOXZEROBYTES) != 0) return (BADARG); if (nc.size != crypto_box_NONCEBYTES) return (BADARG); if (bn.size != crypto_box_BEFORENMBYTES) return (BADARG); /* Allocate space for plain text. NB: Passing ENOMEM as BADARG. */ if (! enif_alloc_binary(ct.size, &pt)) return (BADARG); /* Perform the crypto, strip leading zeros and return rest if authentic. */ if (crypto_box_open_afternm(pt.data, ct.data, ct.size, nc.data, bn.data) != 0) { enif_release_binary(&pt); return (enif_make_atom(hp, "forged_or_garbled")); } raw = enif_make_binary(hp, &pt); sub = enif_make_sub_binary(hp, raw, crypto_box_ZEROBYTES, pt.size - crypto_box_ZEROBYTES); tag = enif_make_atom(hp, "ok"); return (enif_make_tuple2(hp, tag, sub)); }
int crypto_box_open( unsigned char *m, const unsigned char *c,unsigned long long clen, const unsigned char *n, const unsigned char *pk, const unsigned char *sk ) { unsigned char k[crypto_box_BEFORENMBYTES]; crypto_box_beforenm(k,pk,sk); return crypto_box_open_afternm(m,c,clen,n,k); }
ssize_t curve25519_decode(struct curve25519_struct *c, struct curve25519_proto *p, unsigned char *chipertext, size_t size, unsigned char **plaintext, struct taia *arrival_taia) { int ret; ssize_t done = size; struct taia packet_taia, __arrival_taia; spinlock_lock(&c->dec_lock); if (unlikely(size > c->dec_buf_size)) { spinlock_unlock(&c->dec_lock); return -ENOMEM; } if (unlikely(size < crypto_box_boxzerobytes + NONCE_LENGTH)) { spinlock_unlock(&c->dec_lock); return 0; } if (arrival_taia == NULL) { taia_now(&__arrival_taia); arrival_taia = &__arrival_taia; } taia_unpack(chipertext + crypto_box_boxzerobytes - NONCE_LENGTH, &packet_taia); if (is_good_taia(arrival_taia, &packet_taia) == 0) { /* Ignoring packet */ spinlock_unlock(&c->dec_lock); syslog(LOG_ERR, "Bad packet time! Dropping connection!\n"); return 0; } memcpy(p->dnonce + NONCE_OFFSET, chipertext + crypto_box_boxzerobytes - NONCE_LENGTH, NONCE_LENGTH); memset(c->dec_buf, 0, c->dec_buf_size); ret = crypto_box_open_afternm(c->dec_buf, chipertext, size, p->dnonce, p->key); if (unlikely(ret)) { spinlock_unlock(&c->dec_lock); return -EIO; } (*plaintext) = c->dec_buf; spinlock_unlock(&c->dec_lock); return done; }
// decrypted_bytes = crypto_secretbox_open(enc_bytes, nonce, shared_secret); static int tweetnacl_crypto_secretbox_open( lua_State* L ) { unsigned int emsg_len; const char* emsg = luaL_checklstring(L,1,&emsg_len); if(emsg_len < crypto_box_BOXZEROBYTES) return luaL_error( L, "len(emessage)=%d, too short", emsg_len); unsigned int nonce_len; const char* nonce = luaL_checklstring(L,2,&nonce_len); if(nonce_len != crypto_box_NONCEBYTES) return luaL_error( L, "len(nonce)=%d, should be %d", nonce_len, crypto_box_NONCEBYTES); unsigned int secret_len; const char* secret = luaL_checklstring(L,3,&secret_len); if(secret_len != crypto_box_BEFORENMBYTES) return luaL_error( L, "len(secret)=%d, should be %d", secret_len, crypto_box_BEFORENMBYTES); unsigned int pmsg_len = emsg_len + crypto_box_BOXZEROBYTES; char *pmsg = (char *)c_malloc(pmsg_len); if(!pmsg) return luaL_error( L, "malloc failed, %d bytes", pmsg_len); int i; for(i=0;i<crypto_box_BOXZEROBYTES;i++) pmsg[i] = 0; for(;i<pmsg_len;i++) pmsg[i] = emsg[i-crypto_box_BOXZEROBYTES]; unsigned int cmsg_len = pmsg_len; char *cmsg = (char *)c_malloc(cmsg_len); if(!cmsg) { c_free(pmsg); return luaL_error( L, "malloc failed, %d bytes", cmsg_len); } int r; r = crypto_box_open_afternm(cmsg, pmsg, pmsg_len, nonce, secret); if(r!=0) { c_free(cmsg); c_free(pmsg); return luaL_error( L, "decryption failed"); } lua_pushlstring(L, cmsg+crypto_box_ZEROBYTES, cmsg_len-crypto_box_ZEROBYTES); c_free(cmsg); c_free(pmsg); return 1; }
QByteArray PublicKeyCrypto::boxOpenAfterNM(const QByteArray &cipherData, const QByteArray &nonce, const QByteArray &key) { if(key.length() != boxBeforeNMBytes) { qDebug()<< "PublicKeyCrypto::boxOpenAfterNM failed due to key length"; return QByteArray(); } if(nonce.length() != boxNonceBytes) { qDebug()<< "PublicKeyCrypto::boxOpenAfterNM failed due to nonce length"; return QByteArray(); } QByteArray ciphertext; ciphertext.resize(boxBoxZeroBytes); ciphertext.insert(boxBoxZeroBytes, cipherData); unsigned char * ctxt = toUnsignedChar(ciphertext.data()); sodium_memzero(ctxt, boxBoxZeroBytes); QByteArray message; message.resize(ciphertext.length()); if(message.length() != ciphertext.length()) { qDebug()<< "PublicKeyCrypto::boxOpenAfterNM failed to allocate message buffer."; return QByteArray(); } int result = crypto_box_open_afternm( toUnsignedChar(message.data()), ctxt, ciphertext.length(), toConstUnsignedChar(nonce.constData()), toConstUnsignedChar(key.constData()) ); if(result == TEARS_SODIUM_SUCCESS) { // Skip zero bytes return message.mid(boxZeroBytes); } else { qDebug()<< "PublicKeyCrypto::boxOpenAfterNM call to crypto_box_open_afternm() failed."; return QByteArray(); } }
int32_t decrypt_data_symmetric(const uint8_t *secret_key, const uint8_t *nonce, const uint8_t *encrypted, size_t length, uint8_t *plain) { if (length <= crypto_box_BOXZEROBYTES || !secret_key || !nonce || !encrypted || !plain) { return -1; } uint8_t temp_plain[length + crypto_box_ZEROBYTES]; uint8_t temp_encrypted[length + crypto_box_BOXZEROBYTES]; memset(temp_encrypted, 0, crypto_box_BOXZEROBYTES); memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); // Pad the message with 16 0 bytes. if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, secret_key) != 0) { return -1; } memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); return length - crypto_box_MACBYTES; }
int zmq::curve_client_t::process_ready (msg_t *msg_) { if (msg_->size () < 30) { errno = EPROTO; return -1; } const uint8_t *ready = static_cast <uint8_t *> (msg_->data ()); if (memcmp (ready, "\x05READY", 6)) { errno = EPROTO; return -1; } const size_t clen = (msg_->size () - 14) + crypto_box_BOXZEROBYTES; uint8_t ready_nonce [crypto_box_NONCEBYTES]; uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256]; uint8_t ready_box [crypto_box_BOXZEROBYTES + 16 + 256]; memset (ready_box, 0, crypto_box_BOXZEROBYTES); memcpy (ready_box + crypto_box_BOXZEROBYTES, ready + 14, clen - crypto_box_BOXZEROBYTES); memcpy (ready_nonce, "CurveZMQREADY---", 16); memcpy (ready_nonce + 16, ready + 6, 8); int rc = crypto_box_open_afternm (ready_plaintext, ready_box, clen, ready_nonce, cn_precom); if (rc != 0) { errno = EPROTO; return -1; } rc = parse_metadata (ready_plaintext + crypto_box_ZEROBYTES, clen - crypto_box_ZEROBYTES); return rc; }
int zmq::curve_client_t::process_ready ( const uint8_t *msg_data, size_t msg_size) { if (msg_size < 30) { errno = EPROTO; return -1; } const size_t clen = (msg_size - 14) + crypto_box_BOXZEROBYTES; uint8_t ready_nonce [crypto_box_NONCEBYTES]; uint8_t ready_plaintext [crypto_box_ZEROBYTES + 256]; uint8_t ready_box [crypto_box_BOXZEROBYTES + 16 + 256]; memset (ready_box, 0, crypto_box_BOXZEROBYTES); memcpy (ready_box + crypto_box_BOXZEROBYTES, msg_data + 14, clen - crypto_box_BOXZEROBYTES); memcpy (ready_nonce, "CurveZMQREADY---", 16); memcpy (ready_nonce + 16, msg_data + 6, 8); cn_peer_nonce = get_uint64(msg_data + 6); int rc = crypto_box_open_afternm (ready_plaintext, ready_box, clen, ready_nonce, cn_precom); if (rc != 0) { errno = EPROTO; return -1; } rc = parse_metadata (ready_plaintext + crypto_box_ZEROBYTES, clen - crypto_box_ZEROBYTES); if (rc == 0) state = connected; return rc; }
int zmq::curve_server_t::decode (msg_t *msg_) { zmq_assert (state == connected); if (msg_->size () < 33) { // Temporary support for security debugging puts ("CURVE I: invalid CURVE client, sent malformed command"); errno = EPROTO; return -1; } const uint8_t *message = static_cast <uint8_t *> (msg_->data ()); if (memcmp (message, "\x07MESSAGE", 8)) { // Temporary support for security debugging puts ("CURVE I: invalid CURVE client, did not send MESSAGE"); errno = EPROTO; return -1; } uint8_t message_nonce [crypto_box_NONCEBYTES]; memcpy (message_nonce, "CurveZMQMESSAGEC", 16); memcpy (message_nonce + 16, message + 8, 8); uint64_t nonce = get_uint64(message + 8); if (nonce <= cn_peer_nonce) { errno = EPROTO; return -1; } cn_peer_nonce = nonce; const size_t clen = crypto_box_BOXZEROBYTES + msg_->size () - 16; uint8_t *message_plaintext = static_cast <uint8_t *> (malloc (clen)); alloc_assert (message_plaintext); uint8_t *message_box = static_cast <uint8_t *> (malloc (clen)); alloc_assert (message_box); memset (message_box, 0, crypto_box_BOXZEROBYTES); memcpy (message_box + crypto_box_BOXZEROBYTES, message + 16, msg_->size () - 16); int rc = crypto_box_open_afternm (message_plaintext, message_box, clen, message_nonce, cn_precom); if (rc == 0) { rc = msg_->close (); zmq_assert (rc == 0); rc = msg_->init_size (clen - 1 - crypto_box_ZEROBYTES); zmq_assert (rc == 0); const uint8_t flags = message_plaintext [crypto_box_ZEROBYTES]; if (flags & 0x01) msg_->set_flags (msg_t::more); if (flags & 0x02) msg_->set_flags (msg_t::command); memcpy (msg_->data (), message_plaintext + crypto_box_ZEROBYTES + 1, msg_->size ()); } else { // Temporary support for security debugging puts ("CURVE I: connection key used for MESSAGE is wrong"); errno = EPROTO; } free (message_plaintext); free (message_box); return rc; }
int main(int argc,char **argv) { long long hellopackets; long long r; long long nextaction; signal(SIGPIPE,SIG_IGN); if (!argv[0]) die_usage(0); for (;;) { char *x; if (!argv[1]) break; if (argv[1][0] != '-') break; x = *++argv; if (x[0] == '-' && x[1] == 0) break; if (x[0] == '-' && x[1] == '-' && x[2] == 0) break; while (*++x) { if (*x == 'q') { flagverbose = 0; continue; } if (*x == 'Q') { flagverbose = 1; continue; } if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; } if (*x == 'c') { if (x[1]) { keydir = x + 1; break; } if (argv[1]) { keydir = *++argv; break; } } die_usage(0); } } if (!nameparse(servername,*++argv)) die_usage("sname must be at most 255 bytes, at most 63 bytes between dots"); if (!hexparse(serverlongtermpk,32,*++argv)) die_usage("pk must be exactly 64 hex characters"); if (!multiipparse(serverip,*++argv)) die_usage("ip must be a comma-separated series of IPv4 addresses"); if (!portparse(serverport,*++argv)) die_usage("port must be an integer between 0 and 65535"); if (!hexparse(serverextension,16,*++argv)) die_usage("ext must be exactly 32 hex characters"); if (!*++argv) die_usage("missing prog"); for (;;) { r = open_read("/dev/null"); if (r == -1) die_fatal("unable to open /dev/null",0,0); if (r > 9) { close(r); break; } } if (keydir) { fdwd = open_cwd(); if (fdwd == -1) die_fatal("unable to open current working directory",0,0); if (chdir(keydir) == -1) die_fatal("unable to change to directory",keydir,0); if (load("publickey",clientlongtermpk,sizeof clientlongtermpk) == -1) die_fatal("unable to read public key from",keydir,0); if (load(".expertsonly/secretkey",clientlongtermsk,sizeof clientlongtermsk) == -1) die_fatal("unable to read secret key from",keydir,0); } else { crypto_box_keypair(clientlongtermpk,clientlongtermsk); } crypto_box_keypair(clientshorttermpk,clientshorttermsk); clientshorttermnonce = randommod(281474976710656LL); crypto_box_beforenm(clientshortserverlong,serverlongtermpk,clientshorttermsk); crypto_box_beforenm(clientlongserverlong,serverlongtermpk,clientlongtermsk); udpfd = socket_udp(); if (udpfd == -1) die_fatal("unable to create socket",0,0); for (hellopackets = 0;hellopackets < NUMIP;++hellopackets) { recent = nanoseconds(); /* send a Hello packet: */ clientextension_init(); clientshorttermnonce_update(); byte_copy(nonce,16,"CurveCP-client-H"); uint64_pack(nonce + 16,clientshorttermnonce); byte_copy(packet,8,"QvnQ5XlH"); byte_copy(packet + 8,16,serverextension); byte_copy(packet + 24,16,clientextension); byte_copy(packet + 40,32,clientshorttermpk); byte_copy(packet + 72,64,allzero); byte_copy(packet + 136,8,nonce + 16); crypto_box_afternm(text,allzero,96,nonce,clientshortserverlong); byte_copy(packet + 144,80,text + 16); socket_send(udpfd,packet,224,serverip + 4 * hellopackets,serverport); nextaction = recent + hellowait[hellopackets] + randommod(hellowait[hellopackets]); for (;;) { long long timeout = nextaction - recent; if (timeout <= 0) break; p[0].fd = udpfd; p[0].events = POLLIN; if (poll(p,1,timeout / 1000000 + 1) < 0) p[0].revents = 0; do { /* try receiving a Cookie packet: */ if (!p[0].revents) break; r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport); if (r != 200) break; if (!(byte_isequal(packetip,4,serverip + 4 * hellopackets) & byte_isequal(packetport,2,serverport) & byte_isequal(packet,8,"RL3aNMXK") & byte_isequal(packet + 8,16,clientextension) & byte_isequal(packet + 24,16,serverextension) )) break; byte_copy(nonce,8,"CurveCPK"); byte_copy(nonce + 8,16,packet + 40); byte_zero(text,16); byte_copy(text + 16,144,packet + 56); if (crypto_box_open_afternm(text,text,160,nonce,clientshortserverlong)) break; byte_copy(servershorttermpk,32,text + 32); byte_copy(servercookie,96,text + 64); byte_copy(serverip,4,serverip + 4 * hellopackets); goto receivedcookie; } while (0); recent = nanoseconds(); } } errno = ETIMEDOUT; die_fatal("no response from server",0,0); receivedcookie: crypto_box_beforenm(clientshortservershort,servershorttermpk,clientshorttermsk); byte_copy(nonce,8,"CurveCPV"); if (keydir) { if (safenonce(nonce + 8,0) == -1) die_fatal("nonce-generation disaster",0,0); } else { randombytes(nonce + 8,16); } byte_zero(text,32); byte_copy(text + 32,32,clientshorttermpk); crypto_box_afternm(text,text,64,nonce,clientlongserverlong); byte_copy(vouch,16,nonce + 8); byte_copy(vouch + 16,48,text + 16); /* server is responding, so start child: */ if (open_pipe(tochild) == -1) die_fatal("unable to create pipe",0,0); if (open_pipe(fromchild) == -1) die_fatal("unable to create pipe",0,0); child = fork(); if (child == -1) die_fatal("unable to fork",0,0); if (child == 0) { if (keydir) if (fchdir(fdwd) == -1) die_fatal("unable to chdir to original directory",0,0); close(8); if (dup(tochild[0]) != 8) die_fatal("unable to dup",0,0); close(9); if (dup(fromchild[1]) != 9) die_fatal("unable to dup",0,0); /* XXX: set up environment variables */ signal(SIGPIPE,SIG_DFL); execvp(*argv,argv); die_fatal("unable to run",*argv,0); } close(fromchild[1]); close(tochild[0]); for (;;) { p[0].fd = udpfd; p[0].events = POLLIN; p[1].fd = fromchild[0]; p[1].events = POLLIN; if (poll(p,2,-1) < 0) { p[0].revents = 0; p[1].revents = 0; } do { /* try receiving a Message packet: */ if (!p[0].revents) break; r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport); if (r < 80) break; if (r > 1152) break; if (r & 15) break; packetnonce = uint64_unpack(packet + 40); if (flagreceivedmessage && packetnonce <= receivednonce) break; if (!(byte_isequal(packetip,4,serverip + 4 * hellopackets) & byte_isequal(packetport,2,serverport) & byte_isequal(packet,8,"RL3aNMXM") & byte_isequal(packet + 8,16,clientextension) & byte_isequal(packet + 24,16,serverextension) )) break; byte_copy(nonce,16,"CurveCP-server-M"); byte_copy(nonce + 16,8,packet + 40); byte_zero(text,16); byte_copy(text + 16,r - 48,packet + 48); if (crypto_box_open_afternm(text,text,r - 32,nonce,clientshortservershort)) break; if (!flagreceivedmessage) { flagreceivedmessage = 1; randombytes(clientlongtermpk,sizeof clientlongtermpk); randombytes(vouch,sizeof vouch); randombytes(servername,sizeof servername); randombytes(servercookie,sizeof servercookie); } receivednonce = packetnonce; text[31] = (r - 64) >> 4; /* child is responsible for reading all data immediately, so we won't block: */ if (writeall(tochild[1],text + 31,r - 63) == -1) goto done; } while (0); do { /* try receiving data from child: */ long long i; if (!p[1].revents) break; r = read(fromchild[0],childbuf,sizeof childbuf); if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break; if (r <= 0) goto done; childbuflen = r; for (i = 0;i < childbuflen;++i) { if (childmessagelen < 0) goto done; if (childmessagelen >= sizeof childmessage) goto done; childmessage[childmessagelen++] = childbuf[i]; if (childmessage[0] & 128) goto done; if (childmessagelen == 1 + 16 * (unsigned long long) childmessage[0]) { clientextension_init(); clientshorttermnonce_update(); uint64_pack(nonce + 16,clientshorttermnonce); if (flagreceivedmessage) { r = childmessagelen - 1; if (r < 16) goto done; if (r > 1088) goto done; byte_copy(nonce,16,"CurveCP-client-M"); byte_zero(text,32); byte_copy(text + 32,r,childmessage + 1); crypto_box_afternm(text,text,r + 32,nonce,clientshortservershort); byte_copy(packet,8,"QvnQ5XlM"); byte_copy(packet + 8,16,serverextension); byte_copy(packet + 24,16,clientextension); byte_copy(packet + 40,32,clientshorttermpk); byte_copy(packet + 72,8,nonce + 16); byte_copy(packet + 80,r + 16,text + 16); socket_send(udpfd,packet,r + 96,serverip,serverport); } else { r = childmessagelen - 1; if (r < 16) goto done; if (r > 640) goto done; byte_copy(nonce,16,"CurveCP-client-I"); byte_zero(text,32); byte_copy(text + 32,32,clientlongtermpk); byte_copy(text + 64,64,vouch); byte_copy(text + 128,256,servername); byte_copy(text + 384,r,childmessage + 1); crypto_box_afternm(text,text,r + 384,nonce,clientshortservershort); byte_copy(packet,8,"QvnQ5XlI"); byte_copy(packet + 8,16,serverextension); byte_copy(packet + 24,16,clientextension); byte_copy(packet + 40,32,clientshorttermpk); byte_copy(packet + 72,96,servercookie); byte_copy(packet + 168,8,nonce + 16); byte_copy(packet + 176,r + 368,text + 16); socket_send(udpfd,packet,r + 544,serverip,serverport); } childmessagelen = 0; } } } while (0); } done: do { r = waitpid(child,&childstatus,0); } while (r == -1 && errno == EINTR); if (!WIFEXITED(childstatus)) { errno = 0; die_fatal("process killed by signal",0,0); } return WEXITSTATUS(childstatus); }
static int _handle_hello (struct curvecpr_server *server, void *priv, const struct curvecpr_packet_hello *p) { const struct curvecpr_server_cf *cf = &server->cf; struct curvecpr_session s; /* Used only as a temporary store to make what we're doing more clear. */ unsigned char nonce[24]; unsigned char data[96] = { 0 }; /* Dummy initialization. */ curvecpr_session_new(&s); curvecpr_session_set_priv(&s, priv); /* Verify initial connection parameters. */ curvecpr_bytes_copy(s.their_session_pk, p->client_session_pk, 32); crypto_box_beforenm(s.my_global_their_session_key, s.their_session_pk, cf->my_global_sk); curvecpr_bytes_copy(nonce, "CurveCP-client-H", 16); curvecpr_bytes_copy(nonce + 16, p->nonce, 8); curvecpr_bytes_copy(data + 16, p->box, 80); if (crypto_box_open_afternm(data, data, 96, nonce, s.my_global_their_session_key)) return -EINVAL; /* Set up session keys. */ crypto_box_keypair(s.my_session_pk, s.my_session_sk); /* Prepare to send a cookie packet. */ { struct curvecpr_packet_cookie po; struct curvecpr_packet_cookie_box po_box; curvecpr_bytes_zero(po_box._, 32); curvecpr_bytes_copy(po_box.server_session_pk, s.my_session_pk, 32); /* Generate the cookie. */ curvecpr_bytes_zero(po_box.cookie, 32); curvecpr_bytes_copy(po_box.cookie + 32, s.their_session_pk, 32); curvecpr_bytes_copy(po_box.cookie + 64, s.my_session_sk, 32); /* Encrypt the cookie with our global nonce and temporary key. */ curvecpr_bytes_copy(nonce, "minute-k", 8); if (cf->ops.next_nonce(server, nonce + 8, 16)) return -EINVAL; crypto_secretbox(po_box.cookie, po_box.cookie, 96, nonce, server->my_temporal_key); curvecpr_bytes_copy(po_box.cookie, nonce + 8, 16); /* Now encrypt the whole box. */ curvecpr_bytes_copy(nonce, "CurveCPK", 8); crypto_box_afternm((unsigned char *)&po_box, (const unsigned char *)&po_box, sizeof(struct curvecpr_packet_cookie_box), nonce, s.my_global_their_session_key); /* Build the rest of the packet. */ curvecpr_bytes_copy(po.id, "RL3aNMXK", 8); curvecpr_bytes_copy(po.client_extension, p->client_extension, 16); curvecpr_bytes_copy(po.server_extension, cf->my_extension, 16); curvecpr_bytes_copy(po.nonce, nonce + 8, 16); curvecpr_bytes_copy(po.box, (const unsigned char *)&po_box + 16, 144); if (cf->ops.send(server, &s, (const unsigned char *)&po, sizeof(struct curvecpr_packet_cookie))) return -EINVAL; } return 0; }
static int _handle_initiate (struct curvecpr_server *server, struct curvecpr_session *s, void *priv, const struct curvecpr_packet_initiate *p, const unsigned char *buf, size_t num) { const struct curvecpr_server_cf *cf = &server->cf; unsigned char nonce[24]; unsigned char data[sizeof(struct curvecpr_packet_initiate_box) + 640]; if (s != NULL) { /* Update existing client. */ crypto_uint64 unpacked_nonce = curvecpr_bytes_unpack_uint64(p->nonce); if (unpacked_nonce <= s->their_session_nonce) return -EINVAL; curvecpr_bytes_copy(nonce, "CurveCP-client-I", 16); curvecpr_bytes_copy(nonce + 16, p->nonce, 8); curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, buf, num); if (crypto_box_open_afternm(data, data, num + 16, nonce, s->my_session_their_session_key)) return -EINVAL; s->their_session_nonce = unpacked_nonce; curvecpr_session_set_priv(s, priv); if (cf->ops.recv(server, s, data + sizeof(struct curvecpr_packet_initiate_box), num + 16 - sizeof(struct curvecpr_packet_initiate_box))) return -EINVAL; return 0; } else { struct curvecpr_session s_new, *s_new_stored; const struct curvecpr_packet_initiate_box *p_box; /* Register new client. */ curvecpr_bytes_copy(nonce, "minute-k", 8); curvecpr_bytes_copy(nonce + 8, p->cookie, 16); /* We can reuse data; the cookie will fit into it. */ curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, p->cookie + 16, 80); /* Validate cookie. */ if (crypto_secretbox_open(data, data, 96, nonce, server->my_temporal_key)) { curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, p->cookie + 16, 80); if (crypto_secretbox_open(data, data, 96, nonce, server->my_last_temporal_key)) return -EINVAL; } if (!curvecpr_bytes_equal(p->client_session_pk, data + 32, 32)) return -EINVAL; /* Cookie is valid; set up keys. */ curvecpr_session_new(&s_new); curvecpr_bytes_copy(s_new.their_session_pk, data + 32, 32); curvecpr_bytes_copy(s_new.my_session_sk, data + 64, 32); crypto_box_beforenm(s_new.my_session_their_session_key, s_new.their_session_pk, s_new.my_session_sk); curvecpr_bytes_copy(nonce, "CurveCP-client-I", 16); curvecpr_bytes_copy(nonce + 16, p->nonce, 8); curvecpr_bytes_zero(data, 16); curvecpr_bytes_copy(data + 16, buf, num); if (crypto_box_open_afternm(data, data, num + 16, nonce, s_new.my_session_their_session_key)) return -EINVAL; p_box = (struct curvecpr_packet_initiate_box *)data; /* Attempt to validate this client. */ { unsigned char vouch[64]; curvecpr_bytes_copy(s_new.their_global_pk, p_box->client_global_pk, 32); crypto_box_beforenm(s_new.my_global_their_global_key, s_new.their_global_pk, cf->my_global_sk); curvecpr_bytes_copy(nonce, "CurveCPV", 8); curvecpr_bytes_copy(nonce + 8, p_box->nonce, 16); curvecpr_bytes_zero(vouch, 16); curvecpr_bytes_copy(vouch + 16, p_box->vouch, 48); if (crypto_box_afternm(vouch, vouch, 64, nonce, s_new.my_global_their_global_key)) return -EINVAL; if (!curvecpr_bytes_equal(vouch + 32, s_new.their_session_pk, 32)) return -EINVAL; } /* All good, we can go ahead and submit the client for registration. */ s_new.their_session_nonce = curvecpr_bytes_unpack_uint64(p->nonce); curvecpr_bytes_copy(s_new.my_domain_name, p_box->server_domain_name, 256); curvecpr_session_set_priv(&s_new, priv); if (cf->ops.put_session(server, &s_new, &s_new_stored)) return -EINVAL; /* This can fail for a variety of reasons that are up to the delegate to determine, but two typical ones will be too many connections or an invalid domain name. */ /* Now the session is registered; we can send the encapsulated message. */ if (cf->ops.recv(server, s_new_stored, data + sizeof(struct curvecpr_packet_initiate_box), num + 16 - sizeof(struct curvecpr_packet_initiate_box))) return -EINVAL; return 0; } }