diff --git a/cmd/main.go b/cmd/main.go index a1c0e4e..880e330 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -12,10 +12,10 @@ import ( "net" fe "github.com/opiproject/opi-intel-bridge/pkg/frontend" + me "github.com/opiproject/opi-intel-bridge/pkg/middleend" "github.com/opiproject/opi-smbios-bridge/pkg/inventory" "github.com/opiproject/opi-spdk-bridge/pkg/backend" "github.com/opiproject/opi-spdk-bridge/pkg/frontend" - "github.com/opiproject/opi-spdk-bridge/pkg/middleend" "github.com/opiproject/opi-spdk-bridge/pkg/server" "github.com/opiproject/opi-strongswan-bridge/pkg/ipsec" @@ -45,7 +45,7 @@ func main() { frontendOpiIntelServer := fe.NewServer(jsonRPC) frontendOpiSpdkServer := frontend.NewServer(jsonRPC) backendOpiSpdkServer := backend.NewServer(jsonRPC) - middleendOpiSpdkServer := middleend.NewServer(jsonRPC) + middleendOpiIntelServer := me.NewServer(jsonRPC) pb.RegisterFrontendNvmeServiceServer(s, frontendOpiIntelServer) pb.RegisterFrontendVirtioBlkServiceServer(s, frontendOpiSpdkServer) @@ -53,7 +53,7 @@ func main() { pb.RegisterNVMfRemoteControllerServiceServer(s, backendOpiSpdkServer) pb.RegisterNullDebugServiceServer(s, backendOpiSpdkServer) pb.RegisterAioControllerServiceServer(s, backendOpiSpdkServer) - pb.RegisterMiddleendServiceServer(s, middleendOpiSpdkServer) + pb.RegisterMiddleendServiceServer(s, middleendOpiIntelServer) pc.RegisterInventorySvcServer(s, &inventory.Server{}) ps.RegisterIPsecServer(s, &ipsec.Server{}) diff --git a/pkg/middleend/middleend.go b/pkg/middleend/middleend.go new file mode 100644 index 0000000..200ebac --- /dev/null +++ b/pkg/middleend/middleend.go @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Intel Corporation + +// Package middleend implements the MiddleEnd APIs (service) of the storage Server +package middleend + +import ( + "context" + "encoding/hex" + "log" + "runtime" + "runtime/debug" + + pc "github.com/opiproject/opi-api/common/v1/gen/go" + pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go" + intelmodels "github.com/opiproject/opi-intel-bridge/pkg/models" + "github.com/opiproject/opi-spdk-bridge/pkg/middleend" + spdkmodels "github.com/opiproject/opi-spdk-bridge/pkg/models" + "github.com/opiproject/opi-spdk-bridge/pkg/server" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +var ( + errMissingArgument = status.Error(codes.InvalidArgument, "missing argument") + errNotSupportedCipher = status.Error(codes.Unimplemented, "not supported cipher") + errWrongKeySize = status.Error(codes.InvalidArgument, "invalid key size") +) + +// Server contains middleend related OPI services +type Server struct { + pb.MiddleendServiceServer + rpc server.JSONRPC +} + +// NewServer creates initialized instance of middleend server +func NewServer(jsonRPC server.JSONRPC) *Server { + opiSpdkServer := middleend.NewServer(jsonRPC) + return &Server{ + opiSpdkServer, + jsonRPC, + } +} + +// CreateEncryptedVolume creates an encrypted volume +func (s *Server) CreateEncryptedVolume(_ context.Context, in *pb.CreateEncryptedVolumeRequest) (*pb.EncryptedVolume, error) { + defer func() { + if in != nil && in.EncryptedVolume != nil { + for i := range in.EncryptedVolume.Key { + in.EncryptedVolume.Key[i] = 0 + } + in.EncryptedVolume.Cipher = pb.EncryptionType_ENCRYPTION_TYPE_UNSPECIFIED + } + // Run GC to free all variables which contained encryption keys + runtime.GC() + // Return allocated memory to OS, otherwise the memory which contained + // keys can be kept for some time. + debug.FreeOSMemory() + }() + + err := verifyCreateEncryptedVolumeRequestArgs(in) + if err != nil { + return nil, err + } + + bdevUUID, err := s.getBdevUUIDByName(in.EncryptedVolume.VolumeId.Value) + if err != nil { + log.Println("Failed to find UUID for bdev", in.EncryptedVolume.VolumeId.Value) + return nil, err + } + + half := len(in.EncryptedVolume.Key) / 2 + tweakMode := "A" + params := &intelmodels.NpiBdevSetKeysParams{ + UUID: bdevUUID, + Key: hex.EncodeToString(in.EncryptedVolume.Key[:half]), + Key2: hex.EncodeToString(in.EncryptedVolume.Key[half:]), + Cipher: "AES_XTS", + Tweak: tweakMode, + } + defer func() { + params = nil + }() + + var result intelmodels.NpiBdevSetKeysResult + err = s.rpc.Call("npi_bdev_set_keys", params, &result) + if err != nil { + log.Println("error:", err) + return nil, server.ErrFailedSpdkCall + } + if !result { + log.Println("Failed result on SPDK call:", result) + return nil, server.ErrUnexpectedSpdkCallResult + } + + return &pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: in.EncryptedVolume.EncryptedVolumeId.Value}, + VolumeId: &pc.ObjectKey{Value: in.EncryptedVolume.VolumeId.Value}, + }, nil +} + +func verifyCreateEncryptedVolumeRequestArgs(in *pb.CreateEncryptedVolumeRequest) error { + switch { + case in == nil: + log.Println("request cannot be empty") + return errMissingArgument + case in.EncryptedVolume == nil: + log.Println("encrypted_volume should be specified") + return errMissingArgument + case in.EncryptedVolume.EncryptedVolumeId == nil || in.EncryptedVolume.EncryptedVolumeId.Value == "": + log.Println("encrypted_volume_id should be specified") + return errMissingArgument + case in.EncryptedVolume.VolumeId == nil || in.EncryptedVolume.VolumeId.Value == "": + log.Println("volume_id should be specified") + return errMissingArgument + case len(in.EncryptedVolume.Key) == 0: + log.Println("key cannot be empty") + return errMissingArgument + } + + keyLengthInBits := len(in.EncryptedVolume.Key) * 8 + expectedKeyLengthInBits := 0 + switch { + case in.EncryptedVolume.Cipher == pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256: + expectedKeyLengthInBits = 512 + case in.EncryptedVolume.Cipher == pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_128: + expectedKeyLengthInBits = 256 + default: + log.Println("only AES_XTS_128 and AES_XTS_256 are supported") + return errNotSupportedCipher + } + + if keyLengthInBits != expectedKeyLengthInBits { + log.Printf("expected key size %vb, provided size %vb", + expectedKeyLengthInBits, keyLengthInBits) + return errWrongKeySize + } + + return nil +} + +func (s *Server) getBdevUUIDByName(name string) (string, error) { + params := spdkmodels.BdevGetBdevsParams{Name: name} + var result []spdkmodels.BdevGetBdevsResult + err := s.rpc.Call("bdev_get_bdevs", params, &result) + if err != nil { + log.Println("error:", err) + return "", server.ErrFailedSpdkCall + } + if len(result) != 1 { + log.Println("Found bdevs:", result, "under the name", params.Name) + return "", server.ErrUnexpectedSpdkCallResult + } + return result[0].UUID, nil +} diff --git a/pkg/middleend/middleend_test.go b/pkg/middleend/middleend_test.go new file mode 100644 index 0000000..afb1316 --- /dev/null +++ b/pkg/middleend/middleend_test.go @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Intel Corporation + +// Package middleend implements the FrontEnd APIs (host facing) of the storage Server +package middleend + +import ( + "bytes" + "context" + "log" + "net" + "os" + "testing" + + pc "github.com/opiproject/opi-api/common/v1/gen/go" + pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go" + "github.com/opiproject/opi-spdk-bridge/pkg/server" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/test/bufconn" + "google.golang.org/protobuf/proto" +) + +type middleendClient struct { + pb.MiddleendServiceClient +} + +type testEnv struct { + opiSpdkServer *Server + client *middleendClient + ln net.Listener + testSocket string + ctx context.Context + conn *grpc.ClientConn + jsonRPC server.JSONRPC +} + +func (e *testEnv) Close() { + server.CloseListener(e.ln) + if err := os.RemoveAll(e.testSocket); err != nil { + log.Fatal(err) + } + server.CloseGrpcConnection(e.conn) +} + +func createTestEnvironment(startSpdkServer bool, spdkResponses []string) *testEnv { + env := &testEnv{} + env.testSocket = server.GenerateSocketName("middleend") + env.ln, env.jsonRPC = server.CreateTestSpdkServer(env.testSocket, startSpdkServer, spdkResponses) + env.opiSpdkServer = NewServer(env.jsonRPC) + + ctx := context.Background() + conn, err := grpc.DialContext(ctx, + "", + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithContextDialer(dialer(env.opiSpdkServer))) + if err != nil { + log.Fatal(err) + } + env.ctx = ctx + env.conn = conn + + env.client = &middleendClient{ + pb.NewMiddleendServiceClient(env.conn), + } + + return env +} + +func dialer(opiSpdkServer *Server) func(context.Context, string) (net.Conn, error) { + listener := bufconn.Listen(1024 * 1024) + server := grpc.NewServer() + pb.RegisterMiddleendServiceServer(server, opiSpdkServer) + + go func() { + if err := server.Serve(listener); err != nil { + log.Fatal(err) + } + }() + + return func(context.Context, string) (net.Conn, error) { + return listener.Dial() + } +} + +var ( + bdevName = "bdev-42" + foundBdevResponse = `{"id":%d,"error":{"code":0,"message":""},"result":[` + + `{"name":"bdev-42","block_size":4096,"num_blocks":256,"uuid":"9d7988c6-4b42-4196-a46f-a656a89deb36"}]}` + keyOf128Bits = []byte("0123456789abcdef") + keyOf192Bits = []byte("0123456789abcdef01234567") + keyOf256Bits = []byte("0123456789abcdef0123456789abcdef") + keyOf384Bits = []byte("0123456789abcdef0123456789abcdef0123456789abcdef") + keyOf512bits = []byte("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") + // Volumes for supported algorithms + encryptedVolumeAesXts256 = pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: "crypto-test-aes-xts-256"}, + VolumeId: &pc.ObjectKey{Value: bdevName}, + Key: keyOf512bits, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + } + encryptedVolumeAesXts256InResponse = pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + VolumeId: encryptedVolumeAesXts256.VolumeId, + } + encryptedVolumeAesXts128 = pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: "crypto-test-aes-xts-128"}, + VolumeId: &pc.ObjectKey{Value: bdevName}, + Key: keyOf256Bits, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_128, + } + encryptedVolumeAesXts128InResponse = pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts128.EncryptedVolumeId, + VolumeId: encryptedVolumeAesXts128.VolumeId, + } + + // Volumes for not supported algorithms + encryptedVolumeAesXts192 = pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: "crypto-test-aes-xts-192"}, + VolumeId: &pc.ObjectKey{Value: bdevName}, + Key: keyOf384Bits, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_192, + } + encryptedVolumeAesCbc128 = pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: "crypto-test-aes-cbc-128"}, + VolumeId: &pc.ObjectKey{Value: bdevName}, + Key: keyOf128Bits, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_CBC_128, + } + encryptedVolumeAesCbc192 = pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: "crypto-test-aes-cbc-192"}, + VolumeId: &pc.ObjectKey{Value: bdevName}, + Key: keyOf192Bits, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_CBC_192, + } + encryptedVolumeAesCbc256 = pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: "crypto-test-aes-cbc-256"}, + VolumeId: &pc.ObjectKey{Value: bdevName}, + Key: keyOf256Bits, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_CBC_256, + } +) + +func TestMiddleEnd_CreateEncryptedVolume(t *testing.T) { + tests := map[string]struct { + in *pb.CreateEncryptedVolumeRequest + out *pb.EncryptedVolume + spdk []string + expectedInKey []byte + expectedErr error + start bool + }{ + "nil request": { + in: nil, + out: nil, + spdk: []string{}, + expectedInKey: nil, + expectedErr: errMissingArgument, + start: false, + }, + "nil EncryptedVolume": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: nil}, + out: nil, + spdk: []string{}, + expectedInKey: nil, + expectedErr: errMissingArgument, + start: false, + }, + "nil EncryptedVolumeId": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + VolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + Key: encryptedVolumeAesXts256.Key, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: errMissingArgument, + start: false, + }, + "empty EncryptedVolumeId": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: &pc.ObjectKey{Value: ""}, + VolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + Key: encryptedVolumeAesXts256.Key, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: errMissingArgument, + start: false, + }, + "empty Key": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + VolumeId: encryptedVolumeAesXts256.VolumeId, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + Key: make([]byte, 0), + }}, + out: nil, + spdk: []string{}, + expectedInKey: nil, + expectedErr: errMissingArgument, + start: false, + }, + "nil VolumeId": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + Key: encryptedVolumeAesXts256.Key, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: errMissingArgument, + start: false, + }, + "empty VolumeId": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + VolumeId: &pc.ObjectKey{Value: ""}, + Key: encryptedVolumeAesXts256.Key, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: errMissingArgument, + start: false, + }, + "use AES_XTS_128 cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts128}, + out: &encryptedVolumeAesXts128InResponse, + spdk: []string{foundBdevResponse, `{"id":%d,"error":{"code":0,"message":""},"result":true}`}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts128.Key)), + expectedErr: nil, + start: true, + }, + "use AES_XTS_192 cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts192}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts192.Key)), + expectedErr: errNotSupportedCipher, + start: false, + }, + "use AES_XTS_256 cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts256}, + out: &encryptedVolumeAesXts256InResponse, + spdk: []string{foundBdevResponse, `{"id":%d,"error":{"code":0,"message":""},"result":true}`}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: nil, + start: true, + }, + "use AES_CBC_128 cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesCbc128}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesCbc128.Key)), + expectedErr: errNotSupportedCipher, + start: false, + }, + "use AES_CBC_192 cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesCbc192}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesCbc192.Key)), + expectedErr: errNotSupportedCipher, + start: false, + }, + "use AES_CBC_256 cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesCbc256}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesCbc256.Key)), + expectedErr: errNotSupportedCipher, + start: false, + }, + "use UNSPECIFIED cipher": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + VolumeId: encryptedVolumeAesXts256.VolumeId, + Key: encryptedVolumeAesXts256.Key, + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_UNSPECIFIED, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: errNotSupportedCipher, + start: false, + }, + "key of wrong size for AEX_XTS_256": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts256.EncryptedVolumeId, + VolumeId: encryptedVolumeAesXts256.VolumeId, + Key: []byte("1"), + Cipher: pb.EncryptionType_ENCRYPTION_TYPE_AES_XTS_256, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, 1), + expectedErr: errWrongKeySize, + start: false, + }, + "key of wrong size for AEX_XTS_128": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &pb.EncryptedVolume{ + EncryptedVolumeId: encryptedVolumeAesXts128.EncryptedVolumeId, + VolumeId: encryptedVolumeAesXts128.VolumeId, + Key: []byte("1"), + Cipher: encryptedVolumeAesXts128.Cipher, + }}, + out: nil, + spdk: []string{}, + expectedInKey: make([]byte, 1), + expectedErr: errWrongKeySize, + start: false, + }, + "find bdev uuid by name internal SPDK failure": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts256}, + out: nil, + spdk: []string{`{"id":%d,"error":{"code":-19,"message":"No such device"},"result":null}`}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: server.ErrFailedSpdkCall, + start: true, + }, + "find no bdev uuid by name": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts256}, + out: nil, + spdk: []string{`{"id":%d,"error":{"code":0,"message":""},"result":[]}`}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: server.ErrUnexpectedSpdkCallResult, + start: true, + }, + "internal SPDK failure": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts256}, + out: nil, + spdk: []string{foundBdevResponse, `{"id":%d,"error":{"code":1,"message":"some internal error"},"result":true}`}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: server.ErrFailedSpdkCall, + start: true, + }, + "SPDK result false": { + in: &pb.CreateEncryptedVolumeRequest{EncryptedVolume: &encryptedVolumeAesXts256}, + out: nil, + spdk: []string{foundBdevResponse, `{"id":%d,"error":{"code":0,"message":""},"result":false}`}, + expectedInKey: make([]byte, len(encryptedVolumeAesXts256.Key)), + expectedErr: server.ErrUnexpectedSpdkCallResult, + start: true, + }, + } + + for testName, test := range tests { + t.Run(testName, func(t *testing.T) { + testEnv := createTestEnvironment(test.start, test.spdk) + defer testEnv.Close() + var request *pb.CreateEncryptedVolumeRequest + if test.in != nil { + var ok bool + // make a copy to prevent key overwriting in the original structures + request, ok = proto.Clone(test.in).(*pb.CreateEncryptedVolumeRequest) + if !ok { + log.Panic("Failed to copy test structure for CreateEncryptedVolumeRequest") + } + } + + response, err := testEnv.opiSpdkServer.CreateEncryptedVolume(testEnv.ctx, request) + + wantOut, _ := proto.Marshal(test.out) + gotOut, _ := proto.Marshal(response) + if !bytes.Equal(wantOut, gotOut) { + t.Error("response: expected", test.out, "received", response) + } + if err != test.expectedErr { + t.Error("error: expected", test.expectedErr, "received", err) + } + if request != nil && request.EncryptedVolume != nil { + if !bytes.Equal(request.EncryptedVolume.Key, test.expectedInKey) { + t.Error("input key after operation expected", + test.expectedInKey, "received", request.EncryptedVolume.Key) + } + if request.EncryptedVolume.Cipher != pb.EncryptionType_ENCRYPTION_TYPE_UNSPECIFIED { + t.Error("Expect in cipher set to EncryptionType_ENCRYPTION_TYPE_UNSPECIFIED, received", + request.EncryptedVolume.Cipher) + } + } + }) + } +} diff --git a/pkg/models/spdk.go b/pkg/models/spdk.go new file mode 100644 index 0000000..0ee68e0 --- /dev/null +++ b/pkg/models/spdk.go @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (C) 2023 Intel Corporation + +// Package models holds definitions for SPDK json RPC structs +package models + +// NpiBdevSetKeysParams holds the parameters required to set crypto keys +type NpiBdevSetKeysParams struct { + UUID string `json:"uuid"` + Key string `json:"key"` + Key2 string `json:"key2"` + Cipher string `json:"cipher"` + Tweak string `json:"tweak"` +} + +// NpiBdevSetKeysResult is the result of setting crypto keys +type NpiBdevSetKeysResult bool