diff options
Diffstat (limited to 'plugins/MirOTR/libotr-3.2.0/UPGRADING')
-rw-r--r-- | plugins/MirOTR/libotr-3.2.0/UPGRADING | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/plugins/MirOTR/libotr-3.2.0/UPGRADING b/plugins/MirOTR/libotr-3.2.0/UPGRADING new file mode 100644 index 0000000000..6ca2134665 --- /dev/null +++ b/plugins/MirOTR/libotr-3.2.0/UPGRADING @@ -0,0 +1,337 @@ +Table of Contents + +1. Introduction +2. Major Additions +2.1. Fragmentation +2.2. Socialist Millionaires' Protocol +3. Required Changes +3.1. OtrlMessageAppOps Callbacks +3.1.1. Max Message Size +3.1.2. Account Name +3.2. Using Fragmentation +3.3. Using SMP +3.3.1. Initiating +3.3.2. Responding +3.3.3. Aborting +3.3.4. Control Flow and Errors +3.4. Miscellaneous + +1. Introduction + +This file contains information about the changes between the 3.0.0 and +the 3.2.0 APIs for libotr. Note that, as a minor release, applications +compiled against 3.0.0 will continue to work with 3.2.0. This document +explains how to add the new functionality in 3.2.0. + +2. Major Additions + +This section describes the new features in OTR 3.2.0 along with a short +history or motivation for each. + +2.1. Fragmentation [Added in 3.1.0] + +Most IM networks supported by Pidgin have fixed maximum message sizes +(MMS) of approximately 1-3 kB. The longer messages in the initial key +exchange and the new socialist millionaires' protocol may exceed these +common MMS values. To allow these protocols to work properly even over +networks with low MMS values, support for fragmentation was added. + +OTR version 3.0.0 added support for recombining message fragments to +recover the original message. Now that users may be assumed to be able to +handle message fragments, support for fragmenting and sending large +messages has been added to OTR 3.2.0. + +2.2. Socialist Millionaires' Protocol [Added in 3.1.0, revised in 3.2.0] + +In version 3.0.0, the only method available to authenticate a buddy was +fingerprint verification. However, many users who are unfamiliar with +cryptography do not understand what a fingerprint is or how it is useful. +Also, the verification itself relied on the user obtaining an authentic +copy of the other party's fingerprint somehow. The simplest way to do so +may be to relay the displayed hexadecimal values during a phone call, +but this is a large enough hassle that many users omit fingerprint +verification altogether. + +To allow for a method of authentication that is both easier to understand +and easier to use, OTR version 3.2.0 includes the Socialist Millionaires' +Protocol (SMP). SMP runs as follows: each user inputs a secret string, +say "x" and "y". They then exchange a series of messages which reveal +the value of (x==y), but no additional information about the inputs. +This allows users to determine whether they hold the same secret +information with no danger of revealing that secret to an attacker. + +To see how this is useful for authentication in OTR, assume that Alice +and Bob are chatting over OTR for the first time, though they know each +other well in real life. Alice may send Bob the following message: +"Let's make our shared secret the name of that restaurant we both like +in Ottawa." + +Now Alice and Bob run SMP. If Alice is actually talking to Bob directly, +then they will both type in the same restaurant name and SMP will return +success (x==y). However, if an attacker is impersonating Bob or trying +to eavesdrop on the conversation, they will have no idea which restaurant +Alice has in mind, and will type in an incorrect value, causing SMP to +fail. Note that for security reasons, the values compared in the SMP +are actually hashes of several pieces of data, including both parties' +fingerprints, along with their respective secrets. The users, however, +are never exposed to this additional data. + +Thus, SMP turns the problem of obtaining an authentic copy of a +fingerprint into the much simpler problem of obtaining any shared secret, +or simply of drawing on shared experiences to generate one. + +For detailed information on how SMP works, see the paper by Boudot, +Schoenmakers and Traore titled "A Fair and Efficient Solution to the +Socialist Millionaires Problem" (2001), on which our solution is based. + +3. Required Changes [Added in 3.1.0] + +3.1. OtrlMessageAppOps Callbacks + +Three new callbacks have been added to the end of OtrlMessageAppOps. If +the version number passed to otrl_init is less than 3.1.0 then libotr will +not call any of the new callbacks. As well, you may disable individual +callbacks by setting them to NULL. In either case, libotr will revert to +the standard behaviour of version 3.0.0. + +3.1.1. Max Message Size + +The first new callback has the following signature: + + int (*max_message_size)(void *opdata, ConnContext *context); + +This method is called whenever a message is about to be sent with +fragmentation enabled. The return value is checked against the size of +the message to be sent to determine whether fragmentation is necessary. + +Although the maximum message size depends on a number of factors, we +found experimentally that the following rough values based solely on the +(pidgin) protocol name work well: + "prpl-msn", 1409 + "prpl-icq", 2346 + "prpl-aim", 2343 + "prpl-yahoo", 832 + "prpl-gg", 1999 + "prpl-irc", 417 + "prpl-oscar", 2343 + +Setting max_message_size to NULL will disable the fragmentation of all +sent messages; returning 0 from this callback will disable fragmentation +of a particular message. The latter is useful, for example, for +protocols like XMPP (Jabber) that do not require fragmentation at all. + +3.1.2. Account Name + +The other two new callbacks have the following signatures: + + const char *(*account_name)(void *opdata, const char *account, + const char *protocol); + void (*account_name_free)(void *opdata, const char *account_name); + +Normally, if an error message needs to be sent from Alice to Bob, +containing Alice's account name, the value of ConnContext->accountname +will be used. However, if this default name is unsuitable for your +application, you can use the above methods to provide replacement values +for displayed account names. + +account_name is called when libotr requires a human-readable version of +an account name. account_name_free is called once the name has +been used, and the memory allocated by account_name (if any) must be +released. + +Setting account_name to NULL will cause libotr to use +ConnContext->accountname as the displayed name for an account. + +3.2. Using Fragmentation [Added in 3.1.0] + +To make use of fragmentation, first make sure that the max_message_size +callback described in 3.1.1. has been implemented. Then, whenever you +would normally send a message through your IM client, call +otrl_message_fragment_and_send instead: + +gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops, + void *opdata, ConnContext *context, const char *message, + OtrlFragmentPolicy fragPolicy, char **returnFragment); + +Here, message is the original, encrypted, unfragmented message. +This method will break the message into fragments and send either all of +them or almost all of them according to the OtrlFragmentPolicy: + +OTRL_FRAGMENT_SEND_ALL sends all fragments at once +OTRL_FRAGMENT_SEND_ALL_BUT_FIRST sends all but the first fragment +OTRL_FRAGMENT_SEND_ALL_BUT_LAST sends all but the last fragment + +You may wish to use one of the latter two options if you still wish to +pass a message through your IM client. In this case, the unsent +fragment will be returned in returnFragment and should be sent as a +regular message. In order to reassemble the fragments, however, they +must be received in order, so at most one of the latter two options +will result in readable messages. + +3.3. Using SMP [Added in 3.1.0, revised in 3.2.0] + +Recall from section 2.2. above that SMP takes one input string from each +user and outputs either failure or success. + +3.3.1. Initiating + +If you wish to initiate SMP for a user named Alice, you would use +otrl_message_initiate_smp. + +void otrl_message_initiate_smp(OtrlUserState us, const OtrlMessageAppOps *ops, + void *opdata, ConnContext *context, const unsigned char *secret, + size_t secretlen); + +Here, secret and secretlen describe the secret text as entered by Alice, +for example, ("kitten", 6). The other parameters are common to many +otrl_message functions. This method will cause a message to be sent +containing an appropriate OTRL_TLV_SMP1 (see below). + +3.3.2. Responding + +If you wish to continue SMP by supplying the secret for a second user +named Bob, you would use otrl_message_respond_smp: + +void otrl_message_respond_smp(OtrlUserState us, const OtrlMessageAppOps *ops, + void *opdata, ConnContext *context, const unsigned char *secret, + size_t secretlen); + +The arguments for this method are the same as otrl_message_initiate_smp. +This method will send a message with an appropriate OTRL_TLV_SMP2 +(see below). + +3.3.3. Aborting + +If you wish to abort SMP for any reason, including errors occuring +during the protocol, you should use otrl_message_abort_smp: + +void otrl_message_abort_smp(OtrlUserState us, const OtrlMessageAppOps *ops, + void *opdata, ConnContext *context); + +This method will cause the other user to abandon the current state of +SMP by sending an appropriate OTRL_TLV_SMP_ABORT (see below). + +3.3.4. Control Flow and Errors + +The protocol itself consists of 4 messages passed between the two users, +say Alice and Bob. These messages are identified through their TLVs: + +OTRL_TLV_SMP1 The initial message, containing a commitment to + Alice's secret +OTRL_TLV_SMP1Q Like OTRL_TLV_SMP1, but also containing a question + to display to Bob +OTRL_TLV_SMP2 A response containing a commitment to Bob's secret +OTRL_TLV_SMP3 The next message in the chain, from Alice to Bob +OTRL_TLV_SMP4 The final message in the chain, from Bob to Alice +OTRL_TLV_SMP_ABORT Indicates an error has occurred. Will reset SMP state + +To determine whether the protocol is proceeding correctly, additional +information has been added to ConnContext. You may access +context->smstate->nextExpected to find out which TLV should come next, +so you can compare this to what was actually received and take an +appropriate action. The value is of type NextExpectedSMP and could be +any of: + +OTRL_SMP_EXPECT1 Next SMP TLV should be OTRL_TLV_SMP1 +OTRL_SMP_EXPECT2 Next SMP TLV should be OTRL_TLV_SMP2 +OTRL_SMP_EXPECT3 Next SMP TLV should be OTRL_TLV_SMP3 +OTRL_SMP_EXPECT4 Next SMP TLV should be OTRL_TLV_SMP4 + +If at any point, an SMP TLV of an unexpected type is received, the +protocol should abort. Also, if the correct TLV type is received, then +the state should be updated accordingly. A typical control flow looks +like this: + + OtrlTLV *tlvs = NULL; + OtrlTLV *tlv = NULL; + [Initialize tlvs to the list of tlvs. This can be done + as part of otrl_message_receiving.] + + ConnContext *context = [correct context]; + NextExpectedSMP nextMsg = context->smstate->nextExpected; + + if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) { + otrg_plugin_abort_smp(context); + otrg_dialog_update_smp(context, 0.0); + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + context->smstate->sm_prog_state = OTRL_SMP_PROG_OK; + } else { + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT1) + [abort SMP]; + else { + char *question = (char *)tlv->data; + char *eoq = memchr(question, '\0', tlv->len); + if (eoq) { + [prompt the user with question, get the response, + and continue SMP]; + } + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT1) + [abort SMP]; + else { + [get secret from user and continue SMP]; + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT2) + [abort SMP]; + else { + // If we received TLV2, we will send TLV3 and expect TLV4 + context->smstate->nextExpected = OTRL_SMP_EXPECT4; + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT3) + [abort SMP]; + else { + // If we received TLV3, we will send TLV4 + // We will not expect more messages, so prepare for next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + // Report result to user + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); + if (tlv) { + if (nextMsg != OTRL_SMP_EXPECT4) + [abort SMP]; + else { + // We will not expect more messages, so prepare for next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + // Report result to user + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); + if (tlv) { + // The message we are waiting for will not arrive, so reset + // and prepare for the next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + } + } + +To report the result to the user after receiving OTRL_TLV_SMP3 or +OTRL_TLV_SMP4, check whether context->active_fingerprint->trust is a +non-empty string. (That is, check that it's not NULL, and that its +first character is not '\0'.) If that is the case, then the SMP +completed successfully. Otherwise, the parties entered different secrets. + +3.4 Miscellaneous + +b64.h underwent a minor change in OTR 3.1.0. It was purely a +housekeeping change and should not require any changes to dependent code. + +The arguments to otrl_base64_encode and otrl_base64_decode did not agree +in terms of which were of type char* and which were unsigned char* +instead. This has been corrected. The new method signatures are: + +size_t otrl_base64_encode(char *base64data, const unsigned char *data, + size_t datalen); +size_t otrl_base64_decode(unsigned char *data, const char *base64data, + size_t base64len); + |