sma: added tweak mode in sma crypto

AES-XTS requires providing tweak. By definition tweak (128bits)
represents logical position of the data being encrypted or decrypted,
typically for nvme it is LBA.
Various implementations of AES-XTS can treat that requirment
in different way, because AES-XTS specification doesn't define
how exactly tweak look like and how exactly LBA is transformed
into tweak  For example:
 - Tweak[127:0] = {1’b0, ~LBA[62:0], LBA[63:0]}
 - Tweak[127:0] = {LBA[127:0] + 1}
 - Tweak[127:0] = {LBA[63:0] + 1, 64'b0}

So there's a need of specifying mode of tweak

Signed-off-by: Michal Rozegnal <michal.rozegnal@intel.com>
Change-Id: I92edc71f5f4dfeb0d08a34b73424675321e4740e
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/16058
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com>
Reviewed-by: Jacek Kalwas <jacek.kalwas@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Michal Rozegnal 2022-12-22 12:05:24 +01:00 committed by Tomasz Zawadzki
parent b82f1987b9
commit 3408399172
4 changed files with 41 additions and 12 deletions

View File

@ -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] = {1b0, ~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

View File

@ -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):

View File

@ -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:

View File

@ -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)