Exemple #1
0
def verify_signature(context, checksum_hash, image_properties):
    """Retrieve the image properties and use them to verify the signature.

    :param context: the user context for authentication
    :param checksum_hash: the 'checksum' hash of the image data
    :param image_properties: the key-value properties about the image
    :returns: True if verification succeeds
    :raises glance.common.exception.SignatureVerificationError:
            if verification fails
    """
    if not should_verify_signature(image_properties):
        raise exception.SignatureVerificationError(
            _('Required image properties for signature verification do not'
              ' exist. Cannot verify signature.'))

    checksum_hash = encodeutils.to_utf8(checksum_hash)

    signature = get_signature(image_properties[OLD_SIGNATURE])
    hash_method = get_hash_method(image_properties[OLD_HASH_METHOD])
    signature_key_type = SignatureKeyType.lookup(
        image_properties[OLD_KEY_TYPE])
    public_key = get_public_key(context, image_properties[OLD_CERT_UUID],
                                signature_key_type)

    # create the verifier based on the signature key type
    try:
        verifier = signature_key_type.create_verifier(signature, hash_method,
                                                      public_key,
                                                      image_properties)
    except crypto_exception.UnsupportedAlgorithm as e:
        msg = (_LE("Unable to create verifier since algorithm is "
                   "unsupported: %(e)s") % {
                       'e': encodeutils.exception_to_unicode(e)
                   })
        LOG.error(msg)
        raise exception.SignatureVerificationError(
            _('Unable to verify signature since the algorithm is unsupported '
              'on this system'))

    if verifier:
        # Verify the signature
        verifier.update(checksum_hash)
        try:
            verifier.verify()
            return True
        except crypto_exception.InvalidSignature:
            raise exception.SignatureVerificationError(
                _('Signature verification failed.'))
    else:
        # Error creating the verifier
        raise exception.SignatureVerificationError(
            _('Error occurred while verifying the signature'))
Exemple #2
0
def get_public_key(context, signature_certificate_uuid, signature_key_type):
    """Create the public key object from a retrieved certificate.

    :param context: the user context for authentication
    :param signature_certificate_uuid: the uuid to use to retrieve the
                                       certificate
    :param signature_key_type: a SignatureKeyType object
    :returns: the public key cryptography object
    :raises glance.common.exception.SignatureVerificationError: if public
            key format is invalid
    """
    certificate = get_certificate(context, signature_certificate_uuid)

    # Note that this public key could either be
    # RSAPublicKey, DSAPublicKey, or EllipticCurvePublicKey
    public_key = certificate.public_key()

    # Confirm the type is of the type expected based on the signature key type
    if not isinstance(public_key, signature_key_type.public_key_type):
        raise exception.SignatureVerificationError(
            _('Invalid public key type for signature key type: %s')
            % signature_key_type
        )

    return public_key
Exemple #3
0
def fake_old_verify_signature(context, checksum_hash, image_properties):
    if (image_properties is not None and 'signature' in image_properties
            and image_properties['signature'] == 'VALID'):
        return True
    else:
        raise exception.SignatureVerificationError(
            'Signature verification failed.')
Exemple #4
0
def get_certificate(context, signature_certificate_uuid):
    """Create the certificate object from the retrieved certificate data.

    :param context: the user context for authentication
    :param signature_certificate_uuid: the uuid to use to retrieve the
                                       certificate
    :returns: the certificate cryptography object
    :raises glance.common.exception.SignatureVerificationError: if the
            retrieval fails or the format is invalid
    """
    keymgr_api = key_manager.API()

    try:
        # The certificate retrieved here is a castellan certificate object
        cert = keymgr_api.get(context, signature_certificate_uuid)
    except Exception as e:
        # The problem encountered may be backend-specific, since castellan
        # can use different backends.  Rather than importing all possible
        # backends here, the generic "Exception" is used.
        msg = (_LE("Unable to retrieve certificate with ID %(id)s: %(e)s")
               % {'id': signature_certificate_uuid,
                  'e': encodeutils.exception_to_unicode(e)})
        LOG.error(msg)
        raise exception.SignatureVerificationError(
            _('Unable to retrieve certificate with ID: %s')
            % signature_certificate_uuid
        )

    if cert.format not in CERTIFICATE_FORMATS:
        raise exception.SignatureVerificationError(
            _('Invalid certificate format: %s') % cert.format
        )

    if cert.format == X_509:
        # castellan always encodes certificates in DER format
        cert_data = cert.get_encoded()
        certificate = x509.load_der_x509_certificate(cert_data,
                                                     default_backend())
    else:
        raise exception.SignatureVerificationError(
            _('Certificate format not supported: %s') % cert.format
        )

    # verify the certificate
    verify_certificate(certificate)

    return certificate
Exemple #5
0
def get_verifier(context, image_properties):
    """Retrieve the image properties and use them to create a verifier.

    :param context: the user context for authentication
    :param image_properties: the key-value properties about the image
    :return: instance of cryptography AsymmetricVerificationContext
    :raises glance.common.exception.SignatureVerificationError: if building
            the verifier fails
    """
    if not should_create_verifier(image_properties):
        raise exception.SignatureVerificationError(
            _('Required image properties for signature verification do not'
              ' exist. Cannot verify signature.')
        )

    signature = get_signature(image_properties[SIGNATURE])
    hash_method = get_hash_method(image_properties[HASH_METHOD])
    signature_key_type = SignatureKeyType.lookup(
        image_properties[KEY_TYPE])
    public_key = get_public_key(context,
                                image_properties[CERT_UUID],
                                signature_key_type)

    # create the verifier based on the signature key type
    try:
        verifier = signature_key_type.create_verifier(signature,
                                                      hash_method,
                                                      public_key,
                                                      image_properties)
    except crypto_exception.UnsupportedAlgorithm as e:
        msg = (_LE("Unable to create verifier since algorithm is "
                   "unsupported: %(e)s")
               % {'e': encodeutils.exception_to_unicode(e)})
        LOG.error(msg)
        raise exception.SignatureVerificationError(
            _('Unable to verify signature since the algorithm is unsupported '
              'on this system')
        )

    if verifier:
        return verifier
    else:
        # Error creating the verifier
        raise exception.SignatureVerificationError(
            _('Error occurred while creating the verifier')
        )
Exemple #6
0
def verify_certificate(certificate):
    """Verify that the certificate has not expired.

    :param certificate: the cryptography certificate object
    :raises glance.common.exception.SignatureVerificationError: if the
            certificate valid time range does not include now
    """
    # Get now in UTC, since certificate returns times in UTC
    now = datetime.datetime.utcnow()

    # Confirm the certificate valid time range includes now
    if now < certificate.not_valid_before:
        raise exception.SignatureVerificationError(
            _('Certificate is not valid before: %s UTC') %
            certificate.not_valid_before)
    elif now > certificate.not_valid_after:
        raise exception.SignatureVerificationError(
            _('Certificate is not valid after: %s UTC') %
            certificate.not_valid_after)
Exemple #7
0
def create_verifier_for_pss(signature, hash_method, public_key,
                            image_properties):
    """Create the verifier to use when the key type is RSA-PSS.

    :param signature: the decoded signature to use
    :param hash_method: the hash method to use, as a cryptography object
    :param public_key: the public key to use, as a cryptography object
    :param image_properties: the key-value properties about the image
    :returns: the verifier to use to verify the signature for RSA-PSS
    :raises glance.common.exception.SignatureVerificationError: if the
            RSA-PSS specific properties are invalid
    """
    # retrieve other needed properties, or use defaults if not there
    if MASK_GEN_ALG in image_properties:
        mask_gen_algorithm = image_properties[MASK_GEN_ALG]
        if mask_gen_algorithm not in MASK_GEN_ALGORITHMS:
            raise exception.SignatureVerificationError(
                _('Invalid mask_gen_algorithm: %s') % mask_gen_algorithm
            )
        mgf = MASK_GEN_ALGORITHMS[mask_gen_algorithm](hash_method)
    else:
        # default to MGF1
        mgf = padding.MGF1(hash_method)

    if PSS_SALT_LENGTH in image_properties:
        pss_salt_length = image_properties[PSS_SALT_LENGTH]
        try:
            salt_length = int(pss_salt_length)
        except ValueError:
            raise exception.SignatureVerificationError(
                _('Invalid pss_salt_length: %s') % pss_salt_length
            )
    else:
        # default to max salt length
        salt_length = padding.PSS.MAX_LENGTH

    # return the verifier
    return public_key.verifier(
        signature,
        padding.PSS(mgf=mgf, salt_length=salt_length),
        hash_method
    )
Exemple #8
0
def verify_signature(context, checksum_hash, image_properties):
    """Retrieve the image properties and use them to verify the signature.

    :param context: the user context for authentication
    :param checksum_hash: the 'checksum' hash of the image data
    :param image_properties: the key-value properties about the image
    :returns: True if verification succeeds
    :raises: SignatureVerificationError if verification fails
    """
    if not should_verify_signature(image_properties):
        raise exception.SignatureVerificationError(
            'Required image properties for signature verification do not'
            ' exist. Cannot verify signature.')

    if isinstance(checksum_hash, six.text_type):
        checksum_hash = checksum_hash.encode('utf-8')

    signature = get_signature(image_properties[OLD_SIGNATURE])
    hash_method = get_hash_method(image_properties[OLD_HASH_METHOD])
    signature_key_type = get_signature_key_type(image_properties[OLD_KEY_TYPE])
    public_key = get_public_key(context, image_properties[OLD_CERT_UUID],
                                signature_key_type)

    # create the verifier based on the signature key type
    verifier = KEY_TYPE_METHODS[signature_key_type](signature, hash_method,
                                                    public_key,
                                                    image_properties)

    if verifier:
        # Verify the signature
        verifier.update(checksum_hash)
        try:
            verifier.verify()
            return True
        except crypto_exception.InvalidSignature:
            raise exception.SignatureVerificationError(
                'Signature verification failed.')
    else:
        # Error creating the verifier
        raise exception.SignatureVerificationError(
            'Error occurred while verifying the signature')
Exemple #9
0
    def lookup(cls, name):
        """Look up the signature key type.

        :param name: the name of the signature key type
        :returns: the SignatureKeyType object
        :raises: glance.common.exception.SignatureVerificationError if
                 signature key type is invalid
        """
        if name not in cls._REGISTERED_TYPES:
            raise exception.SignatureVerificationError(
                _('Invalid signature key type: %s') % name)
        return cls._REGISTERED_TYPES[name]
def get_signature_key_type(signature_key_type):
    """Verify the signature key type.

    :param signature_key_type: the key type of the signature
    :return: the validated signature key type
    :raises: SignatureVerificationError if the signature key type is invalid
    """
    if signature_key_type not in SIGNATURE_KEY_TYPES:
        raise exception.SignatureVerificationError(
            'Invalid signature key type: %s' % signature_key_type)

    return signature_key_type
def get_hash_method(hash_method_name):
    """Verify the hash method name and create the hash method.

    :param hash_method_name: the name of the hash method to retrieve
    :return: the hash method, a cryptography object
    :raises: SignatureVerificationError if the hash method name is invalid
    """
    if hash_method_name not in HASH_METHODS:
        raise exception.SignatureVerificationError(
            'Invalid signature hash method: %s' % hash_method_name)

    return HASH_METHODS[hash_method_name]
def get_signature(signature_data):
    """Decode the signature data and returns the signature.

    :param siganture_data: the base64-encoded signature data
    :return: the decoded signature
    :raises: SignatureVerificationError if the signature data is malformatted
    """
    try:
        signature = base64.b64decode(signature_data)
    except TypeError:
        raise exception.SignatureVerificationError(
            'The signature data was not properly encoded using base64')

    return signature
Exemple #13
0
def get_signature(signature_data):
    """Decode the signature data and returns the signature.

    :param signature_data: the base64-encoded signature data
    :returns: the decoded signature
    :raises glance.common.exception.SignatureVerificationError: if the
            signature data is malformatted
    """
    try:
        signature = base64.decode_as_bytes(signature_data)
    except (TypeError, binascii.Error):
        raise exception.SignatureVerificationError(
            _('The signature data was not properly encoded using base64'))

    return signature
Exemple #14
0
    def set_data(self, data, size=None):
        if size is None:
            size = 0  # NOTE(markwash): zero -> unknown size

        # Create the verifier for signature verification (if correct properties
        # are present)
        if (signature_utils.should_create_verifier(
                self.image.extra_properties)):
            # NOTE(bpoulos): if creating verifier fails, exception will be
            # raised
            verifier = signature_utils.get_verifier(
                self.context, self.image.extra_properties)
        else:
            verifier = None

        location, size, checksum, loc_meta = self.store_api.add_to_backend(
            CONF,
            self.image.image_id,
            utils.LimitingReader(utils.CooperativeReader(data),
                                 CONF.image_size_cap),
            size,
            context=self.context,
            verifier=verifier)

        self._verify_signature_if_needed(checksum)

        # NOTE(bpoulos): if verification fails, exception will be raised
        if verifier:
            try:
                verifier.verify()
                LOG.info(_LI("Successfully verified signature for image %s"),
                         self.image.image_id)
            except crypto_exception.InvalidSignature:
                raise exception.SignatureVerificationError(
                    _('Signature verification failed'))

        self.image.locations = [{
            'url': location,
            'metadata': loc_meta,
            'status': 'active'
        }]
        self.image.size = size
        self.image.checksum = checksum
        self.image.status = 'active'
def verify_signature(context, checksum_hash, image_properties):
    """Retrieve the image properties and use them to verify the signature.

    :param context: the user context for authentication
    :param checksum_hash: the 'checksum' hash of the image data
    :param image_properties: the key-value properties about the image
    :return: True if verification succeeds
    :raises: SignatureVerificationError if verification fails
    """
    if not should_verify_signature(image_properties):
        raise exception.SignatureVerificationError(
            'Required image properties for signature verification do not'
            ' exist. Cannot verify signature.')

    signature = get_signature(image_properties[SIGNATURE])
    hash_method = get_hash_method(image_properties[HASH_METHOD])
    signature_key_type = get_signature_key_type(image_properties[KEY_TYPE])
    public_key = get_public_key(context, image_properties[CERT_UUID],
                                signature_key_type)

    # Initialize the verifier
    verifier = None

    # create the verifier based on the signature key type
    if signature_key_type == RSA_PSS:
        # retrieve other needed properties, or use defaults if not there
        if MASK_GEN_ALG in image_properties:
            mask_gen_algorithm = image_properties[MASK_GEN_ALG]
            if mask_gen_algorithm in MASK_GEN_ALGORITHMS:
                mgf = MASK_GEN_ALGORITHMS[mask_gen_algorithm](hash_method)
            else:
                raise exception.SignatureVerificationError(
                    'Invalid mask_gen_algorithm: %s' % mask_gen_algorithm)
        else:
            # default to MGF1
            mgf = padding.MGF1(hash_method)
        if PSS_SALT_LENGTH in image_properties:
            pss_salt_length = image_properties[PSS_SALT_LENGTH]
            try:
                salt_length = int(pss_salt_length)
            except ValueError:
                raise exception.SignatureVerificationError(
                    'Invalid pss_salt_length: %s' % pss_salt_length)
        else:
            # default to max salt length
            salt_length = padding.PSS.MAX_LENGTH
        # Create the verifier
        verifier = public_key.verifier(
            signature, padding.PSS(mgf=mgf, salt_length=salt_length),
            hash_method)

    if verifier:
        # Verify the signature
        verifier.update(checksum_hash)
        try:
            verifier.verify()
            return True
        except crypto_exception.InvalidSignature:
            raise exception.SignatureVerificationError(
                'Signature verification failed.')
    else:
        # Error creating the verifier
        raise exception.SignatureVerificationError(
            'Error occurred while verifying the signature')