func buildMessage(msg *outgoingMessage, devices []uint32) ([]jsonMessage, error) { paddedMessage, err := createMessage(msg) if err != nil { return nil, err } recid := recID(msg.tel) messages := []jsonMessage{} for _, devid := range devices { if !textSecureStore.ContainsSession(recid, devid) { pkb, err := makePreKeyBundle(msg.tel, devid) if err != nil { return nil, err } sb := axolotl.NewSessionBuilder(textSecureStore, textSecureStore, textSecureStore, textSecureStore, recid, pkb.DeviceID) err = sb.BuildSenderSession(pkb) if err != nil { return nil, err } } sc := axolotl.NewSessionCipher(textSecureStore, textSecureStore, textSecureStore, textSecureStore, recid, devid) encryptedMessage, messageType, err := sc.SessionEncryptMessage(paddedMessage) if err != nil { return nil, err } rrID, err := sc.GetRemoteRegistrationID() if err != nil { return nil, err } messages = append(messages, jsonMessage{ Type: messageType, DestDeviceID: devid, DestRegistrationID: rrID, Body: base64.StdEncoding.EncodeToString(encryptedMessage), }) } return messages, nil }
// Authenticate and decrypt a received message func handleReceivedMessage(msg []byte) error { macpos := len(msg) - 10 tmac := msg[macpos:] aesKey := registrationInfo.signalingKey[:32] macKey := registrationInfo.signalingKey[32:] if !axolotl.ValidTruncMAC(msg[:macpos], tmac, macKey) { return errors.New("Invalid MAC for Incoming Message") } ciphertext := msg[1:macpos] plaintext, err := axolotl.Decrypt(aesKey, ciphertext) if err != nil { return err } env := &textsecure.Envelope{} err = proto.Unmarshal(plaintext, env) if err != nil { return err } recid := recID(env.GetSource()) sc := axolotl.NewSessionCipher(textSecureStore, textSecureStore, textSecureStore, textSecureStore, recid, env.GetSourceDevice()) switch *env.Type { case textsecure.Envelope_RECEIPT: handleReceipt(env) return nil case textsecure.Envelope_CIPHERTEXT: msg, legacy := getMessage(env) wm, err := axolotl.LoadWhisperMessage(msg) if err != nil { return err } b, err := sc.SessionDecryptWhisperMessage(wm) if err != nil { return err } err = handleMessage(env.GetSource(), env.GetTimestamp(), b, legacy) if err != nil { return err } case textsecure.Envelope_PREKEY_BUNDLE: msg, legacy := getMessage(env) pkwm, err := axolotl.LoadPreKeyWhisperMessage(msg) if err != nil { return err } b, err := sc.SessionDecryptPreKeyWhisperMessage(pkwm) if err != nil { return err } err = handleMessage(env.GetSource(), env.GetTimestamp(), b, legacy) if err != nil { return err } default: return fmt.Errorf("Not implemented %d", *env.Type) } return nil }
// Authenticate and decrypt a received message func handleReceivedMessage(msg []byte) error { macpos := len(msg) - 10 tmac := msg[macpos:] aesKey := registrationInfo.signalingKey[:32] macKey := registrationInfo.signalingKey[32:] if !axolotl.ValidTruncMAC(msg[:macpos], tmac, macKey) { return ErrInvalidMACForMessage } ciphertext := msg[1:macpos] plaintext, err := axolotl.Decrypt(aesKey, ciphertext) if err != nil { return err } env := &textsecure.Envelope{} err = proto.Unmarshal(plaintext, env) if err != nil { return err } recid := recID(env.GetSource()) sc := axolotl.NewSessionCipher(textSecureStore, textSecureStore, textSecureStore, textSecureStore, recid, env.GetSourceDevice()) switch *env.Type { case textsecure.Envelope_RECEIPT: handleReceipt(env) return nil case textsecure.Envelope_CIPHERTEXT: msg, legacy := getMessage(env) wm, err := axolotl.LoadWhisperMessage(msg) if err != nil { return err } b, err := sc.SessionDecryptWhisperMessage(wm) if _, ok := err.(axolotl.DuplicateMessageError); ok { log.Infof("Incoming WhisperMessage %s. Ignoring.\n", err) return nil } if _, ok := err.(axolotl.InvalidMessageError); ok { log.Infof("Incoming WhisperMessage %s. Ignoring.\n", err) return nil } if err != nil { return err } err = handleMessage(env.GetSource(), env.GetTimestamp(), b, legacy) if err != nil { return err } case textsecure.Envelope_PREKEY_BUNDLE: msg, legacy := getMessage(env) pkwm, err := axolotl.LoadPreKeyWhisperMessage(msg) if err != nil { return err } b, err := sc.SessionDecryptPreKeyWhisperMessage(pkwm) if _, ok := err.(axolotl.DuplicateMessageError); ok { log.Infof("Incoming PreKeyWhisperMessage %s. Ignoring.\n", err) return nil } if _, ok := err.(axolotl.PreKeyNotFoundError); ok { log.Infof("Incoming PreKeyWhisperMessage %s. Ignoring.\n", err) return nil } if _, ok := err.(axolotl.InvalidMessageError); ok { log.Infof("Incoming PreKeyWhisperMessage %s. Ignoring.\n", err) return nil } if err != nil { return err } err = handleMessage(env.GetSource(), env.GetTimestamp(), b, legacy) if err != nil { return err } default: return MessageTypeNotImplementedError{uint32(*env.Type)} } return nil }