Example #1
0
/* Extract the flags from an otherwise unreadable Data Message. */
gcry_error_t otrl_proto_data_read_flags(const char *datamsg,
	unsigned char *flagsp)
{
    char *otrtag, *endtag;
    unsigned char *rawmsg = NULL;
    unsigned char *bufp;
    size_t msglen, rawlen, lenp;
    unsigned char version;

    if (flagsp) *flagsp = 0;
    otrtag = strstr(datamsg, "?OTR:");
    if (!otrtag) {
	goto invval;
    }
    endtag = strchr(otrtag, '.');
    if (endtag) {
	msglen = endtag-otrtag;
    } else {
	msglen = strlen(otrtag);
    }

    /* Skip over the "?OTR:" */
    otrtag += 5;
    msglen -= 5;

    /* Base64-decode the message */
    rawlen = OTRL_B64_MAX_DECODED_SIZE(msglen);   /* maximum possible */
    rawmsg = malloc(rawlen);
    if (!rawmsg && rawlen > 0) {
	return gcry_error(GPG_ERR_ENOMEM);
    }
    rawlen = otrl_base64_decode(rawmsg, otrtag, msglen);  /* actual size */

    bufp = rawmsg;
    lenp = rawlen;

    require_len(3);
    version = bufp[1];
    skip_header('\x03');

    if (version == 3) {
	require_len(8);
	bufp += 8; lenp -= 8;
    }

    if (version == 2 || version == 3) {
	require_len(1);
	if (flagsp) *flagsp = bufp[0];
	bufp += 1; lenp -= 1;
    }

    free(rawmsg);
    return gcry_error(GPG_ERR_NO_ERROR);

invval:
    free(rawmsg);
    return gcry_error(GPG_ERR_INV_VALUE);
}
Example #2
0
/* Extract the flags from an otherwise unreadable Data Message. */
gcry_error_t otrl_proto_data_read_flags(const char *datamsg,
	unsigned char *flagsp)
{
    char *otrtag, *endtag;
    unsigned char *rawmsg = NULL;
    unsigned char *bufp;
    size_t msglen, rawlen, lenp;
    unsigned char version;

    if (flagsp) *flagsp = 0;
    otrtag = strstr(datamsg, "?OTR:");
    if (!otrtag) {
	goto invval;
    }
    endtag = strchr(otrtag, '.');
    if (endtag) {
	msglen = endtag-otrtag;
    } else {
	msglen = strlen(otrtag);
    }

    /* Base64-decode the message */
    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
    rawmsg = malloc(rawlen);
    if (!rawmsg && rawlen > 0) {
	return gcry_error(GPG_ERR_ENOMEM);
    }
    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */

    bufp = rawmsg;
    lenp = rawlen;

    require_len(3);
    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
	/* Invalid header */
	goto invval;
    }
    version = bufp[1];
    bufp += 3; lenp -= 3;

    if (version == 2) {
	require_len(1);
	if (flagsp) *flagsp = bufp[0];
	bufp += 1; lenp -= 1;
    }

    free(rawmsg);
    return gcry_error(GPG_ERR_NO_ERROR);

invval:
    free(rawmsg);
    return gcry_error(GPG_ERR_INV_VALUE);
}
Example #3
0
File: parse.c Project: Ri0n/libotr
/* Parse a Key Exchange Message into a newly-allocated KeyExchMsg structure */
KeyExchMsg parse_keyexch(const char *msg)
{
    KeyExchMsg kem = NULL;
    size_t lenp;
    unsigned char *raw = decode(msg, &lenp);
    unsigned char *bufp = raw;
    if (!raw) goto inv;

    kem = calloc(1, sizeof(struct s_KeyExchMsg));
    if (!kem) {
	free(raw);
	goto inv;
    }

    kem->raw = raw;
    kem->sigstart = bufp;

    require_len(3);
    if (memcmp(bufp, "\x00\x01\x0a", 3)) goto inv;
    bufp += 3; lenp -= 3;

    require_len(1);
    kem->reply = *bufp;
    bufp += 1; lenp -= 1;

    read_mpi(kem->p);
    read_mpi(kem->q);
    read_mpi(kem->g);
    read_mpi(kem->e);

    read_int(kem->keyid);

    read_mpi(kem->y);

    kem->sigend = bufp;

    require_len(40);
    gcry_mpi_scan(&kem->r, GCRYMPI_FMT_USG, bufp, 20, NULL);
    gcry_mpi_scan(&kem->s, GCRYMPI_FMT_USG, bufp+20, 20, NULL);
    bufp += 40; lenp -= 40;

    if (lenp != 0) goto inv;

    return kem;
inv:
    free_keyexch(kem);
    return NULL;
}
Example #4
0
void net_msg_write_string(net_outgoing_message *msg, const char *data)
{
	short slen = strlen(data);

	require_len(msg, slen + sizeof(int16_t));
	net_msg_write_int16(msg, slen);
	strncpy(msg->buffer + msg->pos, data, (size_t)slen);
	msg->pos += slen;
}
Example #5
0
File: parse.c Project: Ri0n/libotr
/* Parse a Reveal Signature Message into a newly-allocated RevealSigMsg
 * structure */
RevealSigMsg parse_revealsig(const char *msg)
{
    RevealSigMsg rmsg = NULL;
    size_t lenp;
    unsigned char *raw = decode(msg, &lenp);
    unsigned char *bufp = raw;
    if (!raw) goto inv;

    rmsg = calloc(1, sizeof(struct s_RevealSigMsg));
    if (!rmsg) {
	free(raw);
	goto inv;
    }

    rmsg->raw = raw;

    require_len(3);

    rmsg->version = bufp[1];

    if (!memcmp(bufp, "\x00\x03\x11", 3)) {
	bufp += 3; lenp -= 3;
	read_int(rmsg->sender_instance);
	read_int(rmsg->receiver_instance);
    } else if (!memcmp(bufp, "\x00\x02\x11", 3)) {
	bufp += 3; lenp -= 3;
	rmsg->sender_instance = 0;
	rmsg->receiver_instance = 0;
    } else goto inv;

    read_int(rmsg->keylen);
    rmsg->key = malloc(rmsg->keylen);
    if (!rmsg->key && rmsg->keylen > 0) goto inv;
    read_raw(rmsg->key, rmsg->keylen);

    read_int(rmsg->encsiglen);
    rmsg->encsig = malloc(rmsg->encsiglen);
    if (!rmsg->encsig && rmsg->encsiglen > 0) goto inv;
    read_raw(rmsg->encsig, rmsg->encsiglen);

    read_raw(rmsg->mac, 20);

    if (lenp != 0) goto inv;

    return rmsg;
inv:
    free_revealsig(rmsg);
    return NULL;
}
Example #6
0
File: parse.c Project: Ri0n/libotr
/* Parse a D-H Commit Message into a newly-allocated CommitMsg structure */
CommitMsg parse_commit(const char *msg)
{
    CommitMsg cmsg = NULL;
    size_t lenp;
    unsigned char *raw = decode(msg, &lenp);
    unsigned char *bufp = raw;
    if (!raw) goto inv;

    cmsg = calloc(1, sizeof(struct s_CommitMsg));
    if (!cmsg) {
	free(raw);
	goto inv;
    }

    cmsg->raw = raw;

    require_len(3);

    cmsg->version = bufp[1];

    if (!memcmp(bufp, "\x00\x03\x02", 3)) {
	bufp += 3; lenp -= 3;
	read_int(cmsg->sender_instance);
	read_int(cmsg->receiver_instance);
    } else if (!memcmp(bufp, "\x00\x02\x02", 3)) {
	bufp += 3; lenp -= 3;
	cmsg->sender_instance = 0;
	cmsg->receiver_instance = 0;
    } else goto inv;

    read_int(cmsg->enckeylen);
    cmsg->enckey = malloc(cmsg->enckeylen);
    if (!cmsg->enckey && cmsg->enckeylen > 0) goto inv;
    read_raw(cmsg->enckey, cmsg->enckeylen);

    read_int(cmsg->hashkeylen);
    cmsg->hashkey = malloc(cmsg->hashkeylen);
    if (!cmsg->hashkey && cmsg->hashkeylen > 0) goto inv;
    read_raw(cmsg->hashkey, cmsg->hashkeylen);

    if (lenp != 0) goto inv;

    return cmsg;
inv:
    free_commit(cmsg);
    return NULL;
}
Example #7
0
File: parse.c Project: Ri0n/libotr
/* Parse a Signature Message into a newly-allocated SignatureMsg structure */
SignatureMsg parse_signature(const char *msg)
{
    SignatureMsg smsg = NULL;
    size_t lenp;
    unsigned char *raw = decode(msg, &lenp);
    unsigned char *bufp = raw;
    if (!raw) goto inv;

    smsg = calloc(1, sizeof(struct s_SignatureMsg));
    if (!smsg) {
	free(raw);
	goto inv;
    }

    smsg->raw = raw;

    require_len(3);

    smsg->version = bufp[1];

    if (!memcmp(bufp, "\x00\x03\x12", 3)) {
	bufp += 3; lenp -= 3;
	read_int(smsg->sender_instance);
	read_int(smsg->receiver_instance);
    } else if (!memcmp(bufp, "\x00\x02\x12", 3)) {
	bufp += 3; lenp -= 3;
	smsg->sender_instance = 0;
	smsg->receiver_instance = 0;
    } else goto inv;

    read_int(smsg->encsiglen);
    smsg->encsig = malloc(smsg->encsiglen);
    if (!smsg->encsig && smsg->encsiglen > 0) goto inv;
    read_raw(smsg->encsig, smsg->encsiglen);

    read_raw(smsg->mac, 20);

    if (lenp != 0) goto inv;

    return smsg;
inv:
    free_signature(smsg);
    return NULL;
}
Example #8
0
File: parse.c Project: Ri0n/libotr
/* Parse a D-H Key Message into a newly-allocated KeyMsg structure */
KeyMsg parse_key(const char *msg)
{
    KeyMsg kmsg = NULL;
    size_t lenp;
    unsigned char *raw = decode(msg, &lenp);
    unsigned char *bufp = raw;
    if (!raw) goto inv;

    kmsg = calloc(1, sizeof(struct s_KeyMsg));
    if (!kmsg) {
	free(raw);
	goto inv;
    }

    kmsg->raw = raw;

    require_len(3);

    kmsg->version = bufp[1];

    if (!memcmp(bufp, "\x00\x03\x0a", 3)) {
	bufp += 3; lenp -= 3;
	read_int(kmsg->sender_instance);
	read_int(kmsg->receiver_instance);
    } else if (!memcmp(bufp, "\x00\x02\x0a", 3)) {
	bufp += 3; lenp -= 3;
	kmsg->sender_instance = 0;
	kmsg->receiver_instance = 0;
    } else goto inv;

    read_mpi(kmsg->y);

    if (lenp != 0) goto inv;

    return kmsg;
inv:
    free_key(kmsg);
    return NULL;
}
Example #9
0
/* Accept an OTR Data Message in datamsg.  Decrypt it and put the
 * plaintext into *plaintextp, and any TLVs into tlvsp.  Put any
 * received flags into *flagsp (if non-NULL). */
gcry_error_t otrl_proto_accept_data(char **plaintextp, OtrlTLV **tlvsp,
	ConnContext *context, const char *datamsg, unsigned char *flagsp)
{
    char *otrtag, *endtag;
    gcry_error_t err;
    unsigned char *rawmsg = NULL;
    size_t msglen, rawlen, lenp;
    unsigned char *macstart, *macend;
    unsigned char *bufp;
    unsigned int sender_keyid, recipient_keyid;
    gcry_mpi_t sender_next_y = NULL;
    unsigned char ctr[8];
    unsigned int datalen, reveallen;
    unsigned char *data = NULL;
    unsigned char *nul = NULL;
    unsigned char givenmac[20];
    DH_sesskeys *sess;
    unsigned char version;

    *plaintextp = NULL;
    *tlvsp = NULL;
    if (flagsp) *flagsp = 0;
    otrtag = strstr(datamsg, "?OTR:");
    if (!otrtag) {
	goto invval;
    }
    endtag = strchr(otrtag, '.');
    if (endtag) {
	msglen = endtag-otrtag;
    } else {
	msglen = strlen(otrtag);
    }

    /* Base64-decode the message */
    rawlen = ((msglen-5) / 4) * 3;   /* maximum possible */
    rawmsg = malloc(rawlen);
    if (!rawmsg && rawlen > 0) {
	err = gcry_error(GPG_ERR_ENOMEM);
	goto err;
    }
    rawlen = otrl_base64_decode(rawmsg, otrtag+5, msglen-5);  /* actual size */

    bufp = rawmsg;
    lenp = rawlen;

    macstart = bufp;
    require_len(3);
    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x02\x03", 3)) {
	/* Invalid header */
	goto invval;
    }
    version = bufp[1];
    bufp += 3; lenp -= 3;

    if (version == 2) {
	require_len(1);
	if (flagsp) *flagsp = bufp[0];
	bufp += 1; lenp -= 1;
    }
    read_int(sender_keyid);
    read_int(recipient_keyid);
    read_mpi(sender_next_y);
    require_len(8);
    memmove(ctr, bufp, 8);
    bufp += 8; lenp -= 8;
    read_int(datalen);
    require_len(datalen);
    data = malloc(datalen+1);
    if (!data) {
	err = gcry_error(GPG_ERR_ENOMEM);
	goto err;
    }
    memmove(data, bufp, datalen);
    data[datalen] = '\0';
    bufp += datalen; lenp -= datalen;
    macend = bufp;
    require_len(20);
    memmove(givenmac, bufp, 20);
    bufp += 20; lenp -= 20;
    read_int(reveallen);
    require_len(reveallen);
    /* Just skip over the revealed MAC keys, which we don't need.  They
     * were published for deniability of transcripts. */
    bufp += reveallen; lenp -= reveallen;

    /* That should be everything */
    if (lenp != 0) goto invval;

    /* We don't take any action on this message (especially rotating
     * keys) until we've verified the MAC on this message.  To that end,
     * we need to know which keys this message is claiming to use. */
    if (context->their_keyid == 0 ||
	    (sender_keyid != context->their_keyid &&
		sender_keyid != context->their_keyid - 1) ||
	    (recipient_keyid != context->our_keyid &&
	     recipient_keyid != context->our_keyid - 1) ||
	    sender_keyid == 0 || recipient_keyid == 0) {
	goto conflict;
    }

    if (sender_keyid == context->their_keyid - 1 &&
	    context->their_old_y == NULL) {
	goto conflict;
    }

    /* These are the session keys this message is claiming to use. */
    sess = &(context->sesskeys
	    [context->our_keyid - recipient_keyid]
	    [context->their_keyid - sender_keyid]);

    gcry_md_reset(sess->rcvmac);
    gcry_md_write(sess->rcvmac, macstart, macend-macstart);
    if (memcmp(givenmac, gcry_md_read(sess->rcvmac, GCRY_MD_SHA1), 20)) {
	/* The MACs didn't match! */
	goto conflict;
    }
    sess->rcvmacused = 1;

    /* Check to see that the counter is increasing; i.e. that this isn't
     * a replay. */
    if (otrl_dh_cmpctr(ctr, sess->rcvctr) <= 0) {
	goto conflict;
    }

    /* Decrypt the message */
    memmove(sess->rcvctr, ctr, 8);
    err = gcry_cipher_reset(sess->rcvenc);
    if (err) goto err;
    err = gcry_cipher_setctr(sess->rcvenc, sess->rcvctr, 16);
    if (err) goto err;
    err = gcry_cipher_decrypt(sess->rcvenc, data, datalen, NULL, 0);
    if (err) goto err;

    /* See if either set of keys needs rotating */

    if (recipient_keyid == context->our_keyid) {
	/* They're using our most recent key, so generate a new one */
	err = rotate_dh_keys(context);
	if (err) goto err;
    }

    if (sender_keyid == context->their_keyid) {
	/* They've sent us a new public key */
	err = rotate_y_keys(context, sender_next_y);
	if (err) goto err;
    }

    gcry_mpi_release(sender_next_y);
    *plaintextp = (char *)data;

    /* See if there are TLVs */
    nul = data;
    while (nul < data+datalen && *nul) ++nul;
    /* If we stopped before the end, skip the NUL we stopped at */
    if (nul < data+datalen) ++nul;
    *tlvsp = otrl_tlv_parse(nul, (data+datalen)-nul);

    free(rawmsg);
    return gcry_error(GPG_ERR_NO_ERROR);

invval:
    err = gcry_error(GPG_ERR_INV_VALUE);
    goto err;
conflict:
    err = gcry_error(GPG_ERR_CONFLICT);
    goto err;
err:
    gcry_mpi_release(sender_next_y);
    free(data);
    free(rawmsg);
    return err;
}
Example #10
0
void net_msg_write_int32(net_outgoing_message *msg, int32_t data)
{
	require_len(msg, sizeof(int32_t));
	*((int32_t *)(msg->buffer + msg->pos)) = htonl(data);
	msg->pos += sizeof(int32_t);
}
Example #11
0
// Integer data types
void net_msg_write_byte(net_outgoing_message *msg, char data)
{
	require_len(msg, sizeof(char));
	msg->buffer[msg->pos] = data;
	msg->pos += sizeof(char);
}
Example #12
0
File: parse.c Project: Ri0n/libotr
/* Parse a Data Message into a newly-allocated DataMsg structure */
DataMsg parse_datamsg(const char *msg)
{
    DataMsg datam = NULL;
    size_t lenp;
    unsigned char *raw = decode(msg, &lenp);
    unsigned char *bufp = raw;
    unsigned char version;
    if (!raw) goto inv;

    datam = calloc(1, sizeof(struct s_DataMsg));
    if (!datam) {
	free(raw);
	goto inv;
    }

    datam->raw = raw;
    datam->rawlen = lenp;
    datam->macstart = bufp;

    require_len(3);
    if (memcmp(bufp, "\x00\x01\x03", 3) && memcmp(bufp, "\x00\x03\x03", 3) &&
	memcmp(bufp, "\x00\x02\x03", 3)) goto inv;

    version = bufp[1];

    datam->sender_instance = 0;
    datam->receiver_instance = 0;
    datam->version = version;
    datam->flags = -1;
    bufp += 3; lenp -= 3;

    if (version == 3) {
	read_int(datam->sender_instance);
	read_int(datam->receiver_instance);
    }

    if (version == 2 || version == 3) {
	require_len(1);
	datam->flags = bufp[0];
	bufp += 1; lenp -= 1;
    }

    read_int(datam->sender_keyid);
    read_int(datam->rcpt_keyid);
    read_mpi(datam->y);
    read_raw(datam->ctr, 8);
    read_int(datam->encmsglen);
    datam->encmsg = malloc(datam->encmsglen);
    if (!datam->encmsg && datam->encmsglen > 0) goto inv;
    read_raw(datam->encmsg, datam->encmsglen);
    datam->macend = bufp;
    read_raw(datam->mac, 20);
    read_int(datam->mackeyslen);
    datam->mackeys = malloc(datam->mackeyslen);

    if (!datam->mackeys && datam->mackeyslen > 0) goto inv;

    read_raw(datam->mackeys, datam->mackeyslen);
    if (lenp != 0) goto inv;

    return datam;
inv:
    free_datamsg(datam);
    return NULL;
}