Skip to content

Commit

Permalink
add S390x Cex base disk encryption
Browse files Browse the repository at this point in the history
Co-authored-by: Jonathan Lebon <jonathan@jlebon.com>
  • Loading branch information
madhu-pillai and jlebon committed May 9, 2024
1 parent 9a3b632 commit 31d987e
Show file tree
Hide file tree
Showing 18 changed files with 435 additions and 10 deletions.
5 changes: 5 additions & 0 deletions config/doc/ignition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,11 @@ root:
required: true
- name: needsNetwork
desc: whether or not the device requires networking.
- name: cex
desc: describes the IBM Crypto Express (CEX) card configuration for the luks device.
children:
- name: enabled
desc: whether or not to use a CEX secure key to encrypt the luks device.
- name: systemd
desc: describes the desired state of the systemd units.
children:
Expand Down
2 changes: 2 additions & 0 deletions config/shared/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ var (
ErrInvalidProxy = errors.New("proxies must be http(s)")
ErrInsecureProxy = errors.New("insecure plaintext HTTP proxy specified for HTTPS resources")
ErrPathConflictsSystemd = errors.New("path conflicts with systemd unit or dropin")
ErrCexWithClevis = errors.New("cannot use cex with clevis")
ErrCexWithKeyFile = errors.New("cannot use key file with cex")

// Systemd section errors
ErrInvalidSystemdExt = errors.New("invalid systemd unit extension")
Expand Down
11 changes: 11 additions & 0 deletions config/v3_5_experimental/schema/ignition.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,9 @@
"clevis": {
"$ref": "#/definitions/storage/definitions/clevis"
},
"cex": {
"$ref": "#/definitions/storage/definitions/cex"
},
"options": {
"type": "array",
"items": {
Expand Down Expand Up @@ -334,6 +337,14 @@
}
}
},
"cex": {
"type": "object",
"properties": {
"enabled": {
"type": ["boolean", "null"]
}
}
},
"filesystem": {
"type": "object",
"properties": {
Expand Down
24 changes: 24 additions & 0 deletions config/v3_5_experimental/translate/translate.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,33 @@ func translateIgnition(old old_types.Ignition) (ret types.Ignition) {
return
}

func translateLuks(old old_types.Luks) (ret types.Luks) {
tr := translate.NewTranslator()
tr.AddCustomTranslator(translateTang)
tr.Translate(&old.Clevis, &ret.Clevis)
tr.Translate(&old.Device, &ret.Device)
tr.Translate(&old.KeyFile, &ret.KeyFile)
tr.Translate(&old.Label, &ret.Label)
tr.Translate(&old.Name, &ret.Name)
tr.Translate(&old.OpenOptions, &ret.OpenOptions)
tr.Translate(&old.Options, &ret.Options)
tr.Translate(&old.Discard, &ret.Discard)
tr.Translate(&old.UUID, &ret.UUID)
tr.Translate(&old.WipeVolume, &ret.WipeVolume)
return
}

func translateTang(old old_types.Tang) (ret types.Tang) {
tr := translate.NewTranslator()
tr.Translate(&old.Thumbprint, &ret.Thumbprint)
tr.Translate(&old.URL, &ret.URL)
return
}

func Translate(old old_types.Config) (ret types.Config) {
tr := translate.NewTranslator()
tr.AddCustomTranslator(translateIgnition)
tr.AddCustomTranslator(translateLuks)
tr.Translate(&old, &ret)
return
}
33 changes: 33 additions & 0 deletions config/v3_5_experimental/types/cex.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2020 Red Hat, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
"github.com/coreos/ignition/v2/config/util"

"github.com/coreos/vcontext/path"
"github.com/coreos/vcontext/report"
)

func (cm Cex) IsPresent() bool {
return util.IsTrue(cm.Enabled)
}

func (cx Cex) Validate(c path.ContextPath) (r report.Report) {
if !util.IsTrue(cx.Enabled) {
return
}
return
}
53 changes: 53 additions & 0 deletions config/v3_5_experimental/types/cex_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2021 Red Hat, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
"reflect"
"testing"

"github.com/coreos/ignition/v2/config/util"

"github.com/coreos/vcontext/path"
"github.com/coreos/vcontext/report"
)

func TestCexValidate(t *testing.T) {
tests := []struct {
in Cex
at path.ContextPath
out error
}{
{
in: Cex{},
out: nil,
},
{
in: Cex{
Enabled: util.BoolToPtr(true),
},
out: nil,
},
}

for i, test := range tests {
r := test.in.Validate(path.ContextPath{})
expected := report.Report{}
expected.AddOnError(test.at, test.out)
if !reflect.DeepEqual(expected, r) {
t.Errorf("#%d: bad report: want %v, got %v", i, expected, r)
}
}
}
11 changes: 11 additions & 0 deletions config/v3_5_experimental/types/luks.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ func (l Luks) Validate(c path.ContextPath) (r report.Report) {
if err := validateURLNilOK(l.KeyFile.Source); err != nil {
r.AddOnError(c.Append("keys"), errors.ErrInvalidLuksKeyFile)
}

// fail if Cex use with Clevis
if l.Clevis.IsPresent() && l.Cex.IsPresent() {
r.AddOnError(c.Append("cex"), errors.ErrCexWithClevis)
}

// fail if key file is provided along with Cex
if l.Cex.IsPresent() && util.NotEmpty(l.KeyFile.Source) {
r.AddOnError(c.Append("cex"), errors.ErrCexWithKeyFile)
}

return
}

Expand Down
5 changes: 5 additions & 0 deletions config/v3_5_experimental/types/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package types

// generated by "schematyper --package=types config/v3_5_experimental/schema/ignition.json -o config/v3_5_experimental/types/schema.go --root-type=Config" -- DO NOT EDIT

type Cex struct {
Enabled *bool `json:"enabled,omitempty"`
}

type Clevis struct {
Custom ClevisCustom `json:"custom,omitempty"`
Tang []Tang `json:"tang,omitempty"`
Expand Down Expand Up @@ -109,6 +113,7 @@ type LinkEmbedded1 struct {
}

type Luks struct {
Cex Cex `json:"cex,omitempty"`
Clevis Clevis `json:"clevis,omitempty"`
Device *string `json:"device,omitempty"`
Discard *bool `json:"discard,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions docs/configuration-v3_5_experimental.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ The Ignition configuration is a JSON document conforming to the following specif
* **pin** (string): the clevis pin.
* **config** (string): the clevis configuration JSON.
* **_needsNetwork_** (boolean): whether or not the device requires networking.
* **_cex_** (object): describes the IBM Crypto Express (CEX) card configuration for the luks device.
* **_enabled_** (boolean): whether or not to use a CEX secure key to encrypt the luks device.
* **_systemd_** (object): describes the desired state of the systemd units.
* **_units_** (list of objects): the list of systemd units. Every unit must have a unique `name`.
* **name** (string): the name of the unit. This must be suffixed with a valid unit type (e.g. "thing.service").
Expand Down
1 change: 1 addition & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ nav_order: 9
### Features

- Support Akamai Connected Cloud (Linode)
- Support LUKS encryption using IBM CEX secure keys

### Changes

Expand Down
15 changes: 15 additions & 0 deletions dracut/30ignition/ignition-cex
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Intention of this file.
1. This is a dummy "keyfile" specific to IBM Crypto Card based LUKs encryption.
2. A key used to encrypt and decrypt the user data on a volume formatted in luks2 format.
3. A key slot in luks2 header stores a wrapped copy of this volume key,where the wrapping
key is derived from the users passphrase or "keyfile".
4. In the infrastructure for protected volume encryption, the luks2 volume key is secure key.
5. The effective volume is twofold protected: it is encrypted by an AES master key
from a CCA or EP11 coProcessor and by a wrapping key or KEK derived from a passphrase or "keyfile".
6. Therefore to unlock a luks2 volume a passphrase - provided interactively or from this "keyfile"
is required to decrypt the outer wrapping.
7. The security provided by the passphrase or "keyfile" is typically much lower than that provided by the wrapping AES master key.
8. Therefore the password or "keyfile" may be exposed without any loss of security.
9. When a secure key for the PAES cipher is provide to dm-crypt inorder to open a volume,
it automatically transforms this secure key into a protected key that can be interpreted by the CPACF.
10. The actual effective key of the luks2 volume key is never exposed to the operating system.
13 changes: 11 additions & 2 deletions dracut/30ignition/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,13 @@ install() {

# Required by s390x's z/VM installation.
# Supporting https://github.com/coreos/ignition/pull/865
inst_multiple -o chccwdev vmur
if [[ ${DRACUT_ARCH:-$(uname -m)} == s390x ]]; then
inst_multiple chccwdev vmur zkey zkey-cryptsetup

# Required on system using SELinux
inst_simple "$moddir/ignition-cex" "/etc/luks/cex.key"
fi

# Required on system using SELinux.
inst_multiple -o setfiles

inst_script "$moddir/ignition-kargs-helper.sh" \
Expand Down Expand Up @@ -112,5 +116,10 @@ installkernel() {
instmods -c vsock
instmods -c vmw_vsock_virtio_transport_common
instmods -c vmw_vsock_virtio_transport

# required for cex card early initialization
if [[ ${DRACUT_ARCH:-$(uname -m)} == s390x ]]; then
instmods -c zcrypt_cex4
fi
}

18 changes: 12 additions & 6 deletions internal/distro/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ var (
vfatMkfsCmd = "mkfs.fat"
xfsMkfsCmd = "mkfs.xfs"

//zVM programs
vmurCmd = "vmur"
chccwdevCmd = "chccwdev"
cioIgnoreCmd = "cio_ignore"
// z/VM programs
vmurCmd = "vmur"
chccwdevCmd = "chccwdev"
cioIgnoreCmd = "cio_ignore"
zkeycryptsetupCmd = "zkey-cryptsetup"
zkeyCmd = "zkey"

// LUKS programs
clevisCmd = "clevis"
Expand All @@ -77,6 +79,7 @@ var (
// Special file paths in the real root
luksRealRootKeyFilePath = "/etc/luks/"
resultFilePath = "/etc/.ignition-result.json"
luksCexSecureKeyRepo = "/etc/zkey/repository/"
)

func DiskByLabelDir() string { return diskByLabelDir }
Expand Down Expand Up @@ -108,14 +111,17 @@ func XfsMkfsCmd() string { return xfsMkfsCmd }
func VmurCmd() string { return vmurCmd }
func ChccwdevCmd() string { return chccwdevCmd }
func CioIgnoreCmd() string { return cioIgnoreCmd }
func ZkeyCryptCmd() string { return zkeycryptsetupCmd }
func ZkeyCmd() string { return zkeyCmd }

func ClevisCmd() string { return clevisCmd }
func CryptsetupCmd() string { return cryptsetupCmd }

func KargsCmd() string { return kargsCmd }

func LuksRealRootKeyFilePath() string { return luksRealRootKeyFilePath }
func ResultFilePath() string { return resultFilePath }
func LuksRealRootKeyFilePath() string { return luksRealRootKeyFilePath }
func ResultFilePath() string { return resultFilePath }
func LuksRealVolumeKeyFilePath() string { return luksCexSecureKeyRepo }

func SelinuxRelabel() bool { return bakedStringToBool(selinuxRelabel) && !BlackboxTesting() }
func BlackboxTesting() bool { return bakedStringToBool(blackboxTesting) }
Expand Down
Loading

0 comments on commit 31d987e

Please sign in to comment.