Skip to content

Commit

Permalink
AB#431 : Use new sealing features from ertcrypto (#80)
Browse files Browse the repository at this point in the history
* Use new sealing functions from ertgolib

* Remove remaining references to sealKey

* Add NoEnclaveSealer for -noenclave execution mode

* remove unused parameter; use new tagged ertgolib

Co-authored-by: Thomas Tendyck <[email protected]>
  • Loading branch information
Nirusu and thomasten authored Dec 14, 2020
1 parent 81ce91a commit aa8cef9
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 72 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ jobs:
- name: Integration test
run: ertgo test -tags integration -b ../build -s
working-directory: test

- name: Integration test (-noenclave)
run: ertgo test -tags integration -b ../build -noenclave
working-directory: test

- name: Build artifact
uses: actions/upload-artifact@v2
Expand Down
13 changes: 7 additions & 6 deletions cmd/coordinator/enclavemain.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ package main
import (
"path/filepath"

"github.com/edgelesssys/ertgolib/ertenclave"
"github.com/edgelesssys/marblerun/coordinator/config"
"github.com/edgelesssys/marblerun/coordinator/core"
"github.com/edgelesssys/marblerun/coordinator/quote/ertvalidator"
"github.com/edgelesssys/marblerun/util"
)

func main() {
validator := ertvalidator.NewERTValidator()
issuer := ertvalidator.NewERTIssuer()
sealKey, _, err := ertenclave.GetProductSealKey()
if err != nil {
panic(err)
}
sealDirPrefix := filepath.Join(filepath.FromSlash("/edg"), "hostfs")
run(validator, issuer, sealKey, sealDirPrefix)
sealDir := util.MustGetenv(config.SealDir)
sealDir = filepath.Join(sealDirPrefix, sealDir)
sealer := core.NewAESGCMSealer(sealDir)
run(validator, issuer, sealDir, sealer)
}
12 changes: 9 additions & 3 deletions cmd/coordinator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@

package main

import "github.com/edgelesssys/marblerun/coordinator/quote"
import (
"github.com/edgelesssys/marblerun/coordinator/config"
"github.com/edgelesssys/marblerun/coordinator/core"
"github.com/edgelesssys/marblerun/coordinator/quote"
"github.com/edgelesssys/marblerun/util"
)

func main() {
validator := quote.NewFailValidator()
issuer := quote.NewFailIssuer()
sealKey := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
run(validator, issuer, sealKey, "")
sealDir := util.MustGetenv(config.SealDir)
sealer := core.NewNoEnclaveSealer(sealDir)
run(validator, issuer, sealDir, sealer)
}
6 changes: 1 addition & 5 deletions cmd/coordinator/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package main
import (
"log"
"os"
"path/filepath"
"strings"

"github.com/edgelesssys/marblerun/coordinator/config"
Expand All @@ -20,7 +19,7 @@ import (
"go.uber.org/zap"
)

func run(validator quote.Validator, issuer quote.Issuer, sealKey []byte, sealDirPrefix string) {
func run(validator quote.Validator, issuer quote.Issuer, sealDir string, sealer core.Sealer) {
// Setup logging with Zap Logger
var zapLogger *zap.Logger
var err error
Expand All @@ -41,8 +40,6 @@ func run(validator quote.Validator, issuer quote.Issuer, sealKey []byte, sealDir
zapLogger.Info("starting coordinator")

// fetching env vars
sealDir := util.MustGetenv(config.SealDir)
sealDir = filepath.Join(sealDirPrefix, sealDir)
dnsNamesString := util.MustGetenv(config.DNSNames)
dnsNames := strings.Split(dnsNamesString, ",")
clientServerAddr := util.MustGetenv(config.ClientAddr)
Expand All @@ -54,7 +51,6 @@ func run(validator quote.Validator, issuer quote.Issuer, sealKey []byte, sealDir
if err := os.MkdirAll(sealDir, 0700); err != nil {
zapLogger.Fatal("Cannot create or access sealdir. Please check the permissions for the specified path.", zap.Error(err))
}
sealer := core.NewAESGCMSealer(sealDir, sealKey)
core, err := core.NewCore(dnsNames, validator, issuer, sealer, zapLogger)
if err != nil {
panic(err)
Expand Down
133 changes: 79 additions & 54 deletions coordinator/core/seal.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
package core

import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io/ioutil"
"os"
"path/filepath"
"time"

"github.com/edgelesssys/ertgolib/ertcrypto"
)

// SealedDataFname contains the file name in which the state is sealed on disk in seal_dir
Expand All @@ -37,13 +37,12 @@ type Sealer interface {
// AESGCMSealer implements the Sealer interface using AES-GCM for confidentiallity and authentication
type AESGCMSealer struct {
sealDir string
sealKey []byte
encryptionKey []byte
}

// NewAESGCMSealer creates and initializes a new AESGCMSealer object
func NewAESGCMSealer(sealDir string, sealKey []byte) *AESGCMSealer {
return &AESGCMSealer{sealDir: sealDir, sealKey: sealKey}
func NewAESGCMSealer(sealDir string) *AESGCMSealer {
return &AESGCMSealer{sealDir: sealDir}
}

// Unseal reads and decrypts stored information from the fs
Expand All @@ -63,7 +62,7 @@ func (s *AESGCMSealer) Unseal() ([]byte, error) {
}

// Decrypt data with the unsealed encryption key and return it
return decrypt(sealedData, s.encryptionKey)
return ertcrypto.Decrypt(sealedData, s.encryptionKey)
}

// Seal encrypts and stores information to the fs
Expand All @@ -79,7 +78,7 @@ func (s *AESGCMSealer) Seal(data []byte) ([]byte, error) {
}

// Encrypt data to seal with generated encryption key
encryptedData, err := encrypt(data, s.encryptionKey)
encryptedData, err := ertcrypto.Encrypt(data, s.encryptionKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -108,7 +107,7 @@ func (s *AESGCMSealer) unsealEncryptionKey() error {
}

// Decrypt stored encryption key with seal key
encryptionKey, err := decrypt(sealedKeyData, s.sealKey)
encryptionKey, err := ertcrypto.Unseal(sealedKeyData)
if err != nil {
return err
}
Expand Down Expand Up @@ -141,7 +140,7 @@ func (s *AESGCMSealer) SetEncryptionKey(encryptionKey []byte) error {
}

// Encrypt encryption key with seal key
encryptedKeyData, err := encrypt(encryptionKey, s.sealKey)
encryptedKeyData, err := ertcrypto.SealWithProductKey(encryptionKey)
if err != nil {
return err
}
Expand All @@ -156,75 +155,101 @@ func (s *AESGCMSealer) SetEncryptionKey(encryptionKey []byte) error {
return nil
}

func getCipher(key []byte) (cipher.AEAD, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
return cipher.NewGCM(block)
// MockSealer is a mockup sealer
type MockSealer struct {
data []byte
unsealError error
}

// Unseal implements the Sealer interface
func (s *MockSealer) Unseal() ([]byte, error) {
return s.data, s.unsealError
}

// Seal implements the Sealer interface
func (s *MockSealer) Seal(data []byte) ([]byte, error) {
s.data = data
return []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, nil
}

// SetEncryptionKey implements the Sealer interface
func (s *MockSealer) SetEncryptionKey(key []byte) error {
return nil
}

// GenerateNewEncryptionKey implements the Sealer interface
func (s *MockSealer) GenerateNewEncryptionKey() error {
return nil
}

func encrypt(plaintext []byte, key []byte) ([]byte, error) {
// Create cipher object with the given key
aesgcm, err := getCipher(key)
// NoEnclaveSealer is a sealed for a -noenclave instance and does perform encryption with a fixed key
type NoEnclaveSealer struct {
sealDir string
encryptionKey []byte
}

// NewNoEnclaveSealer creates and initializes a new NoEnclaveSealer object
func NewNoEnclaveSealer(sealDir string) *NoEnclaveSealer {
return &NoEnclaveSealer{sealDir: sealDir}
}

// Seal writes the given data encrypted and the used key as plaintext to the disk
func (s *NoEnclaveSealer) Seal(data []byte) ([]byte, error) {
// Encrypt data
sealedData, err := ertcrypto.Encrypt(data, s.encryptionKey)
if err != nil {
return nil, err
}

// Generate nonce
nonce := make([]byte, aesgcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
// Write encrypted data to disk
if err := ioutil.WriteFile(s.getFname(SealedDataFname), sealedData, 0600); err != nil {
return nil, err
}

// Encrypt data
ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)

return append(nonce, ciphertext...), nil
// Write key in plaintext to disk
if err := ioutil.WriteFile(s.getFname(SealedKeyFname), s.encryptionKey, 0600); err != nil {
return nil, err
}
return s.encryptionKey, nil
}

func decrypt(ciphertext []byte, key []byte) ([]byte, error) {
// Create cipher object with the given key
aesgcm, err := getCipher(key)
if err != nil {
// Unseal reads the plaintext state from disk
func (s *NoEnclaveSealer) Unseal() ([]byte, error) {
// Read sealed data from disk
sealedData, err := ioutil.ReadFile(s.getFname(SealedDataFname))
if os.IsNotExist(err) {
return nil, nil
} else if err != nil {
return nil, err
}

// Split ciphertext into nonce & actual data
nonce, encryptedData := ciphertext[:aesgcm.NonceSize()], ciphertext[aesgcm.NonceSize():]

// Decrypt data
plaintext, err := aesgcm.Open(nil, nonce, encryptedData, nil)
// Read key in plaintext from disk
keyData, err := ioutil.ReadFile(s.getFname(SealedKeyFname))
if err != nil {
return nil, err
}

return plaintext, nil
}

// MockSealer is a mockup sealer
type MockSealer struct {
data []byte
unsealError error
}

// Unseal implements the Sealer interface
func (s *MockSealer) Unseal() ([]byte, error) {
return s.data, s.unsealError
}
// Decrypt data with key from disk
data, err := ertcrypto.Decrypt(sealedData, keyData)
if err != nil {
return nil, ErrEncryptionKey
}

// Seal implements the Sealer interface
func (s *MockSealer) Seal(data []byte) ([]byte, error) {
s.data = data
return []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, nil
return data, nil
}

// SetEncryptionKey implements the Sealer interface
func (s *MockSealer) SetEncryptionKey(key []byte) error {
return nil
func (s *NoEnclaveSealer) SetEncryptionKey(key []byte) error {
s.encryptionKey = key
return ioutil.WriteFile(s.getFname(SealedKeyFname), s.encryptionKey, 0600)
}

// GenerateNewEncryptionKey implements the Sealer interface
func (s *MockSealer) GenerateNewEncryptionKey() error {
func (s *NoEnclaveSealer) GenerateNewEncryptionKey() error {
s.encryptionKey = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
return nil
}

func (s *NoEnclaveSealer) getFname(basename string) string {
return filepath.Join(s.sealDir, basename)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/edgelesssys/marblerun
go 1.14

require (
github.com/edgelesssys/ertgolib v0.1.1
github.com/edgelesssys/ertgolib v0.1.2
github.com/golang/protobuf v1.4.3
github.com/google/go-cmp v0.5.2
github.com/google/uuid v1.1.2
Expand Down
Loading

0 comments on commit aa8cef9

Please sign in to comment.