def setUp(self): super(TestSecretStoreBase, self).setUp() self.patchers = [] # List of patchers utilized in this test class. self.project_id = '12345' self.content_type = 'application/octet-stream' self.content_encoding = 'base64' self.secret = base64.b64encode('secret') self.decrypted_secret = 'decrypted_secret' self.cypher_text = 'cypher_text' self.kek_meta_extended = 'kek-meta-extended' self.spec_aes = secret_store.KeySpec('AES', 64, 'CBC') self.spec_rsa = secret_store.KeySpec('RSA', 1024, passphrase='changeit') self.project_model = mock.MagicMock() self.project_model.id = 'project-model-id' self.project_model.external_id = self.project_id self.secret_dto = secret_store.SecretDTO( secret_store.SecretType.OPAQUE, self.secret, secret_store.KeySpec(), self.content_type) self.response_dto = crypto.ResponseDTO( self.cypher_text, kek_meta_extended=self.kek_meta_extended) self.private_key_dto = crypto.ResponseDTO(self.cypher_text) self.public_key_dto = crypto.ResponseDTO(self.cypher_text) self.passphrase_dto = crypto.ResponseDTO(self.cypher_text) self.kek_meta_project_model = models.KEKDatum() self.kek_meta_project_model.plugin_name = 'plugin-name' self.kek_meta_project_model.kek_label = 'kek-meta-label' self.kek_meta_project_model.algorithm = 'kek-meta-algo' self.kek_meta_project_model.bit_length = 1024 self.kek_meta_project_model.mode = 'kek=meta-mode' self.kek_meta_project_model.plugin_meta = 'kek-meta-plugin-meta' self.encrypted_datum_model = models.EncryptedDatum() self.encrypted_datum_model.kek_meta_project = ( self.kek_meta_project_model) self.encrypted_datum_model.cypher_text = base64.b64encode( 'cypher_text') self.encrypted_datum_model.content_type = 'content_type' self.encrypted_datum_model.kek_meta_extended = 'extended_meta' self.secret_model = models.Secret({ 'algorithm': 'myalg', 'bit_length': 1024, 'mode': 'mymode' }) self.secret_model.id = 'secret-model-id' self.secret_model.encrypted_data = [self.encrypted_datum_model] self.context = store_crypto.StoreCryptoContext( secret_model=self.secret_model, project_model=self.project_model, content_type=self.content_type)
def encrypt(self, encrypt_dto, kek_meta_dto, project_id): session = self.pkcs11.create_working_session() meta = json.loads(kek_meta_dto.plugin_meta) key = self.pkcs11.unwrap_key(meta['iv'], meta['hmac'], meta['wrapped_key'], meta['mkek_label'], meta['hmac_label'], session) iv = self.pkcs11.generate_random(16, session) ck_mechanism = self.pkcs11.build_gcm_mech(iv) rv = self.pkcs11.lib.C_EncryptInit(session, ck_mechanism.mech, key) self.pkcs11.check_error(rv) # GCM does not require padding, but sometimes HSMs don't seem to # know that and then you need to pad things for no reason. pt_padded = self.pkcs11.pad(encrypt_dto.unencrypted) pt_len = len(pt_padded) # The GCM mechanism adds a 16 byte tag to the front of the # cyphertext (which is the same length as the (annoyingly) padded # plaintext) so adding 16 bytes guarantees sufficient space. ct_len = self.pkcs11.ffi.new("CK_ULONG *", pt_len + 16) ct = self.pkcs11.ffi.new("CK_BYTE[{0}]".format(pt_len + 16)) rv = self.pkcs11.lib.C_Encrypt(session, pt_padded, pt_len, ct, ct_len) self.pkcs11.check_error(rv) cyphertext = self.pkcs11.ffi.buffer(ct, ct_len[0])[:] kek_meta_extended = json.dumps( {'iv': base64.b64encode(self.pkcs11.ffi.buffer(iv)[:])}) self.pkcs11.close_session(session) return plugin.ResponseDTO(cyphertext, kek_meta_extended)
def encrypt(self, encrypt_dto, kek_meta_dto, project_id): key = self._unwrap_key(kek_meta_dto.plugin_meta) iv = self._generate_random(16) mech = self._build_gcm_mech(iv) with self.enc_sem: rv = self.lib.C_EncryptInit(self.session, mech, key) self._check_error(rv) # GCM does not require padding, but sometimes HSMs don't seem to # know that and then you need to pad things for no reason. pt_padded = self._pad(encrypt_dto.unencrypted) pt_len = len(pt_padded) # The GCM mechanism adds a 16 byte tag to the front of the # cyphertext (which is the same length as the (annoyingly) padded # plaintext) so adding 16 bytes guarantees sufficient space. ct_len = self.ffi.new("CK_ULONG *", pt_len + 16) ct = self.ffi.new("CK_BYTE[{0}]".format(pt_len + 16)) rv = self.lib.C_Encrypt(self.session, pt_padded, pt_len, ct, ct_len) self._check_error(rv) cyphertext = self.ffi.buffer(ct, ct_len[0])[:] kek_meta_extended = json.dumps( {'iv': base64.b64encode(self.ffi.buffer(iv)[:])}) return plugin.ResponseDTO(cyphertext, kek_meta_extended)
def encrypt(self, encrypt_dto, kek_meta_dto, project_id): kek = self._get_kek(kek_meta_dto) unencrypted = encrypt_dto.unencrypted if not isinstance(unencrypted, six.binary_type): raise ValueError( u._('Unencrypted data must be a byte type, but was ' '{unencrypted_type}').format( unencrypted_type=type(unencrypted))) encryptor = fernet.Fernet(kek) cyphertext = encryptor.encrypt(unencrypted) return c.ResponseDTO(cyphertext, None)
def generate_symmetric(self, generate_dto, kek_meta_dto, project_id): byte_length = int(generate_dto.bit_length) // 8 sealed_secret = self.sgx.generate_key(self.sgx.barbie_s, self.enclave_id, byte_length) sealed_kek = self._get_master_kek() if not sealed_kek: raise Exception( "Master key is not provisioned. Please contact administrator.") proj_id = unicodedata.normalize('NFKD', project_id).encode('ascii', 'ignore') kek_secret = self.sgx.transport(self.sgx.barbie_s, self.enclave_id, sealed_kek, sealed_secret, proj_id) return c.ResponseDTO(kek_secret, None)
def _encrypt(self, encrypt_dto, kek_meta_dto, project_id): kek = self._load_kek_from_meta_dto(kek_meta_dto) try: session = self._get_session() ct_data = self.pkcs11.encrypt(kek, encrypt_dto.unencrypted, session) finally: if 'session' in locals(): self._return_session(session) kek_meta_extended = json_dumps_compact( {'iv': base64.b64encode(ct_data['iv'])}) return plugin.ResponseDTO(ct_data['ct'], kek_meta_extended)
def _generate_symmetric(self, generate_dto, kek_meta_dto, project_id): kek = self._load_kek_from_meta_dto(kek_meta_dto) byte_length = int(generate_dto.bit_length) // 8 try: session = self._get_session() buf = self.pkcs11.generate_random(byte_length, session) ct_data = self.pkcs11.encrypt(kek, buf, session) finally: if 'session' in locals(): self._return_session(session) kek_meta_extended = json_dumps_compact( {'iv': base64.b64encode(ct_data['iv'])}) return plugin.ResponseDTO(ct_data['ct'], kek_meta_extended)
def encrypt(self, encrypt_dto, kek_meta_dto, project_id): project_id = unicodedata.normalize('NFKD', project_id).encode( 'ascii', 'ignore') unencrypted = encrypt_dto.unencrypted enc_keys = encrypt_dto.enc_keys if not isinstance(unencrypted, six.binary_type): raise ValueError( u._('Unencrypted data must be a byte type, but was ' '{unencrypted_type}').format( unencrypted_type=type(unencrypted))) s_mk, mk_sk = self._get_enc_keys(project_id, enc_keys) mk_secret = self.sgx.secret_encrypt(self.sgx.barbie_s, self.enclave_id, s_mk, mk_sk, unencrypted, project_id, len(project_id)) return c.ResponseDTO(mk_secret, None)
def generate_asymmetric(self, generate_dto, kek_meta_dto, project_id): passwd_res_dto = (plugin.ResponseDTO('passphrase', None) if generate_dto.passphrase else None) return (plugin.ResponseDTO('insecure_private_key', None), plugin.ResponseDTO('insecure_public_key', None), passwd_res_dto)
def generate_symmetric(self, generate_dto, kek_meta_dto, project_id): return plugin.ResponseDTO("encrypted insecure key", None)
def encrypt(self, encrypt_dto, kek_meta_dto, project_id): cypher_text = b'cypher_text' return plugin.ResponseDTO(cypher_text, None)