in otr/smp.go [65:159]
func (c *Conversation) processSMP(in tlv) (out tlv, complete bool, err error) {
data := in.data
switch in.typ {
case tlvTypeSMPAbort:
if c.smp.state != smpState1 {
err = smpFailureError
}
c.resetSMP()
return
case tlvTypeSMP1WithQuestion:
// We preprocess this into a SMP1 message.
nulPos := bytes.IndexByte(data, 0)
if nulPos == -1 {
err = errors.New("otr: SMP message with question didn't contain a NUL byte")
return
}
c.smp.question = string(data[:nulPos])
data = data[nulPos+1:]
}
numMPIs, data, ok := getU32(data)
if !ok || numMPIs > 20 {
err = errors.New("otr: corrupt SMP message")
return
}
mpis := make([]*big.Int, numMPIs)
for i := range mpis {
var ok bool
mpis[i], data, ok = getMPI(data)
if !ok {
err = errors.New("otr: corrupt SMP message")
return
}
}
switch in.typ {
case tlvTypeSMP1, tlvTypeSMP1WithQuestion:
if c.smp.state != smpState1 {
c.resetSMP()
out = c.generateSMPAbort()
return
}
if c.smp.secret == nil {
err = smpSecretMissingError
return
}
if err = c.processSMP1(mpis); err != nil {
return
}
c.smp.state = smpState3
out = c.generateSMP2()
case tlvTypeSMP2:
if c.smp.state != smpState2 {
c.resetSMP()
out = c.generateSMPAbort()
return
}
if out, err = c.processSMP2(mpis); err != nil {
out = c.generateSMPAbort()
return
}
c.smp.state = smpState4
case tlvTypeSMP3:
if c.smp.state != smpState3 {
c.resetSMP()
out = c.generateSMPAbort()
return
}
if out, err = c.processSMP3(mpis); err != nil {
return
}
c.smp.state = smpState1
c.smp.secret = nil
complete = true
case tlvTypeSMP4:
if c.smp.state != smpState4 {
c.resetSMP()
out = c.generateSMPAbort()
return
}
if err = c.processSMP4(mpis); err != nil {
out = c.generateSMPAbort()
return
}
c.smp.state = smpState1
c.smp.secret = nil
complete = true
default:
panic("unknown SMP message")
}
return
}