Ejemplo n.º 1
0
  def __init__(self, source, private_key, remote_public_key):
    self.private_key = private_key

    # The CipherProperties() protocol buffer specifying the session keys, that
    # we send to the other end point. It will be encrypted using the RSA private
    # key.
    self.cipher = rdf_flows.CipherProperties(
        name=self.cipher_name,
        key=rdf_crypto.EncryptionKey.GenerateKey(length=self.key_size),
        metadata_iv=rdf_crypto.EncryptionKey.GenerateKey(length=self.key_size),
        hmac_key=rdf_crypto.EncryptionKey.GenerateKey(length=self.key_size),
        hmac_type="FULL_HMAC")

    serialized_cipher = self.cipher.SerializeToString()

    self.cipher_metadata = rdf_flows.CipherMetadata(source=source)

    # Sign this cipher.
    self.cipher_metadata.signature = self.private_key.Sign(serialized_cipher)

    # Now encrypt the cipher.
    stats.STATS.IncrementCounter("grr_rsa_operations")
    self.encrypted_cipher = remote_public_key.Encrypt(serialized_cipher)

    # Encrypt the metadata block symmetrically.
    _, self.encrypted_cipher_metadata = self.Encrypt(
        self.cipher_metadata.SerializeToString(), self.cipher.metadata_iv)
Ejemplo n.º 2
0
    def VerifyMessageSignature(self, unused_response_comms,
                               signed_message_list, cipher, api_version):
        """Verify the message list signature.

    This is the way the messages are verified in the client.

    In the client we also check that the nonce returned by the server is correct
    (the timestamp doubles as a nonce). If the nonce fails we deem the response
    unauthenticated since it might have resulted from a replay attack.

    Args:
       signed_message_list: The SignedMessageList rdfvalue from the server.
       cipher: The cipher belonging to the remote end.
       api_version: The api version we should use.

    Returns:
       a rdf_flows.GrrMessage.AuthorizationState.

    Raises:
       DecryptionError: if the message is corrupt.
    """
        # This is not used atm since we only support a single api version (3).
        _ = api_version
        result = rdf_flows.GrrMessage.AuthorizationState.UNAUTHENTICATED

        # Give the cipher another chance to check its signature.
        if not cipher.signature_verified:
            cipher.VerifyCipherSignature()

        if cipher.signature_verified:
            stats.STATS.IncrementCounter("grr_authenticated_messages")
            result = rdf_flows.GrrMessage.AuthorizationState.AUTHENTICATED

        # Check for replay attacks. We expect the server to return the same
        # timestamp nonce we sent.
        if signed_message_list.timestamp != self.timestamp:
            result = rdf_flows.GrrMessage.AuthorizationState.UNAUTHENTICATED

        if not cipher.cipher_metadata:
            # Fake the metadata
            cipher.cipher_metadata = rdf_flows.CipherMetadata(
                source=signed_message_list.source)

        return result
Ejemplo n.º 3
0
    def __init__(self, source, destination, private_key, pub_key_cache):
        self.private_key = private_key

        # The CipherProperties() protocol buffer specifying the session keys, that
        # we send to the other end point. It will be encrypted using the RSA private
        # key.
        self.cipher = rdf_flows.CipherProperties(
            name=self.cipher_name,
            key=os.urandom(self.key_size / 8),
            metadata_iv=os.urandom(self.iv_size / 8),
            hmac_key=os.urandom(self.key_size / 8),
            hmac_type="FULL_HMAC")

        self.pub_key_cache = pub_key_cache
        serialized_cipher = self.cipher.SerializeToString()

        self.cipher_metadata = rdf_flows.CipherMetadata(source=source)

        # Sign this cipher.
        digest = self.hash_function(serialized_cipher).digest()

        # We never want to have a password dialog
        private_key = self.private_key.GetPrivateKey()

        self.cipher_metadata.signature = private_key.sign(
            digest, self.hash_function_name)

        # Now encrypt the cipher with our key
        rsa_key = pub_key_cache.GetRSAPublicKey(destination)

        stats.STATS.IncrementCounter("grr_rsa_operations")
        # M2Crypto verifies the key on each public_encrypt call which is horribly
        # slow therefore we just call the swig wrapped method directly.
        self.encrypted_cipher = m2.rsa_public_encrypt(rsa_key.rsa,
                                                      serialized_cipher,
                                                      self.e_padding)

        # Encrypt the metadata block symmetrically.
        _, self.encrypted_cipher_metadata = self.Encrypt(
            self.cipher_metadata.SerializeToString(), self.cipher.metadata_iv)

        self.signature_verified = True
Ejemplo n.º 4
0
    def __init__(self, response_comms, private_key):
        self.private_key = private_key
        self.response_comms = response_comms

        if response_comms.api_version not in [3]:
            raise DecryptionError("Unsupported api version: %s, expected 3." %
                                  response_comms.api_version)

        if not response_comms.encrypted_cipher:
            # The message is not encrypted. We do not allow unencrypted
            # messages:
            raise DecryptionError("Server response is not encrypted.")

        try:
            # The encrypted_cipher contains the session key, iv and hmac_key.
            self.serialized_cipher = private_key.Decrypt(
                response_comms.encrypted_cipher)

            # If we get here we have the session keys.
            self.cipher = rdf_flows.CipherProperties(self.serialized_cipher)

            # Check the key lengths.
            if (len(self.cipher.key) != self.key_size / 8
                    or len(self.cipher.metadata_iv) != self.iv_size / 8
                    or len(self.cipher.hmac_key) != self.key_size / 8):
                raise DecryptionError("Invalid cipher.")

            self.VerifyHMAC()

            # Cipher_metadata contains information about the cipher - It is encrypted
            # using the symmetric session key. It contains the RSA signature of the
            # digest of the serialized CipherProperties(). It is stored inside the
            # encrypted payload.
            serialized_metadata = self.Decrypt(
                response_comms.encrypted_cipher_metadata,
                self.cipher.metadata_iv)
            self.cipher_metadata = rdf_flows.CipherMetadata(
                serialized_metadata)

        except (rdf_crypto.InvalidSignature, rdf_crypto.CipherError) as e:
            raise DecryptionError(e)
Ejemplo n.º 5
0
    def __init__(self, response_comms, private_key, pub_key_cache):
        self.private_key = private_key
        self.pub_key_cache = pub_key_cache

        # Decrypt the message
        private_key = self.private_key.GetPrivateKey()

        try:
            # The encrypted_cipher contains the session key, iv and hmac_key.
            self.encrypted_cipher = response_comms.encrypted_cipher

            # M2Crypto verifies the key on each private_decrypt call which is horribly
            # slow therefore we just call the swig wrapped method directly.
            self.serialized_cipher = m2.rsa_private_decrypt(
                private_key.rsa, response_comms.encrypted_cipher,
                self.e_padding)

            # If we get here we have the session keys.
            self.cipher = rdf_flows.CipherProperties(self.serialized_cipher)

            # Check the key lengths.
            if (len(self.cipher.key) != self.key_size / 8
                    or len(self.cipher.metadata_iv) != self.iv_size / 8):
                raise DecryptionError("Invalid cipher.")

            # Check the hmac key for sanity.
            self.VerifyHMAC(response_comms)

            # Cipher_metadata contains information about the cipher - It is encrypted
            # using the symmetric session key. It contains the RSA signature of the
            # digest of the serialized CipherProperties(). It is stored inside the
            # encrypted payload.
            self.cipher_metadata = rdf_flows.CipherMetadata(
                self.Decrypt(response_comms.encrypted_cipher_metadata,
                             self.cipher.metadata_iv))

            self.VerifyCipherSignature()

        except RSA.RSAError as e:
            raise DecryptionError(e)