Beispiel #1
0
// encryptKey encrypts data with the key associated with name inner,
// then name outer
func encryptKey(nameInner, nameOuter string, clearKey []byte, rsaKeys map[string]SingleWrappedKey) (out MultiWrappedKey, err error) {
	out.Name = []string{nameOuter, nameInner}

	recInner, ok := passvault.GetRecord(nameInner)
	if !ok {
		err = errors.New("Missing user on disk")
		return
	}

	recOuter, ok := passvault.GetRecord(nameOuter)
	if !ok {
		err = errors.New("Missing user on disk")
		return
	}

	if recInner.Type != recOuter.Type {
		err = errors.New("Mismatched record types")
		return
	}

	var keyBytes []byte
	var overrideInner SingleWrappedKey
	var overrideOuter SingleWrappedKey

	// For AES records, use the live user key
	// For RSA records, use the public key from the passvault
	switch recInner.Type {
	case passvault.RSARecord:
		if overrideInner, ok = rsaKeys[nameInner]; !ok {
			err = errors.New("Missing user in file")
			return
		}

		if overrideOuter, ok = rsaKeys[nameOuter]; !ok {
			err = errors.New("Missing user in file")
			return
		}

	case passvault.AESRecord:
		break

	default:
		return out, errors.New("Unknown record type inner")
	}

	// double-wrap the keys
	if keyBytes, err = keycache.EncryptKey(clearKey, nameInner, overrideInner.aesKey); err != nil {
		return out, err
	}
	if keyBytes, err = keycache.EncryptKey(keyBytes, nameOuter, overrideOuter.aesKey); err != nil {
		return out, err
	}

	out.Key = keyBytes

	return
}
Beispiel #2
0
// Delegate processes a delegation request.
func Delegate(jsonIn []byte) ([]byte, error) {
	var s delegate
	if err := json.Unmarshal(jsonIn, &s); err != nil {
		return jsonStatusError(err)
	}

	if passvault.NumRecords() == 0 {
		return jsonStatusError(errors.New("Vault is not created yet"))
	}

	// Find password record for user and verify that their password
	// matches. If not found then add a new entry for this user.

	pr, found := passvault.GetRecord(s.Name)
	if found {
		if err := pr.ValidatePassword(s.Password); err != nil {
			return jsonStatusError(err)
		}
	} else {
		var err error
		if pr, err = passvault.AddNewRecord(s.Name, s.Password, false); err != nil {
			log.Printf("Error adding record for %s: %s\n", s.Name, err)
			return jsonStatusError(err)
		}
	}

	// add signed-in record to active set
	if err := keycache.AddKeyFromRecord(pr, s.Name, s.Password, s.Uses, s.Time); err != nil {
		log.Printf("Error adding key to cache for %s: %s\n", s.Name, err)
		return jsonStatusError(err)
	}

	return jsonStatusOk()
}
Beispiel #3
0
// validateAdmin checks that the username and password passed in are
// correct and that the user is an admin
func validateAdmin(name, password string) error {
	if passvault.NumRecords() == 0 {
		return errors.New("Vault is not created yet")
	}

	pr, ok := passvault.GetRecord(name)
	if !ok {
		return errors.New("User not present")
	}
	if err := pr.ValidatePassword(password); err != nil {
		return err
	}
	if !pr.IsAdmin() {
		return errors.New("Admin required")
	}

	return nil
}
Beispiel #4
0
// Modify processes a modify request.
func Modify(jsonIn []byte) ([]byte, error) {
	var s modify

	if err := json.Unmarshal(jsonIn, &s); err != nil {
		return jsonStatusError(err)
	}

	if err := validateAdmin(s.Name, s.Password); err != nil {
		log.Printf("Error validating admin status of %s: %s", s.Name, err)
		return jsonStatusError(err)
	}

	if _, ok := passvault.GetRecord(s.ToModify); !ok {
		return jsonStatusError(errors.New("Record to modify missing"))
	}

	if s.Name == s.ToModify {
		return jsonStatusError(errors.New("Cannot modify own record"))
	}

	var err error
	switch s.Command {
	case "delete":
		err = passvault.DeleteRecord(s.ToModify)
	case "revoke":
		err = passvault.RevokeRecord(s.ToModify)
	case "admin":
		err = passvault.MakeAdmin(s.ToModify)
	default:
		return jsonStatusError(errors.New("Unknown command"))
	}

	if err != nil {
		return jsonStatusError(err)
	} else {
		return jsonStatusOk()
	}
}
Beispiel #5
0
// Encrypt encrypts data with the keys associated with names. This
// requires a minimum of min keys to decrypt.  NOTE: as currently
// implemented, the maximum value for min is 2.
func Encrypt(in []byte, names []string, min int) (resp []byte, err error) {
	if min > 2 {
		return nil, errors.New("Minimum restricted to 2")
	}

	var encrypted EncryptedData
	encrypted.Version = DEFAULT_VERSION
	if encrypted.VaultId, err = passvault.GetVaultId(); err != nil {
		return
	}

	// Generate random IV and encryption key
	ivBytes, err := makeRandom(16)
	if err != nil {
		return
	}

	// append used here to make a new slice from ivBytes and assign to
	// encrypted.IV

	encrypted.IV = append([]byte{}, ivBytes...)
	clearKey, err := makeRandom(16)
	if err != nil {
		return
	}

	// Allocate set of keys to be able to cover all ordered subsets of
	// length 2 of names

	encrypted.KeySet = make([]MultiWrappedKey, len(names)*(len(names)-1))
	encrypted.KeySetRSA = make(map[string]SingleWrappedKey)

	var singleWrappedKey SingleWrappedKey
	for _, name := range names {
		rec, ok := passvault.GetRecord(name)
		if !ok {
			err = errors.New("Missing user on disk")
			return
		}

		if rec.GetType() == passvault.RSARecord {
			// only wrap key with RSA key if found
			if singleWrappedKey.aesKey, err = makeRandom(16); err != nil {
				return nil, err
			}

			if singleWrappedKey.Key, err = rec.EncryptKey(singleWrappedKey.aesKey); err != nil {
				return nil, err
			}
			encrypted.KeySetRSA[name] = singleWrappedKey
		} else {
			err = nil
		}
	}

	// encrypt file key with every combination of two keys
	var n int
	for _, nameOuter := range names {
		for _, nameInner := range names {
			if nameInner != nameOuter {
				encrypted.KeySet[n], err = encryptKey(nameInner, nameOuter, clearKey, encrypted.KeySetRSA)
				n += 1
			}
			if err != nil {
				return
			}
		}
	}

	// encrypt file with clear key
	aesCrypt, err := aes.NewCipher(clearKey)
	if err != nil {
		return
	}

	clearFile := padding.AddPadding(in)

	encryptedFile := make([]byte, len(clearFile))
	aesCBC := cipher.NewCBCEncrypter(aesCrypt, ivBytes)
	aesCBC.CryptBlocks(encryptedFile, clearFile)

	encrypted.Data = encryptedFile

	hmacKey, err := passvault.GetHmacKey()
	if err != nil {
		return
	}
	encrypted.Signature = computeHmac(hmacKey, encrypted)

	return json.Marshal(encrypted)
}