[Tkabber-dev] r2089 - in trunk/tkabber-plugins: . otr otr/tclotr

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Sat Jan 25 18:21:31 MSK 2014


Author: sergei
Date: 2014-01-25 18:21:31 +0400 (Sat, 25 Jan 2014)
New Revision: 2089

Modified:
   trunk/tkabber-plugins/ChangeLog
   trunk/tkabber-plugins/otr/key.tcl
   trunk/tkabber-plugins/otr/otr.tcl
   trunk/tkabber-plugins/otr/tclotr/auth.tcl
   trunk/tkabber-plugins/otr/tclotr/crypto.tcl
   trunk/tkabber-plugins/otr/tclotr/data.tcl
   trunk/tkabber-plugins/otr/tclotr/key.tcl
   trunk/tkabber-plugins/otr/tclotr/message.tcl
   trunk/tkabber-plugins/otr/tclotr/otr.tcl
   trunk/tkabber-plugins/otr/tclotr/smp.tcl
Log:
	* otr/key.tcl, otr/tclotr/crypto.tcl: Code cleanup, made DSA key
	  generation more clear.

	* otr/*: Added short description to procedures definitions.


Modified: trunk/tkabber-plugins/ChangeLog
===================================================================
--- trunk/tkabber-plugins/ChangeLog	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/ChangeLog	2014-01-25 14:21:31 UTC (rev 2089)
@@ -1,3 +1,10 @@
+2014-01-25  Sergei Golovan <sgolovan at nes.ru>
+
+	* otr/key.tcl, otr/tclotr/crypto.tcl: Code cleanup, made DSA key
+	  generation more clear.
+
+	* otr/*: Added short description to procedures definitions.
+
 2014-01-24  Sergei Golovan <sgolovan at nes.ru>
 
 	* otr/key.tcl, otr/otr.tcl: Finish all existing OTR sessions for a

Modified: trunk/tkabber-plugins/otr/key.tcl
===================================================================
--- trunk/tkabber-plugins/otr/key.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/key.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -213,8 +213,9 @@
 		-command [namespace code [list delete_key $w]]
     grid $f.delete -row 5 -column 1 -sticky nsew
 
+    set progress -1
     ProgressBar $f.pb -variable [namespace current]::progress \
-		      -maximum 10000 \
+		      -maximum 40000 \
 		      -type infinite
     grid $f.pb -row 6 -column 0 -columnspan 2 -sticky ew
 
@@ -226,6 +227,23 @@
     $w draw
 }
 
+# key::fill_dialog --
+#
+#	Private procedure which showa an appropriate help message and
+#	enables or disables the dialog controls depending on whether a DSA
+#	key for the selected JID exists.
+#
+# Arguments:
+#	w	    Dialog window path.
+#	args	    Ignored arguments from [trace] command.
+#
+# Result:
+#	Empty string.
+#
+# Side effects:
+#	The help message in the keys dialog is set, the buttons are enabled
+#	or disabled.
+
 proc key::fill_dialog {w args} {
     variable Keys
     variable keyjid
@@ -260,8 +278,27 @@
 	$f.gen configure -state normal
 	$f.delete configure -state disabled
     }
+    return
 }
 
+# key::import_key --
+#
+#	Private procedure which imports DSA key to a key file in PEM format
+#	and either adds it or replaces the existing one.
+#
+# Arguments:
+#	w	    Dialog window path.
+#
+# Result:
+#	Empty string.
+#
+# Side effects:
+#	The key for a given JID is read from an external file. The filename
+#	where to get the key is asked in an addiyional dialog. JID for which
+#	the key is to import is taken from the $keyjid variable. The key
+#	itself is stored to the global $Keys dictionary and to the
+#	~/.tkabber/otr/keys.xml file.
+
 proc key::import_key {w} {
     variable Keys
     variable keyjid
@@ -280,8 +317,26 @@
     store $Keys
     [namespace parent]::clear_all_jid $keyjid
     fill_dialog $w
+    return
 }
 
+# key::export_key --
+#
+#	Private procedure which exports existing DSA key to a key file in PEM
+#	format.
+#
+# Arguments:
+#	w	    Dialog window path.
+#
+# Result:
+#	Empty string.
+#
+# Side effects:
+#	The key for a given JID is saved into an external file. The filename
+#	where to save the key is asked in an addiyional dialog. JID for which
+#	the key is to export is taken from the $keyjid variable. The key
+#	itself is taken from the global $Keys dictionary.
+
 proc key::export_key {w} {
     variable Keys
     variable keyjid
@@ -296,8 +351,25 @@
     set key [dict get $Keys $keyjid]
 
     ::otr::key::writePEM $key $filename
+    return
 }
 
+# key::delete_key --
+#
+#	Private procedure which deletes DSA key from the keys dictionary and
+#	from the external storage.
+#
+# Arguments:
+#	w	    Dialog window path.
+#
+# Result:
+#	Empty string.
+#
+# Side effects:
+#	The key for a given JID is deleted from the $Keys dictionary and
+#	from ~/.tkabber/otr/keys.xml. JID for which the key is to delete
+#	is taken from the $keyjid variable.
+
 proc key::delete_key {w} {
     variable Keys
     variable keyjid
@@ -306,8 +378,39 @@
     store $Keys
     [namespace parent]::clear_all_jid $keyjid
     fill_dialog $w
+    return
 }
 
+# ::otr::crypto::GenPrimesIteration --
+#	A dirty hack which overrides ::otr::crypto::genPrimesIteration and
+#	adds a side effect which updates progressbar. This helps not freezing
+#	the GUI during DSA private key generation.
+
+rename ::otr::crypto::GenPrimesIteration ::otr::crypto::GenPrimesIteration:old
+
+proc ::otr::crypto::GenPrimesIteration {L t q p0 pseed pgen_counter} "
+	incr [namespace current]::key::progress
+	update
+	::otr::crypto::GenPrimesIteration:old \$L \$t \$q \$p0 \$pseed \$pgen_counter"
+
+# key::generate_key --
+#
+#	Private procedure which generates and store new DSA private key.
+#	Before starting, the dialog controls are disabled, upon finishing,
+#	they are enabled again.
+#
+# Arguments:
+#	w	    Dialog window path.
+#
+# Result:
+#	Empty string.
+#
+# Side effects:
+#	New key is generated and stored into the $Keys dictionary and
+#	~/.tkabber/otr/keys.xml. JID for which to store the key is taken
+#	from the $keyjid variable. Progress is tracking by increasing
+#	the $progress variable upon each internal iteration.
+
 proc key::generate_key {w} {
     variable Keys
     variable keyjid
@@ -331,63 +434,34 @@
 	while {!$fstatus} {
 	    lassign [::otr::crypto::getFirstSeed $N $N] \
 		    fstatus firstseed
+	    incr progress
 	    update
 	}
-	incr progress
 
-	set qstatus 0
-	while {!$qstatus} {
-	    lassign [::otr::crypto::genPrimesInit $N $firstseed] \
-		    qstatus q qseed qgen_counter
-	    update
-	}
-	incr progress
-
-	set pstatus 0
-	while {!$pstatus} {
-	    lassign [::otr::crypto::genPrimesCont $L $qseed] \
-		    pstatus p0 pseed pgen_counter
-	    update
-	}
-	incr progress
-
-	set outlen 256
-	set iterations [expr {[::otr::crypto::Ceil $L $outlen]-1}]
-	set old_counter $pgen_counter
-	set x 0
-	set mult 1
-	for {set i 0} {$i <= $iterations} {incr i} {
-	    incr x [expr {[::otr::crypto::Bits2Int \
-				[::sha2::sha256 -bin \
-				    [::otr::crypto::Int2Octets $pseed]]] * $mult}]
-	    incr pseed
-	    set mult [expr {$mult * 2**$outlen}]
-	}
-	set x [expr {2**($L-1) + ($x % (2**($L-1)))}]
-	set t [::otr::crypto::Ceil $x [expr {2*$q*$p0}]]
-
-	while {$pgen_counter <= 4*$L+$old_counter} {
-	    lassign [::otr::crypto::genPrimesIteration \
-			    $L $t $q $p0 $pseed $pgen_counter] \
-		    status t p q pseed pgen_counter
-	    if {$status} {
-		break
-	    }
+	# Generate p and q
+	set status 0
+	while {!$status} {
+	    lassign [::otr::crypto::genPrimes $L $N $firstseed] \
+		    status p q pseed qseed pgen_counter qgen_counter
 	    incr progress
 	    update
 	}
     }
 
+    # Generate g
     set g [::otr::crypto::genGenerator $p $q]
     incr progress
     update
+    # Generate x y
     lassign [::otr::crypto::genKeyPair $p $q $g] kstatus x y
     incr progress
     update
+    set progress -1
     dict set Keys $keyjid [list $p $q $g $y $x]
     store $Keys
     [namespace parent]::clear_all_jid $keyjid
     fill_dialog $w
     $w itemconfigure 0 -state normal
     $f.jid configure -state normal
+    return
 }

Modified: trunk/tkabber-plugins/otr/otr.tcl
===================================================================
--- trunk/tkabber-plugins/otr/otr.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/otr.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -884,25 +884,15 @@
 	lappend x [::xmpp::xml::create "" -xmlns $ns -attrs {discard 1}]
     }
 
-    if {[info exists res(interaction)]} {
-	switch -- $res(interaction) {
-	    smp {
-		if {[info exists res(question)]} {
-		    after idle [namespace code \
-					  [list reply_smp_dialog_qa \
-						$xlib $from $res(question)]]
-		} else {
-		    after idle [namespace code \
-					  [list reply_smp_dialog_ss \
-						$xlib $from]]
-		}
-	    }
-	    default {
-		# Nothing to do
-	    }
-	}
+    if {[info exists res(question)]} {
+	after idle [namespace code [list reply_smp_dialog_qa \
+					 $xlib $from $res(question)]]
     }
 
+    if {[info exists res(secret)]} {
+	after idle [namespace code [list reply_smp_dialog_ss \
+					 $xlib $from]]
+    }
     return
 }
 

Modified: trunk/tkabber-plugins/otr/tclotr/auth.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/auth.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/auth.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -300,7 +300,7 @@
             return [list $authstate $msgstate ""]
         }
         AUTHSTATE_AWAITING_DHKEY {
-            lassign [::otr::crypto::DHKeys $gy $x] ssid c cp m1 m2 m1p m2p
+            lassign [::otr::crypto::AKEKeys $gy $x] ssid c cp m1 m2 m1p m2p
 
             set authstate AUTHSTATE_AWAITING_SIG
             return [list $authstate $msgstate [createRevealSignatureMessage \
@@ -478,7 +478,7 @@
                 #puts "D-H public key is incorrect"
                 return [list $authstate $msgstate ""]
             }
-            lassign [::otr::crypto::DHKeys $gx $y] ssid c cp m1 m2 m1p m2p
+            lassign [::otr::crypto::AKEKeys $gx $y] ssid c cp m1 m2 m1p m2p
 
             set myhmac \
                 [::sha2::hmac -bin -key $m2 [::otr::data::encode DATA $encr]]
@@ -646,7 +646,7 @@
             return [list $authstate $msgstate ""]
         }
         AUTHSTATE_AWAITING_SIG {
-            lassign [::otr::crypto::DHKeys $gy $x] ssid c cp m1 m2 m1p m2p
+            lassign [::otr::crypto::AKEKeys $gy $x] ssid c cp m1 m2 m1p m2p
             set myhmac \
                 [::sha2::hmac -bin -key $m2p [::otr::data::encode DATA $encr]]
             if {[string range $myhmac 0 19] ne $hmac} {

Modified: trunk/tkabber-plugins/otr/tclotr/crypto.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/crypto.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/crypto.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -46,6 +46,19 @@
 #
 #       Diffie-Hellman key exchange auxiliary procedures
 
+# ::otr::crypto::DHGx --
+#
+#       Return the DIffie-Hellman public key.
+#
+# Arguments:
+#       x           Private key.
+#
+# Result:
+#       D-H public key (G**x mod P).
+#
+# Side effects:
+#       Modulus and generator are taken from global variables.
+
 proc ::otr::crypto::DHGx {x} {
     variable Prime
     variable G
@@ -53,19 +66,60 @@
     Power $Prime $G $x
 }
 
+# ::otr::crypto::DHCheck --
+#
+#       Check if the Diffie-Hellman public key is correct.
+#
+# Arguments:
+#       gy          Public key.
+#
+# Result:
+#       1 if gy is correct (1 < gy < P-1).
+#
+# Side effects:
+#       Modulus is taken from a global variable.
+
 proc ::otr::crypto::DHCheck {gy} {
     variable Prime
 
     expr {$gy > 1 && $gy < $Prime-1}
 }
 
+# ::otr::crypto::DHSecret --
+#
+#       Return the common Diffie-Hellman secret.
+#
+# Arguments:
+#       gy          Public key.
+#       x           Private key.
+#
+# Result:
+#       The D-H secret (gy**x mod P).
+#
+# Side effects:
+#       Modulus is taken from a global variable.
+
 proc ::otr::crypto::DHSecret {gy x} {
     variable Prime
 
     Power $Prime $gy $x
 }
 
-proc ::otr::crypto::DHKeys {gy x} {
+# ::otr::crypto::AKEKeys --
+#
+#       Return the set of AKE keys.
+#
+# Arguments:
+#       gy          Public key.
+#       x           Private key.
+#
+# Result:
+#       List of SSID and set of keys which are used in AKE.
+#
+# Side effects:
+#       Modulus is taken from a global variable.
+
+proc ::otr::crypto::AKEKeys {gy x} {
     set s [DHSecret $gy $x]
     set secbytes [::otr::data::encode MPI $s]
     set ssid [string range [::sha2::sha256 -bin \x00$secbytes] 0 7]
@@ -80,6 +134,21 @@
     list $ssid $c $cp $m1 $m2 $m1p $m2p $extrakey
 }
 
+# ::otr::crypto::AESKeys --
+#
+#       Return the set of DES keys to encrypt/decrypt and hash/verify
+#       data messages.
+#
+# Arguments:
+#       gy          Public key.
+#       x           Private key.
+#
+# Result:
+#       List of keys which are used to exchange data messages.
+#
+# Side effects:
+#       Modulus is taken from a global variable.
+
 proc ::otr::crypto::AESKeys {gy x} {
     set s [DHSecret $gy $x]
     set secbytes [::otr::data::encode MPI $s]
@@ -430,142 +499,184 @@
 
 ##############################################################################
 #
-#       Useful procedures implementing arithmetics modulo some prime number.
+#       Generating DSA private key (see FIPS 186-4)
 
-# ::otr::crypto::Mult --
+# ::otr::crypto::getFirstSeed --
 #
-#       Multiplication modulo some positive integer.
+#       Return the first seed for DSA parameters (p, q) generator (see
+#       appendix A.1.2.1.1 in FIPS 186-4).
 #
 # Arguments:
-#       prime       Modulus (usually it's a prime number).
-#       x           The first multiplier.
-#       y           The second multiplier.
+#       N           Length of q in bits.
+#       seedlen     Length of the returned first seed (seedlen >= N)
 #
 # Result:
-#       x*y mod p.
+#       Tuple {status, seedlen} where status is 0 in case of failure (in this
+#       case the seedlen is undefined) and 1 in case of success.
 #
 # Side effects:
-#       None.
+#       The random number of seeldlen bits is used.
 
-proc ::otr::crypto::Mult {prime x y} {
-    expr {($x * $y) % $prime}
+proc ::otr::crypto::getFirstSeed {N seedlen} {
+    switch -- $N {
+        160 - 224 - 256 {}
+        default { return {0} }
+    }
+
+    if {$seedlen < $N} {
+        return {0}
+    }
+
+    set firstseed [random $seedlen]
+    if {$firstseed < 2**($N-1)} {
+        incr firstseed [expr {2**($N-1)}]
+    }
+    return [list 1 $firstseed]
 }
 
-# ::otr::crypto::Inverse --
+# ::otr::crypto::genPrimes --
 #
-#       Inverse modulo some prime number. It's found using the Euclid GCD
-#       algorithm.
+#       Return the DSA parameters (p, q) (see appendix A.1.2.1.2 in FIPS
+#       186-4).
 #
 # Arguments:
-#       prime       Modulus (must be a prime number, or result will not be
-#                   the inversion.
-#       x           Number to inverse.
+#       L               Length of p in bits.
+#       N               Length of q in bits.
+#       firstseed       The first seed to be used (the length of firstseed is
+#                       to be not less then N).
 #
 # Result:
-#       Number y such that x*y mod p = 1.
+#       Tuple {status, p, q, pseed, qseed, pgen_counter, qgen_counter} where
+#       status is 0 in case of failure (in this case all the other values
+#       are unassigned) or 1 in case of success. p and q are the generated
+#       DSA primes, pseed and qseed are the new seed values, pgen_counter and
+#       qgen_counter show how many iterations were used.
 #
 # Side effects:
 #       None.
 
-proc ::otr::crypto::Inverse {prime x} {
-    lassign [EGCD $prime $x] x1 y1
-    expr {$y1 % $prime}
+proc ::otr::crypto::genPrimes {L N firstseed} {
+    switch -- $L/$N {
+        1024/160 - 2048/224 - 2048/256 - 3072/256 {}
+        default {
+            return {0}
+        }
+    }
+
+    lassign [randomPrime $N $firstseed] \
+            qstatus q qseed qgen_counter
+    if {!$qstatus} {
+        return {0}
+    }
+
+    lassign [randomPrime [expr {[Ceil $L 2]+1}] $qseed] \
+            pstatus p0 pseed pgen_counter
+    if {!$pstatus} {
+        return {0}
+    }
+
+    set outlen 256
+    set iterations [expr {[Ceil $L $outlen]-1}]
+    set old_counter $pgen_counter
+    set x 0
+    set mult 1
+    for {set i 0} {$i <= $iterations} {incr i} {
+        incr x [expr {[Bits2Int [::sha2::sha256 \
+                                        -bin [Int2Octets $pseed]]] * $mult}]
+        incr pseed
+        set mult [expr {$mult * 2**$outlen}]
+    }
+    set x [expr {2**($L-1) + ($x % (2**($L-1)))}]
+    set t [Ceil $x [expr {2*$q*$p0}]]
+
+    while {$pgen_counter <= 4*$L+$old_counter} {
+        lassign [GenPrimesIteration $L $t $q $p0 $pseed $pgen_counter] \
+                status t p pseed pgen_counter
+        if {$status} {
+            return [list 1 $p $q $pseed $qseed $pgen_counter $qgen_counter]
+        }
+    }
+    return {0}
 }
 
-# ::otr::crypto::Power --
+# ::otr::crypto::genGenerator --
 #
-#       Power modulo some integer. It's implemented using the exponentiation
-#       by squaring algorithm.
+#       Return the DSA generator g (see appendix A.2.1 of FIPS 186-4).
 #
 # Arguments:
-#       prime       Modulus (usually it's a prime number).
-#       x           Exponentiation base.
-#       n           Exponentiation index.
+#       p               DSA prime p.
+#       q               DSA prime q.
 #
 # Result:
-#       x**n mod p.
+#       The generator g of the DSA key.
 #
 # Side effects:
-#       None.
+#       A random number of bitlength at least L is used.
 
-proc ::otr::crypto::Power {prime x n} {
-    set y 1
-    while {$n > 0} {
-        if {$n % 2 == 0} {
-            set n [expr {$n / 2}]
-            set x [Mult $prime $x $x]
-        } else {
-            incr n -1
-            set y [Mult $prime $y $x]
-        }
+proc ::otr::crypto::genGenerator {p q} {
+    set e [expr {($p-1)/$q}]
+    set g 1
+    set l [BitLength $p]
+    while {$g == 1} {
+        set h [expr {2+([random $l] % ($p-3))}]
+        set g [Power $p $h $e]
     }
-    return $y
+    set g
 }
 
-# ::otr::crypto::EGCD --
+# ::otr::crypto::genKeyPair --
 #
-#       Perform the Euclid algorithm to find the Greatest Common Divisor.
+#       Return the DSA private and public key pair for given parameters
+#       p, q and g (see appendix B.1.1 of FIPS 186-4).
 #
 # Arguments:
-#       a           Positive integer.
-#       b           Positive integer.
+#       p               DSA prime p.
+#       q               DSA prime q.
+#       g               DSA generator g.
 #
 # Result:
-#       Tuple {x y} where x*a+y*b = GCD(a,b).
+#       Tuple {status, x, y} where status is 0 in case of failure (in this
+#       case the x and y are unassigned), or 1 in case of success (in this
+#       case x is a private key, y is a g^x mod p - public key.
 #
 # Side effects:
-#       None.
+#       A random number of bitlength N+64 is used.
 
-proc ::otr::crypto::EGCD {a b} {
-    set r [expr {$a % $b}]
-    if {$r == 0} {
-        return {0 1}
-    } else {
-        lassign [EGCD $b $r] x y
-        return [list $y [expr {$x - $y * ($a / $b)}]]
-    }
-}
+proc ::otr::crypto::genKeyPair {p q g} {
+    set L [BitLength $p]
+    set N [BitLength $q]
 
-# ::otr::crypto::getFirstSeed --
-
-proc ::otr::crypto::getFirstSeed {N seedlen} {
-    switch -- $N {
-        160 - 224 - 256 {}
-        default { return {0 0} }
-    }
-
-    if {$seedlen < $N} {
-        return {0 0}
-    }
-
-    set firstseed [random $seedlen]
-    if {$firstseed < 2**($N-1)} {
-        incr firstseed [expr {2**($N-1)}]
-    }
-    return [list 1 $firstseed]
-}
-
-# ::otr::crypto::testPrime --
-
-proc ::otr::crypto::testPrime {n} {
-    if {$n > 2 && $n % 2 == 0} {
-        return 0
-    }
-    for {set k 3} {$k*$k <= $n} {incr k 2} {
-        if {$n % $k == 0} {
-            return 0
+    switch -- $L/$N {
+        1024/160 - 2048/224 - 2048/256 - 3072/256 {}
+        default {
+            return {0}
         }
     }
-    return 1
-}
 
-# ::otr::crypto::Ceil --
-
-proc ::otr::crypto::Ceil {k n} {
-    expr {($k+$n-1)/$n}
+    set c [random [expr {$N+64}]]
+    set x [expr {$c % ($q-1) + 1}]
+    set y [Power $p $g $x]
+    return [list 1 $x $y]
 }
 
 # ::otr::crypto::randomPrime --
+#
+#       Generate a prime number of a given bitlength using the Shawe-Taylor
+#       algorithm (see Appendix C.6 from FIPS 186-4).
+#
+# Arguments:
+#       length      Bitlength of a number to generate.
+#       input_seed  The seed to be used for the generation.
+#
+# Result:
+#       Tuple {status, prime, prime_seed, prime_gen_counter} where status is
+#       1 if the generation is successful and 0 otherwise. If status is 0 then
+#       the other values aren't assigned. If status is 1 then prime is the
+#       generated prime number, prime_seed is a new seed value,
+#       prime_gen_counter shows hom many iterations were made.
+#
+# Side effects:
+#       None.
 
 proc ::otr::crypto::randomPrime {length input_seed} {
     if {$length < 2} {
@@ -581,13 +692,14 @@
             set c [expr {($c % 2 == 0)? $c+1 : $c}]
             incr prime_gen_counter
             incr prime_seed 2
-            if {[testPrime $c]} {
+            if {[TestPrime $c]} {
                 return [list 1 $c $prime_seed $prime_gen_counter]
             }
         }
         return {0}
     } else {
-        lassign [randomPrime [Ceil $length 2] $input_seed] status c0 prime_seed prime_gen_counter
+        lassign [randomPrime [Ceil $length 2] $input_seed] \
+                status c0 prime_seed prime_gen_counter
         if {!$status} {
             return {0}
         }
@@ -597,7 +709,8 @@
         set x 0
         set mult 1
         for {set i 0} {$i <= $iterations} {incr i} {
-            incr x [expr {[Bits2Int [::sha2::sha256 -bin [Int2Octets $prime_seed]]] * $mult}]
+            incr x [expr {[Bits2Int [::sha2::sha256 \
+                                    -bin [Int2Octets $prime_seed]]] * $mult}]
             incr prime_seed
             set mult [expr {$mult * 2**$outlen}]
         }
@@ -605,91 +718,42 @@
         set t [Ceil $x [expr {2*$c0}]]
 
         while {$prime_gen_counter < 4*$length+$old_counter} {
-            if {2*$t*$c0+1 > 2**$length} {
-                set t [Ceil [expr {2**($length-1)}] [expr {2*$c0}]]
-            }
-            set c [expr {2*$t*$c0+1}]
-            incr prime_gen_counter
-
-            set a 0
-            set mult 1
-            for {set i 0} {$i <= $iterations} {incr i} {
-                incr a [expr {[Bits2Int [::sha2::sha256 -bin [Int2Octets $prime_seed]]] * $mult}]
-                incr prime_seed
-                set mult [expr {$mult * 2**$outlen}]
-            }
-            set a [expr {2+($a % ($c-3))}]
-            set z [Power $c $a [expr {2*$t}]]
-
-            lassign [EGCD $c [expr {$z-1}]] xx yy
-            set pow [Power $c $z $c0]
-            if {$xx*$c + $yy*($z-1) == 1 && $pow == 1} {
+            lassign [GenPrimesIteration \
+                            $length $t 1 $c0 $prime_seed $prime_gen_counter] \
+                    status t c prime_seed prime_gen_counter
+            if {$status} {
                 return [list 1 $c $prime_seed $prime_gen_counter]
             }
-            incr t
         }
         return {0}
     }
 }
 
-# ::otr::crypto::genPrimes --
+# ::otr::crypto::GenPrimesIteration --
+#
+#       Private procedure which implements a common iteration part for
+#       [randomPrime] (steps 23-34 in appendix C.6) and [genPrimes]
+#       (steps 11-22 in appendix A.1.2.1.2) routines (see FIPS 186-4).
+#
+# Arguments:
+#       L               Length of the generated prime p in bits.
+#       t               Candidate for a (p-1) factor.
+#       q               Number which p-1 is to be divisible by.
+#       p0              Prime number which is to be a factor of (p-1).
+#       pseed           Seed.
+#       pgen_counter    Value of the global iteration counter.
+#
+# Result:
+#       Tuple {status, t, p, pseed, pgen_counter} where status equals 0
+#       if iterations are to be continued (in this case p is not prime
+#       and has to be ignored), or 1 in case if p is prime. t is the next
+#       auxiliary factor of p-1, pseed is nes seed, pgen_counter is the
+#       next counter value.
+#
+# Side effects:
+#       None.
 
-proc ::otr::crypto::genPrimes {L N firstseed} {
-    switch -- $L/$N {
-        1024/160 - 2048/224 - 2048/256 - 3072/256 {}
-        default {
-            return {0}
-        }
-    }
-
-    lassign [genPrimesInit $N $firstseed] qstatus q qseed qgen_counter
-    if {!$qstatus} {
-        return {0}
-    }
-
-    lassign [genPrimesCont $L $qseed] pstatus p0 pseed pgen_counter
-    if {!$pstatus} {
-        return {0}
-    }
-
-    set outlen 256
-    set iterations [expr {[Ceil $L $outlen]-1}]
-    set old_counter $pgen_counter
-    set x 0
-    set mult 1
-    for {set i 0} {$i <= $iterations} {incr i} {
-        incr x [expr {[Bits2Int [::sha2::sha256 -bin [Int2Octets $pseed]]] * $mult}]
-        incr pseed
-        set mult [expr {$mult * 2**$outlen}]
-    }
-    set x [expr {2**($L-1) + ($x % (2**($L-1)))}]
-    set t [Ceil $x [expr {2*$q*$p0}]]
-
-    while {$pgen_counter <= 4*$L+$old_counter} {
-        lassign [genPrimesIteration $L $t $q $p0 $pseed $pgen_counter] \
-                status t p q pseed pgen_counter
-        if {$status} {
-            return [list 1 $p $q $pseed $qseed $pgen_counter $qgen_counter]
-        }
-    }
-    return {0}
-}
-
-# ::otr::primes::genPrimesInit --
-
-proc ::otr::crypto::genPrimesInit {N firstseed} {
-    randomPrime $N $firstseed
-}
-
-# ::otr::crypto::genPrimesCont --
-
-proc ::otr::crypto::genPrimesCont {L qseed} {
-    randomPrime [expr {[Ceil $L 2]+1}] $qseed
-}
-
-# ::otr::crypto::genPrimesIteration --
-
-proc ::otr::crypto::genPrimesIteration {L t q p0 pseed pgen_counter} {
+proc ::otr::crypto::GenPrimesIteration {L t q p0 pseed pgen_counter} {
     if {2*$t*$q*$p0+1 > 2**$L} {
         set t [Ceil [expr {2**($L-1)}] [expr {2*$q*$p0}]]
     }
@@ -711,42 +775,157 @@
     lassign [EGCD $p [expr {$z-1}]] xx yy
     set pow [Power $p $z $p0]
     if {$xx*$p + $yy*($z-1) == 1 && $pow == 1} {
-        return [list 1 $t $p $q $pseed $pgen_counter]
+        return [list 1 $t $p $pseed $pgen_counter]
     }
     incr t
-    return [list 0 $t $p $q $pseed $pgen_counter]
+    return [list 0 $t $p $pseed $pgen_counter]
 }
 
-# ::otr::crypto::genGenerator --
+# ::otr::crypto::TestPrime --
+#       Private procedure which tests the given positive integer number for
+#       primality. It does that by division on 2 and all odd numbers up to
+#       the square root of the tested number trials, so it's supposed to
+#       work only with sufficiently short numbers (32 bit).
+#
+# Arguments:
+#       n           Positive integer to test.
+#
+# Result:
+#       1 if it is a prime number, 0 otherwise.
+#
+# Side effects:
+#       None.
 
-proc ::otr::crypto::genGenerator {p q} {
-    set e [expr {($p-1)/$q}]
-    set g 1
-    set l [BitLength $p]
-    while {$g == 1} {
-        set h [expr {2+([random $l] % ($p-3))}]
-        set g [Power $p $h $e]
+proc ::otr::crypto::TestPrime {n} {
+    if {$n < 2} {
+        return 0
     }
-    set g
+    if {$n > 2 && $n % 2 == 0} {
+        return 0
+    }
+    for {set k 3} {$k*$k <= $n} {incr k 2} {
+        if {$n % $k == 0} {
+            return 0
+        }
+    }
+    return 1
 }
 
-# ::otr::crypto::genKeyPair --
+# ::otr::crypto::Ceil --
+#
+#       Private procedure which computes ceiling of the ratio of two positive
+#       integers.
+#
+# Arguments:
+#       k           Positive integer umerator.
+#       n           Positive integer denominator.
+#
+# Result:
+#       ceil(k/n).
+#
+# Side effects:
+#       None.
 
-proc ::otr::crypto::genKeyPair {p q g} {
-    set L [BitLength $p]
-    set N [BitLength $q]
+proc ::otr::crypto::Ceil {k n} {
+    expr {($k+$n-1)/$n}
+}
 
-    switch -- $L/$N {
-        1024/160 - 2048/224 - 2048/256 - 3072/256 {}
-        default {
-            return {0}
+##############################################################################
+#
+#       Useful procedures implementing arithmetics modulo some prime number.
+
+# ::otr::crypto::Mult --
+#
+#       Multiplication modulo some positive integer.
+#
+# Arguments:
+#       prime       Modulus (usually it's a prime number).
+#       x           The first multiplier.
+#       y           The second multiplier.
+#
+# Result:
+#       x*y mod p.
+#
+# Side effects:
+#       None.
+
+proc ::otr::crypto::Mult {prime x y} {
+    expr {($x * $y) % $prime}
+}
+
+# ::otr::crypto::Inverse --
+#
+#       Inverse modulo some prime number. It's found using the Euclid GCD
+#       algorithm.
+#
+# Arguments:
+#       prime       Modulus (must be a prime number, or result will not be
+#                   the inversion.
+#       x           Number to inverse.
+#
+# Result:
+#       Number y such that x*y mod p = 1.
+#
+# Side effects:
+#       None.
+
+proc ::otr::crypto::Inverse {prime x} {
+    lassign [EGCD $prime $x] x1 y1
+    expr {$y1 % $prime}
+}
+
+# ::otr::crypto::Power --
+#
+#       Power modulo some integer. It's implemented using the exponentiation
+#       by squaring algorithm.
+#
+# Arguments:
+#       prime       Modulus (usually it's a prime number).
+#       x           Exponentiation base.
+#       n           Exponentiation index.
+#
+# Result:
+#       x**n mod p.
+#
+# Side effects:
+#       None.
+
+proc ::otr::crypto::Power {prime x n} {
+    set y 1
+    while {$n > 0} {
+        if {$n % 2 == 0} {
+            set n [expr {$n / 2}]
+            set x [Mult $prime $x $x]
+        } else {
+            incr n -1
+            set y [Mult $prime $y $x]
         }
     }
+    return $y
+}
 
-    set c [random [expr {$N+64}]]
-    set x [expr {$c % ($q-1) + 1}]
-    set y [Power $p $g $x]
-    return [list 1 $x $y]
+# ::otr::crypto::EGCD --
+#
+#       Perform the Euclid algorithm to find the Greatest Common Divisor.
+#
+# Arguments:
+#       a           Positive integer.
+#       b           Positive integer.
+#
+# Result:
+#       Tuple {x y} where x*a+y*b = GCD(a,b).
+#
+# Side effects:
+#       None.
+
+proc ::otr::crypto::EGCD {a b} {
+    set r [expr {$a % $b}]
+    if {$r == 0} {
+        return {0 1}
+    } else {
+        lassign [EGCD $b $r] x y
+        return [list $y [expr {$x - $y * ($a / $b)}]]
+    }
 }
 
 # vim:ts=8:sw=4:sts=4:et

Modified: trunk/tkabber-plugins/otr/tclotr/data.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/data.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/data.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -493,20 +493,56 @@
 }
 
 # ::otr::data::encodeTLV --
+#
+#       Encode a TLV record for an OTR data message.
+#
+# Arguments:
+#       type            TLV type (non-negative integer).
+#       data            TLV payload (binary string).
+#
+# Result:
+#       Binary string with encoded TLV.
+#
+# Side effects:
+#       None.
 
 proc ::otr::data::encodeTLV {type data} {
     return [encode SHORT $type][encode SHORT [string length $data]]$data
 }
 
 # ::otr::data::decodeTLV --
+#
+#       Decode a TLV record from an OTR data message.
+#
+# Arguments:
+#       data            Binary string with encoded TLV in it.
+#
+# Result:
+#       Tuple {type, payload, rest} where type is a TLV type, payload is a
+#       TLV payload, and rest is the rest of the given data.
+#
+# Side effects:
+#       Error is raised if decoding fails.
 
 proc ::otr::data::decodeTLV {data} {
     lassign [decode SHORT $data] type data
     lassign [decode SHORT $data] length data
-    list $type [string range $data 0 [expr {$length-1}]] [string range $data $length end]
+    list $type [string range $data 0 [expr {$length-1}]] \
+               [string range $data $length end]
 }
 
 # ::otr::data::Bin2Hex --
+#
+#       Convert binary string to hex representation. Useful for debugging.
+#
+# Arguments:
+#       data            Binary data to print.
+#
+# Result:
+#       Hexadecimal string.
+#
+# Side effects:
+#       None.
 
 proc ::otr::data::Bin2Hex {data} {
     binary scan $data H* hex

Modified: trunk/tkabber-plugins/otr/tclotr/key.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/key.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/key.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -21,6 +21,19 @@
 
 namespace eval ::otr::key {}
 
+# ::otr::key::encodePEM --
+#
+#       Encode the given DSA private key into PEM format.
+#
+# Arguments:
+#       key         DSA private key {p, q, g, y, x}.
+#
+# Result:
+#       Key in PEM format.
+#
+# Side effects:
+#       None.
+
 proc ::otr::key::encodePEM {key} {
     lassign $key p q g y x
     set ev [::asn::asnInteger 0]
@@ -35,6 +48,19 @@
         [::base64::encode -maxlen 64 $seq]
 }
 
+# ::otr::key::decodePEM --
+#
+#       Decode the diven DSA private key from PEM format.
+#
+# Arguments:
+#       data            PEM encoded DSA private key.
+#
+# Result:
+#       DSA private key {p, q, g, y, x}.
+#
+# Side effects:
+#       Error is raised if decoding is failed.
+
 proc ::otr::key::decodePEM {data} {
     if {![regexp -- {-----BEGIN DSA PRIVATE KEY-----\n(.*)\n-----END DSA PRIVATE KEY-----} \
                  $data -> base64]} {
@@ -59,15 +85,41 @@
     list $p $q $g $y $x
 }
 
-proc ::otr::key::readPEM {file} {
+# ::otr::key::readPEM --
+#
+#       Read and decode DSA private key from a file in PEM format.
+#
+# Arguments:
+#       filename        Filename with the key to read.
+#
+# Result:
+#       DSA private key {p, q, g, y, x}.
+#
+# Side effects:
+#       Error is raised if file can't be read or decoding is failed.
+
+proc ::otr::key::readPEM {filename} {
     set fd [open $file]
     set data [read $fd]
     close $fd
     decodePEM $data
 }
 
-proc ::otr::key::writePEM {key file} {
-    set fd [open $file w]
+# ::otr::key::writePEM --
+#
+#       Encode DSA private key to PEM format and write it to a file.
+#
+# Arguments:
+#       key             DSA private key {p, q, g, y, x}.
+#       filename        Filename to write.
+# Result:
+#       Empty string.
+#
+# Side effects:
+#       Error may be raised if the file can't be written.
+
+proc ::otr::key::writePEM {key filename} {
+    set fd [open $filename w]
     set data [encodePEM $key]
     puts $fd $data
     close $fd

Modified: trunk/tkabber-plugins/otr/tclotr/message.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/message.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/message.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -97,6 +97,39 @@
 }
 
 # ::otr::message::processDataMessage --
+#
+#       Process received OTR data message. Check its validity, decode and
+#       process the TLVs if any.
+#
+# Arguments:
+#       version         Protocol version.
+#       msgstate        OTR message state.
+#       smpstate        OTR SMP state.
+#       data            Unparsed yet message data (encrypted text, HMAC and
+#                       old keys for revelation).
+#       flags           Message flags.
+#       skeyid          Sender's (peer's) key serial ID.
+#       rkeyid          Receiver's (your) key serial ID.
+#       gy              Next sender's public key.
+#       ctrtop          Top 8 bytes of AES counter.
+#       rkey            Receiver's key for decrypting.
+#       rmac            Receiver's key for verification.
+#       -smpcommand cmd Callback to call when some SMP state data are to be
+#                       stored or retrieved.
+#       -sinstance tag  The sender's instance tag (for version 3)
+#       -rinstance tag  The receiver's instance tag (for version 3)
+#
+# Result:
+#       Serialized array with the following fields (not all of them may be
+#       present): info - info message to show to theh user, replyerr -
+#       error message to reply, debug - debug message, message - the message
+#       body, msgstate - new message state, smpstate - new smp state,
+#       smpprogress - the progress of SMP procedure, secret - ask user the
+#       SMP secret, question - show user the SMP question, reply - send
+#       the given data message.
+#
+# Side effects:
+#       SMP data may be stored or retrieved via callback.
 
 proc ::otr::message::processDataMessage {version msgstate smpstate data
                                          flags skeyid rkeyid gy ctrtop
@@ -219,7 +252,7 @@
 
                 {*}$smpcommand set data1     $value
 
-                return [list interaction smp]
+                return [list secret ""]
             }
             3 {
                 # SMP message 2
@@ -335,7 +368,7 @@
 
                 {*}$smpcommand set data1     $value
 
-                return [list interaction smp question $question]
+                return [list question $question]
             }
         }
     }
@@ -354,7 +387,10 @@
 #       data            Payload to parse.
 #
 # Result:
-#       Tuple {}.
+#       Tuple {cryptotext, hmac, oldmackeys} where cryptotext is the
+#       encrypted message body (possibly with TLV attached), hmac is
+#       a message HMAC for verifiction, and oldmackeys is a set of old
+#       receiver's MAC keys for revelation.
 #
 # Side effects:
 #       Error is raised if decoding is failed for some reason.
@@ -370,15 +406,18 @@
 
 # ::otr::message::getDataMessageKeyids --
 #
-#       Return D-H key serial IDs encoded in the data message (with stripped
-#       out protocol version, message type, sender and receiver instance tags.
+#       Return message flags, D-H key serial IDs, the peer's next public key,
+#       counter, encoded in the data message (with stripped out protocol
+#       version, message type, sender and receiver instance tags).
 #
 # Arguments:
 #       data            Payload to parse.
 #
 # Result:
-#       Tuple {skeyid, rkeyid} with the sender and recipient key serials, or
-#       tuple {0, 0} if decoding failed.
+#       Tuple {flags, skeyid, rkeyid, gy, ctrtop, data} with the message
+#       flags, sender and recipient key serials, peer's public key, the top
+#       8 bytes of the AES counter, and rest of the message, or tuple
+#       {{}, 0, 0, 0, 0, ""} if decoding fails.
 #
 # Side effects:
 #       None.
@@ -407,6 +446,19 @@
 }
 
 # ::otr::message::createDataMessagePlaintext --
+#
+#       Assemble the plaintext part of OTR data message.
+#
+# Arguments:
+#       humanreadable       Human readable part (message body).
+#       tlvlist             List with an even items number with TLV types
+#                           and payloads.
+#
+# Result:
+#       Encoded plaintext part of OTR data message.
+#
+# Side effects:
+#       None.
 
 proc ::otr::message::createDataMessagePlaintext {humanreadable tlvlist} {
     set res [encoding convertto utf-8 $humanreadable]
@@ -425,6 +477,15 @@
 }
 
 # ::otr::message::parseDataMessagePlaintext --
+#
+#       Parse an OTR data message plaintest part.
+#
+# Arguments:
+#       data            Plaintext part of OTR data message.
+#
+# Result:
+#       Tuple {body, tlvlist} where body is a human readable message, and
+#       tlvlist is an even items number list of TLV types and payloads.
 
 proc ::otr::message::parseDataMessagePlaintext {data} {
     set tlvlist {}

Modified: trunk/tkabber-plugins/otr/tclotr/otr.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/otr.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/otr.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -965,7 +965,7 @@
     set gy $state(gy,$state(keyidy))
     set x  $state(x,[expr {$state(keyid)-1}])
 
-    lassign [::otr::crypto::DHKeys $gy $x] state(ssid)
+    lassign [::otr::crypto::AKEKeys $gy $x] state(ssid)
 }
 
 # ::otr::ShowCantDecipherError --
@@ -1063,7 +1063,7 @@
             }
 
             set ret {}
-            foreach field {message interaction question} {
+            foreach field {message secret question} {
                 if {[info exists res($field)]} {
                     lappend ret $field $res($field)
                 }

Modified: trunk/tkabber-plugins/otr/tclotr/smp.tcl
===================================================================
--- trunk/tkabber-plugins/otr/tclotr/smp.tcl	2014-01-24 20:09:13 UTC (rev 2088)
+++ trunk/tkabber-plugins/otr/tclotr/smp.tcl	2014-01-25 14:21:31 UTC (rev 2089)
@@ -25,6 +25,26 @@
 }
 
 # ::otr::smp::createSMPMessage1 --
+#
+#       Return the SMP message 1 or 1Q binary packet.
+#
+# Arguments:
+#       smpstate            SMP state to check.
+#       privkey             Your DSA private key.
+#       pubkey              Peer's DSA public key.
+#       ssid                Secure session ID.
+#       usersecret          User part of the secret.
+#       -question question  If present, then the 1Q message is created.
+#
+# Result:
+#       Tuple {smpstate, type, payload, x a2 a3} where smpstate is a new SMP
+#       state, type and payload make a binary to encrypt and send, x, a2, a3
+#       are the values to save for the next SMP spteps if SMP state is
+#       SMPSTATE_EXPECT1. Otherwise x, a2, a3 aren't returned.
+#
+# Side effects:
+#       Four 128-bit random numbers are generated.
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::createSMPMessage1 {smpstate privkey pubkey ssid \
                                     usersecret args} {
@@ -68,6 +88,28 @@
 }
 
 # ::otr::smp::processSMPMessage1 --
+#
+#       Process SMP message 1 (or 1Q without the question) and create
+#       SMP message 2 to reply.
+#
+# Arguments:
+#       smpstate            SMP state to check.
+#       data                Message to parse.
+#       privkey             Your DSA private key.
+#       pubkey              Peer's DSA public key.
+#       ssid                Secure session ID.
+#       usersecret          User part of the secret.
+#
+# Result:
+#       Tuple {smpstate, type, payload, g3a, g2, g3, b3, Pb, Qb} where
+#       smpstate is a new SMP state, payload is a binary to encrypt and
+#       send, the rest are the values to save for the next SMP spteps if SMP
+#       state is SMPSTATE_EXPECT1. Otherwise, g3a, g2, g3, b3, Pb, Qb aren't
+#       returned.
+#
+# Side effects:
+#       Seven 128-bit random numbers are generated.
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::processSMPMessage1 {smpstate data privkey pubkey ssid
                                      usersecret} {
@@ -136,6 +178,24 @@
 }
 
 # ::otr::smp::processSMPMessage2 --
+#
+#       Process SMP message 2 and create SMP message 3 to reply.
+#
+# Arguments:
+#       smpstate            SMP state to check.
+#       data                Message to parse.
+#       x a2 a3             SMP values returned by [createSMPMessage1].
+#
+# Result:
+#       Tuple {smpstate, type, payload, Pa, Qa, cP, D5, D6, Ra, cR, D7} where
+#       smpstate is a new SMP state, type and payload make a binary to
+#       encrypt and send, the rest are the values to save for the next SMP
+#       steps if SMP state is SMPSTATE_EXPECT2. Otherwise, Pa, Qa, cP, D5,
+#       D6, Ra, cR, D7 aren't returned.
+#
+# Side effects:
+#       Four 128-bit random numbers are generated.
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::processSMPMessage2 {smpstate data x a2 a3} {
     variable q
@@ -206,6 +266,23 @@
 }
 
 # ::otr::smp::processSMPMessage3 --
+#
+#       Process SMP message 3 and create SMP message 4 to reply.
+#
+# Arguments:
+#       smpstate            SMP state to check.
+#       data                Message to parse.
+#       g3a g2 g3 b3 Pb Qb  SMP values returned by [processSMPMessage1].
+#
+# Result:
+#       Tuple {smpstate, type, payload, result} where smpstate is a new SMP
+#       state, type and payload make a binary to encrypt and send, the result
+#       equals 1 if authentication succeeded, or 0 if not, if SMP state is
+#       SMPSTATE_EXPECT3. Otherwise, no result field is returned.
+#
+# Side effects:
+#       One 128-bit random numbers are generated.
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::processSMPMessage3 {smpstate data g3a g2 g3 b3 Pb Qb} {
     variable q
@@ -266,6 +343,23 @@
 }
 
 # ::otr::smp::processSMPMessage4 --
+#
+#       Process SMP message 4 and return the authentication result.
+#
+# Arguments:
+#       smpstate            SMP state to check.
+#       data                Message to parse.
+#       a3 g3b PaPb QaQb Ra SMP values returned by [createMessage1] and
+#                           [processSMPMessage2].
+#
+# Result:
+#       Tuple {smpstate, type, payload, result} where smpstate is a new SMP
+#       state, type and payload make a binary to encrypt and send, the result
+#       equals 1 if authentication succeeded, or 0 if not, if SMP state is
+#       SMPSTATE_EXPECT3. Otherwise, no result field is returned.
+#
+# Side effects:
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::processSMPMessage4 {smpstate data a3 g3b PaPb QaQb Ra} {
     variable q
@@ -307,28 +401,88 @@
 }
 
 # ::otr::smp::Check --
+#
+#       Wrapper to ::otr::crypto::DHCheck to make the call shorter.
+#
+# Arguments:
+#       a               Number to check.
+#
+# Result:
+#       1 if $a is greater than 1 and less than P-1 (where P is a
+#       D-H prime).
+#
+# Side effects:
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::Check {a} {
     ::otr::crypto::DHCheck $a
 }
 
 # ::otr::smp::Exp --
+#
+#       Exponent a**b mod P where P is a D-H prime.
+#
+# Arguments:
+#       a           Exponent base.
+#       b           Exponent index.
+#
+# Result:
+#       a**b mod P.
+#
+# Side effects:
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::Exp {a b} {
     ::otr::crypto::DHSecret $a $b
 }
 
+# ::otr::smp::Mult --
+#
+#       Multiplication modulo P.
+#
+# Arguments:
+#       a           First multiplier.
+#       b           Second multiplier.
+#
+# Result:
+#       a*b mod P.
+#
+# Side effects:
+#       Modulus is taken from a global variable.
+
 proc ::otr::smp::Mult {a b} {
     ::otr::crypto::Mult $::otr::crypto::Prime $a $b
 }
 
 # ::otr::smp::Inv --
+#
+#       Inverse modulo P.
+#
+# Arguments:
+#       a           Number.
+#
+# Result:
+#       a**(-1) mod P, or b such that a*b = 1 mod P.
+#
+# Side effects:
+#       Modulus is taken from a global variable.
 
 proc ::otr::smp::Inv {a} {
     ::otr::crypto::Inverse $::otr::crypto::Prime $a
 }
 
 # ::otr::smp::ParsePayload --
+#
+#       Decode SMP payload - a series of long integers.
+#
+# Arguments:
+#       data        Binary to parse.
+#
+# Result:
+#       List of integers.
+#
+# Side effects:
+#       Error is raised if parsing fails.
 
 proc ::otr::smp::ParsePayload {data} {
     set res {}
@@ -341,6 +495,17 @@
 }
 
 # ::otr::smp::Payload --
+#
+#       Create SMP payload from a series of integers.
+#
+# Arguments:
+#       args        List of integers.
+#
+# Result:
+#       SMP binary.
+#
+# Side effects:
+#       None.
 
 proc ::otr::smp::Payload {args} {
     set res ""
@@ -352,6 +517,20 @@
 }
 
 # ::otr::smp::Hash --
+#
+#       SMP hash for its zero knowledge proofs.
+#
+# Arguments:
+#       version     Number.
+#       arg1        The first number to hash.
+#       arg2        (optional) The second number to hash.
+#
+# Result:
+#       Integer representation of the SHA256 hash of the concatenated given
+#       arguments.
+#
+# Side effects:
+#       None.
 
 proc ::otr::smp::Hash {version arg1 {arg2 ""}} {
     set res ""
@@ -364,6 +543,20 @@
 }
 
 # ::otr::smp::Secret --
+#
+#       Return the common secret to check for equality using the SMP.
+#
+# Arguments:
+#       pubkey1     The first public key.
+#       pubkey2     The second public key.
+#       ssid        The secure session ID.
+#       secret      The users' common secret.
+#
+# Result:
+#       Secret to compare.
+#
+# Side effects:
+#       None.
 
 proc ::otr::smp::Secret {pubkey1 pubkey2 ssid secret} {
     set res ""



More information about the Tkabber-dev mailing list