Commit 6d754cc0 authored by Jurre van Bergen's avatar Jurre van Bergen

Added new files to mimic site of otr.cypherpunks.ca

parent 4bbe82fb
Off-the-Record Messaging Library and Toolkit
v4.1.1, 9 Mar 2016
This is a library and toolkit which implements Off-the-Record (OTR) Messaging.
OTR allows you to have private conversations over IM by providing:
- Encryption
- No one else can read your instant messages.
- Authentication
- You are assured the correspondent is who you think it is.
- Deniability
- The messages you send do _not_ have digital signatures that are
checkable by a third party. Anyone can forge messages after a
conversation to make them look like they came from you. However,
_during_ a conversation, your correspondent is assured the messages
he sees are authentic and unmodified.
- Perfect forward secrecy
- If you lose control of your private keys, no previous conversation
is compromised.
For more information on Off-the-Record Messaging, see
https://otr.cypherpunks.ca/
LIBRARY USAGE
1. Initialization
Before you call any other libotr routine, you need to initialize the
library. The easiest way to do that is to include proto.h, and use the
macro:
OTRL_INIT;
somewhere early in your program. This should be called only once.
You will also need an OtrlUserState. An OtrlUserState encapsulates the
list of known fingerprints and the list of private keys, so it should be
"one per user". Many OTR-enabled programs (such as IM clients) only have a
single user, so for them, you can just create a single one, and use it
throughout. Create an OtrlUserState as follows:
userstate = otrl_userstate_create();
If you need to free an OtrlUserState:
otrl_userstate_free(userstate);
To read stored private keys:
otrl_privkey_read(userstate, privkeyfilename);
To read stored instance tags:
otrl_instag_read(userstate, instagfilename);
To read stored fingerprints:
otrl_privkey_read_fingerprints(userstate, fingerprintfilename,
add_app_info, add_app_info_data);
add_app_info is a function that will be called in the event that a new
ConnContext is created. It will be passed the add_app_info_data that
you supplied, as well as a pointer to the new ConnContext. You can use
this to add application-specific information to the ConnContext using
the "context->app" field, for example. If you don't need to do this,
you can pass NULL for the last two arguments of
otrl_privkey_read_fingerprints.
2. Setting up the UI functions
You need to let the library know how to do any UI it might require
(error messages, confirming new fingerprints, etc.). To this end, you
need to define a number of UI functions, and collect them in a
OtrlMessageAppOps struct.
The first parameter of every UI function is "void *opdata". This is a
pointer you pass to the library, and it will pass back (opaquely) to the
UI functions when it calls them. You can use this to keep track of
state or any other information.
You will need to include proto.h and message.h, and you can find a list
of the UI functions in message.h.
3. Sending messages
When you have a message you're about to send, you'll need to know four
things: you account name, the protocol id, the name of the recipient,
their instance tag, and the message.
OTR protocol version 3 introduces the notion of "instance tags." A
client may be logged into the same account multiple times from different
locations. An instance tag is intended to differentiate these clients.
When sending a message, you may also specify a particular instance tag,
or use meta instance tags like OTRL_INSTAG_MOST_SECURE.
The protocol id is just a unique string that is used to distinguish
the user foo on AIM from the user foo on MSN, etc. It can be anything
you like, so long as you're consistent, but if you've got nothing better
to use, you may as well use the ids from gaim. (Programs that use the
same protocol ids can share fingerprint and private key files.) The
gaim protocol id for AIM/ICQ is "prpl-oscar".
Note that a name does not uniquely identify a user (as shown by the
"foo" example above). Even if you know both the name and the protocol,
it may not identify the user, since there may be multiple "foo" users on
IRC, on different servers. But the *three* items (your account name,
protocol id, their name) _must_ uniquely identify a user, so your
account name needs to include any network identifier, such as a server
name. Examples would be "foo@irc.freenode.net" or "foo@jabber.org".
Protocols such as AIM that do not have separate networks can just use
"foo", of course.
To encrypt the message (if necessary; the library keeps track of which
users you have secure connections to, so you should *always* call this
next function), simply do this:
gcry_error_t err;
char *newmessage = NULL;
err = otrl_message_sending(userstate, &ui_ops, opdata, accountname,
protocolid, recipient_name, instag, message, tlvs,
&newmessage, fragPolicy, contextp, add_app_info,
add_app_info_data);
add_app_info and add_app_info_data are as above, and may be NULL.
tlvs should usually be NULL. If it's not, then it points to a chain of
OtrlTLVs which represent machine-readable data to send along with this
message.
If contextp is not NULL, it will be set to the context that was used
for sending the message.
If err is non-zero, then the library tried to encrypt the message,
but for some reason failed. DO NOT send the message in the clear in
that case.
If newmessage gets set by the call to something non-NULL, then you
should replace your message with the contents of newmessage, and
send that instead.
Once the message is encrypted, it may still be too large to send over
the network in a single piece. To check the maximum message size and
break your message into fragments if necessary, do this:
gcry_error_t err;
char *extrafragment = NULL;
err = otrl_message_fragment_and_send(&ui_ops, opdata, context,
message, fragmentPolicy, extrafragment);
fragmentPolicy determines which, if any, fragments to return instead
of sending them immediately. For example, you may wish to send all
fragments except the last one, which is handled differently. Valid
policies may be found in proto.h.
If err returns a nonzero value from fragment_and_send, the application
tried to break your message into fragments but failed for some reason.
You may still attempt to send the original message, but it might be
rejected if it too large.
When you're done with newmessage, you must call
otrl_message_free(newmessage)
4. Receiving messages
Receiving messages is similarly straightforward. Again, you need to
know four things: your account name, the protocol id, the sender's name,
and the message.
int ignore_message;
char *newmessage = NULL;
ignore_message = otrl_message_receiving(userstate, &ui_ops, opdata,
accountname, protocolid, sender_name, message, &newmessage,
&tlvs, contextp, add_app_info, add_app_info_data);
add_app_info and add_app_info_data are as above, and may be NULL.
If contextp is not NULL, it will be set to the context that was used
for receiving the message.
If otrl_message_receiving returns 1, then the message you received was
an internal protocol message, and no message should be delivered to the
user.
If it returns 0, then check if newmessage was set to non-NULL. If so,
replace the received message with the contents of newmessage, and
deliver that to the user instead. You must call
otrl_message_free(newmessage) when you're done with it.
If otrl_message_receiving returns 0 and newmessage is NULL, then this
was an ordinary, non-OTR message, which should just be delivered to the
user without modification.
If tlvs is set to non-NULL, then there is machine-readable data that was
sent along with this message. Call otrl_tlv_free(tlvs) when you're done
dealing with it (or ignoring it).
5. Socialist Millionaires' Protocol
The Socialist Millionaires' Protocol (SMP) is a way to detect
eavesdropping and man-in-the-middle attacks without requiring users to
work with fingerprints. This feature was added to OTR starting in
version 3.1.0. To learn how to modify your application to use SMP, read
the UPGRADING file.
TOOLKIT
Along with the library, this package comes with the OTR Messaging
Toolkit. This toolkit is useful for analyzing and/or forging OTR
messages. Why do we offer this? Primarily, to make absolutely sure
that transcripts of OTR conversations are really easy to forge after the
fact. [Note that *during* an OTR conversation, messages can't be forged
without real-time access to the secret keys on the participants'
computers, and in that case, all security has already been lost.]
Easily forgeable transcripts help us provide the "Deniability" property:
if someone claims you said something over OTR, they'll have no proof, as
anyone at all can modify a transcript to make it say whatever they like,
and still have all the verification come out correctly.
Here are the six programs in the toolkit:
- otr_parse
- Parse OTR messages given on stdin, showing the values of all the
fields in OTR protocol messages.
- otr_sesskeys our_privkey their_pubkey
- Shows our public key, the session id, two AES and two MAC keys
derived from the given Diffie-Hellman keys (one private, one public).
- otr_mackey aes_enc_key
- Shows the MAC key derived from the given AES key.
- otr_readforge aes_enc_key [newmsg]
- Decrypts an OTR Data message using the given AES key, and displays
the message, if the key was correct.
- If newmsg is given, replace the message with that one, encrypt
and MAC it properly, and output the resulting OTR Data Message.
This works even if the given key was not correct for the original
message, so as to enable complete forgeries.
- otr_modify mackey old_text new_text offset
- Even if you can't read the data because you don't know either
the AES key or the Diffie-Hellman private key, but you can make a
good guess that the substring "old_text" appears at the given
offset in the message, replace the old_text with the new_text
(which must be of the same length), recalculate the MAC with the
given mackey, and output the resulting Data message.
- Note that, even if you don't know any text in an existing message,
you can still forge messages of your choice using the otr_readforge
command, above.
- otr_remac mackey sender_instance receiver_instance flags keyid keyid
pubkey counter encdata revealed_mackeys
- Make a new OTR Data Message, with the given pieces (note that the
data part is already encrypted). MAC it with the given mackey.
NOTES
Please send your bug reports, comments, suggestions, patches, etc. to us
at the contact address below.
In otrl_message_sending, specifying an instance tag allows you to send a
message to a particular session of a buddy who is logged in multiple times
with an otr-enabled client. The OTRL_INSTAG_RECENT_RECEIVED meta-instance
relies on the time that libotr processed the most recent message. Meta-
instance tags resolve to actual instance tags before a message is sent. An
instant messaging network may not agree on which session of the remote party is
the most recent, e.g., due to underlying network race conditions. If the
behaviour of an instant messaging network is to only deliver to the most recent,
and libotr and the network disagree on which session is the most recent, the
other party will not process the given message. That is, the instant messaging
network will deliver the message to the session whose actual instance tag does
not match the addressed instance tag. Also note that OTRL_INSTAG_BEST also
prefers more recent instance tags in the case of multiple instances with the
same "best" status (most secure). In this case, the most recent has a
resolution of one second.
If otrl_message_sending is called with an original_msg that contains the text
"?OTR?", this is a signal to initiate or refresh an OTR session. There is
currently no way to indicate if this text was actually typed in by a user and
part of a conversation (e.g., someone communicating instructions on how to
refresh OTR). In the future, we may allow a policy to specify whether "?OTR?"
is a signal to start OTR, or just an ordinary message for encrypted and
unencrypted conversations.
MAILING LISTS
There are three mailing lists pertaining to Off-the-Record Messaging:
otr-announce:
https://lists.cypherpunks.ca/mailman/listinfo/otr-announce/
*** All users of OTR software should join this. *** It is used to
announce new versions of OTR software, and other important information.
otr-users:
https://lists.cypherpunks.ca/mailman/listinfo/otr-users/
Discussion of usage issues related to OTR Messaging software.
otr-dev:
https://lists.cypherpunks.ca/mailman/listinfo/otr-dev/
Discussion of OTR Messaging software development.
LICENSE
The Off-the-Record Messaging library (in the src directory) is
covered by the following (LGPL) license:
Off-the-Record Messaging library
Copyright (C) 2004-2016 Ian Goldberg, David Goulet, Rob Smits,
Chris Alexander, Willy Lew, Lisa Du,
Nikita Borisov
<otr@cypherpunks.ca>
This library is free software; you can redistribute it and/or
modify it under the terms of version 2.1 of the GNU Lesser General
Public License as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
There is a copy of the GNU Lesser General Public License in the
COPYING.LIB file packaged with this library; if you cannot find it,
write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Floor, Boston, MA 02110-1301 USA
The library comes with a test suite (in the tests directory), which is
covered by the following (GPL) license:
Copyright (C) 2014 Julien Voisin <julien.voisin@dustri.org>,
David Goulet <dgoulet@ev0ke.net>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License, version 2 only, as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
The Off-the-Record Messaging Toolkit (in the toolkit directory) is covered
by the following (GPL) license:
Off-the-Record Messaging Toolkit
Copyright (C) 2004-2014 Ian Goldberg, David Goulet, Rob Smits,
Chris Alexander, Nikita Borisov
<otr@cypherpunks.ca>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
There is a copy of the GNU General Public License in the COPYING file
packaged with this toolkit; if you cannot find it, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
CONTACT
To report problems, comments, suggestions, patches, etc., you can email
the authors:
Ian Goldberg, David Goulet, Rob Smits, Chris Alexander, Lisa Du,
Nikita Borisov
<otr@cypherpunks.ca>
For more information on Off-the-Record Messaging, visit
https://otr.cypherpunks.ca/
Table of Contents
1. Introduction
2. Major Additions
2.1. Instance Tags
2.2. Asynchronous Private Key Generation
2.3. Extra Symmetric Key
2.4. Convert Operations
2.5. SMP, Error, and Message Event Callbacks
2.6. Fragmentation Changes
3. Required Changes
3.1. OtrlMessageAppOps Callbacks
3.1.1. Removed Operations
3.1.2. Added Operations
3.2. Instance Tags
3.3. Fragmentation Changes
3.4. Asynchronous Private Key Generation
3.5. Library Initialization
1. Introduction
This file contains information about the changes between the 3.2.0 and
the 4.0.0 APIs for libotr. Note that applications compiled against
previous versions of OTR will not work with libotr 4.0.0.
2. Major Additions
This section describes the new features in OTR 4.0.0 along with a short
history or motivation for each.
2.1. Instance Tags
Clients generate instance tags that are intended to be persistent. If
the same client is logged into the same account from multiple locations,
the intention is that he or she will have different instance tags at
each location. OTR wire messages (fragmented and unfragmented) include
the source and destination instance tags. If a client receives a message
that lists a destination instance tag different from his own, the client
will discard it (and issue a callback notifying the application of the
event).
This avoids an issue on IM networks that always relay all messages to
all sessions of a client who is logged in multiple times. In this
situation, OTR clients can attempt to establish an OTR session
indefinitely if there are interleaving messages from each of the
sessions.
2.2. Asynchronous Private Key Generation
Key generation can happen in a separate thread without blocking an
application.
2.3. Extra Symmetric Key
An extra symmetric key is kept synchronized during a conversation with a
buddy. Either side can send a signal that they wish to use this key for
some external purpose (e.g. things like a file transfer, in some other
channel of communication).
2.4. Convert Operations
There is now a callback that is made immediately before a message is
encrypted and immediately after a message is decrypted. This callback
can tweak the plaintext message as needed. For example, this could allow
an application to convert formatting on a message if this would normally
be done on the plaintext by some other entity while the message is in
transit.
2.5. SMP, Error, and Message Event Callbacks
To avoid hard-coded English phrases in libotr, operations which used to
pass back strings are replaced by operations that pass back event codes.
2.6. Fragmentation Changes
In libotr version 3.2.0, you would need to call otrl_message_sending()
to create an encrypted message, and then call fragment_and_send() to get
libotr to fragment and inject that message. In libotr 4.0.0, the
functionality of fragment_and_send() has been integrated into
otrl_message_sending().
3. Required Changes
3.1. OtrlMessageAppOps Callbacks
3.1.1. Removed Operations
/* Display a notification message for a particular accountname /
* protocol / username conversation. */
void (*notify)(void *opdata, OtrlNotifyLevel level,
const char *accountname, const char *protocol,
const char *username, const char *title,
const char *primary, const char *secondary);
The notify() operation was removed since it was used to pass in
hardcoded English strings. This has been replaced by error and message
event callbacks, described below, which pass event codes rather than
hardcoded strings.
/* Display an OTR control message for a particular accountname /
* protocol / username conversation. Return 0 if you are able to
* successfully display it. If you return non-0 (or if this
* function is NULL), the control message will be displayed inline,
* as a received message, or else by using the above notify()
* callback. */
int (*display_otr_message)(void *opdata, const char *accountname,
const char *protocol, const char *username, const char *msg);
The display_otr_message() operation was removed for the same reasons as
above for the notify() operation.
/* Return a newly allocated string containing a human-friendly name
* for the given protocol id */
const char *(*protocol_name)(void *opdata, const char *protocol);
/* Deallocate a string allocated by protocol_name */
void (*protocol_name_free)(void *opdata, const char *protocol_name);
The above operations are no longer required, as they were used when
preparing messages shown to users.
/* Log a message. The passed message will end in "\n". */
void (*log_message)(void *opdata, const char *message);
The log_message() operation was also replaced by message event
callbacks.
3.1.2. Added Operations
/* We received a request from the buddy to use the current "extra"
* symmetric key. The key will be passed in symkey, of length
* OTRL_EXTRAKEY_BYTES. The requested use, as well as use-specific
* data will be passed so that the applications can communicate other
* information (some id for the data transfer, for example). */
void (*received_symkey)(void *opdata, ConnContext *context,
unsigned int use, const unsigned char *usedata,
size_t usedatalen, const unsigned char *symkey);
This is called when a remote buddy has specified a use for the current
symmetric key. If your application does not use the extra symmetric key
it does not need to provide an implementation for this operation.
/* Return a string according to the error event. This string will then
* be concatenated to an OTR header to produce an OTR protocol error
* message. The following are the possible error events:
* - OTRL_ERRCODE_ENCRYPTION_ERROR
* occured while encrypting a message
* - OTRL_ERRCODE_MSG_NOT_IN_PRIVATE
* sent encrypted message to somebody who is not in
* a mutual OTR session
* - OTRL_ERRCODE_MSG_UNREADABLE
* sent an unreadable encrypted message
* - OTRL_ERRCODE_MSG_MALFORMED
* message sent is malformed */
const char *(*otr_error_message)(void *opdata, ConnContext *context,
OtrlErrorCode err_code);
/* Deallocate a string returned by otr_error_message */
void (*otr_error_message_free)(void *opdata, const char *err_msg);
These methods are for producing human-readable error message that will
be sent to the remote buddy when one of these error conditions occurs.
They will be appended to the string "?OTR Error: ". Implementing this
operation is not required, but depending on your application it may be a
good idea.
/* Return a string that will be prefixed to any resent message. If this
* function is not provided by the application then the default prefix,
* "[resent]", will be used.
* */
const char *(*resent_msg_prefix)(void *opdata, ConnContext *context);
/* Deallocate a string returned by resent_msg_prefix */
void (*resent_msg_prefix_free)(void *opdata, const char *prefix);
These operations give the option of chosing an alternative to the
English string "[resent]", when a message is resent.
/* Update the authentication UI with respect to SMP events
* These are the possible events:
* - OTRL_SMPEVENT_ASK_FOR_SECRET
* prompt the user to enter a shared secret. The sender application
* should call otrl_message_initiate_smp, passing NULL as the question.
* When the receiver application resumes the SM protocol by calling
* otrl_message_respond_smp with the secret answer.
* - OTRL_SMPEVENT_ASK_FOR_ANSWER
* (same as OTRL_SMPEVENT_ASK_FOR_SECRET but sender calls
* otrl_message_initiate_smp_q instead)
* - OTRL_SMPEVENT_CHEATED
* abort the current auth and update the auth progress dialog
* with progress_percent. otrl_message_abort_smp should be called to
* stop the SM protocol.
* - OTRL_SMPEVENT_INPROGRESS and
* OTRL_SMPEVENT_SUCCESS and
* OTRL_SMPEVENT_FAILURE and
* OTRL_SMPEVENT_ABORT
* update the auth progress dialog with progress_percent
* - OTRL_SMPEVENT_ERROR
* (same as OTRL_SMPEVENT_CHEATED)
* */
void (*handle_smp_event)(void *opdata, OtrlSMPEvent smp_event,
ConnContext *context, unsigned short progress_percent,
char *question);
These SMP events are initiated by otrl_message_receiving() when it has
received an SMP TLV from a remote buddy. If you application is
implementing support for SMP authentication it should handle these
events appropriately.
Previously applications had to manually check, upon receiving messages,
whether the message contained any SMP TLVs that are relevant to the
current SMP state.
/* Handle and send the appropriate message(s) to the sender/recipient
* depending on the message events. All the events only require an opdata,
* the event, and the context. The message and err will be NULL except for
* some events (see below). The possible events are:
* - OTRL_MSGEVENT_ENCRYPTION_REQUIRED
* Our policy requires encryption but we are trying to send
* an unencrypted message out.
* - OTRL_MSGEVENT_ENCRYPTION_ERROR
* An error occured while encrypting a message and the message
* was not sent.
* - OTRL_MSGEVENT_CONNECTION_ENDED
* Message has not been sent because our buddy has ended the
* private conversation. We should either close the connection,
* or refresh it.
* - OTRL_MSGEVENT_SETUP_ERROR
* A private conversation could not be set up. A gcry_error_t
* will be passed.
* - OTRL_MSGEVENT_MSG_REFLECTED
* Received our own OTR messages.
* - OTRL_MSGEVENT_MSG_RESENT
* The previous message was resent.
* - OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE
* Received an encrypted message but cannot read
* it because no private connection is established yet.
* - OTRL_MSGEVENT_RCVDMSG_UNREADABLE
* Cannot read the received message.
* - OTRL_MSGEVENT_RCVDMSG_MALFORMED
* The message received contains malformed data.
* - OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD
* Received a heartbeat.
* - OTRL_MSGEVENT_LOG_HEARTBEAT_SENT
* Sent a heartbeat.
* - OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR
* Received a general OTR error. The argument 'message' will
* also be passed and it will contain the OTR error message.
* - OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED
* Received an unencrypted message. The argument 'smessage' will
* also be passed and it will contain the plaintext message.
* - OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED
* Cannot recognize the type of OTR message received.
* - OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE
* Received and discarded a message intended for another instance. */
void (*handle_msg_event)(void *opdata, OtrlMessageEvent msg_event,
ConnContext *context, const char *message,
gcry_error_t err);
This operation is called when some type of exceptional event has occured
that your application may want to be aware of. Your application may want
to write an event to a log file, display a message to the user, or
ignore the event. While it is not required to implement this operation,
it is probably a good idea.