Exemple #1
0
    def setup_contexts(self, mechanism, sym_key, iv):
        # Get a PK11 slot based on the cipher
        slot = nss.get_best_slot(mechanism)

        if sym_key is None:
            sym_key = slot.key_gen(mechanism, None,
                                   slot.get_best_key_length(mechanism))

        # If initialization vector was supplied use it, otherwise set it to
        # None
        if iv:
            iv_data = nss.read_hex(iv)
            iv_si = nss.SecItem(iv_data)
            iv_param = nss.param_from_iv(mechanism, iv_si)
        else:
            iv_length = nss.get_iv_length(mechanism)
            if iv_length > 0:
                iv_data = nss.generate_random(iv_length)
                iv_si = nss.SecItem(iv_data)
                iv_param = nss.param_from_iv(mechanism, iv_si)
            else:
                iv_param = None

        # Create an encoding context
        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT, sym_key,
                                                     iv_param)

        # Create a decoding context
        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT, sym_key,
                                                     iv_param)

        return encoding_ctx, decoding_ctx
Exemple #2
0
    def setup_contexts(cls, mechanism, sym_key, nonce_iv):
        """ Set up contexts to do wrapping/unwrapping by symmetric keys. """
        # Get a PK11 slot based on the cipher
        slot = nss.get_best_slot(mechanism)

        if sym_key is None:
            sym_key = slot.key_gen(mechanism,
                                   None,
                                   slot.get_best_key_length(mechanism))

        # If initialization vector was supplied use it, otherwise set it to
        # None
        if nonce_iv:
            iv_si = nss.SecItem(nonce_iv)
            iv_param = nss.param_from_iv(mechanism, iv_si)
        else:
            iv_data = cls.generate_nonce_iv(mechanism)
            if iv_data is not None:
                iv_si = nss.SecItem(iv_data)
                iv_param = nss.param_from_iv(mechanism, iv_si)
            else:
                iv_param = None

        # Create an encoding context
        encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT,
                                                     sym_key, iv_param)

        # Create a decoding context
        decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT,
                                                     sym_key, iv_param)

        return encoding_ctx, decoding_ctx
Exemple #3
0
    def setup_contexts(cls, mechanism, sym_key, nonce_iv):
        """ Set up contexts to do wrapping/unwrapping by symmetric keys. """
        # Get a PK11 slot based on the cipher
        slot = nss.get_best_slot(mechanism)

        if sym_key is None:
            sym_key = slot.key_gen(mechanism, None,
                                   slot.get_best_key_length(mechanism))

        # If initialization vector was supplied use it, otherwise set it to
        # None
        if nonce_iv:
            iv_si = nss.SecItem(nonce_iv)
            iv_param = nss.param_from_iv(mechanism, iv_si)
        else:
            iv_data = cls.generate_nonce_iv(mechanism)
            if iv_data is not None:
                iv_si = nss.SecItem(iv_data)
                iv_param = nss.param_from_iv(mechanism, iv_si)
            else:
                iv_param = None

        # Create an encoding context
        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT, sym_key,
                                                     iv_param)

        # Create a decoding context
        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT, sym_key,
                                                     iv_param)

        return encoding_ctx, decoding_ctx
Exemple #4
0
def generate_sym_key():
    """ This Function generate Symmetric key and nonce data """    
    ## Initialize NSS Database opens temporary database and the internal PKCS #112 module
    nss.nss_init_nodb()
    ## Mechanism to be used for symmetric key 
    mechanism = nss.CKM_DES_CBC_PAD
    # From the Soft token that we initialized get slot to generate symmetric key
    slot = nss.get_best_slot(mechanism)
    # Generate a symmetric key on the pk11 slot, The sym_key is of type PK11SymKey
    sym_key = slot.key_gen(mechanism, None, slot.get_best_key_length(mechanism))

    # Generate Nonce 
    iv_length = nss.get_iv_length(mechanism)

    if iv_length > 0:
        # Generate Nonce
        iv_data = nss.generate_random(iv_length)
        # Pass this random data to NSS SecItem
        iv_si = nss.SecItem(iv_data)
        # Use the Data passed to SecItem for initialization Vector 
        iv_param = nss.param_from_iv(mechanism, iv_si)
        # Random data is converted to hex
        pki_nonce = nss.data_to_hex(data=iv_data, separator=":")
        #print "generated %d bytes initialization vector: %s" % (iv_length, pki_nonce)
    
        # Create a Symmetric key Context using the Symmetric key, nonce  The context should be 
        # used for encrypt as well as decrypt
        encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT, sym_key, iv_param)
        decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT, sym_key, iv_param)
    #return the symmetric key, nonce data, encoding context and decoding context to encrypt and 
    # decrypt
    return sym_key, pki_nonce, encoding_ctx, decoding_ctx
Exemple #5
0
    def setup_contexts(self, mechanism, sym_key, iv):
        # Get a PK11 slot based on the cipher
        slot = nss.get_best_slot(mechanism)

        if sym_key is None:
            sym_key = slot.key_gen(
                mechanism,
                None,
                slot.get_best_key_length(mechanism))

        # If initialization vector was supplied use it, otherwise set it to
        # None
        if iv:
            iv_data = nss.read_hex(iv)
            iv_si = nss.SecItem(iv_data)
            iv_param = nss.param_from_iv(mechanism, iv_si)
        else:
            iv_length = nss.get_iv_length(mechanism)
            if iv_length > 0:
                iv_data = nss.generate_random(iv_length)
                iv_si = nss.SecItem(iv_data)
                iv_param = nss.param_from_iv(mechanism, iv_si)
            else:
                iv_param = None

        # Create an encoding context
        encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT,
                                                     sym_key, iv_param)

        # Create a decoding context
        decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT,
                                                     sym_key, iv_param)

        return encoding_ctx, decoding_ctx
Exemple #6
0
    def generate_symmetric_key(self, mechanism=nss.CKM_DES3_CBC_PAD, size=0):
        """ Returns a symmetric key.

        Note that for fixed length keys, this length should be 0.  If no length
        is provided, then the function will either use 0 (for fixed length keys)
        or the maximum available length for that algorithm and the token.
        """
        slot = nss.get_best_slot(mechanism)
        if size == 0:
            size = slot.get_best_key_length(mechanism)
        return slot.key_gen(mechanism, None, size)
Exemple #7
0
    def generate_symmetric_key(self, mechanism=nss.CKM_DES3_CBC_PAD, size=0):
        """ Returns a symmetric key.

        Note that for fixed length keys, this length should be 0.  If no length
        is provided, then the function will either use 0 (for fixed length keys)
        or the maximum available length for that algorithm and the token.
        """
        slot = nss.get_best_slot(mechanism)
        if size == 0:
            size = slot.get_best_key_length(mechanism)
        return slot.key_gen(mechanism, None, size)
Exemple #8
0
def verify_sym_key(archived_key, archived_iv, algorithm, plain_text):
    """ This function verifies whether archived key is usable, Actually
    verifying this is senseless, reason any random data can be used for encryption, 
    but still just for the heck of it. 
    """
    
    # Initialize NSS 
    nss.nss_init_nodb()

    # Decode the base64 string to binary
    key = base64.decodestring(archived_data)

    # Currently we are assuming the mechanism to AES
    # Will need to add other mechanisms later, but 
    # this is just an example.
    mechanism = nss.CKM_AES_CBC_PAD

    # Get the best pkcs11 slot
    slot = nss.get_best_slot(mechanism)

    # convert the binary to hex with separtor as :
    pki_key = nss.data_to_hex(data=key,separator=":")

    # create a nssSecItem object out of it.
    key_si = nss.SecItem(nss.read_hex(pki_key))

    # Import the key to the slot
    sym_key = nss.import_sym_key(slot, mechanism, nss.PK11_OriginUnwrap, nss.CKA_ENCRYPT, key_si)

    # Same for the nonce data
    iv = base64.decodestring(archived_iv)
    iv_data = nss.data_to_hex(data=iv,separator=":")
    iv_si = nss.SecItem(nss.read_hex(iv_data))
    iv_param = nss.param_from_iv(mechanism, iv_si)


    encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT,sym_key, iv_param)
    decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT,sym_key, iv_param)

    cipher_text = encoding_ctx.cipher_op(plain_text)
    cipher_text += encoding_ctx.digest_final()
    print cipher_text

    decoded_text = decoding_ctx.cipher_op(cipher_text)
    decoded_text += decoding_ctx.digest_final()

    print decoded_text
Exemple #9
0
def setup_contexts(mechanism, key, iv):
    # Get a PK11 slot based on the cipher
    slot = nss.get_best_slot(mechanism)

    # If key was supplied use it, otherwise generate one
    if key:
        if verbose:
            print("using supplied key data")
            print("key:\n%s" % (key))
        key_si = nss.SecItem(nss.read_hex(key))
        sym_key = nss.import_sym_key(slot, mechanism, nss.PK11_OriginUnwrap,
                                     nss.CKA_ENCRYPT, key_si)
    else:
        if verbose:
            print("generating key data")
        sym_key = slot.key_gen(mechanism, None,
                               slot.get_best_key_length(mechanism))

    # If initialization vector was supplied use it, otherwise set it to None
    if iv:
        if verbose:
            print("supplied iv:\n%s" % (iv))
        iv_data = nss.read_hex(iv)
        iv_si = nss.SecItem(iv_data)
        iv_param = nss.param_from_iv(mechanism, iv_si)
    else:
        iv_length = nss.get_iv_length(mechanism)
        if iv_length > 0:
            iv_data = nss.generate_random(iv_length)
            iv_si = nss.SecItem(iv_data)
            iv_param = nss.param_from_iv(mechanism, iv_si)
            if verbose:
                print("generated %d byte initialization vector: %s" %
                      (iv_length, nss.data_to_hex(iv_data, separator=":")))
        else:
            iv_param = None

    # Create an encoding context
    encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT,
                                                 sym_key, iv_param)

    # Create a decoding context
    decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT,
                                                 sym_key, iv_param)

    return encoding_ctx, decoding_ctx
Exemple #10
0
def setup_contexts(mechanism, key, iv):
    # Get a PK11 slot based on the cipher
    slot = nss.get_best_slot(mechanism)

    # If key was supplied use it, otherwise generate one
    if key:
        if verbose:
            print "using supplied key data"
            print "key:\n%s" % (key)
        key_si = nss.SecItem(nss.read_hex(key))
        sym_key = nss.import_sym_key(slot, mechanism, nss.PK11_OriginUnwrap,
                                     nss.CKA_ENCRYPT, key_si)
    else:
        if verbose:
            print "generating key data"
        sym_key = slot.key_gen(mechanism, None, slot.get_best_key_length(mechanism))

    # If initialization vector was supplied use it, otherwise set it to None
    if iv:
        if verbose:
            print "supplied iv:\n%s" % (iv)
        iv_data = nss.read_hex(iv)
        iv_si = nss.SecItem(iv_data)
        iv_param = nss.param_from_iv(mechanism, iv_si)
    else:
        iv_length = nss.get_iv_length(mechanism)
        if iv_length > 0:
            iv_data = nss.generate_random(iv_length)
            iv_si = nss.SecItem(iv_data)
            iv_param = nss.param_from_iv(mechanism, iv_si)
            if verbose:
                print "generated %d byte initialization vector: %s" % \
                    (iv_length, nss.data_to_hex(iv_data, separator=":"))
        else:
            iv_param = None

    # Create an encoding context
    encoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_ENCRYPT,
                                                 sym_key, iv_param)

    # Create a decoding context
    decoding_ctx = nss.create_context_by_sym_key(mechanism, nss.CKA_DECRYPT,
                                                 sym_key, iv_param)

    return encoding_ctx, decoding_ctx
Exemple #11
0
    def __call__(self, element, mac=None):
        (mech, ivlen) = fetch(element, "./xenc:EncryptionMethod/@Algorithm", convertAlgorithm)
        data = fetch(element, "./xenc:CipherData/xenc:CipherValue/text()", base64.b64decode)

        # If a MAC is present, perform validation.
        if mac:
            tmp = self.__hmac.copy()
            tmp.update(data)
            if tmp.digest() != mac:
                raise ValidationError("MAC validation failed!")

        # Decrypt the data.
        slot = nss.get_best_slot(mech)
        key = nss.import_sym_key(slot, mech, nss.PK11_OriginUnwrap, nss.CKA_ENCRYPT, self.__key)
        iv = nss.param_from_iv(mech, nss.SecItem(data[0:ivlen//8]))
        ctx = nss.create_context_by_sym_key(mech, nss.CKA_DECRYPT, key, iv)
        out = ctx.cipher_op(data[ivlen // 8:])
        out += ctx.digest_final()
        return out
    def __call__(self, element, mac=None):
        (mech, ivlen) = fetch(element, "./xenc:EncryptionMethod/@Algorithm", convertAlgorithm)
        data = fetch(element, "./xenc:CipherData/xenc:CipherValue/text()", base64.b64decode)

        # If a MAC is present, perform validation.
        if mac:
            tmp = self.__hmac.copy()
            tmp.update(data)
            if tmp.digest() != mac:
                raise ValidationError("MAC validation failed!")

        # Decrypt the data.
        slot = nss.get_best_slot(mech)
        key = nss.import_sym_key(slot, mech, nss.PK11_OriginUnwrap, nss.CKA_ENCRYPT, self.__key)
        iv = nss.param_from_iv(mech, nss.SecItem(data[0:ivlen/8]))
        ctx = nss.create_context_by_sym_key(mech, nss.CKA_DECRYPT, key, iv)
        out = ctx.cipher_op(data[ivlen / 8:])
        out += ctx.digest_final()
        return out
def generate_sym_key():
    """ This Function generate Symmetric key and nonce data """
    ## Initialize NSS Database opens temporary database and the internal PKCS #112 module
    nss.nss_init_nodb()
    ## Mechanism to be used for symmetric key
    mechanism = nss.CKM_DES_CBC_PAD
    # From the Soft token that we initialized get slot to generate symmetric key
    slot = nss.get_best_slot(mechanism)
    # Generate a symmetric key on the pk11 slot, The sym_key is of type PK11SymKey
    sym_key = slot.key_gen(mechanism, None,
                           slot.get_best_key_length(mechanism))

    # Generate Nonce
    iv_length = nss.get_iv_length(mechanism)

    if iv_length > 0:
        # Generate Nonce
        iv_data = nss.generate_random(iv_length)
        # Pass this random data to NSS SecItem
        iv_si = nss.SecItem(iv_data)
        # Use the Data passed to SecItem for initialization Vector
        iv_param = nss.param_from_iv(mechanism, iv_si)
        # Random data is converted to hex
        pki_nonce = nss.data_to_hex(data=iv_data, separator=":")
        #print "generated %d bytes initialization vector: %s" % (iv_length, pki_nonce)

        # Create a Symmetric key Context using the Symmetric key, nonce  The context should be
        # used for encrypt as well as decrypt
        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT, sym_key,
                                                     iv_param)
        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT, sym_key,
                                                     iv_param)
    #return the symmetric key, nonce data, encoding context and decoding context to encrypt and
    # decrypt
    return sym_key, pki_nonce, encoding_ctx, decoding_ctx
Exemple #14
0
    def forward(self, *args, **options):
        data = options.get('data')
        input_file = options.get('in')

        password = options.get('password')
        password_file = options.get('password_file')

        override_password = options.pop('override_password', False)

        # don't send these parameters to server
        if 'data' in options:
            del options['data']
        if 'in' in options:
            del options['in']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']

        # get data
        if data and input_file:
            raise errors.MutuallyExclusiveError(
                reason=_('Input data specified multiple times'))

        elif data:
            if len(data) > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="data", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})

        elif input_file:
            try:
                stat = os.stat(input_file)
            except OSError as exc:
                raise errors.ValidationError(name="in", error=_(
                    "Cannot read file '%(filename)s': %(exc)s")
                    % {'filename': input_file, 'exc': exc.args[1]})
            if stat.st_size > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="in", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})
            data = validated_read('in', input_file, mode='rb')

        else:
            data = ''

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect()

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        if vault_type == u'standard':

            encrypted_key = None

        elif vault_type == u'symmetric':

            # get password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                if override_password:
                    password = get_new_password()
                else:
                    password = get_existing_password()

            if not override_password:
                # verify password by retrieving existing data
                opts = options.copy()
                opts['password'] = password
                try:
                    self.api.Command.vault_retrieve(*args, **opts)
                except errors.NotFound:
                    pass

            salt = vault['ipavaultsalt'][0]

            # generate encryption key from vault password
            encryption_key = generate_symmetric_key(password, salt)

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            encrypted_key = None

        elif vault_type == u'asymmetric':

            public_key = vault['ipavaultpublickey'][0].encode('utf-8')

            # generate encryption key
            encryption_key = base64.b64encode(os.urandom(32))

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            # encrypt encryption key with public key
            encrypted_key = encrypt(encryption_key, public_key=public_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        # initialize NSS database
        nss.nss_init(api.env.nss_dir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        # pylint: disable=no-member
        public_key = nss_transport_cert.subject_public_key_info.public_key
        # pylint: enable=no-member
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        options['session_key'] = wrapped_session_key.data

        nonce_length = nss.get_iv_length(mechanism)
        nonce = nss.generate_random(nonce_length)
        options['nonce'] = nonce

        vault_data = {}
        vault_data[u'data'] = base64.b64encode(data).decode('utf-8')

        if encrypted_key:
            vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\
                .decode('utf-8')

        json_vault_data = json.dumps(vault_data)

        # wrap vault_data with session key
        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT,
                                                     session_key,
                                                     iv_param)

        wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\
            + encoding_ctx.digest_final()

        options['vault_data'] = wrapped_vault_data

        return self.api.Command.vault_archive_internal(*args, **options)
Exemple #15
0
    def retrieve_security_data(self, recovery_request_id, passphrase=None):
        """
        :param recovery_request_id:  identifier of key recovery request
        :param passphrase:           passphrase to be used to wrap the data

        Recover the passphrase or symmetric key.  We require an approved
        recovery request.

        If a passphrase is provided, the DRM will return a blob that can be decrypted
        with the passphrase.  If not, then a symmetric key will be created to wrap the
        data for transport to this server.  Upon receipt, the data will be unwrapped
        and returned unencrypted.

        The command returns a dict with the values described in parse_key_data_xml(),
        as well as the following field

        +-----------------+---------------+-------------------------------------- +
        |result name      |result type    |comments                               |
        +=================+===============+=======================================+
        |data             |String         | Key data (either wrapped using        |
        |                 |               | passphrase or unwrapped)              |
        +-----------------+---------------+---------------------------------------+
        """
        self.debug('%s.retrieve_security_data()', self.fullname)

        if recovery_request_id is None:
            raise CertificateOperationError(
                error=_('Bad arguments to retrieve_security_data'))

        # generate symmetric key
        slot = nss.get_best_slot(self.mechanism)
        session_key = slot.key_gen(self.mechanism, None,
                                   slot.get_best_key_length(self.mechanism))

        # wrap this key with the transport cert
        public_key = self.transport_cert.subject_public_key_info.public_key
        wrapped_session_key = b64encode(
            nss.pub_wrap_sym_key(self.mechanism, public_key, session_key))
        wrapped_passphrase = None
        if passphrase is not None:
            # wrap passphrase with session key
            wrapped_session_key = b64encode(
                self.symmetric_wrap(passphrase, session_key))

        request = self.create_recovery_request(None, recovery_request_id,
                                               wrapped_session_key,
                                               wrapped_passphrase)

        # Call CMS
        http_status, http_reason_phrase, _http_headers, http_body = \
            self._request('/kra/rest/agent/keys/retrieve',
                          self.kra_agent_port,
                          self.POST,
                          etree.tostring(request.getroot(), encoding='UTF-8'))

        # Parse and handle errors
        if (http_status != 200):
            raise CertificateOperationError(
                error=_('Error in retrieving security data (%s)') %
                http_reason_phrase)

        parse_result = self.get_parse_result_xml(http_body, parse_key_data_xml)

        if passphrase is None:
            iv = nss.data_to_hex(b64decode(parse_result['nonce_data']))
            parse_result['data'] = self.symmetric_unwrap(
                b64decode(parse_result['wrapped_data']), session_key, iv)

        return parse_result
Exemple #16
0
    def forward(self, *args, **options):

        name = args[-1]

        data = options.get('data')
        input_file = options.get('in')

        password = options.get('password')
        password_file = options.get('password_file')

        # don't send these parameters to server
        if 'data' in options:
            del options['data']
        if 'in' in options:
            del options['in']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']

        # get data
        if data and input_file:
            raise errors.MutuallyExclusiveError(
                reason=_('Input data specified multiple times'))

        elif input_file:
            data = validated_read('in', input_file, mode='rb')

        elif not data:
            data = ''

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect(ccache=krbV.default_context().default_ccache())

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        if vault_type == u'standard':

            encrypted_key = None

        elif vault_type == u'symmetric':

            # get password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                password = self.obj.get_existing_password()

            # verify password by retrieving existing data
            opts = options.copy()
            opts['password'] = password
            try:
                self.api.Command.vault_retrieve(*args, **opts)
            except errors.NotFound:
                pass

            salt = vault['ipavaultsalt'][0]

            # generate encryption key from vault password
            encryption_key = self.obj.generate_symmetric_key(
                password, salt)

            # encrypt data with encryption key
            data = self.obj.encrypt(data, symmetric_key=encryption_key)

            encrypted_key = None

        elif vault_type == u'asymmetric':

            public_key = vault['ipavaultpublickey'][0].encode('utf-8')

            # generate encryption key
            encryption_key = base64.b64encode(os.urandom(32))

            # encrypt data with encryption key
            data = self.obj.encrypt(data, symmetric_key=encryption_key)

            # encrypt encryption key with public key
            encrypted_key = self.obj.encrypt(
                encryption_key, public_key=public_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        # initialize NSS database
        current_dbdir = paths.IPA_NSSDB_DIR
        nss.nss_init(current_dbdir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        public_key = nss_transport_cert.subject_public_key_info.public_key
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        options['session_key'] = wrapped_session_key.data

        nonce_length = nss.get_iv_length(mechanism)
        nonce = nss.generate_random(nonce_length)
        options['nonce'] = nonce

        vault_data = {}
        vault_data[u'data'] = base64.b64encode(data).decode('utf-8')

        if encrypted_key:
            vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\
                .decode('utf-8')

        json_vault_data = json.dumps(vault_data)

        # wrap vault_data with session key
        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT,
                                                     session_key,
                                                     iv_param)

        wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\
            + encoding_ctx.digest_final()

        options['vault_data'] = wrapped_vault_data

        return self.api.Command.vault_archive_internal(*args, **options)
Exemple #17
0
    def forward(self, *args, **options):

        name = args[-1]

        output_file = options.get('out')

        password = options.get('password')
        password_file = options.get('password_file')
        private_key = options.get('private_key')
        private_key_file = options.get('private_key_file')

        # don't send these parameters to server
        if 'out' in options:
            del options['out']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']
        if 'private_key' in options:
            del options['private_key']
        if 'private_key_file' in options:
            del options['private_key_file']

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect(ccache=krbV.default_context().default_ccache())

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        # initialize NSS database
        current_dbdir = paths.IPA_NSSDB_DIR
        nss.nss_init(current_dbdir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        public_key = nss_transport_cert.subject_public_key_info.public_key
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        # send retrieval request to server
        options['session_key'] = wrapped_session_key.data

        response = self.api.Command.vault_retrieve_internal(*args, **options)

        result = response['result']
        nonce = result['nonce']

        # unwrap data with session key
        wrapped_vault_data = result['vault_data']

        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT,
                                                     session_key,
                                                     iv_param)

        json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\
            + decoding_ctx.digest_final()

        vault_data = json.loads(json_vault_data)
        data = base64.b64decode(vault_data[u'data'].encode('utf-8'))

        encrypted_key = None

        if 'encrypted_key' in vault_data:
            encrypted_key = base64.b64decode(vault_data[u'encrypted_key']
                                             .encode('utf-8'))

        if vault_type == u'standard':

            pass

        elif vault_type == u'symmetric':

            salt = vault['ipavaultsalt'][0]

            # get encryption key from vault password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                password = self.obj.get_existing_password()

            # generate encryption key from password
            encryption_key = self.obj.generate_symmetric_key(password, salt)

            # decrypt data with encryption key
            data = self.obj.decrypt(data, symmetric_key=encryption_key)

        elif vault_type == u'asymmetric':

            # get encryption key with vault private key
            if private_key and private_key_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Private key specified multiple times'))

            elif private_key:
                pass

            elif private_key_file:
                private_key = validated_read('private-key-file',
                                             private_key_file,
                                             mode='rb')

            else:
                raise errors.ValidationError(
                    name='private_key',
                    error=_('Missing vault private key'))

            # decrypt encryption key with private key
            encryption_key = self.obj.decrypt(
                encrypted_key, private_key=private_key)

            # decrypt data with encryption key
            data = self.obj.decrypt(data, symmetric_key=encryption_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        if output_file:
            with open(output_file, 'w') as f:
                f.write(data)

        else:
            response['result'] = {'data': data}

        return response
Exemple #18
0
    def forward(self, *args, **options):
        data = options.get('data')
        input_file = options.get('in')

        password = options.get('password')
        password_file = options.get('password_file')

        override_password = options.pop('override_password', False)

        # don't send these parameters to server
        if 'data' in options:
            del options['data']
        if 'in' in options:
            del options['in']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']

        # get data
        if data and input_file:
            raise errors.MutuallyExclusiveError(
                reason=_('Input data specified multiple times'))

        elif data:
            if len(data) > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="data", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})

        elif input_file:
            try:
                stat = os.stat(input_file)
            except OSError as exc:
                raise errors.ValidationError(name="in", error=_(
                    "Cannot read file '%(filename)s': %(exc)s")
                    % {'filename': input_file, 'exc': exc.args[1]})
            if stat.st_size > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="in", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})
            data = validated_read('in', input_file, mode='rb')

        else:
            data = ''

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect()

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        if vault_type == u'standard':

            encrypted_key = None

        elif vault_type == u'symmetric':

            # get password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                if override_password:
                    password = get_new_password()
                else:
                    password = get_existing_password()

            if not override_password:
                # verify password by retrieving existing data
                opts = options.copy()
                opts['password'] = password
                try:
                    self.api.Command.vault_retrieve(*args, **opts)
                except errors.NotFound:
                    pass

            salt = vault['ipavaultsalt'][0]

            # generate encryption key from vault password
            encryption_key = generate_symmetric_key(password, salt)

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            encrypted_key = None

        elif vault_type == u'asymmetric':

            public_key = vault['ipavaultpublickey'][0].encode('utf-8')

            # generate encryption key
            encryption_key = base64.b64encode(os.urandom(32))

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            # encrypt encryption key with public key
            encrypted_key = encrypt(encryption_key, public_key=public_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        # initialize NSS database
        nss.nss_init(api.env.nss_dir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        # pylint: disable=no-member
        public_key = nss_transport_cert.subject_public_key_info.public_key
        # pylint: enable=no-member
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        options['session_key'] = wrapped_session_key.data

        nonce_length = nss.get_iv_length(mechanism)
        nonce = nss.generate_random(nonce_length)
        options['nonce'] = nonce

        vault_data = {}
        vault_data[u'data'] = base64.b64encode(data).decode('utf-8')

        if encrypted_key:
            vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\
                .decode('utf-8')

        json_vault_data = json.dumps(vault_data)

        # wrap vault_data with session key
        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT,
                                                     session_key,
                                                     iv_param)

        wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\
            + encoding_ctx.digest_final()

        options['vault_data'] = wrapped_vault_data

        return self.api.Command.vault_archive_internal(*args, **options)
Exemple #19
0
    def retrieve_security_data(self, recovery_request_id, passphrase=None):
        """
        :param recovery_request_id:  identifier of key recovery request
        :param passphrase:           passphrase to be used to wrap the data

        Recover the passphrase or symmetric key.  We require an approved
        recovery request.

        If a passphrase is provided, the DRM will return a blob that can be decrypted
        with the passphrase.  If not, then a symmetric key will be created to wrap the
        data for transport to this server.  Upon receipt, the data will be unwrapped
        and returned unencrypted.

        The command returns a dict with the values described in parse_key_data_xml(),
        as well as the following field

        +-----------------+---------------+-------------------------------------- +
        |result name      |result type    |comments                               |
        +=================+===============+=======================================+
        |data             |String         | Key data (either wrapped using        |
        |                 |               | passphrase or unwrapped)              |
        +-----------------+---------------+---------------------------------------+
        """
        self.debug('%s.retrieve_security_data()', self.fullname)

        if recovery_request_id is None:
            raise CertificateOperationError(
                error=_('Bad arguments to retrieve_security_data'))

        # generate symmetric key
        slot = nss.get_best_slot(self.mechanism)
        session_key = slot.key_gen(
            self.mechanism,
            None,
            slot.get_best_key_length(
                self.mechanism))

        # wrap this key with the transport cert
        public_key = self.transport_cert.subject_public_key_info.public_key
        wrapped_session_key = b64encode(
            nss.pub_wrap_sym_key(
                self.mechanism,
                public_key,
                session_key))
        wrapped_passphrase = None
        if passphrase is not None:
            # wrap passphrase with session key
            wrapped_session_key = b64encode(
                self.symmetric_wrap(
                    passphrase,
                    session_key))

        request = self.create_recovery_request(None, recovery_request_id,
                                               wrapped_session_key,
                                               wrapped_passphrase)

        # Call CMS
        http_status, http_reason_phrase, _http_headers, http_body = \
            self._request('/kra/rest/agent/keys/retrieve',
                          self.kra_agent_port,
                          self.POST,
                          etree.tostring(request.getroot(), encoding='UTF-8'))

        # Parse and handle errors
        if (http_status != 200):
            raise CertificateOperationError(error=_('Error in retrieving security data (%s)') %
                                            http_reason_phrase)

        parse_result = self.get_parse_result_xml(http_body, parse_key_data_xml)

        if passphrase is None:
            iv = nss.data_to_hex(
                b64decode(
                    parse_result['nonce_data']))
            parse_result['data'] = self.symmetric_unwrap(
                b64decode(parse_result['wrapped_data']),
                session_key, iv)

        return parse_result
Exemple #20
0
    def forward(self, *args, **options):
        output_file = options.get('out')

        password = options.get('password')
        password_file = options.get('password_file')
        private_key = options.get('private_key')
        private_key_file = options.get('private_key_file')

        # don't send these parameters to server
        if 'out' in options:
            del options['out']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']
        if 'private_key' in options:
            del options['private_key']
        if 'private_key_file' in options:
            del options['private_key_file']

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect()

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        # initialize NSS database
        nss.nss_init(api.env.nss_dir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        # pylint: disable=no-member
        public_key = nss_transport_cert.subject_public_key_info.public_key
        # pylint: enable=no-member
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        # send retrieval request to server
        options['session_key'] = wrapped_session_key.data

        response = self.api.Command.vault_retrieve_internal(*args, **options)

        result = response['result']
        nonce = result['nonce']

        # unwrap data with session key
        wrapped_vault_data = result['vault_data']

        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT,
                                                     session_key,
                                                     iv_param)

        json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\
            + decoding_ctx.digest_final()

        vault_data = json.loads(json_vault_data.decode('utf-8'))
        data = base64.b64decode(vault_data[u'data'].encode('utf-8'))

        encrypted_key = None

        if 'encrypted_key' in vault_data:
            encrypted_key = base64.b64decode(vault_data[u'encrypted_key']
                                             .encode('utf-8'))

        if vault_type == u'standard':

            pass

        elif vault_type == u'symmetric':

            salt = vault['ipavaultsalt'][0]

            # get encryption key from vault password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                password = get_existing_password()

            # generate encryption key from password
            encryption_key = generate_symmetric_key(password, salt)

            # decrypt data with encryption key
            data = decrypt(data, symmetric_key=encryption_key)

        elif vault_type == u'asymmetric':

            # get encryption key with vault private key
            if private_key and private_key_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Private key specified multiple times'))

            elif private_key:
                pass

            elif private_key_file:
                private_key = validated_read('private-key-file',
                                             private_key_file,
                                             mode='rb')

            else:
                raise errors.ValidationError(
                    name='private_key',
                    error=_('Missing vault private key'))

            # decrypt encryption key with private key
            encryption_key = decrypt(encrypted_key, private_key=private_key)

            # decrypt data with encryption key
            data = decrypt(data, symmetric_key=encryption_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        if output_file:
            with open(output_file, 'w') as f:
                f.write(data)

        else:
            response['result'] = {'data': data}

        return response