Made HMAC Key Wrap mechanism configurable

Introduced the parameter 'hmac_keywrap_mechanism' in group
'[p11_crypto_plugin]' in Barbican config. The default value, which were
hard coded before, is 'CKM_SHA256_HMAC'. This defines the machanism used
to compute the HMAC from an wrapped PKEK. However with Utimaco HSMs this
leads to an CKR_MECHANISM_INVALID error. Therefore for Utimaco HSMs
'hmac_keywrap_mechanism' has to be changed to 'CKM_AES_MAC'.

Change-Id: I53537a96bc4b2acb30be5fa85e10bac89917851f
Story: 2004833
Task: 29027
This commit is contained in:
Alexander Gräb 2019-02-08 11:13:11 +01:00 committed by Ade Lee
parent 6dc5259012
commit b7da1f771c
6 changed files with 61 additions and 13 deletions

View File

@ -184,9 +184,14 @@ class HSMCommands(object):
help='Password to login to PKCS11 session')
@args('--label', '-L', metavar='<label>', default='primarymkek',
help='The label of the Master Key Encrypt Key')
def check_mkek(self, passphrase, libpath=None, slotid=None, label=None):
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC')
def check_mkek(self, passphrase, libpath=None, slotid=None, label=None,
hmacwrap=None):
CKK_AES = 'CKK_AES'
self._create_pkcs11_session(str(passphrase), str(libpath), int(slotid))
self._create_pkcs11_session(str(passphrase), str(libpath),
int(slotid), str(hmacwrap))
handle = self.pkcs11.get_key_handle(CKK_AES, str(label), self.session)
self.pkcs11.return_session(self.session)
if not handle:
@ -208,11 +213,15 @@ class HSMCommands(object):
@args('--length', '-l', metavar='<length>', default=32,
help='The length in bytes of the Master Key Encryption Key'
' (default is 32)')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC')
def gen_mkek(self, passphrase, libpath=None, slotid=None, label=None,
length=None):
length=None, hmacwrap=None):
CKK_AES = 'CKK_AES'
CKM_AES_KEY_GEN = 'CKM_AES_KEY_GEN'
self._create_pkcs11_session(str(passphrase), str(libpath), int(slotid))
self._create_pkcs11_session(str(passphrase), str(libpath),
int(slotid), str(hmacwrap))
self._verify_label_does_not_exist(CKK_AES, str(label), self.session)
self.pkcs11.generate_key(CKK_AES, int(length), CKM_AES_KEY_GEN,
self.session, str(label),
@ -234,9 +243,13 @@ class HSMCommands(object):
help='The label of the Master HMAC key')
@args('--key-type', '-t', metavar='<key type>', dest='keytype',
default='CKK_AES', help='The HMAC Key Type (e.g. CKK_AES)')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC')
def check_hmac(self, passphrase, libpath=None, slotid=None, label=None,
keytype=None):
self._create_pkcs11_session(str(passphrase), str(libpath), int(slotid))
keytype=None, hmacwrap=None):
self._create_pkcs11_session(str(passphrase), str(libpath),
int(slotid), str(hmacwrap))
handle = self.pkcs11.get_key_handle(str(keytype), str(label),
self.session)
self.pkcs11.return_session(self.session)
@ -262,9 +275,13 @@ class HSMCommands(object):
help='The length in bytes of the Master HMAC Key (default is 32)')
@args('--mechanism', '-m', metavar='<mechanism>',
default='CKM_AES_KEY_GEN', help='The HMAC Key Generation mechanism')
@args('--hmac-wrap-mechanism', metavar='<hmac key wrap mechanism>',
dest='hmacwrap', default='CKM_SHA256_HMAC',
help='HMAC Key wrap mechanism, default is CKM_SHA256_HMAC')
def gen_hmac(self, passphrase, libpath=None, slotid=None, label=None,
keytype=None, mechanism=None, length=None):
self._create_pkcs11_session(str(passphrase), str(libpath), int(slotid))
keytype=None, mechanism=None, length=None, hmacwrap=None):
self._create_pkcs11_session(str(passphrase), str(libpath), int(slotid),
str(hmacwrap))
self._verify_label_does_not_exist(str(keytype), str(label),
self.session)
self.pkcs11.generate_key(str(keytype), int(length), str(mechanism),
@ -282,11 +299,13 @@ class HSMCommands(object):
rewrapper.execute(dryrun)
rewrapper.pkcs11.return_session(rewrapper.hsm_session)
def _create_pkcs11_session(self, passphrase, libpath, slotid):
def _create_pkcs11_session(self, passphrase, libpath, slotid,
hmacwrap):
self.pkcs11 = pkcs11.PKCS11(
library_path=libpath, login_passphrase=passphrase,
rw_session=True, slot_id=slotid,
encryption_mechanism='CKM_AES_CBC',
hmac_keywrap_mechanism=hmacwrap
)
self.session = self.pkcs11.get_session()

View File

@ -69,6 +69,9 @@ p11_crypto_plugin_opts = [
cfg.StrOpt('hmac_keygen_mechanism',
help=u._('HMAC Key Generation Algorithm'),
default='CKM_AES_KEY_GEN'),
cfg.StrOpt('hmac_keywrap_mechanism',
help=u._('HMAC key wrap mechanism'),
default='CKM_SHA256_HMAC'),
cfg.StrOpt('seed_file',
help=u._('File to pull entropy for seeding RNG'),
default=''),
@ -307,6 +310,7 @@ class P11CryptoPlugin(plugin.CryptoPluginBase):
seed_random_buffer=seed_random_buffer,
generate_iv=plugin_conf.aes_gcm_generate_iv,
always_set_cka_sensitive=plugin_conf.always_set_cka_sensitive,
hmac_keywrap_mechanism=plugin_conf.hmac_keywrap_mechanism
)
def _reinitialize_pkcs11(self):

View File

@ -134,6 +134,7 @@ CKA_SUPPORTED_CMS_ATTRIBUTES = 0x503
CKM_SHA256_HMAC = 0x251
CKM_AES_KEY_GEN = 0x1080
CKM_AES_CBC = 0x1082
CKM_AES_MAC = 0x1083
CKM_AES_CBC_PAD = 0x1085
CKM_AES_GCM = 0x1087
CKM_AES_KEY_WRAP = 0x1090
@ -158,9 +159,15 @@ _KEY_GEN_MECHANISMS = {
'CKM_GENERIC_SECRET_KEY_GEN': CKM_GENERIC_SECRET_KEY_GEN,
}
_KEY_WRAP_MECHANISMS = {
'CKM_SHA256_HMAC': CKM_SHA256_HMAC,
'CKM_AES_MAC': CKM_AES_MAC
}
CKM_NAMES = dict()
CKM_NAMES.update(_ENCRYPTION_MECHANISMS)
CKM_NAMES.update(_KEY_GEN_MECHANISMS)
CKM_NAMES.update(_KEY_WRAP_MECHANISMS)
ERROR_CODES = {
1: 'CKR_CANCEL',
@ -356,7 +363,8 @@ class PKCS11(object):
encryption_mechanism=None,
ffi=None, algorithm=None,
seed_random_buffer=None,
generate_iv=None, always_set_cka_sensitive=None):
generate_iv=None, always_set_cka_sensitive=None,
hmac_keywrap_mechanism='CKM_SHA256_HMAC'):
if algorithm:
LOG.warning("WARNING: Using deprecated 'algorithm' argument.")
encryption_mechanism = encryption_mechanism or algorithm
@ -369,6 +377,9 @@ class PKCS11(object):
'_{}_encrypt'.format(encryption_mechanism)
)
if hmac_keywrap_mechanism not in _KEY_WRAP_MECHANISMS:
raise ValueError("Invalid HMAC keywrap mechanism")
self.ffi = ffi or build_ffi()
self.lib = self.ffi.dlopen(library_path)
rv = self.lib.C_Initialize(self.ffi.NULL)
@ -386,6 +397,7 @@ class PKCS11(object):
self.gcmtagsize = 16
self.generate_iv = generate_iv
self.always_set_cka_sensitive = always_set_cka_sensitive
self.hmac_keywrap_mechanism = CKM_NAMES[hmac_keywrap_mechanism]
# Validate configuration and RNG
session = self.get_session()
@ -674,7 +686,7 @@ class PKCS11(object):
def compute_hmac(self, hmac_key, data, session):
mech = self.ffi.new("CK_MECHANISM *")
mech.mechanism = CKM_SHA256_HMAC
mech.mechanism = self.hmac_keywrap_mechanism
rv = self.lib.C_SignInit(session, mech, hmac_key)
self._check_error(rv)
@ -687,7 +699,7 @@ class PKCS11(object):
def verify_hmac(self, hmac_key, sig, data, session):
mech = self.ffi.new("CK_MECHANISM *")
mech.mechanism = CKM_SHA256_HMAC
mech.mechanism = self.hmac_keywrap_mechanism
rv = self.lib.C_VerifyInit(session, mech, hmac_key)
self._check_error(rv)

View File

@ -63,6 +63,8 @@ class WhenTestingP11CryptoPlugin(utils.BaseTestCase):
self.cfg_mock.p11_crypto_plugin.encryption_mechanism = 'CKM_AES_CBC'
self.cfg_mock.p11_crypto_plugin.seed_file = ''
self.cfg_mock.p11_crypto_plugin.seed_length = 32
self.cfg_mock.p11_crypto_plugin.hmac_keywrap_mechanism = \
'CKM_SHA256_HMAC'
self.plugin_name = 'Test PKCS11 plugin'
self.cfg_mock.p11_crypto_plugin.plugin_name = self.plugin_name

View File

@ -60,12 +60,14 @@ class WhenTestingPKCS11(utils.BaseTestCase):
self.cfg_mock.rw_session = False
self.cfg_mock.slot_id = 1
self.cfg_mock.encryption_mechanism = 'CKM_AES_CBC'
self.cfg_mock.hmac_keywrap_mechanism = 'CKM_SHA256_HMAC'
self.pkcs11 = pkcs11.PKCS11(
self.cfg_mock.library_path, self.cfg_mock.login_passphrase,
self.cfg_mock.rw_session, self.cfg_mock.slot_id,
self.cfg_mock.encryption_mechanism,
ffi=self.ffi
ffi=self.ffi,
hmac_keywrap_mechanism=self.cfg_mock.hmac_keywrap_mechanism
)
def _generate_random(self, session, buf, length):

View File

@ -0,0 +1,9 @@
---
fixes:
- |
Fixed Story #2004734: Added a new option 'hmac_keywrap_mechanism' to make
the mechanism used to calculate a HMAC from an wrapped PKEK configurable.
This was introduced because of an problem with Utimaco HSMs which throw an
'CKR_MECHANISM_INVALID' error, e.g. when a new PKEK is generated. For
Utimaco HSMs, 'hmac_keywrap_mechanism' should be set to 'CKM_AES_MAC' in
barbican.conf.