diff --git a/proto/sma.proto b/proto/sma.proto index ea02471f3..a725bc40f 100644 --- a/proto/sma.proto +++ b/proto/sma.proto @@ -33,6 +33,26 @@ message VolumeCryptoParameters { } // Cipher to use Cipher cipher = 3; + // Tweak mode - determine how nvme LBA is converted into tweak + enum TweakMode { + // default for SPDK bdev_crypto + // Tweak[127:0] = {64'b0, LBA[63:0]} + TWEAK_MODE_SIMPLE_LBA = 0; + + // Tweak[127:0] = {1’b0, ~LBA[62:0], LBA[63:0]} + TWEAK_MODE_NOT_AND_LBA = 1; + + // tweak is derived from nvme LBA that is internally incremented by 1 for every 512 bytes processed + // so initial lba = (BLOCK_SIZE_IN_BYTES / 512) * LBA + // Tweak[127:0] = {lba[127:0]} + TWEAK_MODE_FORCE_512_FULL = 2; + + // tweak is derived from nvme LBA that is internally incremented by 1 for every 512 bytes processed + // so initial lba = (BLOCK_SIZE_IN_BYTES / 512) * LBA + // Tweak[127:0] = {lba[63:0], 64'b0} + TWEAK_MODE_FORCE_512_UPPER = 3; + } + TweakMode tweak_mode = 4; } // Parameters describing a volume diff --git a/python/spdk/sma/volume/crypto.py b/python/spdk/sma/volume/crypto.py index 6079d4604..3edfdf590 100644 --- a/python/spdk/sma/volume/crypto.py +++ b/python/spdk/sma/volume/crypto.py @@ -23,7 +23,7 @@ class CryptoEngine: """Initialize crypto engine""" self._client = client - def setup(self, volume_id, key, cipher, key2=None): + def setup(self, volume_id, key, cipher, key2=None, tweak_mode=None): """Set up crypto on a given volume""" raise NotImplementedError() @@ -34,7 +34,7 @@ class CryptoEngine: """ raise NotImplementedError() - def verify(self, volume_id, key, cipher, key2=None): + def verify(self, volume_id, key, cipher, key2=None, tweak_mode=None): """ Verify that specified crypto parameters match those that are currently deployed on a given volume. If key is None, this mehtod ensures that the volume doesn't use crypto. If @@ -56,13 +56,13 @@ class CryptoEngineNop(CryptoEngine): def __init__(self): super().__init__('nop') - def setup(self, volume_id, key, cipher, key2=None): + def setup(self, volume_id, key, cipher, key2=None, tweak_mode=None): raise CryptoException(grpc.StatusCode.INVALID_ARGUMENT, 'Crypto is disabled') def cleanup(self, volume_id): pass - def verify(self, volume_id, key, cipher, key2=None): + def verify(self, volume_id, key, cipher, key2=None, tweak_mode=None): pass def get_crypto_bdev(self, volume_id): diff --git a/python/spdk/sma/volume/crypto_bdev.py b/python/spdk/sma/volume/crypto_bdev.py index 9911a6ce9..8d465ad75 100644 --- a/python/spdk/sma/volume/crypto_bdev.py +++ b/python/spdk/sma/volume/crypto_bdev.py @@ -26,7 +26,7 @@ class CryptoEngineBdev(crypto.CryptoEngine): # _driver can be None self._driver = params.get('driver') - def setup(self, volume_id, key, cipher, key2=None): + def setup(self, volume_id, key, cipher, key2=None, tweak_mode=None): try: with self._client() as client: cipher = self._ciphers.get(cipher) @@ -41,6 +41,10 @@ class CryptoEngineBdev(crypto.CryptoEngine): params['crypto_pmd'] = self._driver if key2 is not None: params['key2'] = key2 + if tweak_mode is not None and tweak_mode != sma_pb2.VolumeCryptoParameters.TWEAK_MODE_SIMPLE_LBA: + raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT, + 'Invalid volume crypto configuration: bad tweak_mode') + log.info('Creating crypto bdev: {} on volume: {}'.format( params['name'], volume_id)) client.call('bdev_crypto_create', params) @@ -62,7 +66,7 @@ class CryptoEngineBdev(crypto.CryptoEngine): raise crypto.CryptoException(grpc.StatusCode.INTERNAL, 'Failed to delete crypto bdev') - def verify(self, volume_id, key, cipher, key2=None): + def verify(self, volume_id, key, cipher, key2=None, tweak_mode=None): crypto_bdev = self._get_crypto_bdev(volume_id) # Key being None/non-None defines whether we expect a bdev_crypto on top of a given volume if ((key is None and crypto_bdev is not None) or (key is not None and crypto_bdev is None)): @@ -91,6 +95,9 @@ class CryptoEngineBdev(crypto.CryptoEngine): if crypto_key['name'].lower() != params['key_name'].lower(): raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT, 'Invalid volume crypto configuration: key name does not match') + if tweak_mode is not None and tweak_mode != sma_pb2.VolumeCryptoParameters.TWEAK_MODE_SIMPLE_LBA: + raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT, + 'Invalid volume crypto configuration: bad tweak_mode') def _get_crypto_bdev(self, volume_id): try: diff --git a/python/spdk/sma/volume/volume.py b/python/spdk/sma/volume/volume.py index 8c0226b4b..7d49503d6 100644 --- a/python/spdk/sma/volume/volume.py +++ b/python/spdk/sma/volume/volume.py @@ -163,23 +163,25 @@ class VolumeManager: 'Failed to stop discovery') def _get_crypto_params(self, params): - key, cipher, key2 = None, None, None + key, cipher, key2, tweak_mode = None, None, None, None try: if params.HasField('crypto'): key, cipher = params.crypto.key.decode('ascii'), params.crypto.cipher if len(params.crypto.key2) > 0: key2 = params.crypto.key2.decode('ascii') + if params.crypto.tweak_mode is not None: + tweak_mode = params.crypto.tweak_mode except UnicodeDecodeError: raise VolumeException(grpc.StatusCode.INVALID_ARGUMENT, 'Corrupted crypto key') - return key, cipher, key2 + return key, cipher, key2, tweak_mode def _setup_crypto(self, volume_id, params): try: if not params.HasField('crypto'): return - key, cipher, key2 = self._get_crypto_params(params) - crypto.get_crypto_engine().setup(volume_id, key, cipher, key2) + key, cipher, key2, tweak_mode = self._get_crypto_params(params) + crypto.get_crypto_engine().setup(volume_id, key, cipher, key2, tweak_mode) except crypto.CryptoException as ex: raise VolumeException(ex.code, ex.message) @@ -191,8 +193,8 @@ class VolumeManager: def _verify_crypto(self, volume_id, params): try: - key, cipher, key2 = self._get_crypto_params(params) - crypto.get_crypto_engine().verify(volume_id, key, cipher, key2) + key, cipher, key2, tweak_mode = self._get_crypto_params(params) + crypto.get_crypto_engine().verify(volume_id, key, cipher, key2, tweak_mode) except crypto.CryptoException as ex: raise VolumeException(ex.code, ex.message)