Logo Search packages:      
Sourcecode: ecryptfs-utils version File versions

ecryptfs_pki_example.c

/**
 * Copyright (C) 2006 International Business Machines Corp.
 * Author(s): Trevor S. Highland <trevor.highland@gmail.com>
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */

#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "../include/ecryptfs.h"
#include "../include/decision_graph.h"

00038 struct pki_openssl {
      char *path;
      char *password;
      char *signature;
};

static int
ecryptfs_openssl_get_pki_data(unsigned char *data, struct pki_openssl *pki_data)
{
      size_t path_length;
      size_t pass_length;
      size_t i = 0;

      path_length = data[i++] % 256;
      path_length += data[i++] << 8;
      i += path_length;
      pass_length = data[i++] % 256;
      pass_length += data[i++] << 8;
      pki_data->path = data + 2;
      pki_data->password = pki_data->path + path_length + 2;
      pki_data->signature = pki_data->password + pass_length + 2;
      return 0;
}

static int generate_signature(RSA *key, char *sig)
{
      int len, nbits, ebits, i;
      int nbytes, ebytes;
      char *hash;
      char *data = NULL;
      int rc = 0;

      hash = malloc(SHA_DIGEST_LENGTH);
      if (!hash) {
            syslog(LOG_ERR, "Out of memory\n");
            rc = -ENOMEM;
            goto out;
      }
      nbits = BN_num_bits(key->n);
      nbytes = nbits / 8;
      if (nbits % 8)
            nbytes++;
      ebits = BN_num_bits(key->e);
      ebytes = ebits / 8;
      if (ebits % 8)
            ebytes++;
      len = 10 + nbytes + ebytes;
      data = malloc(3 + len);
      if (!data) {
            syslog(LOG_ERR, "Out of memory\n");
            rc = -ENOMEM;
            goto out;
      }
      i = 0;
      data[i++] = '\x99';
      data[i++] = (char)(len >> 8);
      data[i++] = (char)len;
      data[i++] = '\x04';
      data[i++] = '\00';
      data[i++] = '\00';
      data[i++] = '\00';
      data[i++] = '\00';
      data[i++] = '\02';
      data[i++] = (char)(nbits >> 8);
      data[i++] = (char)nbits;
      BN_bn2bin(key->n, &(data[i]));
      i += nbytes;
      data[i++] = (char)(ebits >> 8);
      data[i++] = (char)ebits;
      BN_bn2bin(key->e, &(data[i]));
      i += ebytes;
      SHA1(data, len + 3, hash);
      to_hex(sig, hash, ECRYPTFS_SIG_SIZE);
      sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
out:
      free(data);
      free(hash);
      return rc;
}

static int write_key_to_file(RSA *rsa, char *filename, char *pass)
{
      BIO *out;
      const EVP_CIPHER *enc = EVP_aes_256_cbc();
      int rc = 0;

      if ((out = BIO_new(BIO_s_file())) == NULL) {
            syslog(LOG_ERR, "Unable to create BIO for output\n");
            rc= -EIO;
            goto out;
      }
      if (BIO_write_filename(out, filename) <= 0) {
            syslog(LOG_ERR, "Failed to open file for reading\n");
            rc = -EIO;
            goto out;
      }
      if (!PEM_write_bio_RSAPrivateKey(out, rsa, enc, NULL, 0, NULL, pass)) {
            rc = -1;
            syslog(LOG_ERR, "Failed to write key to file\n");
            goto out;
      }
out:
      if (out)
            BIO_free_all(out);
      return rc;
}

static int read_key(RSA **rsa, unsigned char *private_key_data)
{
      struct pki_openssl *pki_data = NULL;
      char *read_key_sig = NULL;
      BIO *in = NULL;
      int rc;

      CRYPTO_malloc_init();
      ERR_load_crypto_strings();
      OpenSSL_add_all_algorithms();
      ENGINE_load_builtin_engines();
      pki_data = malloc(sizeof(struct pki_openssl));
      if (!pki_data) {
            syslog(LOG_ERR, "Out of memory\n");
            rc = -ENOMEM;
            goto out;
      }
      ecryptfs_openssl_get_pki_data(private_key_data, pki_data);
      if ((in = BIO_new(BIO_s_file())) == NULL) {
            syslog(LOG_ERR, "Unable to create BIO for output\n");
            rc = -EIO;
            goto out;
      }
      if (BIO_read_filename(in, pki_data->path) <= 0) {
            syslog(LOG_ERR, "Unable to read filename [%s]\n",
                   pki_data->path);
            rc = -EIO;
            goto out;
      }
      if ((*rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL,
                                     pki_data->password )) == NULL) {
            syslog(LOG_ERR, "Unable to read private key from file [%s]\n",
                   pki_data->password);
            rc = -EIO;
            goto out;
      }
      read_key_sig = malloc(ECRYPTFS_SIG_SIZE_HEX);
      if (!read_key_sig) {
            syslog(LOG_ERR, "Out of memory\n");
            rc = -ENOMEM;
            goto out;
      }
      rc = generate_signature(*rsa, read_key_sig);
      if (strcmp(pki_data->signature, read_key_sig)) {
            syslog(LOG_ERR, "The loaded key has incorrect signature\n");
            rc = -EINVAL;
      }
out:
      free(read_key_sig);
      free(pki_data);
      BIO_free_all(in);
      EVP_cleanup();
      CRYPTO_cleanup_all_ex_data();
      ERR_remove_state(0);
      ERR_free_strings();
      return rc;
}

/* TODO: If sig == NULL, just return *length; the caller can use this
 * information to allocate memory and call again. There should also be
 * a max_length parameter. -Halcrow */
static int ecryptfs_openssl_set_key_data(unsigned char *private_key_data,
                               char *sig, int *length)
{
      struct pki_openssl *pki_data = NULL;
      BIO *in = NULL;
      RSA *rsa = NULL;
      int rc;

      CRYPTO_malloc_init();
      ERR_load_crypto_strings();
      OpenSSL_add_all_algorithms();
      ENGINE_load_builtin_engines();
      pki_data = malloc(sizeof(pki_data));
      if (!pki_data) {
            syslog(LOG_ERR, "Out of memory\n");
            rc = -ENOMEM;
            goto out;
      }
      ecryptfs_openssl_get_pki_data(private_key_data, pki_data);
      if ((in = BIO_new(BIO_s_file())) == NULL) {
            syslog(LOG_ERR, "Unable to create BIO for output\n");
            rc = -EIO;
            goto out;
      }
      if (BIO_read_filename(in, pki_data->path) <= 0) {
            syslog(LOG_ERR, "Unable to read filename [%s]\n",
                   pki_data->path);
            rc = -EIO;
            goto out;
      }
      if ((rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL,
                                    pki_data->password )) == NULL) {
            syslog(LOG_ERR, "Unable to read private key from file\n");
            rc = -EIO;
            goto out;
      }
      *length = RSA_size(rsa);
      rc = generate_signature(rsa, pki_data->signature);
      memcpy(sig, pki_data->signature, ECRYPTFS_SIG_SIZE_HEX + 1);
out:
      free(pki_data);
      RSA_free(rsa);
      BIO_free_all(in);
      EVP_cleanup();
      CRYPTO_cleanup_all_ex_data();
      ERR_remove_state(0);
      ERR_free_strings();
      return rc;
}

static int ecryptfs_openssl_generate_key(char *filename)
{
      RSA *rsa;
      BIGNUM *e;
      int rc = 0;

      rsa = RSA_new();
      if (!rsa) {
            rc = -ENOMEM;
            goto out;
      }
      e = BN_new();
      if (!rsa) {
            rc = -ENOMEM;
            goto out;
      }
      /* Set e to 65537 */
      if (BN_set_bit(e, 0) == 0 || BN_set_bit(e, 16) == 0) {
            rc = -EINVAL;
            goto out;
      }
      rsa = RSA_generate_key(1024, 65537, NULL, NULL);
      if (write_key_to_file(rsa, filename, NULL))
            rc = -EIO;
out:
      BN_free(e);
      RSA_free(rsa);
      if (rc)
            syslog(LOG_ERR, "Failed to write key file rc = [%x]\n", rc);
      return rc;
}

static int ecryptfs_openssl_encrypt(int size, char *from, char *to,
                            unsigned char *private_key_data)
{
      RSA *rsa = NULL;
      int rc;

      rc = read_key(&rsa,  private_key_data);
      if (rc) {
            rc = -(int)ERR_get_error();
            syslog(LOG_ERR, "Error attempting to read RSA key from file;"
                   " rc = [%d]\n", rc);
            goto out;
      }
      rc = RSA_public_encrypt(size, from, to, rsa,
                        RSA_PKCS1_OAEP_PADDING);
      if (rc == -1) {
            rc = -(int)ERR_get_error();
            syslog(LOG_ERR, "Error attempting to perform RSA public key "
                   "encryption; rc = [%d]\n", rc);
      } else {
            rc = 0;
      }
out:
      RSA_free(rsa);
      return rc;
}

/* currently assumes that a single block is passed in for decryption */
static int ecryptfs_openssl_decrypt(char *from, char *to,
                            size_t *decrypted_key_size,
                            unsigned char *private_key_data)
{
      RSA *rsa = NULL;
      int rc;

      rc = read_key(&rsa, private_key_data);
      if (rc) {
            rc = -(int)ERR_get_error();
            syslog(LOG_ERR, "Error attempting to read RSA key from file;"
                   " rc = [%d]\n", rc);
            goto out;
      }
      rc = RSA_private_decrypt(RSA_size(rsa), from, to,
                         rsa, RSA_PKCS1_OAEP_PADDING);
      if (rc == -1) {
            rc = -(int)ERR_get_error();
            syslog(LOG_ERR, "Error attempting to perform RSA public key "
                   "decryption; rc = [%d]\n", rc);
      } else {
            *decrypted_key_size = rc;
            rc = 0;
      }
out:
      RSA_free(rsa);
      return 0;
}

/* TODO: This seems a bit magical. Should it be a NULL mode in a
 * serialize function, perhaps? -Halcrow */
static int
ecryptfs_openssl_get_pki_data_length(struct ecryptfs_name_val_pair *pair)
{
      size_t length;
      char *password;
      char *path;

      while (pair) {
            if (!pair->name)
                  ;
            else if (!strcmp(pair->name, "passphrase"))
                  password = pair->value;
            else if (!strcmp(pair->name, "path"))
                  path = pair->value;
            pair = pair->next;
      }
      if (path) 
            length = (strlen(path) + 3);
      else
            return -1;
      if (password)
            length += (strlen(password) + 3);
      else
            return -1;
      length += (2 + (ECRYPTFS_SIG_SIZE_HEX + 1));
      return length;
}

00375 struct pki_nvp_map_elem {
      char *name;
      uint32_t flags;
};

static struct pki_nvp_map_elem pki_nvp_map[] = {
      {"path", ECRYPTFS_ECHO | ECRYPTFS_DEFAULT_VALUE_SET},
      {"passphrase", ECRYPTFS_MLOCK},
      {NULL, 0}
};

/* TODO: In general, we should be passing the head of the lists
 * around; the head's only job is to provide a pointer to the first
 * real element in the list. Please update this function to reflect
 * that. -Halcrow */
static int ecryptfs_openssl_set_pki_data(struct ecryptfs_name_val_pair *pair,
                               unsigned char *data)
{
      size_t password_length;
      size_t path_length;
      char *password;
      char *path;
      size_t i = 0;

      while (pair) {
            if (!pair->name)
                  ;
            else if (!strcmp(pair->name, "passphrase"))
                  password = pair->value;
            else if (!strcmp(pair->name, "path"))
                  path = pair->value;
            pair = pair->next;
      }
      if (path) {
            path_length = strlen(path) + 1;
            data[i++] = path_length % 256;
            data[i++] = path_length >> 8;
            memcpy(&data[i], path, path_length);
            i += path_length;
      } else {
            return -1;
      }
      if (password) {
            password_length = strlen(password) + 1;
            data[i++] = password_length % 256;
            data[i++] = password_length >> 8;
            memcpy(&data[i], password, password_length);
            i += password_length;
      } else {
            return -1;
      }
      return 0;
}

static int ssl_sig(struct ecryptfs_pki_elem *pki, struct val_node **head)
{
      struct ecryptfs_name_val_pair *openssl_nvp;
      char *sig;
      char *param;
      int rc;

      pki->nvp_head.next = malloc(sizeof(struct ecryptfs_name_val_pair));
      if (!pki->nvp_head.next) {
            rc = -ENOMEM;
            goto out;
      }
      openssl_nvp = pki->nvp_head.next;
      openssl_nvp->name = "passphrase";
      stack_pop_val(head, (void *)&(openssl_nvp->value));
      openssl_nvp->next = malloc(sizeof(struct ecryptfs_name_val_pair));
      if (!openssl_nvp->next) {
            rc = -ENOMEM;
            goto out;
      }
      openssl_nvp = openssl_nvp->next;
      openssl_nvp->name = "path";
      stack_pop_val(head, (void *)&(openssl_nvp->value));
      openssl_nvp->next = NULL;
      sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
      if (!sig) {
            rc = -ENOMEM;
            goto out;
      }
      rc = ecryptfs_add_key_module_key_to_keyring(sig, pki);
      if (rc < 0)
            goto out;
      else
            rc = 0;
      asprintf(&param, "ecryptfs_sig=%s", sig);
      free(sig);
      stack_push(head, param);
out:
      if (rc)
            return MOUNT_ERROR;
      return DEFAULT_TOK;
}

static int tf_ssl_file(struct ecryptfs_ctx *ctx, struct param_node *node,
                   struct val_node **head, void **foo)
{
      stack_push(head, node->val);
      node->val = NULL;
      return DEFAULT_TOK;
}

static int tf_ssl_passwd(struct ecryptfs_ctx *ctx, struct param_node *node,
                   struct val_node **head, void **foo)
{
      stack_push(head, node->val);
      node->val = NULL;
      return ssl_sig((struct ecryptfs_pki_elem *)*foo, head);
}

static int tf_ssl_passfile(struct ecryptfs_ctx *ctx, struct param_node *node,
                     struct val_node **head, void **foo)
{
      int rc = 0;
      char *tmp_val = NULL;
      int fd;
      struct ecryptfs_name_val_pair *file_head = NULL;
      struct ecryptfs_name_val_pair *walker = NULL;

      file_head = malloc(sizeof(struct ecryptfs_name_val_pair));
      if (!file_head) {
            rc = -ENOMEM;
            goto out;
      }
      memset(file_head, 0, sizeof(struct ecryptfs_name_val_pair));
      if (strcmp(node->mnt_opt_names[0], "passfile") == 0)
            fd = open(node->val, O_RDONLY);
      else if (strcmp(node->mnt_opt_names[0], "passfd") == 0)
            fd = strtol(node->val, NULL, 0);
      else {
            rc = MOUNT_ERROR;
            goto out;
      }
      rc = parse_options_file(fd, file_head);
      if (rc) {
            rc = MOUNT_ERROR;
            goto out;
      }
      close(fd);
      walker = file_head->next;
      while (walker) {
            if (strcmp(walker->name, "passwd") == 0) {
                  asprintf(&tmp_val, "%s", walker->value);
                  stack_push(head, tmp_val);
                  break;
            }
            walker = walker->next;
      }
      if (!walker) {
            rc = MOUNT_ERROR;
            goto out;
      }
      free_name_val_pairs(file_head);
      file_head = NULL;
      walker = NULL;
      rc = ssl_sig((struct ecryptfs_pki_elem *)*foo, head);
out:
      free(node->val);
      node->val = NULL;
      return rc;
}

#define OPENSSL_TOK 0
#define SSL_FILE_TOK 1
#define SSL_PASSWD_TOK 2
#define SSL_PASS_FILE_TOK 3
#define SSL_PASS_ENV_TOK 4
#define SSL_PASS_FD_TOK 5
#define SSL_PASS_STDIN_TOK 6
#define SSL_DEFAULT_PASS_TOK 7
static struct param_node ssl_param_nodes[] = {
      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"keyformat"},
       .prompt = "Key format",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = "keyfile",
       .flags = NO_VALUE,
       .num_transitions = 1,
       .tl = {{.val = "default",
             .pretty_val = "OpenSSL Key File",
             .next_token = &ssl_param_nodes[SSL_FILE_TOK],
             .trans_func = NULL}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"keyfile"},
       .prompt = "SSL key file",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .suggested_val = NULL,
       .flags = ECHO_INPUT,
       .num_transitions = 6,
       .tl = {{.val = "passwd",
             .pretty_val = "",
             .next_token = &ssl_param_nodes[SSL_PASSWD_TOK],
             .trans_func = tf_ssl_file},
            {.val = "passfile",
             .pretty_val = "Passphrase File",
             .next_token = &ssl_param_nodes[SSL_PASS_FILE_TOK],
             .trans_func = tf_ssl_file},
            {.val = "passenv",
             .pretty_val = "Passphrase ENV",
             .next_token = &ssl_param_nodes[SSL_PASS_ENV_TOK],
             .trans_func = tf_ssl_file},
            {.val = "passfd",
             .pretty_val = "Passphrase File Descriptor",
             .next_token = &ssl_param_nodes[SSL_PASS_FD_TOK],
             .trans_func = tf_ssl_file},
            {.val = "passstdin",
             .pretty_val = "Passphrase STDIN",
             .next_token = &ssl_param_nodes[SSL_PASS_STDIN_TOK],
             .trans_func = tf_ssl_file},
            {.val = "default",
             .pretty_val = "Passphrase",
             .next_token = &ssl_param_nodes[SSL_DEFAULT_PASS_TOK],
             .trans_func = tf_ssl_file}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"passwd"},
       .prompt = "Passphrase",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .flags = MASK_OUTPUT,
       .num_transitions = 1,
       .tl = {{.val = NULL,
             .pretty_val = NULL,
             .next_token = NULL,
             .trans_func = tf_ssl_passwd}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"passfile"},
       .prompt = "Passphrase",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .flags = MASK_OUTPUT,
       .num_transitions = 1,
       .tl = {{.val = NULL,
             .pretty_val = NULL,
             .next_token = NULL,
             .trans_func = tf_ssl_passfile}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"passenv"},
       .prompt = "Passphrase",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .flags = MASK_OUTPUT,
       .num_transitions = 1,
       .tl = {{.val = NULL,
             .pretty_val = NULL,
             .next_token = NULL,
             .trans_func = tf_ssl_passwd}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"passfd"},
       .prompt = "Passphrase",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .flags = MASK_OUTPUT,
       .num_transitions = 1,
       .tl = {{.val = NULL,
             .pretty_val = NULL,
             .next_token = NULL,
             .trans_func = tf_ssl_passfile}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"passstdin"},
       .prompt = "Passphrase",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .flags = VERIFY_VALUE | STDIN_REQUIRED,
       .num_transitions = 1,
       .tl = {{.val = NULL,
             .pretty_val = NULL,
             .next_token = NULL,
             .trans_func = tf_ssl_passwd}}},

      {.num_mnt_opt_names = 1,
       .mnt_opt_names = {"defaultpass"},
       .prompt = "Passphrase",
       .val_type = VAL_STR,
       .val = NULL,
       .display_opts = NULL,
       .default_val = NULL,
       .flags = STDIN_REQUIRED,
       .num_transitions = 1,
       .tl = {{.val = NULL,
             .pretty_val = NULL,
             .next_token = NULL,
             .trans_func = tf_ssl_passwd}}},
};

static int generate_name_val_list(struct ecryptfs_name_val_pair *head)
{
      struct stat buf;
      int i = 0;
      uid_t id = getuid();
      struct passwd *pw = getpwuid(id);
      int rc = 0;

      while (pki_nvp_map[i].name) {
            head->next = malloc(sizeof(struct ecryptfs_name_val_pair));
            if (!head->next) {
                  rc = -ENOMEM;
                  goto out;
            }
            head = head->next;
            head->name = pki_nvp_map[i].name;
            head->flags = pki_nvp_map[i].flags;
            if (!strcmp(head->name, "path")) {
                  asprintf(&head->value,
                         "%s/.ecryptfs/pki/openssl/key.pem",
                         pw->pw_dir);
                  if (stat(head->value, &buf))
                        head->flags &= ~ECRYPTFS_DEFAULT_VALUE_SET;
                  asprintf(&ssl_param_nodes[SSL_FILE_TOK].suggested_val,
                         "%s/.ecryptfs/pki/openssl/key.pem",
                         pw->pw_dir);
            }
            i++;
      }
      head->next = NULL;
out:
      return rc;
}

static int tf_openssl_enter(struct ecryptfs_ctx *ctx, struct param_node *node,
                      struct val_node **head, void **foo)
{
      int rc;
      rc = ecryptfs_find_pki(ctx, node->val,
                         (struct ecryptfs_pki_elem **)foo);
      return rc;
}

struct transition_node openssl_transition = {
      .val = "openssl",
      .pretty_val = "OpenSSL module",
      .next_token = &(ssl_param_nodes[0]),
      .trans_func = tf_openssl_enter
};

static int ecryptfs_openssl_get_param_subgraph_trans_node(
      struct transition_node **trans, uint32_t version)
{
      if ((version & ECRYPTFS_VERSIONING_PUBKEY) == 0)
            return -1;
      *trans = &openssl_transition;
      return 0;
}

int destruct_pki(void)
{
      if (ssl_param_nodes[SSL_FILE_TOK].suggested_val)
            free(ssl_param_nodes[SSL_FILE_TOK].suggested_val);
}

/**
 * init_pki
 * @pki_name: ...
 * @pki: ...
 *
 * This is the function that
 * src/libecryptfs/pki_list.c::ecryptfs_get_pki_list() calls when
 * initializing key modules.
 *
 * Returns zero on success; non-zero on error
 */
int init_pki(char **pki_name, struct ecryptfs_pki_elem *pki)
{
      struct ecryptfs_pki_ops example_ops = {
            &ecryptfs_example_set_key_data,
            &ecryptfs_example_generate_key,
            &ecryptfs_example_encrypt,
            &ecryptfs_example_decrypt,
            &ecryptfs_example_get_pki_data_length,
            &ecryptfs_example_set_pki_data,
            &ecryptfs_example_get_param_subgraph_trans_node
      };
      int rc;

      rc = generate_name_val_list(&pki->nvp_head);
      if (rc) {
            syslog(LOG_ERR, "Error attempting to generate name/val list; "
                   "rc = [%d]\n", rc);
            goto out;
      }
      if (asprintf(pki_name, "example") == -1) {
            rc = -ENOMEM;
            ecryptfs_syslog(LOG_ERR, "Out of memory\n");
            goto out;
      }
      memcpy(&pki->ops, &example_ops, sizeof(struct ecryptfs_pki_ops));
out:
      return rc;
}

Generated by  Doxygen 1.6.0   Back to index