[Pkg-privacy-commits] [libotr] 67/225: Protocol-v3.html: Draft protocol v3 doc UPGRADING: Draft upgrading doc src/instag.c: Adding warning to instag file

Ximin Luo infinity0 at moszumanska.debian.org
Sat Aug 22 12:44:56 UTC 2015


This is an automated email from the git hooks/post-receive script.

infinity0 pushed a commit to branch master
in repository libotr.

commit d44b60d903053bb6d06d18a8e5e63f583fd9a583
Author: Rob Smits <rdfsmits at cs.uwaterloo.ca>
Date:   Tue May 22 15:46:43 2012 -0400

    	Protocol-v3.html: Draft protocol v3 doc
    	UPGRADING: Draft upgrading doc
    	src/instag.c: Adding warning to instag file
---
 Protocol-v2.html => Protocol-v3.html | 293 ++++++++-------
 UPGRADING                            | 706 ++++++++++++++++++++---------------
 src/instag.c                         |   4 +
 3 files changed, 560 insertions(+), 443 deletions(-)

diff --git a/Protocol-v2.html b/Protocol-v3.html
similarity index 89%
copy from Protocol-v2.html
copy to Protocol-v3.html
index 401a293..8ca89b8 100644
--- a/Protocol-v2.html
+++ b/Protocol-v3.html
@@ -2,7 +2,7 @@
 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html><head>
-<title>Off-the-Record Messaging Protocol version 2 - DRAFT</title>
+<title>Off-the-Record Messaging Protocol version 3 - DRAFT</title>
 <style type="text/css">
     body { background: white; color: black }
     h1 { text-align: center }
@@ -10,19 +10,15 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     dl.doublespace dd { margin-bottom: 2ex }
 </style>
 </head><body>
-<h1>Off-the-Record Messaging Protocol version 2</h1>
-<p>This document describes version 2 of the Off-the-Record Messaging
-protocol.  The main changes over version 1 include:</p>
+<h1>Off-the-Record Messaging Protocol version 3</h1>
+<p>This document describes version 3 of the Off-the-Record Messaging
+protocol.  The main changes over version 2 include:</p>
 <ul>
-<li>Resolving the identity-binding flaw identified by Di Raimondo,
-Gennaro, and Krawczyk</li>
-<li>Not revealing the users' public keys to passive eavesdroppers; this
-could be useful if the application sending the OTR messages is also
-privacy-preserving</li>
-<li>Supporting fragmentation of OTR messages, to support IM networks
-whose maximum message size is very small.</li>
-<li>Adding a way to authenticate without the use of fingerprints.</li>
-<li>Better protocol version control, for future extensibility.</li>
+<li>Both fragmented and unfragmented messages contain sender and
+recipient instance tags.</li>
+<li>An extra symmetric key is derived during AKE. This may be used for
+secure communication over a different channel (e.g., file transfer,
+voice chat).</li>
 </ul>
 <h2>Very high level overview</h2>
 <p>OTR assumes a network model which provides in-order delivery of
@@ -36,7 +32,7 @@ or is willing (using a whitespace-tagged plaintext message) to use OTR
 to communicate.  Either mechanism should convey the version(s) of OTR
 that Alice is willing to use.</li>
 <li>Bob initiates the authenticated key exchange (AKE) with Alice.
-Version 2 of OTR uses a variant of the SIGMA protocol as its AKE.</li>
+Version 2 and 3 of OTR uses a variant of the SIGMA protocol as its AKE.</li>
 <li>Alice and Bob exchange Data Messages to send information to each
 other.</li>
 </ol>
@@ -268,9 +264,9 @@ version string is constructed as follows:</p>
 start with "?".</li>
 <li>If she is willing to use OTR versions other than 1, a "v" followed
 by the byte identifiers for the versions in question, followed by "?".
-The byte identifier for OTR version 2 is "2".  The order of the
-identifiers between the "v" and the "?" does not matter, but none should
-be listed more than once.</li>
+The byte identifier for OTR version 2 is "2", and similarly for 3.  The
+order of the identifiers between the "v" and the "?" does not matter,
+but none should be listed more than once.</li>
 </ul>
 <p>For example:</p>
 <dl>
@@ -278,6 +274,8 @@ be listed more than once.</li>
 <dd>Version 1 only</dd>
 <dt>"?OTRv2?"</dt>
 <dd>Version 2 only</dd>
+<dt>"?OTRv23?"</dt>
+<dd>Version 2 and 3</dd>
 <dt>"?OTR?v2?"</dt>
 <dd>Versions 1 and 2</dd>
 <dt>"?OTRv24x?"</dt>
@@ -402,6 +400,26 @@ data to be hashed.  The encoding assures that, assuming the hash
 function itself has no useful collisions, and DSA keys have length less
 than 524281 bits (500 times larger than most DSA keys), no two public
 keys will have the same fingerprint.</p>
+<h4>Instance Tags</h4>
+<p>Clients include instance tags in all OTR version 3 messages. Instance
+tags are 32-bit values 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. As shown below, OTR version 3 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, he should discard it.</p>
+<p>The first valid instance tag is 0x00000100. It is appropriate to set the
+destination instance tag to '0' when an actual destination instance tag is
+not known at the time the message is prepared. If a client receives a
+message with the sender instance tag set to less than 0x00000100, he should
+discard the message.
+</p>
+
+<p>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.</p>
 <h4>D-H Commit Message</h4>
 <p>This is the first message of the AKE.  Bob sends it to Alice to
 commit to a choice of D-H encryption key (but the key itself is not yet
@@ -410,9 +428,15 @@ OTR version 1, while still preventing a man-in-the-middle attack on
 it.</p>
 <dl>
 <dt>Protocol version (SHORT)</dt>
-<dd>The version number of this protocol is 0x0002.</dd>
+<dd>The version number of this protocol is 0x0003.</dd>
 <dt>Message type (BYTE)</dt>
 <dd>The D-H Commit Message has type 0x02.</dd>
+<dt>Sender Instance tag (INT)</dt>
+<dd>The instance tag of the person sending this message.</dd>
+<dt>Receiver Instance tag (INT)</dt>
+<dd>The instance tag of the intended receiptient.
+For a commit message this will often be 0, since the other party
+may not have identified their instance tag yet.</dd>
 <dt>Encrypted g<sup>x</sup> (DATA)</dt>
 <dd>Produce this field as follows:
 <ul>
@@ -432,9 +456,13 @@ it.</p>
 simply consists of Alice's D-H encryption key.</p>
 <dl>
 <dt>Protocol version (SHORT)</dt>
-<dd>The version number of this protocol is 0x0002.</dd>
+<dd>The version number of this protocol is 0x0003.</dd>
 <dt>Message type (BYTE)</dt>
 <dd>The D-H Key Message has type 0x0a.</dd>
+<dt>Sender Instance tag (INT)</dt>
+<dd>The instance tag of the person sending this message.</dd>
+<dt>Receiver Instance tag (INT)</dt>
+<dd>The instance tag of the intended receiptient.</dd>
 <dt>g<sup>y</sup> (MPI)</dt>
 <dd>Choose a random value y (at least 320 bits), and calculate
 g<sup>y</sup>.</dd>
@@ -447,9 +475,13 @@ channel, preventing a man-in-the-middle attack on the channel itself) to
 Alice.</p>
 <dl>
 <dt>Protocol version (SHORT)</dt>
-<dd>The version number of this protocol is 0x0002.</dd>
+<dd>The version number of this protocol is 0x0003.</dd>
 <dt>Message type (BYTE)</dt>
 <dd>The Reveal Signature Message has type 0x11.</dd>
+<dt>Sender Instance tag (INT)</dt>
+<dd>The instance tag of the person sending this message.</dd>
+<dt>Receiver Instance tag (INT)</dt>
+<dd>The instance tag of the intended receiptient.</dd>
 <dt>Revealed key (DATA)</dt>
 <dd>This is the value r picked earlier.</dd>
 <dt>Encrypted signature (DATA)</dt>
@@ -488,9 +520,13 @@ length), using the key m2.</dd>
 authenticating herself and the channel parameters to him.</p>
 <dl>
 <dt>Protocol version (SHORT)</dt>
-<dd>The version number of this protocol is 0x0002.</dd>
+<dd>The version number of this protocol is 0x0003.</dd>
 <dt>Message type (BYTE)</dt>
 <dd>The Signature Message has type 0x12.</dd>
+<dt>Sender Instance tag (INT)</dt>
+<dd>The instance tag of the person sending this message.</dd>
+<dt>Receiver Instance tag (INT)</dt>
+<dd>The instance tag of the intended receiptient.</dd>
 <dt>Encrypted signature (DATA)</dt>
 <dd>This field is calculated as follows:
 <ul>
@@ -580,6 +616,15 @@ human-readable part) with this TLV type to instruct the other party's
 client to abort the protocol.  The associated length should be zero and
 the associated value should be empty.  If you receive a TLV of this type,
 you should change the SMP state to SMP_EXPECT1 (see below).</dd>
+<dt>Type 7: SMP Message 1Q</dt>
+<dd>Like a SMP Message 1, but whose value begins with a user-specified
+question.</dd>
+<dt>Type 8: Extra symmetric key</dt>
+<dd>The value begins with a 4-byte indication of what this symmetric key
+will be used for (file transfer, voice encryption, etc.). After that, the
+contents are use-specific (which file, etc.). There are no currently
+defined uses. See the "extra symmetric key" section below for details on
+how this key is derived.</dd>
 </dl>
 <p>SMP Message TLVs (types 2-5) all carry data sharing the same general
 format:</p> 
@@ -602,9 +647,13 @@ rotations.)</p>
 <p>Data Message format:</p>
 <dl>
 <dt>Protocol version (SHORT)</dt>
-<dd>The version number of this protocol is 0x0002.</dd>
+<dd>The version number of this protocol is 0x0003.</dd>
 <dt>Message type (BYTE)</dt>
 <dd>The Data Message has type 0x03.</dd>
+<dt>Sender Instance tag (INT)</dt>
+<dd>The instance tag of the person sending this message.</dd>
+<dt>Receiver Instance tag (INT)</dt>
+<dd>The instance tag of the intended receiptient.</dd>
 <dt>Flags (BYTE)</dt>
 <dd>The bitwise-OR of the flags for this message.  Usually you should
 set this to 0x00.  The only currently defined flag is:<dl>
@@ -667,7 +716,7 @@ the current conversation.</dd>
 using in the current conversation.</dd>
 <dt>Secure Session ID</dt>
 <dd>The ssid described below.</dd>
-<dt>User input</dt>
+<dt>User-specified secret</dt>
 <dd>The input string given by the user at runtime.</dd>
 </dl>
 <p>Then the SHA256 hash of the above is taken, and the digest becomes the 
@@ -686,10 +735,11 @@ be accepted.  This variable has no effect on type 0 or type 1 TLVs, which
 are always allowed.  smpstate can take one of four values:</p>
 <dl>
 <dt>SMPSTATE_EXPECT1</dt>
-<dd>This state indicates that only type 2 TLVs (SMP message 1) should
-be accepted.  This is the default state when SMP has not yet begun.  This
-state is also reached whenever an error occurs or SMP is aborted, and the
-protocol must be restarted from the beginning.</dd>
+<dd>This state indicates that only type 2 (SMP message 1) and type 7
+(SMP message 1Q) TLVs should be accepted.  This is the default state when
+SMP has not yet begun.  This state is also reached whenever an error
+occurs or SMP is aborted, and the protocol must be restarted from the
+beginning.</dd>
 <dt>SMPSTATE_EXPECT2</dt>
 <dd>This state indicates that only type 3 TLVs (SMP message 2) should
 be accepted.</dd>
@@ -751,6 +801,9 @@ her transmitted value g<sub>2a</sub>.</dd>
 <dd>A zero-knowledge proof that Alice knows the exponent associated with
 her transmitted value g<sub>3a</sub>.</dd>
 </dl>
+<p>A type 7 (SMP Message 1Q) TLV is the same as the above, but is
+preceded by a user-specified question, which is associated with the
+user-specified portion of the secret.</p>
 <p>When Bob receives this TLV he should do:</p>
 <dl>
 <dt>If smpstate is not SMPSTATE_EXPECT1:</dt>
@@ -1141,6 +1194,11 @@ sending AES key.</li>
 <li>The "receiving MAC key" is the 20-byte SHA-1 hash of the 16-byte
 receiving AES key.</li>
 </ul>
+<h4>Extra symmetric key</h4>
+<p>OTR version 3 defined an additional symmetric key that is derived
+during the AKE. The extra symmetric key is derived by calculating
+h2(0xFF) and keeping the entire 256 bits, using the same definition
+of h2 as above.</p>
 <h4>Revealing MAC keys</h4>
 <p>Whenever you are about to forget either one of your old D-H key pairs, or
 one of your correspondent's old D-H public keys, take all of the
@@ -1161,9 +1219,9 @@ uses a MAC key which has already been revealed.</p>
 <p>Some networks may have a maximum message size that is too small to
 contain an encoded OTR message.  In that event, the sender may choose
 to split the message into a number of <em>fragments</em>.  This section
-describes the format of the fragments.  All OTR version 2 clients must
-be able to assemble received fragments, but performing fragmentation on
-outgoing messages is optional.</p>
+describes the format of the fragments.  All OTR version 2 and 3 clients
+must be able to assemble received fragments, but performing
+fragmentation on outgoing messages is optional.</p>
 
 <dl class="doublespace">
 <dt>Transmitting Fragments</dt>
@@ -1177,10 +1235,17 @@ outgoing messages is optional.</p>
     <li>Break it up into sufficiently small pieces.  Let the number of
       pieces be (n), and the pieces be
       piece[1],piece[2],...,piece[n].</li>
-    <li>Transmit (n) messages with the following (printf-like) structure
-      (as k runs from 1 to n inclusive):
+    <li>Transmit (n) OTR version 3 fragmented messages with the following
+      (printf-like) structure (as k runs from 1 to n inclusive):
 
-      <p>"?OTR,%hu,%hu,%s," , k , n , piece[k]</p></li>
+      <p>"?OTR|%x|%x,%hu,%hu,%s," , sender_instance, receiver_instance, 
+      k , n , piece[k]</p>
+      
+      OTR version 2 messages get fragmented in a similar format, but 
+      without the instance tags fields:
+      
+      <p>"?OTR,%hu,%hu,%s," , sender_instance, receiver_instance, 
+      k , n , piece[k]</p></li>
 
     <li>Note that k and n are unsigned short ints (2 bytes), and each has
       a maximum value of 65535.  Also, each piece[k] must be
@@ -1189,13 +1254,16 @@ outgoing messages is optional.</p>
 
 <dt>Receiving Fragments:</dt>
 
-<dd>If you receive a message containing "?OTR," (note that you'll need
+<dd>If you receive a message containing "?OTR|" (note that you'll need
     to check for this _before_ checking for any of the other "?OTR:"
     markers):
 
     <ul>
     <li>Parse it as the printf statement above into k, n, and
     piece.</li>
+    <li>If the recipient's own instance tag does not match the listed
+    receiver instance tag, and the listed receiver instance tag is not
+    zero, the recipient should discard the message.</li>
     <li>Let (K,N) be your currently stored fragment number, and F be your
       currently stored fragment.  [If you have no currently stored
       fragment, then K = N = 0 and F = "".]</li>
@@ -1229,55 +1297,45 @@ outgoing messages is optional.</p>
 
     <p>If you receive a non-OTR message, or an unfragmented message,
     forget any stored fragment you may have, store "" as F and store
-    (0,0) as (K,N).</p></dd>
+    (0,0) as (K,N).</p>
+    
+    <p>OTR version 2 fragmented messages follow the same behaviour as
+    described above, but do not list the sender and receiver instance
+    tags.</dd>
 </dl>
 
 <p>For example, here is a Data Message we would like to transmit over a
 network with an unreasonably small maximum message size:</p>
 
 <blockquote><pre>
-?OTR:AAEDAAAAAQAAAAEAAADAVf3Ei72ZgFeKqWvLMnuVPVCwxktsOZ1Qdje
-Lp6jn62mCVtlY9nS6sRkecpjuLYHRxyTdRu2iEVtSsjZqK55ovZ35SfkOPHe
-FYa9BIuxWi9djHMVKQ8KOVGAVLibjZ6P8LreDSKtWDv9YQjIEnkwFVGCPfpB
-q2SX4VTQfJAQXHggR8izKxPvluXUdG9rIPh4cac98++VLdIuFMiEXjUIoTX2
-rEzunaCLMy0VIfowlRsgsKGrwhCCv7hBWyglbzwz+AAAAAAAAAAQAAAF2SOr
-JvPUerB9mtf4bqQDFthfoz/XepysnYuReHHEXKe+BFkaEoMNGiBl4TCLZx72
-DvmZwKCewWRH1+W66ggrXKw2VdVl+vLsmzxNyWChGLfBTL5/3SUF09BfmCEl
-03Ckk7htAgyAQcBf90RJznZndv7HwVAi3syupi0sQDdOKNPyObR5FRtqyqud
-ttWmSdmGCGFcZ/fZqxQNsHB8QuYaBiGL7CDusES+wwfn8Q7BGtoJzOPDDx6K
-yIyox/flPx2DZDJIZrMz9b0V70a9kqKLo/wcGhvHO6coCyMxenBAacLJ1DiI
-NLKoYOoJTM7zcxsGnvCxaDZCvsmjx3j8Yc5r3i3ylllCQH2/lpr/xCvXFarG
-tG7+wts+UqstS9SThLBQ9Ojq4oPsX7HBHKvq19XU3/ChIgWMy+bczc5gpkC/
-eLAIGfJ0D5DJsl68vMXSmCoFK0HTwzzNa7lnZK4IutYPBNBCv0pWORQqDpsk
-Ez96YOGyB8+gtpFgCrkuV1bSB9SRVmEBfDtKPQFhKowAAAAA=.
+?OTR:AAMDJ+MVmSfjFZcAAAAAAQAAAAIAAADA1g5IjD1ZGLDVQEyCgCyn9hb
+rL3KAbGDdzE2ZkMyTKl7XfkSxh8YJnudstiB74i4BzT0W2haClg6dMary/jo
+9sMudwmUdlnKpIGEKXWdvJKT+hQ26h9nzMgEditLB8vjPEWAJ6gBXvZrY6ZQ
+rx3gb4v0UaSMOMiR5sB7Eaulb2Yc6RmRnnlxgUUC2alosg4WIeFN951PLjSc
+ajVba6dqlDi+q1H5tPvI5SWMN7PCBWIJ41+WvF+5IAZzQZYgNaVLbAAAAAAA
+AAAEAAAAHwNiIi5Ms+4PsY/L2ipkTtquknfx6HodLvk3RAAAAAA==.
 </pre></blockquote>
 
     <p>We could fragment this message into (for example) three
     pieces:</p>
 
 <blockquote><pre>
-?OTR,1,3,?OTR:AAEDAAAAAQAAAAEAAADAVf3Ei72ZgFeKqWvLMnuVPVCwxk
-tsOZ1QdjeLp6jn62mCVtlY9nS6sRkecpjuLYHRxyTdRu2iEVtSsjZqK55ovZ
-35SfkOPHeFYa9BIuxWi9djHMVKQ8KOVGAVLibjZ6P8LreDSKtWDv9YQjIEnk
-wFVGCPfpBq2SX4VTQfJAQXHggR8izKxPvluXUdG9rIPh4cac98++VLdIuFMi
-EXjUIoTX2rEzunaCLMy0VIfowlRsgsKGrwhCCv7hBWyglbzwz+AAAAAAAAAA
-QAAAF2SOr,
+?OTR|5a73a599|27e31597,00001,00003,?OTR:AAMDJ+MVmSfjFZcAAAAA
+AQAAAAIAAADA1g5IjD1ZGLDVQEyCgCyn9hbrL3KAbGDdzE2ZkMyTKl7XfkSx
+h8YJnudstiB74i4BzT0W2haClg6dMary/jo9sMudwmUdlnKpIGEKXWdvJKT+
+hQ26h9nzMgEditLB8v,
 </pre></blockquote>
 
 <blockquote><pre>
-?OTR,2,3,JvPUerB9mtf4bqQDFthfoz/XepysnYuReHHEXKe+BFkaEoMNGiB
-l4TCLZx72DvmZwKCewWRH1+W66ggrXKw2VdVl+vLsmzxNyWChGLfBTL5/3SU
-F09BfmCEl03Ckk7htAgyAQcBf90RJznZndv7HwVAi3syupi0sQDdOKNPyObR
-5FRtqyqudttWmSdmGCGFcZ/fZqxQNsHB8QuYaBiGL7CDusES+wwfn8Q7BGto
-JzOPDDx6KyIyox/flPx2DZDJIZrMz9b0V70a9kqKLo/wcGhvHO6coCyMxenB
-AacLJ1DiI,
+?OTR|5a73a599|27e31597,00002,00003,jPEWAJ6gBXvZrY6ZQrx3gb4v0
+UaSMOMiR5sB7Eaulb2Yc6RmRnnlxgUUC2alosg4WIeFN951PLjScajVba6dq
+lDi+q1H5tPvI5SWMN7PCBWIJ41+WvF+5IAZzQZYgNaVLbAAAAAAAAAAEAAAA
+HwNiIi5Ms+4PsY/L2i,
 </pre></blockquote>
 
 <blockquote><pre>
-?OTR,3,3,NLKoYOoJTM7zcxsGnvCxaDZCvsmjx3j8Yc5r3i3ylllCQH2/lpr
-/xCvXFarGtG7+wts+UqstS9SThLBQ9Ojq4oPsX7HBHKvq19XU3/ChIgWMy+b
-czc5gpkC/eLAIGfJ0D5DJsl68vMXSmCoFK0HTwzzNa7lnZK4IutYPBNBCv0p
-WORQqDpskEz96YOGyB8+gtpFgCrkuV1bSB9SRVmEBfDtKPQFhKowAAAAA=.,
+?OTR|5a73a599|27e31597,00003,00003,pkTtquknfx6HodLvk3RAAAAAA
+==.,
 </pre></blockquote>
 <h3>The protocol state machine</h3>
 <p>An OTR client maintains separate state for every correspondent.  For
@@ -1315,7 +1373,7 @@ just as Alice hits Enter.)</dd>
 </dl>
 <h4>Authentication state</h4>
 <p>The authentication state variable, authstate, can take one of four
-values (plus one extra for OTR version 1 compatibility):</p>
+values:</p>
 <dl>
 <dt>AUTHSTATE_NONE</dt>
 <dd>This state indicates that the authentication protocol is not
@@ -1329,21 +1387,14 @@ own D-H Key Message, she enters this state to await Bob's reply.</dd>
 <dt>AUTHSTATE_AWAITING_SIG</dt>
 <dd>After Bob receives Alice's D-H Key Message, and replies with his own
 Reveal Signature Message, he enters this state to await Alice's reply.</dd>
-<dt>AUTHSTATE_V1_SETUP</dt>
-<dd>For OTR version 1 compatibility, if Bob sends a version 1 Key
-Exchange Message to Alice, he enters this state to await Alice's
-reply.</dd>
 </dl>
 <p>After:</p>
 <ul>
 <li>Alice (in AUTHSTATE_AWAITING_REVEALSIG) receives Bob's Reveal
-Signature Message (and replies with her own Signature Message),</li>
-<li>Alice (in AUTHSTATE_NONE) receives Bob's Version 1 Key Exchange
-Message (and replies with her own Key Exchange Message),</li>
+Signature Message (and replies with her own Signature Message), <b>or</b>
+</li>
 <li>Bob (in AUTHSTATE_AWAITING_SIG) receives Alice's Signature Message,
-<b>or</b></li>
-<li>Bob (in AUTHSTATE_V1_SETUP) receives Alice's Version 1 Key Exchange
-Message,</li>
+/li>
 </ul>
 <p>then,
 assuming the signature verifications succeed, the msgstate
@@ -1353,17 +1404,17 @@ transitioned to AUTHSTATE_NONE.</p>
 <h4>Policies</h4>
 <p>OTR clients can set different <b>policies</b> for different
 correspondents.  For example, Alice could set up her client so that it
-speaks only OTR version 2, except with Charlie, who she knows has only
+speaks only OTR version 3, except with Charlie, who she knows has only
 an old client; so that it will opportunistically start an OTR conversation
 whenever it detects the correspondent supports it; or so that it refuses
 to send non-encrypted messages to Bob, ever.</p>
 <p>The policies that can be set (on a global or per-correspondent basis)
 are any combination of the following boolean flags:</p>
 <dl>
-<dt>ALLOW_V1</dt>
-<dd>Allow version 1 of the OTR protocol to be used.</dd>
 <dt>ALLOW_V2</dt>
 <dd>Allow version 2 of the OTR protocol to be used.</dd>
+<dt>ALLOW_V3</dt>
+<dd>Allow version 3 of the OTR protocol to be used.</dd>
 <dt>REQUIRE_ENCRYPTION</dt>
 <dd>Refuse to send unencrypted messages.</dd>
 <dt>SEND_WHITESPACE_TAG</dt>
@@ -1373,21 +1424,6 @@ are any combination of the following boolean flags:</p>
 <dt>ERROR_START_AKE</dt>
 <dd>Start the OTR AKE when you receive an OTR Error Message.</dd>
 </dl>
-<p>The four old version 1 policies correspond to the following
-combinations of flags (adding an allowance for version 2 of the
-protocol):</p>
-<dl>
-<dt>NEVER</dt>
-<dd>No flags set</dd>
-<dt>MANUAL</dt>
-<dd>ALLOW_V1 | ALLOW_V2</dd>
-<dt>OPPORTUNISTIC</dt>
-<dd>ALLOW_V1 | ALLOW_V2 | SEND_WHITESPACE_TAG | WHITESPACE_START_AKE |
-ERROR_START_AKE</dd>
-<dt>ALWAYS</dt>
-<dd>ALLOW_V1 | ALLOW_V2 | REQUIRE_ENCRYPTION | WHITESPACE_START_AKE |
-ERROR_START_AKE</dd>
-</dl>
 <p>Note that it is possible for UIs simply to offer the old
 "combinations" of options, and not ask about each one separately.</p>
 <h4>State transitions</h4>
@@ -1403,7 +1439,6 @@ ERROR_START_AKE</dd>
 <li>D-H Key Message</li>
 <li>Reveal Signature Message</li>
 <li>Signature Message</li>
-<li>Version 1 Key Exchange Message</li>
 <li>Data Message</li>
 </ul></li>
 <li>User actions:
@@ -1414,9 +1449,11 @@ ERROR_START_AKE</dd>
 </ul></li>
 </ul>
 <p>The following sections will outline what actions to take in each
-case.  They all assume that at least one of ALLOW_V1 or ALLOW_V2 is set;
+case.  They all assume that at least one of ALLOW_V2 or ALLOW_V3 is set;
 if not, then OTR is completely disabled, and no special handling of
-messages should be done at all.</p>
+messages should be done at all. For version 3 messages, someone receiving
+a message with a recipient instance tag specified that does not equal
+their own should discard the message.</p>
 <h4>Receiving plaintext without the whitespace tag</h4>
 <dl>
 <dt>If msgstate is MSGSTATE_PLAINTEXT:</dt>
@@ -1438,21 +1475,21 @@ warn him that the message was received unencrypted.</dd>
 </dl>
 <p>In any event, if WHITESPACE_START_AKE is set:</p>
 <dl>
-<dt>If the tag offers OTR version 2 and ALLOW_V2 is set:</dt>
-<dd>Send a D-H Commit Message, and transition authstate to
+<dt>If the tag offers OTR version 3 and ALLOW_V3 is set:</dt>
+<dd>Send a version 3 D-H Commit Message, and transition authstate to
+AUTHSTATE_AWAITING_DHKEY.</dd>
+<dt>Otherwise, if the tag offers OTR version 2 and ALLOW_V2 is set:</dt>
+<dd>Send a version 2 D-H Commit Message, and transition authstate to
 AUTHSTATE_AWAITING_DHKEY.</dd>
-<dt>Otherwise, if the tag offers OTR version 1 and ALLOW_V1 is set:</dt>
-<dd>Send a Version 1 Key Exchange Message, and transition authstate to
-AUTHSTATE_V1_SETUP.</dd>
 </dl>
 <h4>Receiving a Query Message</h4>
 <dl>
-<dt>If the Query Message offers OTR version 2 and ALLOW_V2 is set:</dt>
-<dd>Send a D-H Commit Message, and transition authstate to
+<dt>If the query message offers OTR version 3 and ALLOW_V3 is set:</dt>
+<dd>Send a version 3 D-H Commit Message, and transition authstate to
+AUTHSTATE_AWAITING_DHKEY.</dd>
+<dt>Otherwise, if the message offers OTR version 2 and ALLOW_V2 is set:</dt>
+<dd>Send a version 2 D-H Commit Message, and transition authstate to
 AUTHSTATE_AWAITING_DHKEY.</dd>
-<dt>Otherwise, if the message offers OTR version 1 and ALLOW_V1 is set:</dt>
-<dd>Send a Version 1 Key Exchange Message, and transition authstate to
-AUTHSTATE_V1_SETUP.</dd>
 </dl>
 <h4>Receiving an Error Message</h4>
 <p>Display the message to the user.  If ERROR_START_AKE is set, reply
@@ -1460,7 +1497,9 @@ with a Query Message.</p>
 <h4>User requests to start an OTR conversation</h4>
 <p>Send an OTR Query Message to the correspondent.</p>
 <h4>Receiving a D-H Commit Message</h4>
-<p>If ALLOW_V2 is not set, ignore this message.  Otherwise:</p>
+<p>If the message is version 2 and ALLOW_V2 is not set, ignore this message.
+Similarly if the message is version 3 and ALLOW_V3 is not set, ignore the
+message. Otherwise:</p>
 <dl>
 <dt>If authstate is AUTHSTATE_NONE:</dt>
 <dd>Reply with a D-H Key Message, and transition authstate to
@@ -1504,7 +1543,9 @@ in multiple times.]</li>
 AUTHSTATE_AWAITING_REVEALSIG.</dd>
 </dl>
 <h4>Receiving a D-H Key Message</h4>
-<p>If ALLOW_V2 is not set, ignore this message.  Otherwise:</p>
+<p>If the message is version 2 and ALLOW_V2 is not set, ignore this
+message. Similarly if the message is version 3 and ALLOW_V3 is not
+set, ignore this message. Otherwise:</p>
 <dl>
 <dt>If authstate is AUTHSTATE_AWAITING_DHKEY:</dt>
 <dd>Reply with a Reveal Signature Message and transition authstate to
@@ -1556,41 +1597,9 @@ Data Message.</li>
 </ul>
 Otherwise, ignore the message.</dd>
 <dt>If authstate is AUTHSTATE_NONE, AUTHSTATE_AWAITING_DHKEY, 
-AUTHSTATE_AWAITING_REVEALSIG, or AUTHSTATE_V1_SETUP:</dt>
+or AUTHSTATE_AWAITING_REVEALSIG:</dt>
 <dd>Ignore the message.</dd>
 </dl>
-<h4>Receiving a Version 1 Key Exchange Message</h4>
-<p>If ALLOW_V1 is not set, ignore this message.  Otherwise:</p>
-<dl>
-<dt>If authstate is AUTHSTATE_NONE, AUTHSTATE_AWAITING_DHKEY,
-AUTHSTATE_AWAITING_REVEALSIG, or AUTHSTATE_AWAITING_SIG:</dt>
-<dd><dl><dt>If the reply field is not set to 0x01:</dt>
-<dd>Verify the information in the Key Exchange Message.  If the
-verification succeeds:
-<ul>
-<li>Reply with a Key Exchange Message with the reply field set to
-0x01.</li>
-<li>Transition authstate to AUTHSTATE_NONE.</li>
-<li>Transition msgstate to MSGSTATE_ENCRYPTED.</li>
-<li>If there is a recent stored message, encrypt it and send it as a
-Data Message.</li>
-</ul>
-Otherwise, ignore the message.</dd>
-<dt>Otherwise, ignore the message.</dt></dl></dd>
-<dt>If authstate is AUTHSTATE_V1_SETUP:</dt>
-<dd>Verify the information in the Key Exchange Message.  If the
-verification succeeds:
-<ul>
-<li>If the received Key Exchange Message did not have the reply field
-set to 0x01, reply with a Key Exchange Message with the reply field set
-to 0x01.</li>
-<li>Transition authstate to AUTHSTATE_NONE.</li>
-<li>Transition msgstate to MSGSTATE_ENCRYPTED.</li>
-<li>If there is a recent stored message, encrypt it and send it as a
-Data Message.</li>
-</ul>
-Otherwise, ignore the message.</dd>
-</dl>
 <h4>User types a message to be sent</h4>
 <dl>
 <dt>If msgstate is MSGSTATE_PLAINTEXT:</dt>
diff --git a/UPGRADING b/UPGRADING
index 6ca2134..d77a261 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -2,336 +2,440 @@ Table of Contents
 
 1. Introduction
 2. Major Additions
-2.1. Fragmentation
-2.2. Socialist Millionaires' Protocol
+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. 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
+3.1.1. Removed Operations
+3.1.2. Added Operations
+3.2. Instance Tags
+3.3. Fragmentation Changes
+3.4. Asynchronous Private Key Generation
 
 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.
+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 3.2.0 along with a short
+This section describes the new features in OTR 4.0.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]
+2.1. Instance Tags
 
-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
+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 after the OTR/fragment header portion. If a client receives a
+message that lists a destination instance tag different from his own, he will
+discard it (and issue a callback notifying the application of the event).
 
-The first new callback has the following signature:
+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.
 
-    int (*max_message_size)(void *opdata, ConnContext *context);
+2.2. Asynchronous Private Key Generation
 
-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.
+Key generation can happen in a separate thread without blocking an application.
 
-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
+2.3. Extra Symmetric Key
 
-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.
+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).
 
-3.1.2. Account Name
+2.4. Convert Operations
 
-The other two new callbacks have the following signatures: 
+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.
 
-    const char *(*account_name)(void *opdata, const char *account,
-	    const char *protocol);
-    void (*account_name_free)(void *opdata, const char *account_name);
+2.5. SMP, Error, and Message Event Callbacks
 
-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.
+To avoid hard-coded English phrases in libotr, a lot of the operation which
+used to pass back strings are replaced by operations that pass back event codes.
 
-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.
+2.6. Fragmentation Changes
 
-Setting account_name to NULL will cause libotr to use
-ConnContext->accountname as the displayed name for an account.
+In libotr version 3.2.0, you would need to call otrl_message_sending() to
+receive 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.2. Using Fragmentation  [Added in 3.1.0]
+3. Required Changes
 
-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:
+3.1. OtrlMessageAppOps Callbacks
 
-gcry_error_t otrl_message_fragment_and_send(const OtrlMessageAppOps *ops,
-	void *opdata, ConnContext *context, const char *message,
-	OtrlFragmentPolicy fragPolicy, char **returnFragment);
+3.1.1. Removed Operations
 
-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;
-	}
+/* 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.
+
+
+/* Create a instance tag for the given accountname/protocol if
+ * desired. */
+void (*create_instag)(void *opdata, const char *accountname,
+	const char *protocol);
+
+This is called when the library notices this account name and protocol pair does
+not have an instance tag. Similar to create_privkey(), your application may
+simply open a file handle and call:
+gcry_error_t otrl_instag_generate_FILEp(OtrlUserState us, FILE *instf,
+        const char *accountname, const char *protocol)
+
+If you don't provide an implementation for this operation, a new 
+non-persistent instance tag will be randomly generated. One benefit to having a
+persisted instance tag is that if your application closes and re-opens during
+a private conversation, further messages you receive from this buddy will
+correctly raise the OTRL_MSGEVENT_RCVDMSG_UNREADABLE event instead of raising
+OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE because destination instance tag is now
+different from your own.
+
+
+/* Called immediately before a data message is encrypted, and after a data
+ * message is decrypted. The OtrlConvertType parameter has the value
+ * OTRL_CONVERT_SENDING or OTRL_CONVERT_RECEIVING to differentiate these
+ * cases. */
+void (*convert_msg)(void *opdata, ConnContext *context,
+	OtrlConvertType convert_type, char ** dest, const char *src);
+
+/* Deallocate a string returned by convert_msg. */
+void (*convert_free)(void *opdata, ConnContext *context, char *dest);
+
+The convert_msg() operation is called immediately before a message is encrypted
+and immediately after a message is decrypted. This callback can tweak the
+plaintext message as needed. One use case would be for an application to tweak
+formatting on the plaintext if, for example, this is something that would
+normally be done on the plaintext by some other entity while the message is in
+transit.
+
+
+3.2. Instance Tags
+
+If your application allows the same user to be logged in multiple times from
+different locations, it should probably be aware of instance tags. A user can
+maintain multiple concurrent OTR conversations with a buddy who is logged in
+multiple times. Only one of the buddy's sessions can be a client who is running
+OTR protocol version 2. When a user has a conversation with a buddy who is
+running OTR protocol version 2, the conversation is associated with a
+ConnContext that lists "their_instance" as OTRL_INSTAG_MASTER (which has a value
+of 0). Each version 3 conversation with the same buddy will have its own
+ConnContext, which you can differentiate by the value in the "their_instance"
+field.
+
+In the linked list of ConnContexts, the master context for a buddy is always
+listed immediately before its children. Fingerprints are only stored with the
+master context. Given a ConnContext associated to a conversation with a buddy,
+you can easily iterate over all the contexts for that buddy by doing the
+following:
+
+void example_something_happened(ConnContext * context) {
+    ConnContext * context_iter = context->m_context;
+    
+    while (context_iter && context_iter->m_context == context->m_context) {
+	/* Something you wish to affect all contexts of a particular buddy */
+	context_iter = context_iter->next;
     }
 
-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
+If a user has multiple OTR sessions with the same buddy, your application will
+likely want to provide some way for the user to select which instance to send
+outgoing messages to. You can detect when a user has multiple OTR sessions with
+the same buddy by iterating over the ConnContexts of a buddy when a
+conversation has gone secure and checking whether more than one is not in
+plaintext state. You specify which instance outgoing messages are directed to
+in otrl_message_sending:
+
+gcry_error_t otrl_message_sending(OtrlUserState us,
+	const OtrlMessageAppOps *ops,
+	void *opdata, const char *accountname, const char *protocol,
+	const char *recipient, otrl_instag_t instag, const char *original_msg,
+	OtrlTLV *tlvs, char **messagep, OtrlFragmentPolicy fragPolicy,
+	ConnContext **contextp,
+	void (*add_appdata)(void *data, ConnContext *context),
+	void *data);
+
+Instead of an actual instance tag, you can specify a meta instance tag (e.g.,
+if the user has not made an explicit selection). Here are the list of meta
+instance tags, as defined in instag.h:
+
+#define OTRL_INSTAG_BEST 1 /* Most secure, based on: conv status,
+                            * then fingerprint status, then most recent. */
+#define OTRL_INSTAG_RECENT 2 /* Most recent of the two meta instances below */
+#define OTRL_INSTAG_RECENT_RECEIVED 3
+#define OTRL_INSTAG_RECENT_SENT 4
+
+OTRL_INSTAG_BEST choses the instance that has the best conv status, then
+fingerprint status (in the event of a tie), then most recent (similarly in the
+event of a tie). When calculating how recent an instance has been active,
+OTRL_INSTAG_BEST is limited by a one second resolution. OTRL_INSTAG_RECENT*
+does not have this limitation, but due to inherent uncertainty in some networks,
+libotr's notion of the most recent may not always agree with the remote network.
+It is important to understand this limitation due to the issue noted in the next
+paragraph.
+
+Note that instances do add some uncertainty when dealing with networks that only
+deliver messages to the most recently active session for a buddy who is logged
+in multiple times. If you have a particular instance selected, and the IM
+network is simply not going to deliver to that particular instance, there isn't
+too much libotr can do. In this case, you may want your application to warn when
+a user has selected an instance that is not the most recent.
+
+To explicitly specify the destination instance of a protocol version 2
+conversation with a particular buddy, the instag value is OTRL_INSTAG_MASTER.
+
+To look up a ConnContext associated with a particular instance (or meta-
+instance), specify the instance in otrl_context_find():
+
+ConnContext * otrl_context_find(OtrlUserState us, const char *user,
+	const char *accountname, const char *protocol,
+	otrl_instag_t their_instance, int add_if_missing, int *addedp,
+	void (*add_app_data)(void *data, ConnContext *context), void *data)
+
+If your application persists instance tags, when it starts up, it should call
+one the following functions to read the persisted instance tags:
+
+gcry_error_t otrl_instag_read(OtrlUserState us, const char *filename);
+gcry_error_t otrl_instag_read_FILEp(OtrlUserState us, FILE *instf);
+
+It would make sense to do this immediately after your application has read
+stored privkeys and fingerprints.
+
+3.3. Fragmentation Changes
+
+In libotr version 3.2.0, you would need to call otrl_message_sending() to
+receive 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(). Simply
+specify an OtrlFragmentPolicy to otrl_message_sending(). The fragmentation
+policies are the same as before, and an addition policy
+"OTRL_FRAGMENT_SEND_SKIP" has been added for cases when fragmentation is not
+desired.
+
+3.4. Asynchronous Private Key Generation
+
+An application that wants to begin asynchronous key generation calls the
+following method:
+
+/* Begin a private key generation that will potentially take place in
+ * a background thread.  This routine must be called from the main
+ * thread.  It will set *newkeyp, which you can pass to
+ * otrl_privkey_generate_calculate in a background thread.  If it
+ * returns gcry_error(GPG_ERR_EEXIST), then a privkey creation for
+ * this accountname/protocol is already in progress, and *newkeyp will
+ * be set to NULL. */
+gcry_error_t otrl_privkey_generate_start(OtrlUserState us,
+        const char *accountname, const char *protocol, void **newkeyp)
+
+A background thread can call the following method with the structure that was
+passed into "newkeyp" above:
+
+/* Do the private key generation calculation.  You may call this from a
+ * background thread.  When it completes, call
+ * otrl_privkey_generate_finish from the _main_ thread. */
+gcry_error_t otrl_privkey_generate_calculate(void *newkey)
+
+
+Upon completion the application would call:
+
+/* Call this from the main thread only.  It will write the newly created
+ * private key into the given file and store it in the OtrlUserState. */
+gcry_error_t otrl_privkey_generate_finish(OtrlUserState us,
+        void *newkey, const char *filename)
+
+If the privkey generation was cancelled, the application should call:
+
+/* Call this from the main thread only, in the event that the background
+ * thread generating the key is cancelled.  The newkey is deallocated,
+ * and must not be used further. */
+void otrl_privkey_generate_cancelled(OtrlUserState us, void *newkey)
 
-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);
 
diff --git a/src/instag.c b/src/instag.c
index 8a42bfb..f3de8bd 100644
--- a/src/instag.c
+++ b/src/instag.c
@@ -249,6 +249,10 @@ gcry_error_t otrl_instag_write(OtrlUserState us, const char *filename)
 gcry_error_t otrl_instag_write_FILEp(OtrlUserState us, FILE *instf)
 {
     OtrlInsTag *p;
+    /* This line should be ignored when read back in, since there are no
+    tabs. */
+    fprintf(instf, "%s\n", "WARNING! You shouldn't copy this file to another"
+    " computer. It is unnecessary and can cause problems.")
     for(p=us->instag_root; p; p=p->next) {
 	fprintf(instf, "%s\t%s\t%08x\n", p->accountname, p->protocol,
 		p->instag);

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/libotr.git



More information about the Pkg-privacy-commits mailing list