Example #1
0
// Create tries to create an encrypted database with the given passphrase and
// iter many KDF iterations. Thereby, dbname is the prefix of the following
// two database files which will be created and must not exist already:
//
//  dbname.db
//  dbname.key
//
// The SQL database is initialized with the statements given in createStmts.
// In case of error (for example, the database files do exist already or
// cannot be created) an error is returned.
func Create(dbname string, passphrase []byte, iter int, createStmts []string) error {
	dbfile := dbname + DBSuffix
	keyfile := dbname + KeySuffix
	// make sure files do not exist already
	if _, err := os.Stat(dbfile); err == nil {
		return log.Errorf("encdb: dbfile '%s' exists already", dbfile)
	}
	if _, err := os.Stat(keyfile); err == nil {
		return log.Errorf("encdb: dbfile '%s' exists already", keyfile)
	}
	// create keyfile
	key, err := generateKeyfile(keyfile, passphrase, iter)
	if err != nil {
		return err
	}
	// create DB
	dbfile += fmt.Sprintf("?_pragma_key=x'%s'&_pragma_cipher_page_size=4096",
		hex.EncodeToString(key))
	db, err := sql.Open("sqlite3", dbfile)
	if err != nil {
		return log.Error(err)
	}
	defer db.Close()
	_, err = db.Exec("PRAGMA auto_vacuum = full;")
	if err != nil {
		return log.Error(err)
	}
	return createTables(db, createStmts)
}
Example #2
0
func checkDelayArgs(c *cli.Context) error {
	if !c.Bool("nodelaycheck") {
		if c.Int("mindelay") < def.MinMinDelay {
			return log.Errorf("--mindelay must be at least %d", def.MinMinDelay)
		}
		if c.Int("maxdelay") < def.MinMaxDelay {
			return log.Errorf("--maxdelay must be at least %d", def.MinMaxDelay)
		}
		if c.Int("mindelay") >= c.Int("maxdelay") {
			return log.Error("--mindelay must be strictly smaller than --maxdelay")
		}
	}
	return nil
}
Example #3
0
func readInnerHeader(r io.Reader) (*innerHeader, error) {
	var ih innerHeader
	// read Type
	if err := binary.Read(r, binary.BigEndian, &ih.Type); err != nil {
		return nil, err
	}
	// check Type
	if ih.Type != paddingType &&
		ih.Type != dataType &&
		ih.Type != dataType|signType &&
		ih.Type != signatureType {
		return nil, log.Errorf("msg: invalid inner header type %d", ih.Type)
	}
	// read Plen
	if err := binary.Read(r, binary.BigEndian, &ih.PLen); err != nil {
		return nil, log.Error(err)
	}
	// read More
	if err := binary.Read(r, binary.BigEndian, &ih.More); err != nil {
		return nil, log.Error(err)
	}
	// read Skip
	if err := binary.Read(r, binary.BigEndian, &ih.Skip); err != nil {
		return nil, log.Error(err)
	}
	// read content
	ih.content = make([]byte, ih.PLen)
	if _, err := io.ReadFull(r, ih.content); err != nil {
		return nil, log.Error(err)
	}
	return &ih, nil
}
Example #4
0
func parseFDOption(c *cli.Context, name string) (
	fd uintptr,
	fp *os.File,
	err error,
) {
	fs := c.GlobalString(name)
	switch fs {
	case "stdin":
		fd = uintptr(syscall.Stdin)
		fp = os.Stdin
	case "stdout":
		fd = uintptr(syscall.Stdout)
		fp = os.Stdout
	case "stderr":
		fd = uintptr(syscall.Stderr)
		fp = os.Stderr
	default:
		i, err := strconv.Atoi(fs)
		if err != nil {
			return 0, nil,
				log.Errorf("cannot parse --%s %s: argument must be \"stdin\", "+
					"\"stdout\", \"stderr\" or an integer (a file descriptor)",
					name, fs)
		}
		fd = uintptr(i)
		fp = os.NewFile(fd, name)
	}
	return
}
Example #5
0
func mutecryptDeleteUID(c *cli.Context, id string, passphrase []byte) error {
	args := []string{
		"--homedir", c.GlobalString("homedir"),
		"--loglevel", c.GlobalString("loglevel"),
		"--logdir", c.GlobalString("logdir"),
		"uid", "delete",
		"--id", id,
		"--force",
	}
	cmd := exec.Command("mutecrypt", args...)
	var errbuf bytes.Buffer
	cmd.Stderr = &errbuf
	ppR, ppW, err := os.Pipe()
	if err != nil {
		return err
	}
	defer ppR.Close()
	ppW.Write(passphrase)
	ppW.Close()
	cmd.ExtraFiles = append(cmd.ExtraFiles, ppR)
	if err := cmd.Run(); err != nil {
		return log.Errorf("%s: %s", err, strings.TrimSpace(errbuf.String()))
	}
	return nil
}
Example #6
0
func readOuterHeader(r io.Reader) (*outerHeader, error) {
	var oh outerHeader
	// read Type
	if err := binary.Read(r, binary.BigEndian, &oh.Type); err != nil {
		return nil, log.Error(err)
	}
	// check Type
	if oh.Type != preHeaderPacket &&
		oh.Type != encryptedHeader &&
		oh.Type != cryptoSetup &&
		oh.Type != hmacPacket &&
		oh.Type != encryptedPacket {
		return nil, log.Errorf("msg: invalid outer header type %d", oh.Type)
	}
	// read Plen
	if err := binary.Read(r, binary.BigEndian, &oh.PLen); err != nil {
		return nil, log.Error(err)
	}
	// read PacketCount
	if err := binary.Read(r, binary.BigEndian, &oh.PacketCount); err != nil {
		return nil, log.Error(err)
	}
	// read inner packet
	oh.inner = make([]byte, oh.PLen)
	if _, err := io.ReadFull(r, oh.inner); err != nil {
		return nil, log.Error(err)
	}
	return &oh, nil
}
Example #7
0
// ReadKeyfile reads a randomly generated and encrypted AES-256 key from the
// file with the given filename and returns it in unencrypted form.
// The key is protected by a passphrase, which is processed by PBKDF2 to
// derive the AES-256 key to decrypt the generated key.
func ReadKeyfile(filename string, passphrase []byte) (key []byte, err error) {
	// open keyfile
	keyfile, err := os.Open(filename)
	if err != nil {
		return nil, log.Error(err)
	}
	defer keyfile.Close()
	// read iter and convert to int
	var biter = make([]byte, 8)
	if _, err := keyfile.Read(biter); err != nil {
		return nil, log.Error(err)
	}
	uiter := encode.ToUint64(biter)
	if uiter > 2147483647 {
		return nil, log.Errorf("encdb: ReadKeyfile: invalid iter value")
	}
	iter := int(uiter)
	// read salt
	var salt = make([]byte, 32)
	if _, err := keyfile.Read(salt); err != nil {
		return nil, log.Error(err)
	}
	// read encrypted key
	var encKey = make([]byte, 16+32)
	if _, err := keyfile.Read(encKey); err != nil {
		return nil, log.Error(err)
	}
	// compute derived key from passphrase
	dk := pbkdf2.Key([]byte(passphrase), salt, iter, 32, sha256.New)
	// decrypt key
	return cipher.AES256CBCDecrypt([]byte(dk), encKey), nil
}
Example #8
0
func (ce *CryptEngine) verifyServerSig(
	uid *uid.Message,
	msgReply *uid.MessageReply,
	position uint64,
) error {
	// For the first keyserver message we do not need to verify the server signature
	if uid.Localpart() == "keyserver" && uid.UIDContent.MSGCOUNT == 0 {
		return nil
	}

	// Get keyserver UID
	srvUID, _, found, err := ce.keyDB.GetPublicUID("keyserver@"+uid.Domain(), position)
	if err != nil {
		return err
	}
	if !found {
		return log.Errorf("cryptengine: no keyserver signature key found for domain '%s'", uid.Domain())
	}

	// Verify server signature
	if err := msgReply.VerifySrvSig(uid, srvUID.UIDContent.SIGKEY.PUBKEY); err != nil {
		return log.Error(err)
	}
	return nil
}
Example #9
0
// ECDH computes a Diffie-Hellman (DH) key exchange over the elliptic curve (EC)
// curve25519. If ownPublicKey is given it is used to check for the key
// reflection attack. Otherwise it is derived from privateKey.
func ECDH(privateKey, peersPublicKey, ownPublicKey *[32]byte) (*[32]byte, error) {
	var (
		sharedKey [32]byte
		pubKey    []byte
	)
	// check mandatory key length
	if privateKey == nil {
		return nil, log.Error("cipher: curve25519.ECDH(): privateKey == nil")
	}
	if peersPublicKey == nil {
		return nil, log.Error("cipher: curve25519.ECDH(): peersPublicKey == nil")
	}
	// check for key reflection attack
	if ownPublicKey != nil {
		pubKey = ownPublicKey[:]
	} else {
		var publicKey [32]byte
		curve25519.ScalarBaseMult(&publicKey, privateKey)
		pubKey = publicKey[:]
	}
	if bytes.Equal(pubKey, peersPublicKey[:]) {
		return nil, log.Errorf("cipher: curve25519.ECDH(): publicKey == peersPublicKey")
	}
	// perform Diffie-Hellman key exchange
	curve25519.ScalarMult(&sharedKey, privateKey, peersPublicKey)
	return &sharedKey, nil
}
Example #10
0
func mutecryptHashchainValidate(
	c *cli.Context,
	domain, host string,
	passphrase []byte,
) error {
	args := []string{
		"--homedir", c.GlobalString("homedir"),
		"--loglevel", c.GlobalString("loglevel"),
		"--logdir", c.GlobalString("logdir"),
	}
	if host != "" {
		args = append(args,
			"--keyhost", host,
			"--keyport", ":8080") // TODO: remove keyport hack!
	}
	args = append(args,
		"hashchain", "validate",
		"--domain", domain,
	)
	cmd := exec.Command("mutecrypt", args...)
	var errbuf bytes.Buffer
	cmd.Stderr = &errbuf
	ppR, ppW, err := os.Pipe()
	if err != nil {
		return err
	}
	defer ppR.Close()
	ppW.Write(passphrase)
	ppW.Close()
	cmd.ExtraFiles = append(cmd.ExtraFiles, ppR)
	if err := cmd.Run(); err != nil {
		return log.Errorf("%s: %s", err, strings.TrimSpace(errbuf.String()))
	}
	return nil
}
Example #11
0
// SetPrivateKey sets the private key of curve25519Key to key.
// SetPrivateKey returns an error, if len(key) != 32.
func (c *Curve25519Key) SetPrivateKey(key []byte) error {
	if len(key) != 32 {
		return log.Errorf("cipher: Curve25519Key.SetPrivateKey(): len(key) = %d != 32", len(key))
	}
	c.privateKey = new([32]byte)
	copy(c.privateKey[:], key)
	return nil
}
Example #12
0
// Check that the content of the UID message is consistent with it's version.
func (msg *Message) Check() error {
	// we only support version 1.0 at this stage
	if msg.UIDContent.VERSION != "1.0" {
		return log.Errorf("uid: unknown UIDContent.VERSION: %s",
			msg.UIDContent.VERSION)
	}
	// generic checks
	optional := Optional.String()
	if msg.UIDContent.PREFERENCES.FORWARDSEC != optional {
		if msg.UIDContent.MIXADDRESS != "" {
			return log.Errorf("uid: MIXADDRESS must be null, if FORWARDSEC is not %q",
				optional)
		}
		if msg.UIDContent.NYMADDRESS != "" {
			return log.Errorf("uid: NYMADDRESS must be null, if FORWARDSEC is not %q",
				optional)
		}
	}
	if err := identity.IsMapped(msg.UIDContent.IDENTITY); err != nil {
		return log.Error(err)
	}
	// check SIGKEY
	if msg.UIDContent.SIGKEY.CIPHERSUITE != DefaultCiphersuite {
		return log.Error("uid: UIDContent.SIGKEY.CIPHERSUITE != DefaultCiphersuite")
	}
	if msg.UIDContent.SIGKEY.FUNCTION != "ED25519" {
		return log.Error("uid: UIDContent.SIGKEY.FUNCTION != \"ED25519\"")
	}
	// make sure LASTENTRY is parseable for a non-keyserver localpart.
	// For keyservers the LASTENTRY can be empty, iff this is the first entry
	// in the hashchain.
	lp, _, _ := identity.Split(msg.UIDContent.IDENTITY)
	if lp != "keyserver" {
		_, _, _, _, _, _, err := hashchain.SplitEntry(msg.UIDContent.LASTENTRY)
		if err != nil {
			return err
		}
	}
	// make sure ESCROWSIGNATURE and USERSIGNATURE are not set at the same time
	if msg.ESCROWSIGNATURE != "" && msg.USERSIGNATURE != "" {
		return log.Error("uid: USERSIGNATURE and ESCROWSIGNATURE cannot be set at the same time")
	}

	// version 1.0 specific checks
	return msg.checkV1_0()
}
Example #13
0
func (ce *CryptEngine) fetchKeyInit(pseudonym string) error {
	// map pseudonym
	id, domain, err := identity.MapPlus(pseudonym)
	if err != nil {
		return err
	}
	// get corresponding public ID
	msg, _, found, err := ce.keyDB.GetPublicUID(id, math.MaxInt64) // TODO: use simpler API
	if err != nil {
		return err
	}
	if !found {
		return log.Errorf("not UID for '%s' found", id)
	}
	// get SIGKEYHASH
	sigKeyHash, err := msg.SigKeyHash()
	if err != nil {
		return err
	}
	// get JSON-RPC client and capabilities
	client, _, err := ce.cache.Get(domain, ce.keydPort, ce.keydHost,
		ce.homedir, "KeyInitRepository.FetchKeyInit")
	if err != nil {
		return err
	}
	// call server
	content := make(map[string]interface{})
	content["SigKeyHash"] = sigKeyHash
	reply, err := client.JSONRPCRequest("KeyInitRepository.FetchKeyInit", content)
	if err != nil {
		return err
	}
	rep, ok := reply["KeyInit"].(string)
	if !ok {
		return log.Errorf("cryptengine: could not fetch key init for '%s'", sigKeyHash)
	}
	ki, err := uid.NewJSONKeyInit([]byte(rep))
	if err != nil {
		return err
	}
	// store public key init message
	if err := ce.keyDB.AddPublicKeyInit(ki); err != nil {
		return err
	}
	return nil
}
Example #14
0
// SetPrivateKey sets the private key of naclbox to key.
// SetPrivateKey returns an error, if len(key) != 32.
func (naClBoxKey *NaClBoxKey) SetPrivateKey(key []byte) error {
	if len(key) != 32 {
		return log.Errorf("cipher: NaClBoxKey.SetPrivateKey(): len(key) != 32")
	}
	naClBoxKey.privateKey = new([32]byte)
	copy(naClBoxKey.privateKey[:], key)
	return nil
}
Example #15
0
// encrypt reads data from r, encrypts it for identity to (with identity from
// as sender), and writes it to w.
func (ce *CryptEngine) encrypt(
	w io.Writer,
	from, to string,
	sign bool,
	nymAddress string,
	r io.Reader,
	statusfp *os.File,
) error {
	// map pseudonyms
	fromID, fromDomain, err := identity.MapPlus(from)
	if err != nil {
		return err
	}
	toID, err := identity.Map(to)
	if err != nil {
		return err
	}
	// get fromUID from keyDB
	fromUID, _, err := ce.keyDB.GetPrivateUID(fromID, true)
	if err != nil {
		return err
	}
	// get toUID from keyDB
	toUID, _, found, err := ce.keyDB.GetPublicUID(toID, math.MaxInt64) // TODO: use simpler API
	if err != nil {
		return err
	}
	if !found {
		return log.Errorf("not UID for '%s' found", toID)
	}
	// encrypt message
	senderLastKeychainHash, err := ce.keyDB.GetLastHashChainEntry(fromDomain)
	if err != nil {
		return err
	}
	var privateSigKey *[64]byte
	if sign {
		privateSigKey = fromUID.PrivateSigKey64()
	}
	args := &msg.EncryptArgs{
		Writer:                 w,
		From:                   fromUID,
		To:                     toUID,
		NymAddress:             nymAddress,
		SenderLastKeychainHash: senderLastKeychainHash,
		PrivateSigKey:          privateSigKey,
		Reader:                 r,
		Rand:                   cipher.RandReader,
		KeyStore:               ce,
	}
	nymAddress, err = msg.Encrypt(args)
	if err != nil {
		return err
	}
	// show nymaddress on status-fd
	fmt.Fprintf(statusfp, "NYMADDRESS:\t%s\n", nymAddress)
	return nil
}
Example #16
0
func (ce *CryptEngine) decrypt(w io.Writer, r io.Reader, statusfp *os.File) error {
	// retrieve all possible recipient identities from keyDB
	identities, err := ce.getRecipientIdentities()
	if err != nil {
		return err
	}

	// read pre-header
	r = base64.NewDecoder(r)
	version, preHeader, err := msg.ReadFirstOuterHeader(r)
	if err != nil {
		return err
	}

	// check version
	if version > msg.Version {
		return log.Errorf("cryptengine: newer message version, please update software")
	}
	if version < msg.Version {
		return log.Errorf("cryptengine: outdated message version, cannot process")
	}

	// decrypt message
	var senderID string
	var sig string
	args := &msg.DecryptArgs{
		Writer:     w,
		Identities: identities,
		PreHeader:  preHeader,
		Reader:     r,
		Rand:       cipher.RandReader,
		KeyStore:   ce,
	}
	senderID, sig, err = msg.Decrypt(args)
	if err != nil {
		// TODO: handle msg.ErrStatusError, should trigger a subsequent
		// encrypted message with StatusError
		return err
	}
	fmt.Fprintf(statusfp, "SENDERIDENTITY:\t%s\n", senderID)
	if sig != "" {
		fmt.Fprintf(statusfp, "SIGNATURE:\t%s\n", sig)
	}
	return nil
}
Example #17
0
// SetPrivateKey sets the private key of ed25519Key to key.
// SetPrivateKey returns an error, if len(key) != ed25519.PrivateKeySize.
func (ed25519Key *Ed25519Key) SetPrivateKey(key []byte) error {
	if len(key) != ed25519.PrivateKeySize {
		return log.Errorf("cipher: Ed25519Key.SetPrivateKey(): len(key) = %d != %d = ed25519.PrivateKeySize",
			len(key), ed25519.PrivateKeySize)
	}
	ed25519Key.privateKey = new([ed25519.PrivateKeySize]byte)
	copy(ed25519Key.privateKey[:], key)
	return nil
}
Example #18
0
func createTables(db *sql.DB, createStmts []string) error {
	for _, stmt := range createStmts {
		_, err := db.Exec(stmt)
		if err != nil {
			return log.Errorf("encdb: %q: %s", err, stmt)
		}
	}
	return nil
}
Example #19
0
// Check that the content of KeyInit is consistent with it's version.
func (ki *KeyInit) Check() error {
	// we only support version 1.0 at this stage
	if ki.Contents.VERSION != "1.0" {
		return log.Errorf("uid: unknown ki.Contents.VERSION: %s",
			ki.Contents.VERSION)
	}
	// version 1.0 specific checks
	return ki.checkV1_0()
}
Example #20
0
// writeKeyFile writes a key file with the given filename that contains the
// supplied key in AES-256 encrypted form.
func writeKeyfile(filename string, passphrase []byte, iter int, key []byte) error {
	// make sure keyfile does not exist already
	if _, err := os.Stat(filename); err == nil {
		return log.Errorf("encdb: keyfile '%s' exists already", filename)
	}
	// convert iter to uint64
	var uiter uint64
	if iter < 0 || iter > 2147483647 {
		return log.Errorf("encdb: writeKeyfile: invalid iter value")
	}
	uiter = uint64(iter)
	// check keylength
	if len(key) != 32 {
		return log.Errorf("encdb: writeKeyfile: len(key) != 32")
	}
	// create keyfile
	keyfile, err := os.Create(filename)
	if err != nil {
		return log.Error(err)
	}
	defer keyfile.Close()
	// generate salt
	var salt = make([]byte, 32)
	if _, err := io.ReadFull(cipher.RandReader, salt); err != nil {
		return err
	}
	// compute derived key from passphrase
	dk := pbkdf2.Key(passphrase, salt, iter, 32, sha256.New)
	// compute AES-256 encrypted key (with IV)
	encKey := cipher.AES256CBCEncrypt([]byte(dk), key, cipher.RandReader)
	// write number of iterations
	if _, err := keyfile.Write(encode.ToByte8(uiter)); err != nil {
		return err
	}
	// write salt
	if _, err := keyfile.Write(salt); err != nil {
		return err
	}
	// write IV and AES-256 encrypted key
	if _, err := keyfile.Write(encKey); err != nil {
		return err
	}
	return nil
}
Example #21
0
func readPreHeader(r io.Reader) (*preHeader, error) {
	var ph preHeader
	// read version
	if err := binary.Read(r, binary.BigEndian, &ph.Version); err != nil {
		return nil, log.Error(err)
	}
	if ph.Version != Version {
		return nil, log.Errorf("msg: invalid message version %d", ph.Version)
	}
	//log.Debugf("ph.Version: %d", ph.Version)
	// read length of ciphersuite
	if err := binary.Read(r, binary.BigEndian, &ph.LengthCiphersuite); err != nil {
		return nil, log.Error(err)
	}
	if ph.LengthCiphersuite != uint16(len(DefaultCiphersuite)) {
		return nil, log.Errorf("msg: invalid ciphersuite length %d", ph.LengthCiphersuite)
	}
	//log.Debugf("ph.LengthCiphersuite: %d", ph.LengthCiphersuite)
	// read ciphersuite
	p := make([]byte, ph.LengthCiphersuite)
	if _, err := io.ReadFull(r, p); err != nil {
		return nil, log.Error(err)
	}
	ph.Ciphersuite = string(p)
	if ph.Ciphersuite != DefaultCiphersuite {
		return nil, log.Errorf("msg: invalid ciphersuite '%s'", ph.Ciphersuite)
	}
	//log.Debugf("ph.Ciphersuite: %s", ph.Ciphersuite)
	// read length sender header pub
	if err := binary.Read(r, binary.BigEndian, &ph.LengthSenderHeaderPub); err != nil {
		return nil, log.Error(err)
	}
	//log.Debugf("ph.LengthSenderHeaderPub: %d", ph.LengthSenderHeaderPub)
	ph.SenderHeaderPub = make([]byte, ph.LengthSenderHeaderPub)
	if _, err := io.ReadFull(r, ph.SenderHeaderPub); err != nil {
		return nil, log.Error(err)
	}
	//log.Debugf("ph.SenderHeaderPub: %s", base64.Encode(ph.SenderHeaderPub))
	return &ph, nil
}
Example #22
0
// loop runs the crypt engine in a loop and reads commands from the file
// descriptor command-fd.
func (ce *CryptEngine) loop(c *cli.Context) {
	if len(c.Args()) > 0 {
		ce.err = fmt.Errorf("cryptengine: unknown command '%s', try 'help'",
			strings.Join(c.Args(), " "))
		return
	}

	log.Info("cryptengine: starting")

	// run command(s)
	log.Infof("read commands from fd %d", ce.fileTable.CommandFD)

	scanner := bufio.NewScanner(ce.fileTable.CommandFP)

	for scanner.Scan() {
		args := []string{ce.app.Name}
		line := scanner.Text()
		if line == "" {
			log.Infof("read empty line")
			continue
		}
		log.Infof("read: %s", line)
		args = append(args, strings.Fields(line)...)
		if err := ce.app.Run(args); err != nil {
			// command execution failed -> issue status and continue
			log.Infof("command execution failed (app): %s", err)
			fmt.Fprintln(ce.fileTable.StatusFP, err)
			continue
		}
		if ce.err != nil {
			if ce.err == errExit {
				// exit requested -> return
				log.Info("cryptengine: stopping (exit requested)")
				fmt.Fprintln(ce.fileTable.StatusFP, "QUITTING")
				ce.err = nil
				return
			}
			// command execution failed -> issue status and continue
			log.Infof("command execution failed (cmd): %s", ce.err)
			fmt.Fprintln(ce.fileTable.StatusFP, ce.err)
			ce.err = nil
		} else {
			log.Info("command successful")
		}
		fmt.Fprintln(ce.fileTable.StatusFP, "READY.")
	}
	if err := scanner.Err(); err != nil {
		ce.err = log.Errorf("cryptengine: %s", err)
	}
	log.Info("cryptengine: stopping (error)")
	return
}
Example #23
0
// Verify KeyEntry messages in header.
func (h *header) verify() error {
	// check h.SenderSessionPub
	if err := h.SenderSessionPub.Verify(); err != nil {
		return err
	}
	if h.SenderSessionPub.FUNCTION != "ECDHE25519" {
		return log.Errorf("msg: wrong uid.SenderSessionPub.FUNCTION: %s",
			h.SenderSessionPub.FUNCTION)
	}
	// check h.SenderIdentityPub
	if err := h.SenderIdentityPub.Verify(); err != nil {
		return err
	}
	if h.SenderIdentityPub.FUNCTION != "ECDHE25519" {
		return log.Errorf("msg: wrong uid.SenderIdentityPub.FUNCTION: %s",
			h.SenderIdentityPub.FUNCTION)
	}
	// check h.NextSenderSessionPub
	if h.NextSenderSessionPub != nil {
		if err := h.NextSenderSessionPub.Verify(); err != nil {
			return err
		}
		if h.NextSenderSessionPub.FUNCTION != "ECDHE25519" {
			return log.Errorf("msg: wrong uid.NextSenderSessionPub.FUNCTION: %s",
				h.SenderSessionPub.FUNCTION)
		}
	}
	// check h.NextRecipientSessionPubSeen
	if h.NextRecipientSessionPubSeen != nil {
		if err := h.NextRecipientSessionPubSeen.Verify(); err != nil {
			return err
		}
		if h.NextRecipientSessionPubSeen.FUNCTION != "ECDHE25519" {
			return log.Errorf("msg: wrong uid.NextRecipientSessionPubSeen.FUNCTION: %s",
				h.NextRecipientSessionPubSeen.FUNCTION)
		}
	}
	return nil
}
Example #24
0
func muteprotoDeliver(
	c *cli.Context,
	envelope string,
) (resend bool, err error) {
	args := []string{
		"--homedir", c.GlobalString("homedir"),
		"--loglevel", c.GlobalString("loglevel"),
		"--logdir", c.GlobalString("logdir"),
		"deliver",
	}
	cmd := exec.Command("muteproto", args...)
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return false, err
	}
	var errbuf bytes.Buffer
	cmd.Stderr = &errbuf
	if err := cmd.Start(); err != nil {
		return false, err
	}
	if _, err := io.WriteString(stdin, envelope); err != nil {
		return false, err
	}
	stdin.Close()
	if err := cmd.Wait(); err != nil {
		return false,
			log.Errorf("%s: %s", err, strings.TrimSpace(errbuf.String()))
	}
	if len(errbuf.String()) > 0 {
		errstr := strings.TrimSpace(errbuf.String())
		if !strings.HasPrefix(errstr, "RESEND:\t") {
			return false,
				log.Errorf("ctrlengine: muteproto status output not parsable: %s", errstr)
		}
		log.Warn(errstr)
		resend = true
	}
	return
}
Example #25
0
// GetMessageKey implements corresponding method for msg.KeyStore interface.
func (ce *CryptEngine) GetMessageKey(
	sessionKey string,
	sender bool,
	msgIndex uint64,
) (*[64]byte, error) {
	key, err := ce.keyDB.GetMessageKey(sessionKey, sender, msgIndex)
	if err != nil {
		return nil, err
	}
	// decode key
	var messageKey [64]byte
	k, err := base64.Decode(key)
	if err != nil {
		return nil,
			log.Errorf("cryptengine: cannot decode key for %s", sessionKey)
	}
	if copy(messageKey[:], k) != 64 {
		return nil,
			log.Errorf("cryptengine: key for %s has wrong length", sessionKey)
	}
	return &messageKey, nil
}
Example #26
0
// SplitEntry splits a base64 encoded key hashchain entry. Specification:
// https://github.com/mutecomm/mute/blob/master/doc/keyserver.md#key-hashchain-operation
func SplitEntry(entry string) (hash, typ, nonce, hashID, crUID, uidIndex []byte, err error) {
	e, err := base64.Decode(entry)
	if err != nil {
		return nil, nil, nil, nil, nil, nil, log.Error(err)
	}
	if len(e) != EntryByteLen {
		return nil, nil, nil, nil, nil, nil,
			log.Errorf("hashchain: entry '%s' does not have byte length %d (but %d)",
				entry, EntryByteLen, len(e))
	}
	// HASH(entry[n]) | TYPE | NONCE | HashID | CrUID | UIDIndex
	hash = e[:32]
	typ = e[32:33]
	nonce = e[33:41]
	hashID = e[41:73]
	crUID = e[73:121]
	uidIndex = e[121:]
	// check type
	if !bytes.Equal(typ, Type) {
		return nil, nil, nil, nil, nil, nil,
			log.Errorf("hashchain: wrong type 0x%x (should be 0x%x)", typ, Type)
	}
	return
}
Example #27
0
// GetLastHashChainEntry returns the last hash chain entry for the given domain.
func (keyDB *KeyDB) GetLastHashChainEntry(domain string) (string, error) {
	dmn := identity.MapDomain(domain)
	pos, found, err := keyDB.GetLastHashChainPos(dmn)
	if err != nil {
		return "", err
	}
	if !found {
		return "", log.Errorf("keydb: no entry found for domain '%s'", dmn)
	}
	entry, err := keyDB.GetHashChainEntry(dmn, pos)
	if err != nil {
		return "", err
	}
	return entry, nil
}
Example #28
0
// DelNym deletes the nym mappedID and all associated contacts and messages!
func (msgDB *MsgDB) DelNym(mappedID string) error {
	if err := identity.IsMapped(mappedID); err != nil {
		return log.Error(err)
	}
	unmappedID, _, err := msgDB.GetNym(mappedID)
	if err != nil {
		return err
	}
	if unmappedID == "" {
		return log.Errorf("msgdb: nym %s unkown", mappedID)
	}
	if _, err := msgDB.delNymQuery.Exec(mappedID); err != nil {
		return log.Error(err)
	}
	return nil
}
Example #29
0
// GetChainKey implements corresponding method for msg.KeyStore interface.
func (ce *CryptEngine) GetChainKey(sessionKey string) (*[32]byte, error) {
	_, chainKey, _, err := ce.keyDB.GetSession(sessionKey)
	if err != nil {
		return nil, err
	}
	// decode chain key
	var key [32]byte
	k, err := base64.Decode(chainKey)
	if err != nil {
		return nil, log.Error("cryptengine: cannot decode chain key")
	}
	if copy(key[:], k) != 32 {
		return nil, log.Errorf("cryptengine: chain key has wrong length")
	}
	return &key, nil
}
Example #30
0
// GetRootKeyHash implements corresponding method for msg.KeyStore interface.
func (ce *CryptEngine) GetRootKeyHash(sessionKey string) (*[64]byte, error) {
	rootKeyHash, _, _, err := ce.keyDB.GetSession(sessionKey)
	if err != nil {
		return nil, err
	}
	// decode root key hash
	var hash [64]byte
	k, err := base64.Decode(rootKeyHash)
	if err != nil {
		return nil, log.Error("cryptengine: cannot decode root key hash")
	}
	if copy(hash[:], k) != 64 {
		return nil, log.Errorf("cryptengine: root key hash has wrong length")
	}
	return &hash, nil
}