VeraCrypt

Documentation >> Security Requirements and Precautions >> VeraCrypt RAM Encryption

VeraCrypt RAM Encryption Mechanism

Introduction

VeraCrypt RAM Encryption aims to protect disk encryption keys stored in volatile memory against certain types of attacks. The primary objectives of this mechanism are:

Implementation Overview

Here's a summary of how RAM encryption is achieved:

  1. At Windows startup, the VeraCrypt driver allocates a 1MiB memory region. If this fails, we device the size by two until allocation succeeds (minimal size being 8KiB). All these variables are allocated in non-paged Kernel memory space.
  2. This memory region is then populated with random bytes generated by a CSPRNG based on ChaCha20.
  3. Two random 64-bit integers, HashSeedMask and CipherIVMask, are generated.
  4. For every master key of a volume, the RAM encryption algorithm derives a unique key from a combination of the memory region and unique values extracted from the memory to be encrypted. This ensures a distinct key for each encrypted memory region. The use of location-dependent keys and IVs prevents master keys from being easily extracted from memory dumps.
  5. The master keys are decrypted for every request, requiring a fast decryption algorithm. For this, ChaCha12 is utilized.
  6. Once a volume is mounted, its master keys are immediately encrypted using the described algorithm.
  7. For each I/O request for a volume, the master keys are decrypted only for the duration of that request and then securely wiped.
  8. Upon volume dismounting, the encrypted master keys are securely removed from memory.
  9. At Windows shutdown or reboot, the memory region allocated during startup is securely wiped.

Protection against Cold Boot Attacks

The mitigation of cold boot attacks is achieved by utilizing a large memory page for key derivation. This ensures that attackers cannot recover the master key since parts of this large memory area would likely be corrupted and irrecoverable after shutdown. Further details on cold boot attacks and mitigation techniques can be found in the referenced papers:

Incompatibility with Windows Hibernate and Fast Startup

RAM Encryption in VeraCrypt is not compatible with the Windows Hibernate and Fast Startup features. Before activating RAM Encryption, these features will be disabled by VeraCrypt to ensure the security and functionality of the encryption mechanism.

Algorithm Choices

The choice of algorithms was based on a balance between security and performance:

Key Algorithms

Two core algorithms are fundamental to the RAM encryption process:

1. VcGetEncryptionID

Computes a unique ID for the RAM buffer set to be encrypted.

    
    - Input: pCryptoInfo, a CRYPTO_INFO variable to encrypt/decrypt
    - Output: A 64-bit integer identifying the pCryptoInfo variable
    - Steps:
      - Compute the sum of the virtual memory addresses of the fields ks and ks2 of pCryptoInfo: encID = ((uint64) pCryptoInfo->ks) + ((uint64) pCryptoInfo->ks2)
      - Return the result
    

2. VcProtectMemory

Encrypts the RAM buffer using the unique ID generated by VcGetEncryptionID.

.highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
  zip_discard.c -- discard and free struct zip
  Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner

  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.
  3. The names of the authors may not be used to endorse or promote
     products derived from this software without specific prior
     written permission.
 
  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#include <stdlib.h>

#include "zipint.h"


/* zip_discard:
   frees the space allocated to a zipfile struct, and closes the
   corresponding file. */

void
zip_discard(zip_t *za)
{
    zip_uint64_t i;

    if (za == NULL)
	return;

    if (za->src) {
	zip_source_close(za->src);
	zip_source_free(za->src);
    }

    free(za->default_password);
    _zip_string_free(za->comment_orig);
    _zip_string_free(za->comment_changes);

    _zip_hash_free(za->names);

    if (za->entry) {
	for (i=0; i<za->nentry; i++)
	    _zip_entry_finalize(za->entry+i);
	free(za->entry);
    }

    for (i=0; i<za->nopen_source; i++) {
	_zip_source_invalidate(za->open_source[i]);
    }
    free(za->open_source);

    zip_error_fini(&za->error);
    
    free(za);

    return;
}