From 539705d58fc39a28388ff18c695dd406f4ffd1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Sch=C3=BCmann?= Date: Fri, 20 Mar 2015 12:32:29 +0000 Subject: MirOTR: Libgcrypt and Libgpg-error update Libgcrypt 1.4.6 => 1.6.3 Libgpg-error 1.9 => 1.18 git-svn-id: http://svn.miranda-ng.org/main/trunk@12449 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/MirOTR/Libgcrypt/cipher/pubkey-util.c | 1050 +++++++++++++++++++++++++ 1 file changed, 1050 insertions(+) create mode 100644 plugins/MirOTR/Libgcrypt/cipher/pubkey-util.c (limited to 'plugins/MirOTR/Libgcrypt/cipher/pubkey-util.c') diff --git a/plugins/MirOTR/Libgcrypt/cipher/pubkey-util.c b/plugins/MirOTR/Libgcrypt/cipher/pubkey-util.c new file mode 100644 index 0000000000..616b4990fe --- /dev/null +++ b/plugins/MirOTR/Libgcrypt/cipher/pubkey-util.c @@ -0,0 +1,1050 @@ +/* pubkey-util.c - Supporting functions for all pubkey modules. + * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, + * 2007, 2008, 2011 Free Software Foundation, Inc. + * Copyright (C) 2013 g10 Code GmbH + * + * 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 "g10lib.h" +#include "mpi.h" +#include "cipher.h" +#include "pubkey-internal.h" + + +/* Callback for the pubkey algorithm code to verify PSS signatures. + OPAQUE is the data provided by the actual caller. The meaning of + TMP depends on the actual algorithm (but there is only RSA); now + for RSA it is the output of running the public key function on the + input. */ +static int +pss_verify_cmp (void *opaque, gcry_mpi_t tmp) +{ + struct pk_encoding_ctx *ctx = opaque; + gcry_mpi_t hash = ctx->verify_arg; + + return _gcry_rsa_pss_verify (hash, tmp, ctx->nbits - 1, + ctx->hash_algo, ctx->saltlen); +} + + +/* Parser for a flag list. On return the encoding is stored at + R_ENCODING and the flags are stored at R_FLAGS. If any of them is + not needed, NULL may be passed. The function returns 0 on success + or an error code. */ +gpg_err_code_t +_gcry_pk_util_parse_flaglist (gcry_sexp_t list, + int *r_flags, enum pk_encoding *r_encoding) +{ + gpg_err_code_t rc = 0; + const char *s; + size_t n; + int i; + int encoding = PUBKEY_ENC_UNKNOWN; + int flags = 0; + int igninvflag = 0; + + for (i = list ? sexp_length (list)-1 : 0; i > 0; i--) + { + s = sexp_nth_data (list, i, &n); + if (!s) + continue; /* Not a data element. */ + + switch (n) + { + case 3: + if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_PSS; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given. */ + } + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 4: + if (!memcmp (s, "comp", 4)) + flags |= PUBKEY_FLAG_COMP; + else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_OAEP; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else if (!memcmp (s, "gost", 4)) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_GOST; + } + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 5: + if (!memcmp (s, "eddsa", 5)) + { + encoding = PUBKEY_ENC_RAW; + flags |= PUBKEY_FLAG_EDDSA; + } + else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN) + { + encoding = PUBKEY_ENC_PKCS1; + flags |= PUBKEY_FLAG_FIXEDLEN; + } + else if (!memcmp (s, "param", 5)) + flags |= PUBKEY_FLAG_PARAM; + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 6: + if (!memcmp (s, "nocomp", 6)) + flags |= PUBKEY_FLAG_NOCOMP; + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 7: + if (!memcmp (s, "rfc6979", 7)) + flags |= PUBKEY_FLAG_RFC6979; + else if (!memcmp (s, "noparam", 7)) + ; /* Ignore - it is the default. */ + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 8: + if (!memcmp (s, "use-x931", 8)) + flags |= PUBKEY_FLAG_USE_X931; + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 10: + if (!memcmp (s, "igninvflag", 10)) + igninvflag = 1; + break; + + case 11: + if (!memcmp (s, "no-blinding", 11)) + flags |= PUBKEY_FLAG_NO_BLINDING; + else if (!memcmp (s, "use-fips186", 11)) + flags |= PUBKEY_FLAG_USE_FIPS186; + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 13: + if (!memcmp (s, "use-fips186-2", 13)) + flags |= PUBKEY_FLAG_USE_FIPS186_2; + else if (!memcmp (s, "transient-key", 13)) + flags |= PUBKEY_FLAG_TRANSIENT_KEY; + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + default: + if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + } + } + + if (r_flags) + *r_flags = flags; + if (r_encoding) + *r_encoding = encoding; + + return rc; +} + + +static int +get_hash_algo (const char *s, size_t n) +{ + static const struct { const char *name; int algo; } hashnames[] = { + { "sha1", GCRY_MD_SHA1 }, + { "md5", GCRY_MD_MD5 }, + { "sha256", GCRY_MD_SHA256 }, + { "ripemd160", GCRY_MD_RMD160 }, + { "rmd160", GCRY_MD_RMD160 }, + { "sha384", GCRY_MD_SHA384 }, + { "sha512", GCRY_MD_SHA512 }, + { "sha224", GCRY_MD_SHA224 }, + { "md2", GCRY_MD_MD2 }, + { "md4", GCRY_MD_MD4 }, + { "tiger", GCRY_MD_TIGER }, + { "haval", GCRY_MD_HAVAL }, + { NULL, 0 } + }; + int algo; + int i; + + for (i=0; hashnames[i].name; i++) + { + if ( strlen (hashnames[i].name) == n + && !memcmp (hashnames[i].name, s, n)) + break; + } + if (hashnames[i].name) + algo = hashnames[i].algo; + else + { + /* In case of not listed or dynamically allocated hash + algorithm we fall back to this somewhat slower + method. Further, it also allows to use OIDs as + algorithm names. */ + char *tmpname; + + tmpname = xtrymalloc (n+1); + if (!tmpname) + algo = 0; /* Out of core - silently give up. */ + else + { + memcpy (tmpname, s, n); + tmpname[n] = 0; + algo = _gcry_md_map_name (tmpname); + xfree (tmpname); + } + } + return algo; +} + + +/* Get the "nbits" parameter from an s-expression of the format: + * + * (algo + * (parameter_name_1 ....) + * .... + * (parameter_name_n ....)) + * + * Example: + * + * (rsa + * (nbits 4:2048)) + * + * On success the value for nbits is stored at R_NBITS. If no nbits + * parameter is found, the function returns success and stores 0 at + * R_NBITS. For parsing errors the function returns an error code and + * stores 0 at R_NBITS. + */ +gpg_err_code_t +_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits) +{ + char buf[50]; + const char *s; + size_t n; + + *r_nbits = 0; + + list = sexp_find_token (list, "nbits", 0); + if (!list) + return 0; /* No NBITS found. */ + + s = sexp_nth_data (list, 1, &n); + if (!s || n >= DIM (buf) - 1 ) + { + /* NBITS given without a cdr. */ + sexp_release (list); + return GPG_ERR_INV_OBJ; + } + memcpy (buf, s, n); + buf[n] = 0; + *r_nbits = (unsigned int)strtoul (buf, NULL, 0); + sexp_release (list); + return 0; +} + + +/* Get the optional "rsa-use-e" parameter from an s-expression of the + * format: + * + * (algo + * (parameter_name_1 ....) + * .... + * (parameter_name_n ....)) + * + * Example: + * + * (rsa + * (nbits 4:2048) + * (rsa-use-e 2:41)) + * + * On success the value for nbits is stored at R_E. If no rsa-use-e + * parameter is found, the function returns success and stores 65537 at + * R_E. For parsing errors the function returns an error code and + * stores 0 at R_E. + */ +gpg_err_code_t +_gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e) +{ + char buf[50]; + const char *s; + size_t n; + + *r_e = 0; + + list = sexp_find_token (list, "rsa-use-e", 0); + if (!list) + { + *r_e = 65537; /* Not given, use the value generated by old versions. */ + return 0; + } + + s = sexp_nth_data (list, 1, &n); + if (!s || n >= DIM (buf) - 1 ) + { + /* No value or value too large. */ + sexp_release (list); + return GPG_ERR_INV_OBJ; + } + memcpy (buf, s, n); + buf[n] = 0; + *r_e = strtoul (buf, NULL, 0); + sexp_release (list); + return 0; +} + + +/* Parse a "sig-val" s-expression and store the inner parameter list at + R_PARMS. ALGO_NAMES is used to verify that the algorithm in + "sig-val" is valid. Returns 0 on success and stores a new list at + R_PARMS which must be freed by the caller. On error R_PARMS is set + to NULL and an error code returned. If R_ECCFLAGS is not NULL flag + values are set into it; as of now they are only used with ecc + algorithms. */ +gpg_err_code_t +_gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names, + gcry_sexp_t *r_parms, int *r_eccflags) +{ + gpg_err_code_t rc; + gcry_sexp_t l1 = NULL; + gcry_sexp_t l2 = NULL; + char *name = NULL; + int i; + + *r_parms = NULL; + if (r_eccflags) + *r_eccflags = 0; + + /* Extract the signature value. */ + l1 = sexp_find_token (s_sig, "sig-val", 0); + if (!l1) + { + rc = GPG_ERR_INV_OBJ; /* Does not contain a signature value object. */ + goto leave; + } + + l2 = sexp_nth (l1, 1); + if (!l2) + { + rc = GPG_ERR_NO_OBJ; /* No cadr for the sig object. */ + goto leave; + } + name = sexp_nth_string (l2, 0); + if (!name) + { + rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */ + goto leave; + } + else if (!strcmp (name, "flags")) + { + /* Skip a "flags" parameter and look again for the algorithm + name. This is not used but here just for the sake of + consistent S-expressions we need to handle it. */ + sexp_release (l2); + l2 = sexp_nth (l1, 2); + if (!l2) + { + rc = GPG_ERR_INV_OBJ; + goto leave; + } + xfree (name); + name = sexp_nth_string (l2, 0); + if (!name) + { + rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */ + goto leave; + } + } + + for (i=0; algo_names[i]; i++) + if (!stricmp (name, algo_names[i])) + break; + if (!algo_names[i]) + { + rc = GPG_ERR_CONFLICT; /* "sig-val" uses an unexpected algo. */ + goto leave; + } + if (r_eccflags) + { + if (!strcmp (name, "eddsa")) + *r_eccflags = PUBKEY_FLAG_EDDSA; + if (!strcmp (name, "gost")) + *r_eccflags = PUBKEY_FLAG_GOST; + } + + *r_parms = l2; + l2 = NULL; + rc = 0; + + leave: + xfree (name); + sexp_release (l2); + sexp_release (l1); + return rc; +} + + +/* Parse a "enc-val" s-expression and store the inner parameter list + at R_PARMS. ALGO_NAMES is used to verify that the algorithm in + "enc-val" is valid. Returns 0 on success and stores a new list at + R_PARMS which must be freed by the caller. On error R_PARMS is set + to NULL and an error code returned. If R_ECCFLAGS is not NULL flag + values are set into it; as of now they are only used with ecc + algorithms. + + (enc-val + [(flags [raw, pkcs1, oaep, no-blinding])] + [(hash-algo )] + [(label