Esempio n. 1
0
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);
}
Esempio n. 2
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;
}
Esempio n. 3
0
File: box2.c Progetto: 52M/libsodium
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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);
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
// 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;
}
Esempio n. 12
0
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();
    }
}
Esempio n. 13
0
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;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
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);
}
Esempio n. 18
0
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;
}
Esempio n. 19
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;
    }
}