Files
cloud-services/pkg/db/queries/ecckeys.go

224 lines
6.4 KiB
Go

package queries
import (
"fiskerinc.com/modules/common"
"fiskerinc.com/modules/logger"
s "fiskerinc.com/modules/security"
"github.com/go-pg/pg/v10"
"github.com/go-pg/pg/v10/orm"
"github.com/pkg/errors"
)
const sqlLastManifestEnv = "WITH sub AS (SELECT COALESCE((SELECT env FROM update_manifests WHERE id IN (SELECT update_manifest_id FROM car_updates WHERE id IN (SELECT MAX(id) FROM car_updates WHERE vin = ?))), 'current') as env)"
const sqlCarUpdateIDEnv = "WITH sub AS (SELECT COALESCE((SELECT env FROM update_manifests WHERE update_manifests.id IN (SELECT update_manifest_id FROM car_updates WHERE id = ?)), 'current') as env)"
const sqlECCPrivKeysEnv = " SELECT priv_key_level_1, priv_key_level_2, priv_key_level_3, ecu, ecc_keys.env FROM ecc_keys INNER JOIN sub ON ecc_keys.env = sub.env ORDER BY ecu;"
type EccKeysInterface interface {
Insert(keys common.ECCKeys) (orm.Result, error)
SelectAllPrivateKeys() ([]common.ECCKeys, error)
SelectAllPrivateKeysByEnv(env string) ([]common.ECCKeys, error)
SelectPublicKeysByECUByEnv(ecu string, env string) (common.ECCKeys, error)
SelectAllPublicKeysByEnv(env string) ([]common.ECCKeys, error)
SelectPrivateKeysByECUsEnv(ecus []string, env string) ([]common.ECCKeys, error)
SelectAllPrivateKeysByVIN(vin string) ([]common.ECCKeys, error)
SelectAllPrivateKeysByCarUpdateID(id int64) ([]common.ECCKeys, error)
}
type EccKeys struct {
QueryBase
}
func (ek *EccKeys) Insert(keys common.ECCKeys) (orm.Result, error) {
enc := s.Encrypt{}
encryptor, err := enc.GetEncryptor()
if err != nil {
return nil, err
}
keys.PubKey1.SetBytes(encryptor.EncryptChunk(keys.PubKey1.Bytes()))
keys.PrivKey1.SetBytes(encryptor.EncryptChunk(keys.PrivKey1.Bytes()))
keys.PubKey2.SetBytes(encryptor.EncryptChunk(keys.PubKey2.Bytes()))
keys.PrivKey2.SetBytes(encryptor.EncryptChunk(keys.PrivKey2.Bytes()))
keys.PubKey3.SetBytes(encryptor.EncryptChunk(keys.PubKey3.Bytes()))
keys.PrivKey3.SetBytes(encryptor.EncryptChunk(keys.PrivKey3.Bytes()))
return ek.resultWithStack(ek.GetDBConn().Model(&keys).Insert())
}
// Selects all private keys and ECU's
func (ek *EccKeys) SelectAllPrivateKeys() ([]common.ECCKeys, error) {
return ek.selectKeys("current", "priv_key_level_1", "priv_key_level_2", "priv_key_level_3", "ecu")
}
// Selects all private keys and ECU's by env
func (ek *EccKeys) SelectAllPrivateKeysByEnv(env string) ([]common.ECCKeys, error) {
return ek.selectKeys(env, "priv_key_level_1", "priv_key_level_2", "priv_key_level_3", "ecu")
}
// Selects public keys associated with ECU by env
func (ek *EccKeys) SelectAllPublicKeysByEnv(env string) ([]common.ECCKeys, error) {
return ek.selectKeys(env, "pub_key_level_1", "pub_key_level_2", "pub_key_level_3", "ecu")
}
// Selects keys associated with ECU
func (ek *EccKeys) SelectAllKeys() ([]common.ECCKeys, error) {
return ek.selectKeys("current", "pub_key_level_1", "pub_key_level_2", "pub_key_level_3", "priv_key_level_1", "priv_key_level_2", "priv_key_level_3", "ecu")
}
// Selects public keys associated with ECU by env
func (ek *EccKeys) SelectPublicKeysByECUByEnv(ecu string, env string) (common.ECCKeys, error) {
ecckey := common.ECCKeys{}
err := ek.GetDBConn().Model(&ecckey).Column("pub_key_level_1", "pub_key_level_2", "pub_key_level_3", "ecu").Where("ecu = ? AND env = ?", ecu, env).Select()
if err != nil {
return ecckey, errors.WithStack(err)
}
err = ek.decrypt(&ecckey)
return ecckey, err
}
func (ek *EccKeys) SelectPrivateKeysByECUsEnv(ecus []string, env string) ([]common.ECCKeys, error) {
var keys []common.ECCKeys
if env == "" {
env = common.EnvCurrent
}
err := ek.GetDBConn().Model(&keys).
Column("priv_key_level_1", "priv_key_level_2", "priv_key_level_3", "ecu").
Where("ecu IN (?) AND env = ?", pg.In(ecus), env).
Order("ecu").
Select()
if err != nil {
return nil, errors.WithStack(err)
}
for i := range keys {
err = ek.decrypt(&keys[i])
if err != nil {
return nil, err
}
}
return keys, nil
}
// SelectAllPrivateKeysByVIN returns the ECC keys for an environment based on the last update sent to the VIN
// If no update was sent, it will send the keys for the current environment
func (ek *EccKeys) SelectAllPrivateKeysByVIN(vin string) ([]common.ECCKeys, error) {
var keys []common.ECCKeys
_, err := ek.GetDBConn().Query(&keys, sqlLastManifestEnv+sqlECCPrivKeysEnv, vin)
if err != nil {
return nil, errors.WithStack(err)
}
if len(keys) == 0 {
return nil, errors.Errorf("No ECC keys for %s", vin)
}
logger.Info().Msgf("SelectAllPrivateKeysByVIN %s %s", vin, keys[0].Env)
for i := range keys {
keys[i].Env = ""
err = ek.decrypt(&keys[i])
if err != nil {
return nil, err
}
}
return keys, nil
}
func (ek *EccKeys) SelectAllPrivateKeysByCarUpdateID(id int64) ([]common.ECCKeys, error) {
var keys []common.ECCKeys
_, err := ek.GetDBConn().Query(&keys, sqlCarUpdateIDEnv+sqlECCPrivKeysEnv, id)
if err != nil {
return nil, errors.WithStack(err)
}
if len(keys) == 0 {
return nil, errors.Errorf("No ECC keys for car update id %d", id)
}
logger.Info().Msgf("SelectAllPrivateKeysByCarUpdateID %d %s", id, keys[0].Env)
for i := range keys {
keys[i].Env = ""
err = ek.decrypt(&keys[i])
if err != nil {
return nil, err
}
}
return keys, nil
}
func (ek *EccKeys) selectKeys(env string, columns ...string) ([]common.ECCKeys, error) {
ecckeys := []common.ECCKeys{}
err := ek.GetDBConn().Model(&ecckeys).Column(columns...).Where("env = ?", env).Order("ecu").Select()
if err != nil {
return ecckeys, errors.WithStack(err)
}
for i := range ecckeys {
err = ek.decrypt(&ecckeys[i])
}
return ecckeys, err
}
func (ek *EccKeys) decrypt(eccKeys *common.ECCKeys) error {
enc := s.Encrypt{}
encryptor, err := enc.GetEncryptor()
if err != nil {
return err
}
err = ek.decryptKey(encryptor, eccKeys.PrivKey1)
if err != nil {
return err
}
err = ek.decryptKey(encryptor, eccKeys.PrivKey2)
if err != nil {
return err
}
err = ek.decryptKey(encryptor, eccKeys.PrivKey3)
if err != nil {
return err
}
err = ek.decryptKey(encryptor, eccKeys.PubKey1)
if err != nil {
return err
}
err = ek.decryptKey(encryptor, eccKeys.PubKey2)
if err != nil {
return err
}
err = ek.decryptKey(encryptor, eccKeys.PubKey3)
if err != nil {
return err
}
return nil
}
func (ek *EccKeys) decryptKey(encryptor s.IEncryptor, key *common.BinaryHex) error {
if key != nil {
keys, err := encryptor.DecryptChunk(key.Bytes())
if err != nil {
return err
}
key.SetBytes(keys)
}
return nil
}