=== modified file 'src/include/ecryptfs.h'
Index: src/include/ecryptfs.h
===================================================================
--- src/include/ecryptfs.h.orig
+++ src/include/ecryptfs.h
@@ -515,10 +515,12 @@ int ecryptfs_read_salt_hex_from_rc(char
 int ecryptfs_check_sig(char *auth_tok_sig, char *sig_cache_filename,
 		       int *flags);
 int ecryptfs_append_sig(char *auth_tok_sig, char *sig_cache_filename);
+int __ecryptfs_detect_wrapped_passphrase_file_version(const char *filename,
+						      uint8_t *version);
 int ecryptfs_wrap_passphrase_file(char *dest, char *wrapping_passphrase,
  			     char *wrapping_salt, char *src);
 int ecryptfs_wrap_passphrase(char *filename, char *wrapping_passphrase,
-			     char *wrapping_salt, char *decrypted_passphrase);
+			     char *unused, char *decrypted_passphrase);
 int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, char *filename,
 			       char *wrapping_passphrase, char *wrapping_salt);
 int ecryptfs_insert_wrapped_passphrase_into_keyring(
Index: src/libecryptfs/key_management.c
===================================================================
--- src/libecryptfs/key_management.c.orig
+++ src/libecryptfs/key_management.c
@@ -38,6 +38,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <pwd.h>
+#include <inttypes.h>
 #include "../include/ecryptfs.h"
 
 #ifndef ENOKEY
@@ -242,6 +243,163 @@ out:
 	return rc;
 }
 
+/**
+ * A wrapper around write(2) that handles short and interrupted writes.
+ *
+ * Returns the number of bytes written or -1 with errno set on failure.
+ */
+static ssize_t do_write(int fd, const void *buf, size_t count)
+{
+	ssize_t rc = 0;
+
+	do {
+		ssize_t bytes = write(fd, buf + rc, count - rc);
+
+		if (bytes == -1) {
+			if (errno == EINTR)
+				continue;
+			return -1;
+		}
+
+		rc += bytes;
+	} while (rc < count);
+
+	return rc;
+}
+
+/**
+ * A wrapper around read(2) that handles short and interrupted reads.
+ *
+ * Returns the number of bytes read or -1 with errno set on failure.
+ */
+static ssize_t do_read(int fd, void *buf, size_t count)
+{
+	ssize_t rc = 0;
+
+	do {
+		ssize_t bytes = read(fd, buf + rc, count - rc);
+
+		if (bytes == 0) {
+			break;
+		} else if (bytes == -1) {
+			if (errno == EINTR)
+				continue;
+
+			return -1;
+		}
+
+		rc += bytes;
+	} while (rc < count);
+
+	return rc;
+}
+
+/**
+ * read_wrapped_passphrase_file_version
+ * @fd: A file descriptor, opened for reading, of a wrapped passphrase file
+ * @version: On success, *version is set to the detected file version
+ *
+ * Sets the fd offset to 0 and attempts to determine the version number of the
+ * opened wrapped-passphrase file. If a versioned wrapped-passphrase file is
+ * not found and the first 16 bytes of the file are hex encoded values, then
+ * the version is assumed to be '1'.
+ *
+ * Returns 0 on success, sets *version to the determined wrapped-passphrase
+ * file version, and ensures that the fd offset is appropriately set for
+ * reading the next field in the wrapped passphrase file. Returns negative on
+ * error (*version and the fd offset is undefined upon error).
+ */
+static int read_wrapped_passphrase_file_version(int fd, uint8_t *version)
+{
+	char buf[ECRYPTFS_SIG_SIZE_HEX];
+	int bytes_read, i;
+
+	memset(buf, 0, sizeof(buf));
+
+	if (lseek(fd, 0, SEEK_SET) != 0)
+		return -errno;
+
+	bytes_read = do_read(fd, buf, sizeof(buf));
+	if (bytes_read < 0)
+		return -errno;
+	else if (bytes_read != sizeof(buf))
+		return -EINVAL;
+
+	if (buf[0] == ':') {
+		/* A leading ':' character means that this is a properly
+		 * versioned wrapped passphrase file. The second octet contains
+		 * the version number.
+		 */
+		uint8_t v = buf[1];
+
+		/* Only version 2 files are currently supported */
+		if (v != 2)
+			return -ENOTSUP;
+
+		/* Set the offset to the beginning of the wrapping salt field */
+		if (lseek(fd, 2, SEEK_SET) != 2)
+			return -errno;
+
+		*version = v;
+	} else {
+		/* This wrapped passphrase file isn't versioned. We can assume
+		 * that it is a "version 1" file if the first 16 bytes are hex
+		 * encoded values.
+		 */
+		for (i = 0; i < bytes_read; i++) {
+			if (!isxdigit(buf[i]))
+				return -EINVAL;
+		}
+
+		/* Reset the offset to 0 since there is no actual version field
+		 * in version 1 files
+		 */
+		if (lseek(fd, 0, SEEK_SET) != 0)
+			return -errno;
+
+		*version = 1;
+	}
+
+	return 0;
+}
+
+/**
+ * __ecryptfs_detect_wrapped_passphrase_file_version
+ * @filename: The path of a wrapped passphrase file
+ * @version: On success, *version is set to the detected file version
+ *
+ * THIS FUNCTION IS NOT PART OF THE LIBECRYPTFS PUBLIC API. Code external to
+ * ecryptfs-utils should not use it.
+ *
+ * Detects the wrapped passphrase file version of @filename.
+ *
+ * Returns 0 on success, sets *version to the determined wrapped-passphrase
+ * file version. Returns negative on error (*version is undefined upon error).
+ */
+int __ecryptfs_detect_wrapped_passphrase_file_version(const char *filename,
+						      uint8_t *version)
+{
+	int fd = -1;
+	int rc;
+
+	fd = open(filename, O_RDONLY);
+	if (fd == -1) {
+		rc = -errno;
+		goto out;
+	}
+
+	rc = read_wrapped_passphrase_file_version(fd, version);
+	if (rc != 0)
+		goto out;
+
+	rc = 0;
+out:
+	if (fd != -1)
+		close(fd);
+
+	return rc;
+}
+
 int ecryptfs_wrap_passphrase_file(char *dest, char *wrapping_passphrase,
 				  char *salt, char *src)
 {
@@ -260,8 +418,8 @@ int ecryptfs_wrap_passphrase_file(char *
 		close(fd);
 		goto out;
 	}
-	if ((size = read(fd, decrypted_passphrase,
-			 ECRYPTFS_MAX_PASSPHRASE_BYTES)) <= 0) {
+	if ((size = do_read(fd, decrypted_passphrase,
+			    ECRYPTFS_MAX_PASSPHRASE_BYTES)) <= 0) {
 		syslog(LOG_ERR, "Error attempting to read encrypted "
 		       "passphrase from file [%s]; size = [%zd]\n",
 		       src, size);
@@ -285,9 +443,127 @@ out:
 	return rc;
 }
 
+static int read_urandom(void *buf, size_t count)
+{
+	ssize_t bytes;
+	int fd = -1;
+
+	fd = open("/dev/urandom", O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	bytes = do_read(fd, buf, count);
+	close(fd);
+
+	return bytes;
+}
+
+/**
+ * write_v2_wrapped_passphrase_file
+ * @filename: Path to the wrapped passphrase file
+ * @wrapping_salt: The salt to be used with the wrapping passphrase
+ * @wrapping_key_sig: The signature of the wrapping key
+ * @encrypted_passphrase: The encrypted passphrase
+ * @encrypted_passphrase_bytes: The size of the encrypted passphrase
+ *
+ * Writes a version 2 wrapped passphrase file containing the following format
+ * described in the read_v2_wrapped_passphrase_file() function.
+ *
+ * Returns 0 upon success. Negative upon error.
+ */
+static int write_v2_wrapped_passphrase_file(const char *filename,
+			const char wrapping_salt[ECRYPTFS_SALT_SIZE],
+			const char wrapping_key_sig[ECRYPTFS_SIG_SIZE_HEX],
+			const char *encrypted_passphrase,
+			int encrypted_passphrase_bytes)
+{
+	ssize_t size;
+	uint8_t version = 2;
+	mode_t old_umask;
+	char *temp = NULL;
+	int fd = -1;
+	int rc;
+
+	if (asprintf(&temp, "%s-XXXXXX", filename) < 0) {
+		rc = -errno;
+		temp = NULL;
+		goto out;
+	}
+
+	old_umask = umask(S_IRWXG | S_IRWXO);
+	fd = mkstemp(temp);
+	umask(old_umask);
+	if (fd == -1) {
+		rc = -errno;
+		goto out;
+	}
+
+	size = do_write(fd, ":", 1);
+	if (size != 1) {
+		rc = size == -1 ? -errno : -EIO;
+		goto out;
+	}
+
+	size = do_write(fd, &version, 1);
+	if (size != 1) {
+		rc = size == -1 ? -errno : -EIO;
+		goto out;
+	}
+
+	size = do_write(fd, wrapping_salt, ECRYPTFS_SALT_SIZE);
+	if (size != ECRYPTFS_SALT_SIZE) {
+		rc = size == -1 ? -errno : -EIO;
+		goto out;
+	}
+
+	size = do_write(fd, wrapping_key_sig, ECRYPTFS_SIG_SIZE_HEX);
+	if (size != ECRYPTFS_SIG_SIZE_HEX) {
+		rc = size == -1 ? -errno : -EIO;
+		goto out;
+	}
+
+	size = do_write(fd, encrypted_passphrase, encrypted_passphrase_bytes);
+	if (size != encrypted_passphrase_bytes) {
+		rc = size == -1 ? -errno : -EIO;
+		goto out;
+	}
+
+	if (fsync(fd) == -1) {
+		rc = -errno;
+		goto out;
+	}
+
+	close(fd);
+	fd = -1;
+
+	if (rename(temp, filename) == -1) {
+		rc = -errno;
+		goto out;
+	}
+
+	rc = 0;
+out:
+	if (fd != -1)
+		close(fd);
+	free(temp);
+
+	return rc;
+}
+
+/**
+ * ecryptfs_wrap_passphrase
+ * @filename: Path to the wrapped passphrase file
+ * @wrapping_passphrase: The passphrase used for wrapping the @decrypted_passphrase
+ * @unused: Previously used for specifying a wrapping salt. It is now randomly
+ *  generated so @unused is no longer used.
+ * @decrypted_passphrase: The passphrase to be wrapped
+ *
+ * Returns 0 upon success. Negative upon error.
+ */
 int ecryptfs_wrap_passphrase(char *filename, char *wrapping_passphrase,
-			     char *wrapping_salt, char *decrypted_passphrase)
+			     char *unused, char *decrypted_passphrase)
 {
+	char wrapping_salt[ECRYPTFS_SALT_SIZE];
 	char wrapping_auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
 	char wrapping_key[ECRYPTFS_MAX_KEY_BYTES];
 	char padded_decrypted_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES +
@@ -318,6 +594,13 @@ int ecryptfs_wrap_passphrase(char *filen
 		rc = -EIO;
 		goto out;
 	}
+	rc = read_urandom(wrapping_salt, ECRYPTFS_SALT_SIZE);
+	if (rc != ECRYPTFS_SALT_SIZE) {
+		rc = rc == -1 ? -errno : -EIO;
+		syslog(LOG_ERR, "Error generating random salt: %s\n",
+		       strerror(-rc));
+		goto out;
+	}
 	rc = generate_passphrase_sig(wrapping_auth_tok_sig, wrapping_key,
 				     wrapping_salt, wrapping_passphrase);
 	if (rc) {
@@ -395,35 +678,163 @@ nss_finish:
 		rc = - EIO;
 		goto out;
 	}
-	unlink(filename);
-	if ((fd = open(filename, (O_WRONLY | O_CREAT | O_EXCL),
-		       (S_IRUSR | S_IWUSR))) == -1) {
-		syslog(LOG_ERR, "Error attempting to open [%s] for writing\n",
+	rc = write_v2_wrapped_passphrase_file(filename, wrapping_salt,
+					      wrapping_auth_tok_sig,
+					      encrypted_passphrase,
+					      encrypted_passphrase_bytes);
+	if (rc)
+		goto out;
+	rc = 0;
+out:
+	return rc;
+}
+
+/**
+ * read_v1_wrapped_passphrase_file - Reads a v1 wrapped passphrase file
+ * @filename: Path to the wrapped passphrase file
+ * @wrapping_key_sig: Will contain the parsed wrapping key sig upon success.
+ *  MUST be zeroed prior to calling this function.
+ * @encrypted_passphrase: Will contain the parsed encrypted passphrase upon
+ *  success. MUST be zeroed prior to calling this function.
+ * @encrypted_passphrase_bytes: Will contain the size of the parsed encrypted
+ *  passphrase upon success
+ *
+ * Reads a version 1 wrapped passphrase file containing the following format:
+ *
+ *   Octets 0-15:   Signature of wrapping key
+ *   Octets 16-79:  Variable length field containing the encrypted
+ *                  passphrase.
+ *
+ * Returns 0 upon success with the size of the encrypted passphrase returned in
+ * *encrypted_passphrase_bytes. Returns negative upon failure.
+ */
+static int read_v1_wrapped_passphrase_file(const char *filename,
+				char wrapping_key_sig[ECRYPTFS_SIG_SIZE_HEX],
+				char encrypted_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES],
+				int *encrypted_passphrase_bytes)
+{
+	ssize_t size;
+	int fd;
+	int rc;
+
+	*encrypted_passphrase_bytes = 0;
+
+	if ((fd = open(filename, O_RDONLY)) == -1) {
+		syslog(LOG_ERR, "Error attempting to open [%s] for reading\n",
 		       filename);
 		rc = -EIO;
 		goto out;
 	}
-	if ((size = write(fd, wrapping_auth_tok_sig,
-			  ECRYPTFS_SIG_SIZE_HEX)) <= 0) {
-		syslog(LOG_ERR, "Error attempting to write encrypted "
-		       "passphrase ([%d] bytes) to file [%s]; size = [%zu]\n",
-		       encrypted_passphrase_bytes, filename, size);
+
+	if ((size = do_read(fd, wrapping_key_sig,
+			    ECRYPTFS_SIG_SIZE_HEX)) < ECRYPTFS_SIG_SIZE_HEX) {
+		syslog(LOG_ERR,
+		       "Error attempting to read encrypted passphrase from file [%s]; size = [%zu]\n",
+		       filename, size);
 		rc = -EIO;
-		close(fd);
 		goto out;
 	}
-	if ((size = write(fd, encrypted_passphrase,
-			  encrypted_passphrase_bytes)) <= 0) {
-		syslog(LOG_ERR, "Error attempting to write encrypted "
-		       "passphrase ([%d] bytes) to file [%s]; size = [%zu]\n",
-		       encrypted_passphrase_bytes, filename, size);
+
+	if ((size = do_read(fd, encrypted_passphrase,
+			    ECRYPTFS_MAX_PASSPHRASE_BYTES)) <= 0) {
+		syslog(LOG_ERR,
+		       "Error attempting to read encrypted passphrase from file [%s]; size = [%zu]\n",
+		       filename, size);
 		rc = -EIO;
+		goto out;
+	}
+
+	*encrypted_passphrase_bytes = size;
+	rc = 0;
+out:
+	if (fd != -1)
 		close(fd);
+
+	return 0;
+}
+
+/**
+ * read_v2_wrapped_passphrase_file - Reads a v2 wrapped passphrase file
+ * @filename: Path to the wrapped passphrase file
+ * @wrapping_salt: Will contain the parsed wrapping salt upon success. MUST be
+ *  zeroed prior to calling this function.
+ * @wrapping_key_sig: Will contain the parsed wrapping key sig upon success.
+ *  MUST be zeroed prior to calling this function.
+ * @encrypted_passphrase: Will contain the parsed encrypted passphrase upon
+ *  success. MUST be zeroed prior to calling this function.
+ * @encrypted_passphrase_bytes: Will contain the size of the parsed encrypted
+ *  passphrase upon success
+ *
+ * Reads a version 2 wrapped passphrase file containing the following format:
+ *
+ *   Octet  0:      A ':' character
+ *   Octet  1:      uint8_t value indicating file version (MUST be 0x02)
+ *   Octets 2-9:    Wrapping salt
+ *   Octets 10-25:  Signature of wrapping key (16 octets)
+ *   Octets 26-N1:  Variable length field containing the encrypted
+ *                  passphrase. (Up to 64 octets. Must be non-empty.)
+ *
+ * Returns 0 upon success with the size of the encrypted passphrase returned in
+ * *encrypted_passphrase_bytes. Returns negative upon failure.
+ */
+static int read_v2_wrapped_passphrase_file(const char *filename,
+				char wrapping_salt[ECRYPTFS_SALT_SIZE],
+				char wrapping_key_sig[ECRYPTFS_SIG_SIZE_HEX],
+				char encrypted_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES],
+				int *encrypted_passphrase_bytes)
+{
+	uint8_t version = 0;
+	uint8_t salt_len = 0;
+	ssize_t size;
+	int fd = -1;
+	int rc;
+
+	*encrypted_passphrase_bytes = 0;
+
+	if ((fd = open(filename, O_RDONLY)) == -1) {
+		rc = -errno;
 		goto out;
 	}
-	close(fd);
+
+	/* Parse file version (must be 2) */
+	rc = read_wrapped_passphrase_file_version(fd, &version);
+	if (rc != 0) {
+		goto out;
+	} else if (version != 2) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* Parse the wrapping salt */
+	size = do_read(fd, wrapping_salt, ECRYPTFS_SALT_SIZE);
+	if (size != ECRYPTFS_SALT_SIZE) {
+		rc = size == -1 ? errno : -EINVAL;
+		goto out;
+	}
+
+	/* Parse the wrapping key signature */
+	size = do_read(fd, wrapping_key_sig, ECRYPTFS_SIG_SIZE_HEX);
+	if (size != ECRYPTFS_SIG_SIZE_HEX) {
+		rc = size == -1 ? errno : -EINVAL;
+		goto out;
+	}
+
+	/* Parse the encrypted passphrase */
+	size = do_read(fd, encrypted_passphrase, ECRYPTFS_MAX_PASSPHRASE_BYTES);
+	if (size < 0) {
+		rc = size;
+		goto out;
+	} else if(size == 0) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	*encrypted_passphrase_bytes = size;
 	rc = 0;
 out:
+	if (fd != -1)
+		close(fd);
+
 	return rc;
 }
 
@@ -434,6 +845,7 @@ out:
 int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, char *filename,
 			       char *wrapping_passphrase, char *wrapping_salt)
 {
+	char v2_wrapping_salt[ECRYPTFS_SALT_SIZE];
 	char wrapping_auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1];
 	char wrapping_auth_tok_sig_from_file[ECRYPTFS_SIG_SIZE_HEX + 1];
 	char wrapping_key[ECRYPTFS_MAX_KEY_BYTES];
@@ -448,14 +860,53 @@ int ecryptfs_unwrap_passphrase(char *dec
 	PK11SlotInfo *slot = NULL;
 	PK11Context *enc_ctx = NULL;
 	SECItem *sec_param = NULL;
+	uint8_t version = 0;
 	int encrypted_passphrase_bytes;
-	int fd;
-	ssize_t size;
 	int rc;
 
 	memset(wrapping_auth_tok_sig_from_file, 0,
 	       sizeof(wrapping_auth_tok_sig_from_file));
 	memset(encrypted_passphrase, 0, sizeof(encrypted_passphrase));
+
+	rc = __ecryptfs_detect_wrapped_passphrase_file_version(filename,
+							       &version);
+	if (rc) {
+		syslog(LOG_ERR,
+		       "Failed to detect wrapped passphrase version: %s\n",
+		       strerror(-rc));
+		goto out;
+	}
+
+	if (version == 1) {
+		rc = read_v1_wrapped_passphrase_file(filename,
+						wrapping_auth_tok_sig_from_file,
+						encrypted_passphrase,
+						&encrypted_passphrase_bytes);
+		if (rc)
+			goto out;
+	} else if (version == 2) {
+		rc = read_v2_wrapped_passphrase_file(filename,
+						v2_wrapping_salt,
+						wrapping_auth_tok_sig_from_file,
+						encrypted_passphrase,
+						&encrypted_passphrase_bytes);
+		if (rc)
+			goto out;
+
+		/**
+		 * Version 2 wrapped passphrase self-contains the wrapping salt.
+		 * The passed in @wrapping_salt buffer is ignored and the
+		 * parsed wrapping salt is used instead.
+		 */
+		wrapping_salt = v2_wrapping_salt;
+	} else {
+		syslog(LOG_ERR,
+		       "Unsupported wrapped passphrase file version: %u\n",
+		       version);
+		rc = -ENOTSUP;
+		goto out;
+	}
+
 	rc = generate_passphrase_sig(wrapping_auth_tok_sig, wrapping_key,
 				     wrapping_salt, wrapping_passphrase);
 	if (rc) {
@@ -464,31 +915,7 @@ int ecryptfs_unwrap_passphrase(char *dec
 		rc = (rc < 0) ? rc : rc * -1;
 		goto out;
 	}
-	if ((fd = open(filename, O_RDONLY)) == -1) {
-		syslog(LOG_ERR, "Error attempting to open [%s] for reading\n",
-		       filename);
-		rc = -EIO;
-		goto out;
-	}
-	if ((size = read(fd, wrapping_auth_tok_sig_from_file,
-			 ECRYPTFS_SIG_SIZE_HEX)) <= 0) {
-		syslog(LOG_ERR, "Error attempting to read encrypted "
-		       "passphrase from file [%s]; size = [%zu]\n",
-		       filename, size);
-		rc = -EIO;
-		close(fd);
-		goto out;
-	}
-	if ((size = read(fd, encrypted_passphrase,
-			 ECRYPTFS_MAX_PASSPHRASE_BYTES)) <= 0) {
-		syslog(LOG_ERR, "Error attempting to read encrypted "
-		       "passphrase from file [%s]; size = [%zu]\n",
-		       filename, size);
-		rc = -EIO;
-		close(fd);
-		goto out;
-	}
-	close(fd);
+
 	if (memcmp(wrapping_auth_tok_sig_from_file, wrapping_auth_tok_sig,
 		   ECRYPTFS_SIG_SIZE_HEX) != 0) {
 		syslog(LOG_ERR, "Incorrect wrapping key for file [%s]\n",
@@ -496,7 +923,6 @@ int ecryptfs_unwrap_passphrase(char *dec
 		rc = -EIO;
 		goto out;
 	}
-	encrypted_passphrase_bytes = size;
 	NSS_NoDB_Init(NULL);
 	slot = PK11_GetBestSlot(CKM_AES_ECB, NULL);
 	key_item.data = (unsigned char *)wrapping_key;
Index: src/pam_ecryptfs/pam_ecryptfs.c
===================================================================
--- src/pam_ecryptfs/pam_ecryptfs.c.orig
+++ src/pam_ecryptfs/pam_ecryptfs.c
@@ -120,6 +120,34 @@ static int wrap_passphrase_if_necessary(
 	return 0;
 }
 
+static int rewrap_passphrase_if_necessary(char *wrapped_pw_filename,
+					  char *wrapping_passphrase, char *salt)
+{
+	char passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES + 1];
+	uint8_t version;
+	int rc;
+
+	memset(passphrase, 0, sizeof(passphrase));
+
+	rc = __ecryptfs_detect_wrapped_passphrase_file_version(
+							wrapped_pw_filename,
+							&version);
+	if (rc)
+		return rc;
+
+	/* Only rewrap version 1 files */
+	if (version > 1)
+		return 0;
+
+	rc = ecryptfs_unwrap_passphrase(passphrase, wrapped_pw_filename,
+					wrapping_passphrase, salt);
+	if (rc)
+		return rc;
+
+	return ecryptfs_wrap_passphrase(wrapped_pw_filename,
+					wrapping_passphrase, NULL, passphrase);
+}
+
 PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
 				   const char **argv)
 {
@@ -228,6 +256,10 @@ PAM_EXTERN int pam_sm_authenticate(pam_h
 			} else {
 				goto out_child;
 			}
+			if (rewrap_passphrase_if_necessary(wrapped_pw_filename, passphrase, salt)) {
+				/* Non fatal condition. Log a warning. */
+				syslog(LOG_WARNING, "pam_ecryptfs: Unable to rewrap passphrase file\n");
+			}
 			rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
 				auth_tok_sig, wrapped_pw_filename, passphrase,
 				salt);
Index: tests/userspace/Makefile.am
===================================================================
--- tests/userspace/Makefile.am.orig
+++ tests/userspace/Makefile.am
@@ -1,17 +1,15 @@
 AUTOMAKE_OPTIONS = subdir-objects
 
 # Only place tests worth of 'make check' here. All other tests are noinst.
-dist_check_SCRIPTS = verify-passphrase-sig.sh
-check_PROGRAMS = verify-passphrase-sig/test
+dist_check_SCRIPTS = verify-passphrase-sig.sh wrap-unwrap.sh v1-to-v2-wrapped-passphrase.sh
+check_PROGRAMS = verify-passphrase-sig/test wrap-unwrap/test v1-to-v2-wrapped-passphrase/test
 
 dist_noinst_DATA = tests.rc
 
-dist_noinst_SCRIPTS = $(dist_check_SCRIPTS) \
-		      wrap-unwrap.sh
+dist_noinst_SCRIPTS = $(dist_check_SCRIPTS)
 
 if ENABLE_TESTS
-noinst_PROGRAMS = $(check_PROGRAMS) \
-		  wrap-unwrap/test
+noinst_PROGRAMS = $(check_PROGRAMS)
 endif
 
 verify_passphrase_sig_test_SOURCES = verify-passphrase-sig/test.c
@@ -20,5 +18,9 @@ verify_passphrase_sig_test_LDADD = $(top
 wrap_unwrap_test_SOURCES = wrap-unwrap/test.c
 wrap_unwrap_test_LDADD = $(top_builddir)/src/libecryptfs/libecryptfs.la
 
-TESTS = verify-passphrase-sig.sh
+v1_to_v2_wrapped_passphrase_test_SOURCES = v1-to-v2-wrapped-passphrase/test.c
+v1_to_v2_wrapped_passphrase_test_LDADD = $(top_builddir)/src/libecryptfs/libecryptfs.la
+
+
+TESTS = verify-passphrase-sig.sh wrap-unwrap.sh v1-to-v2-wrapped-passphrase.sh
 
Index: tests/userspace/v1-to-v2-wrapped-passphrase.sh
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+#
+# v1-to-v2-wrapped-passphrase.sh: Verify that v1 wrapped passphrase files can
+#				   be unwrapped and then rewrapped as v2 files.
+# Author: Tyler Hicks <tyhicks@canonical.com>
+#
+# Copyright (C) 2015 Canonical Ltd.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation version 2
+# of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+test_script_dir=$(dirname $0)
+rc=1
+
+. ${test_script_dir}/../lib/etl_funcs.sh
+
+test_cleanup()
+{
+	etl_remove_test_dir $test_dir
+	exit $rc
+}
+trap test_cleanup 0 1 2 3 15
+
+do_test()
+{
+	${test_script_dir}/v1-to-v2-wrapped-passphrase/test "$@"
+	rc=$?
+	if [ "$rc" -ne 0 ]; then
+		exit
+	fi
+}
+
+test_dir_parent="$TMPDIR"
+if [ -z "$test_dir_parent"]; then
+	test_dir_parent="/tmp"
+fi
+
+test_dir=$(etl_create_test_dir "$test_dir_parent") || exit
+cp "${test_script_dir}/v1-to-v2-wrapped-passphrase/wp"* "$test_dir"
+
+do_test "${test_dir}/wp01" "This is test #1" "Wrapping pass" "0011223344556677"
+
+do_test "${test_dir}/wp02" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" "0011223344556677"
+
+do_test "${test_dir}/wp03" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" "5a175a175a175a17"
+
+do_test "${test_dir}/wp04" "!" "*" "0011223344556677"
+
+do_test "${test_dir}/wp05" "!" "*" "0123456789abcdef"
+
+rc=0
+exit
Index: tests/userspace/v1-to-v2-wrapped-passphrase/test.c
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase/test.c
@@ -0,0 +1,189 @@
+/**
+ * test.c: Verify the migration from version 1 to version 2 wrapped-passphrase
+ * 	   files
+ * Author: Tyler Hicks <tyhicks@canonical.com>
+ *
+ * Copyright (C) 2015 Canonical, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include "../../src/include/ecryptfs.h"
+
+#define ECRYPTFS_MAX_KEY_HEX_BYTES (ECRYPTFS_MAX_KEY_BYTES * 2)
+
+#define NEW_WRAPPING_PASSPHRASE "The *new* eCryptfs wrapping passphrase."
+
+static void usage(const char *name)
+{
+	fprintf(stderr,
+		"%s FILENAME EXPECTED_PASS WRAPPING_PASS WRAPPING_SALT_HEX\n",
+		name);
+}
+
+/**
+ * Returns 0 if the unwrap operation resulted in the expected decrypted
+ * passphrase
+ */
+static int verify_unwrap(char *expected_decrypted_passphrase, char *filename,
+			 char *wrapping_passphrase, char *wrapping_salt)
+{
+	char decrypted_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES + 1];
+	int rc;
+
+	memset(decrypted_passphrase, 0, sizeof(decrypted_passphrase));
+
+	rc = ecryptfs_unwrap_passphrase(decrypted_passphrase, filename,
+					wrapping_passphrase, wrapping_salt);
+	if (rc)
+		return 1;
+
+	if (strcmp(decrypted_passphrase, expected_decrypted_passphrase))
+		return 1;
+
+	return 0;
+}
+
+/**
+ * Returns 0 if the *invalid* unwrap operations always fail
+ */
+static int verify_bad_unwrap(char *expected_decrypted_passphrase, char *filename,
+			     char *wrapping_passphrase, char *wrapping_salt)
+{
+	char *last;
+	int rc;
+
+	/* Increment first char in the wrapping_passphrase and verify that the
+	 * unwrapping operation fails */
+	wrapping_passphrase[0]++;
+	rc = verify_unwrap(expected_decrypted_passphrase, filename,
+			   wrapping_passphrase, wrapping_salt);
+	wrapping_passphrase[0]--;
+	if (!rc)
+		return 1;
+
+	/* Increment last char in the wrapping_passphrase and verify that the
+	 * unwrapping operation fails */
+	last = wrapping_passphrase + (strlen(wrapping_passphrase) - 1);
+	(*last)++;
+	rc = verify_unwrap(expected_decrypted_passphrase, filename,
+			   wrapping_passphrase, wrapping_salt);
+	(*last)--;
+	if (!rc)
+		return 1;
+
+	/* Perform a one's complement on the first char in the salt and verify
+	 * that the unwrapping operation fails */
+	wrapping_salt[0] = ~wrapping_salt[0];
+	rc = verify_unwrap(expected_decrypted_passphrase, filename,
+			   wrapping_passphrase, wrapping_salt);
+	wrapping_salt[0] = ~wrapping_salt[0];
+	if (!rc)
+		return 1;
+
+	/* Perform a one's complement on the last char in the salt and verify
+	 * that the unwrapping operation fails */
+	last = wrapping_salt + (ECRYPTFS_SALT_SIZE - 1);
+	*last = ~(*last);
+	rc = verify_unwrap(expected_decrypted_passphrase, filename,
+			  wrapping_passphrase, wrapping_salt);
+	*last = ~(*last);
+	if (!rc)
+		return 1;
+
+	return 0;
+}
+
+static int do_rewrap(char *filename, char *old_wrapping_passphrase,
+		     char *old_wrapping_salt, char *new_wrapping_passphrase)
+{
+	char decrypted_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES + 1];
+	uint8_t version = 0;
+	int rc;
+
+	memset(decrypted_passphrase, 0, sizeof(decrypted_passphrase));
+
+	rc = ecryptfs_unwrap_passphrase(decrypted_passphrase, filename,
+					old_wrapping_passphrase,
+					old_wrapping_salt);
+	if (rc)
+		return 1;
+
+	rc = ecryptfs_wrap_passphrase(filename, new_wrapping_passphrase, NULL,
+				      decrypted_passphrase);
+	if (rc)
+		return 1;
+
+	rc = __ecryptfs_detect_wrapped_passphrase_file_version(filename,
+							       &version);
+	if (version != 2)
+		return 1;
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	char wrapping_salt[ECRYPTFS_SALT_SIZE];
+	char *expected_decrypted_passphrase, *filename, *wrapping_passphrase,
+	     *wrapping_salt_hex;
+	int rc;
+
+	if (argc != 5) {
+		usage(argv[0]);
+		return EINVAL;
+	}
+
+	filename = argv[1];
+	expected_decrypted_passphrase = argv[2];
+	wrapping_passphrase = argv[3];
+	wrapping_salt_hex = argv[4];
+
+	if (strlen(expected_decrypted_passphrase) > ECRYPTFS_MAX_PASSPHRASE_BYTES ||
+	    strlen(wrapping_passphrase) > ECRYPTFS_MAX_PASSPHRASE_BYTES ||
+	    strlen(wrapping_salt_hex) != ECRYPTFS_SALT_SIZE_HEX) {
+		usage(argv[0]);
+		return EINVAL;
+	}
+
+	from_hex(wrapping_salt, wrapping_salt_hex, ECRYPTFS_SALT_SIZE);
+
+	rc = verify_unwrap(expected_decrypted_passphrase, filename,
+			   wrapping_passphrase, wrapping_salt);
+	if (rc)
+		return 1;
+
+	rc = verify_bad_unwrap(expected_decrypted_passphrase, filename,
+			       wrapping_passphrase, wrapping_salt);
+	if (rc)
+		return 2;
+
+	rc = do_rewrap(filename, wrapping_passphrase, wrapping_salt,
+		       NEW_WRAPPING_PASSPHRASE);
+	if (rc)
+		return 3;
+
+	rc = verify_unwrap(expected_decrypted_passphrase, filename,
+			   NEW_WRAPPING_PASSPHRASE, NULL);
+	if (rc)
+		return 4;
+
+	return 0;
+}
+
Index: tests/userspace/v1-to-v2-wrapped-passphrase/wp01
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase/wp01
@@ -0,0 +1 @@
+6ee51761d91019e7±:³gf¤ã|ºHF]”
\ No newline at end of file
Index: tests/userspace/v1-to-v2-wrapped-passphrase/wp02
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase/wp02
@@ -0,0 +1 @@
+ebe6ff9d87ea09d6ßºùè�Ëµ©îÁ:…ÁÄßºùè�Ëµ©îÁ:…ÁÄßºùè�Ëµ©îÁ:…ÁÄßºùè�Ëµ©îÁ:…ÁÄ
\ No newline at end of file
Index: tests/userspace/v1-to-v2-wrapped-passphrase/wp03
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase/wp03
@@ -0,0 +1 @@
+4cc3757c3f538695R”u'Pƒý2N¤ˆ"_<�R”u'Pƒý2N¤ˆ"_<�R”u'Pƒý2N¤ˆ"_<�R”u'Pƒý2N¤ˆ"_<�
\ No newline at end of file
Index: tests/userspace/v1-to-v2-wrapped-passphrase/wp04
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase/wp04
@@ -0,0 +1 @@
+308b7ec65c69de6b$y­ØÓA|æ6£Ç¿À*É
\ No newline at end of file
Index: tests/userspace/v1-to-v2-wrapped-passphrase/wp05
===================================================================
--- /dev/null
+++ tests/userspace/v1-to-v2-wrapped-passphrase/wp05
@@ -0,0 +1 @@
+bef9457e4740a855Ï³›'964¹÷¬‰¾p
\ No newline at end of file
Index: tests/userspace/wrap-unwrap.sh
===================================================================
--- tests/userspace/wrap-unwrap.sh.orig
+++ tests/userspace/wrap-unwrap.sh
@@ -32,7 +32,12 @@ test_cleanup()
 }
 trap test_cleanup 0 1 2 3 15
 
-test_dir=$(etl_create_test_dir) || exit
+test_dir_parent="$TMPDIR"
+if [ -z "$test_dir_parent"]; then
+	test_dir_parent="/tmp"
+fi
+
+test_dir=$(etl_create_test_dir "$test_dir_parent") || exit
 path="${test_dir}/foo"
 
 ${test_script_dir}/wrap-unwrap/test ${path}
