Beispiel #1
0
    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)
Beispiel #2
0
    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)
Beispiel #3
0
    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)
Beispiel #4
0
 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)
Beispiel #5
0
 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)
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
 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)
Beispiel #10
0
 def generate_symmetric(self, generate_dto, kek_meta_dto, project_id):
     return plugin.ResponseDTO("encrypted insecure key", None)
Beispiel #11
0
 def encrypt(self, encrypt_dto, kek_meta_dto, project_id):
     cypher_text = b'cypher_text'
     return plugin.ResponseDTO(cypher_text, None)