resolved conflicts for merge of 88aba541 to lmp-mr1-dev-plus-aosp

Change-Id: Ie5ef819dd8168cb6a73f84a881a92c116705fffc
diff --git a/Android.mk b/Android.mk
index f7e8170..532a843 100644
--- a/Android.mk
+++ b/Android.mk
@@ -81,6 +81,13 @@
 LOCAL_C_INCLUDES := $(common_c_includes)
 LOCAL_CFLAGS := $(vold_cflags)
 LOCAL_CONLYFLAGS := $(vold_conlyflags)
+
+ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
+LOCAL_C_INCLUDES += $(TARGET_CRYPTFS_HW_PATH)
+common_shared_libraries += libcryptfs_hw
+LOCAL_CFLAGS += -DCONFIG_HW_DISK_ENCRYPTION
+endif
+
 LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
 LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
 
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 261da8e..df4c627 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -645,17 +645,33 @@
         SLOGD("cryptfs verifypw {}");
         rc = cryptfs_verify_passwd(argv[2]);
     } else if (!strcmp(argv[1], "getfield")) {
-        char valbuf[PROPERTY_VALUE_MAX];
+        char *valbuf;
+        int valbuf_len = PROPERTY_VALUE_MAX;
 
         if (argc != 3) {
             cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs getfield <fieldname>", false);
             return 0;
         }
         dumpArgs(argc, argv, -1);
-        rc = cryptfs_getfield(argv[2], valbuf, sizeof(valbuf));
-        if (rc == 0) {
+
+        // Increase the buffer size until it is big enough for the field value stored.
+        while (1) {
+            valbuf = (char*)malloc(valbuf_len);
+            if (valbuf == NULL) {
+                cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", false);
+                return 0;
+            }
+            rc = cryptfs_getfield(argv[2], valbuf, valbuf_len);
+            if (rc != CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL) {
+                break;
+            }
+            free(valbuf);
+            valbuf_len *= 2;
+        }
+        if (rc == CRYPTO_GETFIELD_OK) {
             cli->sendMsg(ResponseCode::CryptfsGetfieldResult, valbuf, false);
         }
+        free(valbuf);
     } else if (!strcmp(argv[1], "setfield")) {
         if (argc != 4) {
             cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs setfield <fieldname> <value>", false);
@@ -693,8 +709,14 @@
         dumpArgs(argc, argv, -1);
         char* password = cryptfs_get_password();
         if (password) {
-            cli->sendMsg(ResponseCode::CommandOkay, password, false);
-            return 0;
+            char* message = 0;
+            int size = asprintf(&message, "{{sensitive}} %s", password);
+            if (size != -1) {
+                cli->sendMsg(ResponseCode::CommandOkay, message, false);
+                memset(message, 0, size);
+                free (message);
+                return 0;
+            }
         }
         rc = -1;
     } else if (!strcmp(argv[1], "clearpw")) {
diff --git a/cryptfs.c b/cryptfs.c
index aaa2b86..9c84fe5 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -41,6 +41,7 @@
 #include <linux/kdev_t.h>
 #include <fs_mgr.h>
 #include <time.h>
+#include <math.h>
 #include "cryptfs.h"
 #define LOG_TAG "Cryptfs"
 #include "cutils/log.h"
@@ -62,6 +63,10 @@
 
 #define UNUSED __attribute__((unused))
 
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+#include "cryptfs_hw.h"
+#endif
+
 #define DM_CRYPT_BUF_SIZE 4096
 
 #define HASH_COUNT 2000
@@ -137,7 +142,8 @@
         goto out;
     }
 
-    if (keymaster_dev->flags & KEYMASTER_BLOBS_ARE_STANDALONE) {
+    if (!(keymaster_dev->flags & KEYMASTER_SOFTWARE_ONLY) &&
+        (keymaster_dev->flags & KEYMASTER_BLOBS_ARE_STANDALONE)) {
         rc = 1;
     }
 
@@ -989,7 +995,16 @@
   tgt->status = 0;
   tgt->sector_start = 0;
   tgt->length = crypt_ftr->fs_size;
-  strcpy(tgt->target_type, "crypt");
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+  if (!strcmp((char *)crypt_ftr->crypto_type_name, "aes-xts")) {
+    strlcpy(tgt->target_type, "req-crypt", DM_MAX_TYPE_NAME);
+  }
+  else {
+    strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
+  }
+#else
+  strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
+#endif
 
   crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
   convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
@@ -1034,7 +1049,11 @@
      */
     v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)];
     while (v->next) {
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+        if (! strcmp(v->name, "crypt") || ! strcmp(v->name, "req-crypt")) {
+#else
         if (! strcmp(v->name, "crypt")) {
+#endif
             /* We found the crypt driver, return the version, and get out */
             version[0] = v->version[0];
             version[1] = v->version[1];
@@ -1053,7 +1072,7 @@
   char buffer[DM_CRYPT_BUF_SIZE];
   struct dm_ioctl *io;
   unsigned int minor;
-  int fd;
+  int fd=0;
   int retval = -1;
   int version[3];
   char *extra_params;
@@ -1736,6 +1755,14 @@
 
   fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+  if (!strcmp((char *)crypt_ftr->crypto_type_name, "aes-xts")) {
+    if(!set_hw_device_encryption_key(passwd, (char*) crypt_ftr->crypto_type_name)) {
+      SLOGE("Hardware encryption key does not match");
+    }
+  }
+#endif
+
   // Create crypto block device - all (non fatal) code paths
   // need it
   if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
@@ -1882,7 +1909,10 @@
     create_crypto_blk_dev(&sd_crypt_ftr, saved_master_key, real_blkdev, 
                           crypto_blkdev, label);
 
-    stat(crypto_blkdev, &statbuf);
+    if (stat(crypto_blkdev, &statbuf) < 0) {
+        SLOGE("Error get stat for crypto_blkdev %s. err=%d(%s)\n",
+              crypto_blkdev, errno, strerror(errno));
+    }
     *new_major = MAJOR(statbuf.st_rdev);
     *new_minor = MINOR(statbuf.st_rdev);
 
@@ -2182,7 +2212,11 @@
 /* aligned 32K writes tends to make flash happy.
  * SD card association recommends it.
  */
+#ifndef CONFIG_HW_DISK_ENCRYPTION
 #define BLOCKS_AT_A_TIME 8
+#else
+#define BLOCKS_AT_A_TIME 1024
+#endif
 
 struct encryptGroupsData
 {
@@ -3040,16 +3074,6 @@
          * restart the graphics services.
          */
         sleep(2);
-
-        /* startup service classes main and late_start */
-        property_set("vold.decrypt", "trigger_restart_min_framework");
-        SLOGD("Just triggered restart_min_framework\n");
-
-        /* OK, the framework is restarted and will soon be showing a
-         * progress bar.  Time to setup an encrypted mapping, and
-         * either write a new filesystem, or encrypt in place updating
-         * the progress bar as we work.
-         */
     }
 
     /* Start the actual work of making an encrypted filesystem */
@@ -3071,7 +3095,23 @@
            On successfully completing encryption, remove this flag */
         crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
         crypt_ftr.crypt_type = crypt_type;
-        strcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256");
+#ifndef CONFIG_HW_DISK_ENCRYPTION
+        strlcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256", MAX_CRYPTO_TYPE_NAME_LEN);
+#else
+        strlcpy((char *)crypt_ftr.crypto_type_name, "aes-xts", MAX_CRYPTO_TYPE_NAME_LEN);
+
+        rc = clear_hw_device_encryption_key();
+        if (!rc) {
+          SLOGE("Error clearing device encryption hardware key. rc = %d", rc);
+        }
+
+        rc = set_hw_device_encryption_key(passwd,
+                                          (char*) crypt_ftr.crypto_type_name);
+        if (!rc) {
+          SLOGE("Error initializing device encryption hardware key. rc = %d", rc);
+          goto error_shutting_down;
+        }
+#endif
 
         /* Make an encrypted master key */
         if (create_encrypted_random_key(passwd, crypt_ftr.master_key, crypt_ftr.salt, &crypt_ftr)) {
@@ -3097,6 +3137,18 @@
         }
     }
 
+    if (how == CRYPTO_ENABLE_INPLACE) {
+        /* startup service classes main and late_start */
+        property_set("vold.decrypt", "trigger_restart_min_framework");
+        SLOGD("Just triggered restart_min_framework\n");
+
+        /* OK, the framework is restarted and will soon be showing a
+         * progress bar.  Time to setup an encrypted mapping, and
+         * either write a new filesystem, or encrypt in place updating
+         * the progress bar as we work.
+         */
+    }
+
     decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
     create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
                           "userdata");
@@ -3121,7 +3173,8 @@
     }
 
     /* Calculate checksum if we are not finished */
-    if (!rc && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
+    if (!rc && how == CRYPTO_ENABLE_INPLACE
+            && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
         rc = cryptfs_SHA256_fileblock(crypto_blkdev,
                                       crypt_ftr.hash_first_block);
         if (rc) {
@@ -3139,7 +3192,8 @@
         /* Success */
         crypt_ftr.flags &= ~CRYPT_INCONSISTENT_STATE;
 
-        if (crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
+        if (how == CRYPTO_ENABLE_INPLACE
+              && crypt_ftr.encrypted_upto != crypt_ftr.fs_size) {
             SLOGD("Encrypted up to sector %lld - will continue after reboot",
                   crypt_ftr.encrypted_upto);
             crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS;
@@ -3147,7 +3201,8 @@
 
         put_crypt_ftr_and_key(&crypt_ftr);
 
-        if (crypt_ftr.encrypted_upto == crypt_ftr.fs_size) {
+        if (how == CRYPTO_ENABLE_WIPE
+              || crypt_ftr.encrypted_upto == crypt_ftr.fs_size) {
           char value[PROPERTY_VALUE_MAX];
           property_get("ro.crypto.state", value, "");
           if (!strcmp(value, "")) {
@@ -3281,10 +3336,49 @@
     put_crypt_ftr_and_key(&crypt_ftr);
 
     free(adjusted_passwd);
+
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+    if (!strcmp((char *)crypt_ftr.crypto_type_name, "aes-xts")) {
+        if (crypt_type == CRYPT_TYPE_DEFAULT) {
+            int rc = update_hw_device_encryption_key(DEFAULT_PASSWORD, (char*) crypt_ftr.crypto_type_name);
+            SLOGD("Update hardware encryption key to default for crypt_type: %d. rc = %d", crypt_type, rc);
+            if (!rc)
+                return -1;
+        } else {
+            int rc = update_hw_device_encryption_key(newpw, (char*) crypt_ftr.crypto_type_name);
+            SLOGD("Update hardware encryption key for crypt_type: %d. rc = %d", crypt_type, rc);
+            if (!rc)
+                return -1;
+        }
+    }
+#endif
     return 0;
 }
 
-static int persist_get_key(char *fieldname, char *value)
+static unsigned int persist_get_max_entries(int encrypted) {
+    struct crypt_mnt_ftr crypt_ftr;
+    unsigned int dsize;
+    unsigned int max_persistent_entries;
+
+    /* If encrypted, use the values from the crypt_ftr, otherwise
+     * use the values for the current spec.
+     */
+    if (encrypted) {
+        if (get_crypt_ftr_and_key(&crypt_ftr)) {
+            return -1;
+        }
+        dsize = crypt_ftr.persist_data_size;
+    } else {
+        dsize = CRYPT_PERSIST_DATA_SIZE;
+    }
+
+    max_persistent_entries = (dsize - sizeof(struct crypt_persist_data)) /
+        sizeof(struct crypt_persist_entry);
+
+    return max_persistent_entries;
+}
+
+static int persist_get_key(const char *fieldname, char *value)
 {
     unsigned int i;
 
@@ -3302,31 +3396,17 @@
     return -1;
 }
 
-static int persist_set_key(char *fieldname, char *value, int encrypted)
+static int persist_set_key(const char *fieldname, const char *value, int encrypted)
 {
     unsigned int i;
     unsigned int num;
-    struct crypt_mnt_ftr crypt_ftr;
     unsigned int max_persistent_entries;
-    unsigned int dsize;
 
     if (persist_data == NULL) {
         return -1;
     }
 
-    /* If encrypted, use the values from the crypt_ftr, otherwise
-     * use the values for the current spec.
-     */
-    if (encrypted) {
-        if(get_crypt_ftr_and_key(&crypt_ftr)) {
-            return -1;
-        }
-        dsize = crypt_ftr.persist_data_size;
-    } else {
-        dsize = CRYPT_PERSIST_DATA_SIZE;
-    }
-    max_persistent_entries = (dsize - sizeof(struct crypt_persist_data)) /
-                             sizeof(struct crypt_persist_entry);
+    max_persistent_entries = persist_get_max_entries(encrypted);
 
     num = persist_data->persist_valid_entries;
 
@@ -3351,14 +3431,108 @@
     return -1;
 }
 
+/**
+ * Test if key is part of the multi-entry (field, index) sequence. Return non-zero if key is in the
+ * sequence and its index is greater than or equal to index. Return 0 otherwise.
+ */
+static int match_multi_entry(const char *key, const char *field, unsigned index) {
+    unsigned int i;
+    unsigned int field_len;
+    unsigned int key_index;
+    field_len = strlen(field);
+
+    if (index == 0) {
+        // The first key in a multi-entry field is just the filedname itself.
+        if (!strcmp(key, field)) {
+            return 1;
+        }
+    }
+    // Match key against "%s_%d" % (field, index)
+    if (strlen(key) < field_len + 1 + 1) {
+        // Need at least a '_' and a digit.
+        return 0;
+    }
+    if (strncmp(key, field, field_len)) {
+        // If the key does not begin with field, it's not a match.
+        return 0;
+    }
+    if (1 != sscanf(&key[field_len],"_%d", &key_index)) {
+        return 0;
+    }
+    return key_index >= index;
+}
+
+/*
+ * Delete entry/entries from persist_data. If the entries are part of a multi-segment field, all
+ * remaining entries starting from index will be deleted.
+ * returns PERSIST_DEL_KEY_OK if deletion succeeds,
+ * PERSIST_DEL_KEY_ERROR_NO_FIELD if the field does not exist,
+ * and PERSIST_DEL_KEY_ERROR_OTHER if error occurs.
+ *
+ */
+static int persist_del_keys(const char *fieldname, unsigned index)
+{
+    unsigned int i;
+    unsigned int j;
+    unsigned int num;
+
+    if (persist_data == NULL) {
+        return PERSIST_DEL_KEY_ERROR_OTHER;
+    }
+
+    num = persist_data->persist_valid_entries;
+
+    j = 0; // points to the end of non-deleted entries.
+    // Filter out to-be-deleted entries in place.
+    for (i = 0; i < num; i++) {
+        if (!match_multi_entry(persist_data->persist_entry[i].key, fieldname, index)) {
+            persist_data->persist_entry[j] = persist_data->persist_entry[i];
+            j++;
+        }
+    }
+
+    if (j < num) {
+        persist_data->persist_valid_entries = j;
+        // Zeroise the remaining entries
+        memset(&persist_data->persist_entry[j], 0, (num - j) * sizeof(struct crypt_persist_entry));
+        return PERSIST_DEL_KEY_OK;
+    } else {
+        // Did not find an entry matching the given fieldname
+        return PERSIST_DEL_KEY_ERROR_NO_FIELD;
+    }
+}
+
+static int persist_count_keys(const char *fieldname)
+{
+    unsigned int i;
+    unsigned int count;
+
+    if (persist_data == NULL) {
+        return -1;
+    }
+
+    count = 0;
+    for (i = 0; i < persist_data->persist_valid_entries; i++) {
+        if (match_multi_entry(persist_data->persist_entry[i].key, fieldname, 0)) {
+            count++;
+        }
+    }
+
+    return count;
+}
+
 /* Return the value of the specified field. */
-int cryptfs_getfield(char *fieldname, char *value, int len)
+int cryptfs_getfield(const char *fieldname, char *value, int len)
 {
     char temp_value[PROPERTY_VALUE_MAX];
-    /* 0 is success, 1 is not encrypted,
-     * -1 is value not set, -2 is any other error
+    /* CRYPTO_GETFIELD_OK is success,
+     * CRYPTO_GETFIELD_ERROR_NO_FIELD is value not set,
+     * CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL is buffer (as given by len) too small,
+     * CRYPTO_GETFIELD_ERROR_OTHER is any other error
      */
-    int rc = -2;
+    int rc = CRYPTO_GETFIELD_ERROR_OTHER;
+    int i;
+    char temp_field[PROPERTY_KEY_MAX];
 
     if (persist_data == NULL) {
         load_persistent_data();
@@ -3368,13 +3542,40 @@
         }
     }
 
+    // Read value from persistent entries. If the original value is split into multiple entries,
+    // stitch them back together.
     if (!persist_get_key(fieldname, temp_value)) {
-        /* We found it, copy it to the caller's buffer and return */
-        strlcpy(value, temp_value, len);
-        rc = 0;
+        // We found it, copy it to the caller's buffer and keep going until all entries are read.
+        if (strlcpy(value, temp_value, len) >= (unsigned) len) {
+            // value too small
+            rc = CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
+            goto out;
+        }
+        rc = CRYPTO_GETFIELD_OK;
+
+        for (i = 1; /* break explicitly */; i++) {
+            if (snprintf(temp_field, sizeof(temp_field), "%s_%d", fieldname, i) >=
+                    (int) sizeof(temp_field)) {
+                // If the fieldname is very long, we stop as soon as it begins to overflow the
+                // maximum field length. At this point we have in fact fully read out the original
+                // value because cryptfs_setfield would not allow fields with longer names to be
+                // written in the first place.
+                break;
+            }
+            if (!persist_get_key(temp_field, temp_value)) {
+                  if (strlcat(value, temp_value, len) >= (unsigned)len) {
+                      // value too small.
+                      rc = CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL;
+                      goto out;
+                  }
+            } else {
+                // Exhaust all entries.
+                break;
+            }
+        }
     } else {
         /* Sadness, it's not there.  Return the error */
-        rc = -1;
+        rc = CRYPTO_GETFIELD_ERROR_NO_FIELD;
     }
 
 out:
@@ -3382,12 +3583,16 @@
 }
 
 /* Set the value of the specified field. */
-int cryptfs_setfield(char *fieldname, char *value)
+int cryptfs_setfield(const char *fieldname, const char *value)
 {
     char encrypted_state[PROPERTY_VALUE_MAX];
-    /* 0 is success, -1 is an error */
-    int rc = -1;
+    /* 0 is success, negative values are error */
+    int rc = CRYPTO_SETFIELD_ERROR_OTHER;
     int encrypted = 0;
+    unsigned int field_id;
+    char temp_field[PROPERTY_KEY_MAX];
+    unsigned int num_entries;
+    unsigned int max_keylen;
 
     if (persist_data == NULL) {
         load_persistent_data();
@@ -3402,10 +3607,52 @@
         encrypted = 1;
     }
 
-    if (persist_set_key(fieldname, value, encrypted)) {
+    // Compute the number of entries required to store value, each entry can store up to
+    // (PROPERTY_VALUE_MAX - 1) chars
+    if (strlen(value) == 0) {
+        // Empty value also needs one entry to store.
+        num_entries = 1;
+    } else {
+        num_entries = (strlen(value) + (PROPERTY_VALUE_MAX - 1) - 1) / (PROPERTY_VALUE_MAX - 1);
+    }
+
+    max_keylen = strlen(fieldname);
+    if (num_entries > 1) {
+        // Need an extra "_%d" suffix.
+        max_keylen += 1 + log10(num_entries);
+    }
+    if (max_keylen > PROPERTY_KEY_MAX - 1) {
+        rc = CRYPTO_SETFIELD_ERROR_FIELD_TOO_LONG;
         goto out;
     }
 
+    // Make sure we have enough space to write the new value
+    if (persist_data->persist_valid_entries + num_entries - persist_count_keys(fieldname) >
+        persist_get_max_entries(encrypted)) {
+        rc = CRYPTO_SETFIELD_ERROR_VALUE_TOO_LONG;
+        goto out;
+    }
+
+    // Now that we know persist_data has enough space for value, let's delete the old field first
+    // to make up space.
+    persist_del_keys(fieldname, 0);
+
+    if (persist_set_key(fieldname, value, encrypted)) {
+        // fail to set key, should not happen as we have already checked the available space
+        SLOGE("persist_set_key() error during setfield()");
+        goto out;
+    }
+
+    for (field_id = 1; field_id < num_entries; field_id++) {
+        snprintf(temp_field, sizeof(temp_field), "%s_%d", fieldname, field_id);
+
+        if (persist_set_key(temp_field, value + field_id * (PROPERTY_VALUE_MAX - 1), encrypted)) {
+            // fail to set key, should not happen as we have already checked the available space.
+            SLOGE("persist_set_key() error during setfield()");
+            goto out;
+        }
+    }
+
     /* If we are running encrypted, save the persistent data now */
     if (encrypted) {
         if (save_persistent_data()) {
@@ -3414,7 +3661,7 @@
         }
     }
 
-    rc = 0;
+    rc = CRYPTO_SETFIELD_OK;
 
 out:
     return rc;
@@ -3477,7 +3724,7 @@
 char* cryptfs_get_password()
 {
     struct timespec now;
-    clock_gettime(CLOCK_MONOTONIC, &now);
+    clock_gettime(CLOCK_BOOTTIME, &now);
     if (now.tv_sec < password_expiry_time) {
         return password;
     } else {
diff --git a/cryptfs.h b/cryptfs.h
index 66e0b4c..d873c26 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -201,6 +201,23 @@
 #define ENABLE_INPLACE_ERR_OTHER -1
 #define ENABLE_INPLACE_ERR_DEV -2  /* crypto_blkdev issue */
 
+/* Return values for cryptfs_getfield */
+#define CRYPTO_GETFIELD_OK                   0
+#define CRYPTO_GETFIELD_ERROR_NO_FIELD      -1
+#define CRYPTO_GETFIELD_ERROR_OTHER         -2
+#define CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL -3
+
+/* Return values for cryptfs_setfield */
+#define CRYPTO_SETFIELD_OK                    0
+#define CRYPTO_SETFIELD_ERROR_OTHER          -1
+#define CRYPTO_SETFIELD_ERROR_FIELD_TOO_LONG -2
+#define CRYPTO_SETFIELD_ERROR_VALUE_TOO_LONG -3
+
+/* Return values for persist_del_key */
+#define PERSIST_DEL_KEY_OK                 0
+#define PERSIST_DEL_KEY_ERROR_OTHER       -1
+#define PERSIST_DEL_KEY_ERROR_NO_FIELD    -2
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -219,8 +236,8 @@
                            char *crypto_dev_path, unsigned int max_pathlen,
                            int *new_major, int *new_minor);
   int cryptfs_revert_volume(const char *label);
-  int cryptfs_getfield(char *fieldname, char *value, int len);
-  int cryptfs_setfield(char *fieldname, char *value);
+  int cryptfs_getfield(const char *fieldname, char *value, int len);
+  int cryptfs_setfield(const char *fieldname, const char *value);
   int cryptfs_mount_default_encrypted(void);
   int cryptfs_get_password_type(void);
   char* cryptfs_get_password(void);