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:
parent
b82f1987b9
commit
3408399172
@ -33,6 +33,26 @@ message VolumeCryptoParameters {
|
|||||||
}
|
}
|
||||||
// Cipher to use
|
// Cipher to use
|
||||||
Cipher cipher = 3;
|
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
|
// Parameters describing a volume
|
||||||
|
@ -23,7 +23,7 @@ class CryptoEngine:
|
|||||||
"""Initialize crypto engine"""
|
"""Initialize crypto engine"""
|
||||||
self._client = client
|
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"""
|
"""Set up crypto on a given volume"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ class CryptoEngine:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
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
|
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
|
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):
|
def __init__(self):
|
||||||
super().__init__('nop')
|
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')
|
raise CryptoException(grpc.StatusCode.INVALID_ARGUMENT, 'Crypto is disabled')
|
||||||
|
|
||||||
def cleanup(self, volume_id):
|
def cleanup(self, volume_id):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def verify(self, volume_id, key, cipher, key2=None):
|
def verify(self, volume_id, key, cipher, key2=None, tweak_mode=None):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_crypto_bdev(self, volume_id):
|
def get_crypto_bdev(self, volume_id):
|
||||||
|
@ -26,7 +26,7 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
|||||||
# _driver can be None
|
# _driver can be None
|
||||||
self._driver = params.get('driver')
|
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:
|
try:
|
||||||
with self._client() as client:
|
with self._client() as client:
|
||||||
cipher = self._ciphers.get(cipher)
|
cipher = self._ciphers.get(cipher)
|
||||||
@ -41,6 +41,10 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
|||||||
params['crypto_pmd'] = self._driver
|
params['crypto_pmd'] = self._driver
|
||||||
if key2 is not None:
|
if key2 is not None:
|
||||||
params['key2'] = key2
|
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(
|
log.info('Creating crypto bdev: {} on volume: {}'.format(
|
||||||
params['name'], volume_id))
|
params['name'], volume_id))
|
||||||
client.call('bdev_crypto_create', params)
|
client.call('bdev_crypto_create', params)
|
||||||
@ -62,7 +66,7 @@ class CryptoEngineBdev(crypto.CryptoEngine):
|
|||||||
raise crypto.CryptoException(grpc.StatusCode.INTERNAL,
|
raise crypto.CryptoException(grpc.StatusCode.INTERNAL,
|
||||||
'Failed to delete crypto bdev')
|
'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)
|
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
|
# 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)):
|
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():
|
if crypto_key['name'].lower() != params['key_name'].lower():
|
||||||
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
raise crypto.CryptoException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||||
'Invalid volume crypto configuration: key name does not match')
|
'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):
|
def _get_crypto_bdev(self, volume_id):
|
||||||
try:
|
try:
|
||||||
|
@ -163,23 +163,25 @@ class VolumeManager:
|
|||||||
'Failed to stop discovery')
|
'Failed to stop discovery')
|
||||||
|
|
||||||
def _get_crypto_params(self, params):
|
def _get_crypto_params(self, params):
|
||||||
key, cipher, key2 = None, None, None
|
key, cipher, key2, tweak_mode = None, None, None, None
|
||||||
try:
|
try:
|
||||||
if params.HasField('crypto'):
|
if params.HasField('crypto'):
|
||||||
key, cipher = params.crypto.key.decode('ascii'), params.crypto.cipher
|
key, cipher = params.crypto.key.decode('ascii'), params.crypto.cipher
|
||||||
if len(params.crypto.key2) > 0:
|
if len(params.crypto.key2) > 0:
|
||||||
key2 = params.crypto.key2.decode('ascii')
|
key2 = params.crypto.key2.decode('ascii')
|
||||||
|
if params.crypto.tweak_mode is not None:
|
||||||
|
tweak_mode = params.crypto.tweak_mode
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
raise VolumeException(grpc.StatusCode.INVALID_ARGUMENT,
|
raise VolumeException(grpc.StatusCode.INVALID_ARGUMENT,
|
||||||
'Corrupted crypto key')
|
'Corrupted crypto key')
|
||||||
return key, cipher, key2
|
return key, cipher, key2, tweak_mode
|
||||||
|
|
||||||
def _setup_crypto(self, volume_id, params):
|
def _setup_crypto(self, volume_id, params):
|
||||||
try:
|
try:
|
||||||
if not params.HasField('crypto'):
|
if not params.HasField('crypto'):
|
||||||
return
|
return
|
||||||
key, cipher, key2 = self._get_crypto_params(params)
|
key, cipher, key2, tweak_mode = self._get_crypto_params(params)
|
||||||
crypto.get_crypto_engine().setup(volume_id, key, cipher, key2)
|
crypto.get_crypto_engine().setup(volume_id, key, cipher, key2, tweak_mode)
|
||||||
except crypto.CryptoException as ex:
|
except crypto.CryptoException as ex:
|
||||||
raise VolumeException(ex.code, ex.message)
|
raise VolumeException(ex.code, ex.message)
|
||||||
|
|
||||||
@ -191,8 +193,8 @@ class VolumeManager:
|
|||||||
|
|
||||||
def _verify_crypto(self, volume_id, params):
|
def _verify_crypto(self, volume_id, params):
|
||||||
try:
|
try:
|
||||||
key, cipher, key2 = self._get_crypto_params(params)
|
key, cipher, key2, tweak_mode = self._get_crypto_params(params)
|
||||||
crypto.get_crypto_engine().verify(volume_id, key, cipher, key2)
|
crypto.get_crypto_engine().verify(volume_id, key, cipher, key2, tweak_mode)
|
||||||
except crypto.CryptoException as ex:
|
except crypto.CryptoException as ex:
|
||||||
raise VolumeException(ex.code, ex.message)
|
raise VolumeException(ex.code, ex.message)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user