From b1509f22892dc98057c750e7fae39ded5cea3b09 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Sat, 19 May 2012 18:01:32 +0000 Subject: added MirOTR git-svn-id: http://svn.miranda-ng.org/main/trunk@83 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirOTR/libgcrypt-1.4.6/cipher/ac.c | 3301 ++++++++++++++++++++++++++++ 1 file changed, 3301 insertions(+) create mode 100644 plugins/MirOTR/libgcrypt-1.4.6/cipher/ac.c (limited to 'plugins/MirOTR/libgcrypt-1.4.6/cipher/ac.c') diff --git a/plugins/MirOTR/libgcrypt-1.4.6/cipher/ac.c b/plugins/MirOTR/libgcrypt-1.4.6/cipher/ac.c new file mode 100644 index 0000000000..ee9498b23d --- /dev/null +++ b/plugins/MirOTR/libgcrypt-1.4.6/cipher/ac.c @@ -0,0 +1,3301 @@ +/* ac.c - Alternative interface for asymmetric cryptography. + Copyright (C) 2003, 2004, 2005, 2006 + 2007, 2008 Free Software Foundation, Inc. + + This file is part of Libgcrypt. + + Libgcrypt is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser general Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + Libgcrypt 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "mpi.h" + + + +/* At the moment the ac interface is a wrapper around the pk + interface, but this might change somewhen in the future, depending + on how many people prefer the ac interface. */ + +/* Mapping of flag numbers to the according strings as it is expected + for S-expressions. */ +static struct number_string +{ + int number; + const char *string; +} ac_flags[] = + { + { GCRY_AC_FLAG_NO_BLINDING, "no-blinding" }, + }; + +/* The positions in this list correspond to the values contained in + the gcry_ac_key_type_t enumeration list. */ +static const char *ac_key_identifiers[] = + { + "private-key", + "public-key" + }; + +/* These specifications are needed for key-pair generation; the caller + is allowed to pass additional, algorithm-specific `specs' to + gcry_ac_key_pair_generate. This list is used for decoding the + provided values according to the selected algorithm. */ +struct gcry_ac_key_generate_spec +{ + int algorithm; /* Algorithm for which this flag is + relevant. */ + const char *name; /* Name of this flag. */ + size_t offset; /* Offset in the cipher-specific spec + structure at which the MPI value + associated with this flag is to be + found. */ +} ac_key_generate_specs[] = + { + { GCRY_AC_RSA, "rsa-use-e", offsetof (gcry_ac_key_spec_rsa_t, e) }, + { 0 } + }; + +/* Handle structure. */ +struct gcry_ac_handle +{ + int algorithm; /* Algorithm ID associated with this + handle. */ + const char *algorithm_name; /* Name of the algorithm. */ + unsigned int flags; /* Flags, not used yet. */ + gcry_module_t module; /* Reference to the algorithm + module. */ +}; + +/* A named MPI value. */ +typedef struct gcry_ac_mpi +{ + char *name; /* Self-maintained copy of name. */ + gcry_mpi_t mpi; /* MPI value. */ + unsigned int flags; /* Flags. */ +} gcry_ac_mpi_t; + +/* A data set, that is simply a list of named MPI values. */ +struct gcry_ac_data +{ + gcry_ac_mpi_t *data; /* List of named values. */ + unsigned int data_n; /* Number of values in DATA. */ +}; + +/* A single key. */ +struct gcry_ac_key +{ + gcry_ac_data_t data; /* Data in native ac structure. */ + gcry_ac_key_type_t type; /* Type of the key. */ +}; + +/* A key pair. */ +struct gcry_ac_key_pair +{ + gcry_ac_key_t public; + gcry_ac_key_t secret; +}; + + + +/* + * Functions for working with data sets. + */ + +/* Creates a new, empty data set and store it in DATA. */ +gcry_error_t +_gcry_ac_data_new (gcry_ac_data_t *data) +{ + gcry_ac_data_t data_new; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + data_new = gcry_malloc (sizeof (*data_new)); + if (! data_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + data_new->data = NULL; + data_new->data_n = 0; + *data = data_new; + err = 0; + + out: + + return err; +} + +/* Destroys all the entries in DATA, but not DATA itself. */ +static void +ac_data_values_destroy (gcry_ac_data_t data) +{ + unsigned int i; + + for (i = 0; i < data->data_n; i++) + if (data->data[i].flags & GCRY_AC_FLAG_DEALLOC) + { + gcry_mpi_release (data->data[i].mpi); + gcry_free (data->data[i].name); + } +} + +/* Destroys the data set DATA. */ +void +_gcry_ac_data_destroy (gcry_ac_data_t data) +{ + if (data) + { + ac_data_values_destroy (data); + gcry_free (data->data); + gcry_free (data); + } +} + +/* This function creates a copy of the array of named MPIs DATA_MPIS, + which is of length DATA_MPIS_N; the copy is stored in + DATA_MPIS_CP. */ +static gcry_error_t +ac_data_mpi_copy (gcry_ac_mpi_t *data_mpis, unsigned int data_mpis_n, + gcry_ac_mpi_t **data_mpis_cp) +{ + gcry_ac_mpi_t *data_mpis_new; + gcry_error_t err; + unsigned int i; + gcry_mpi_t mpi; + char *label; + + data_mpis_new = gcry_malloc (sizeof (*data_mpis_new) * data_mpis_n); + if (! data_mpis_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + memset (data_mpis_new, 0, sizeof (*data_mpis_new) * data_mpis_n); + + err = 0; + for (i = 0; i < data_mpis_n; i++) + { + /* Copy values. */ + + label = gcry_strdup (data_mpis[i].name); + mpi = gcry_mpi_copy (data_mpis[i].mpi); + if (! (label && mpi)) + { + err = gcry_error_from_errno (errno); + gcry_mpi_release (mpi); + gcry_free (label); + break; + } + + data_mpis_new[i].flags = GCRY_AC_FLAG_DEALLOC; + data_mpis_new[i].name = label; + data_mpis_new[i].mpi = mpi; + } + if (err) + goto out; + + *data_mpis_cp = data_mpis_new; + err = 0; + + out: + + if (err) + if (data_mpis_new) + { + for (i = 0; i < data_mpis_n; i++) + { + gcry_mpi_release (data_mpis_new[i].mpi); + gcry_free (data_mpis_new[i].name); + } + gcry_free (data_mpis_new); + } + + return err; +} + +/* Create a copy of the data set DATA and store it in DATA_CP. */ +gcry_error_t +_gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data) +{ + gcry_ac_mpi_t *data_mpis = NULL; + gcry_ac_data_t data_new; + gcry_error_t err; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Allocate data set. */ + data_new = gcry_malloc (sizeof (*data_new)); + if (! data_new) + { + err = gcry_error_from_errno (errno); + goto out; + } + + err = ac_data_mpi_copy (data->data, data->data_n, &data_mpis); + if (err) + goto out; + + data_new->data_n = data->data_n; + data_new->data = data_mpis; + *data_cp = data_new; + + out: + + if (err) + gcry_free (data_new); + + return err; +} + +/* Returns the number of named MPI values inside of the data set + DATA. */ +unsigned int +_gcry_ac_data_length (gcry_ac_data_t data) +{ + return data->data_n; +} + + +/* Add the value MPI to DATA with the label NAME. If FLAGS contains + GCRY_AC_FLAG_COPY, the data set will contain copies of NAME + and MPI. If FLAGS contains GCRY_AC_FLAG_DEALLOC or + GCRY_AC_FLAG_COPY, the values contained in the data set will + be deallocated when they are to be removed from the data set. */ +gcry_error_t +_gcry_ac_data_set (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t mpi) +{ + gcry_error_t err; + gcry_mpi_t mpi_cp; + char *name_cp; + unsigned int i; + + name_cp = NULL; + mpi_cp = NULL; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & ~(GCRY_AC_FLAG_DEALLOC | GCRY_AC_FLAG_COPY)) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + if (flags & GCRY_AC_FLAG_COPY) + { + /* Create copies. */ + + flags |= GCRY_AC_FLAG_DEALLOC; + name_cp = gcry_strdup (name); + mpi_cp = gcry_mpi_copy (mpi); + if (! (name_cp && mpi_cp)) + { + err = gcry_error_from_errno (errno); + goto out; + } + } + + /* Search for existing entry. */ + for (i = 0; i < data->data_n; i++) + if (! strcmp (name, data->data[i].name)) + break; + if (i < data->data_n) + { + /* An entry for NAME does already exist. */ + if (data->data[i].flags & GCRY_AC_FLAG_DEALLOC) + { + gcry_mpi_release (data->data[i].mpi); + gcry_free (data->data[i].name); + } + } + else + { + /* Create a new entry. */ + + gcry_ac_mpi_t *ac_mpis; + + ac_mpis = gcry_realloc (data->data, + sizeof (*data->data) * (data->data_n + 1)); + if (! ac_mpis) + { + err = gcry_error_from_errno (errno); + goto out; + } + + if (data->data != ac_mpis) + data->data = ac_mpis; + data->data_n++; + } + + data->data[i].name = name_cp ? name_cp : ((char *) name); + data->data[i].mpi = mpi_cp ? mpi_cp : mpi; + data->data[i].flags = flags; + err = 0; + + out: + + if (err) + { + gcry_mpi_release (mpi_cp); + gcry_free (name_cp); + } + + return err; +} + +/* Stores the value labelled with NAME found in the data set DATA in + MPI. The returned MPI value will be released in case + gcry_ac_data_set is used to associate the label NAME with a + different MPI value. */ +gcry_error_t +_gcry_ac_data_get_name (gcry_ac_data_t data, unsigned int flags, + const char *name, gcry_mpi_t *mpi) +{ + gcry_mpi_t mpi_return; + gcry_error_t err; + unsigned int i; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & ~(GCRY_AC_FLAG_COPY)) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + for (i = 0; i < data->data_n; i++) + if (! strcmp (name, data->data[i].name)) + break; + if (i == data->data_n) + { + err = gcry_error (GPG_ERR_NOT_FOUND); + goto out; + } + + if (flags & GCRY_AC_FLAG_COPY) + { + mpi_return = gcry_mpi_copy (data->data[i].mpi); + if (! mpi_return) + { + err = gcry_error_from_errno (errno); /* FIXME? */ + goto out; + } + } + else + mpi_return = data->data[i].mpi; + + *mpi = mpi_return; + err = 0; + + out: + + return err; +} + +/* Stores in NAME and MPI the named MPI value contained in the data + set DATA with the index IDX. NAME or MPI may be NULL. The + returned MPI value will be released in case gcry_ac_data_set is + used to associate the label NAME with a different MPI value. */ +gcry_error_t +_gcry_ac_data_get_index (gcry_ac_data_t data, unsigned int flags, + unsigned int idx, + const char **name, gcry_mpi_t *mpi) +{ + gcry_error_t err; + gcry_mpi_t mpi_cp; + char *name_cp; + + name_cp = NULL; + mpi_cp = NULL; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + if (flags & ~(GCRY_AC_FLAG_COPY)) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + if (idx >= data->data_n) + { + err = gcry_error (GPG_ERR_INV_ARG); + goto out; + } + + if (flags & GCRY_AC_FLAG_COPY) + { + /* Return copies to the user. */ + if (name) + { + name_cp = gcry_strdup (data->data[idx].name); + if (! name_cp) + { + err = gcry_error_from_errno (errno); + goto out; + } + } + if (mpi) + { + mpi_cp = gcry_mpi_copy (data->data[idx].mpi); + if (! mpi_cp) + { + err = gcry_error_from_errno (errno); + goto out; + } + } + } + + if (name) + *name = name_cp ? name_cp : data->data[idx].name; + if (mpi) + *mpi = mpi_cp ? mpi_cp : data->data[idx].mpi; + err = 0; + + out: + + if (err) + { + gcry_mpi_release (mpi_cp); + gcry_free (name_cp); + } + + return err; +} + +/* Convert the data set DATA into a new S-Expression, which is to be + stored in SEXP, according to the identifiers contained in + IDENTIFIERS. */ +gcry_error_t +_gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, + const char **identifiers) +{ + gcry_sexp_t sexp_new; + gcry_error_t err; + char *sexp_buffer; + size_t sexp_buffer_n; + size_t identifiers_n; + const char *label; + gcry_mpi_t mpi; + void **arg_list; + size_t data_n; + unsigned int i; + + sexp_buffer_n = 1; + sexp_buffer = NULL; + arg_list = NULL; + err = 0; + + if (fips_mode ()) + return gpg_error (GPG_ERR_NOT_SUPPORTED); + + /* Calculate size of S-expression representation. */ + + i = 0; + if (identifiers) + while (identifiers[i]) + { + /* For each identifier, we add "()". */ + sexp_buffer_n += 1 + strlen (identifiers[i]) + 1; + i++; + } + identifiers_n = i; + + if (! identifiers_n) + /* If there are NO identifiers, we still add surrounding braces so + that we have a list of named MPI value lists. Otherwise it + wouldn't be too much fun to process these lists. */ + sexp_buffer_n += 2; + + data_n = _gcry_ac_data_length (data); + for (i = 0; i < data_n; i++) + { + err = gcry_ac_data_get_index (data, 0, i, &label, NULL); + if (err) + break; + /* For each MPI we add "(