libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 2bdfce2c5a5348faa69ca52f1721a911d527c9fa
parent 45c6900e368f4269b2eb435eab32d9f5e98da072
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 24 Aug 2008 15:17:11 +0000

removing dead stuff

Diffstat:
Mconfigure.ac | 19-------------------
Msrc/daemon/Makefile.am | 4+---
Msrc/daemon/daemon_test.c | 2+-
Msrc/daemon/https/Makefile.am | 7+------
Dsrc/daemon/https/extra.h | 186-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/Makefile.am | 14--------------
Dsrc/daemon/https/opencdk/README | 5-----
Dsrc/daemon/https/opencdk/armor.c | 763-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/cipher.c | 528-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/compress.c | 238-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/context.h | 120-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/dummy.c | 15---------------
Dsrc/daemon/https/opencdk/filters.h | 95-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/kbnode.c | 581-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/keydb.c | 2303-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/literal.c | 307-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/main.c | 779-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/main.h | 183-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/misc.c | 571-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/new-packet.c | 874-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/opencdk.h | 1169-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/packet.h | 40----------------------------------------
Dsrc/daemon/https/opencdk/pubkey.c | 1380-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/read-packet.c | 1179-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/seskey.c | 717-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/sig-check.c | 489-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/stream.c | 1446-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/stream.h | 88-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/types.h | 44--------------------------------------------
Dsrc/daemon/https/opencdk/verify.c | 306-------------------------------------------------------------------------------
Dsrc/daemon/https/opencdk/write-packet.c | 947-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/Makefile.am | 28----------------------------
Dsrc/daemon/https/openpgp/compat.c | 252-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/extras.c | 170-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/gnutls_extra.c | 103-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/gnutls_extra.h | 50--------------------------------------------------
Dsrc/daemon/https/openpgp/gnutls_ia.c | 901-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/gnutls_openpgp.c | 966-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/gnutls_openpgp.h | 98-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/openpgp.h | 182-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/pgp.c | 543-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/pgp_privkey.c | 134-------------------------------------------------------------------------------
Dsrc/daemon/https/openpgp/pgp_verify.c | 144-------------------------------------------------------------------------------
43 files changed, 3 insertions(+), 18967 deletions(-)

diff --git a/configure.ac b/configure.ac @@ -218,24 +218,6 @@ AC_ARG_ENABLE([x509], AC_MSG_RESULT($enable_x509) -# optional: OpenPGP support -AC_MSG_CHECKING(--enable-OpenPGP argument) -AC_ARG_ENABLE([OpenPGP], - [AS_HELP_STRING([--enable-OpenPGP], - [enable OpenPGP support (default is no)])], - [enable_openpgp=$enableval], - [enable_openpgp="no"]) -AC_MSG_RESULT($enable_openpgp) -# currently we ignore this option. -if test "$enable_openpgp" = "yes" -then - AC_DEFINE([ENABLE_OPENPGP],[0],[Include OpenGPG support]) -else - AC_DEFINE([ENABLE_OPENPGP],[0],[Include OpenGPG support]) -fi -AM_CONDITIONAL(ENABLE_OPENPGP, test "$enable_openpgp" = "yes") - - # Libgcrypt linkage : required for HTTPS support AC_CHECK_HEADERS(gcrypt.h,gcrypt=true,gcrypt=false) AC_ARG_WITH(libgcrypt, @@ -342,7 +324,6 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: HTTPS support: ${enable_HTTPS} TLS support: ${enable_TLS} SSLv3 support: ${enable_SSL} - OpenGPG support: ${enable_openpgp} x509 support: ${enable_x509} libgcrypt: ${MSG_GCRYPT} diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am @@ -42,9 +42,7 @@ libmicrohttpd_la_LIBADD = \ https/lgl/liblgl.la \ https/x509/libx509.la \ https/tls/libtls.la \ - https/minitasn1/libasn1.la \ - https/opencdk/libopencdk.la \ - https/openpgp/libopenpgp.la + https/minitasn1/libasn1.la endif diff --git a/src/daemon/daemon_test.c b/src/daemon/daemon_test.c @@ -24,7 +24,7 @@ * @author Christian Grothoff */ -#include "config.h" +#include "platform.h" #include "platform.h" #include "microhttpd.h" #include <stdlib.h> diff --git a/src/daemon/https/Makefile.am b/src/daemon/https/Makefile.am @@ -1,6 +1 @@ -# placing '.' at the end of SUBDIRS having OPENPGP enabled mixes up build order ! -SUBDIRS = minitasn1 lgl x509 tls - -if ENABLE_OPENPGP -# SUBDIRS += opencdk openpgp -endif +SUBDIRS = minitasn1 lgl x509 tls . diff --git a/src/daemon/https/extra.h b/src/daemon/https/extra.h @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation - * - * Author: Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the - * License, or (at your option) any later version. - * - * GNUTLS-EXTRA 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 GNUTLS-EXTRA; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -/* Note the libgnutls-extra is not a standalone library. It requires - * to link also against libgnutls. - */ - -#ifndef GNUTLS_EXTRA_H -#define GNUTLS_EXTRA_H - -#include "gnutls.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define LIBGNUTLS_EXTRA_VERSION LIBGNUTLS_VERSION - -/* Openpgp certificate stuff - */ - - typedef enum gnutls_openpgp_crt_fmt - { GNUTLS_OPENPGP_FMT_RAW, - GNUTLS_OPENPGP_FMT_BASE64 - } gnutls_openpgp_crt_fmt_t; - -/** - * mhd_gtls_openpgp_recv_key_func - Callback prototype to get OpenPGP keys - * @session: a TLS session - * @keyfpr: key fingerprint - * @keyfpr_length: length of key fingerprint - * @key: output key. - * - * A callback of this type is used to retrieve OpenPGP keys. Only - * useful on the server, and will only be used if the peer send a key - * fingerprint instead of a full key. See also - * gnutls_openpgp_set_recv_key_function(). - * - */ - typedef int (*mhd_gtls_openpgp_recv_key_func) (mhd_gtls_session_t session, - const unsigned char *keyfpr, - unsigned int keyfpr_length, - gnutls_datum_t * key); - - void gnutls_openpgp_set_recv_key_function (mhd_gtls_session_t session, - mhd_gtls_openpgp_recv_key_func - func); - - int - gnutls_certificate_set_openpgp_key_file (mhd_gtls_cert_credentials_t - res, const char *CERTFILE, - const char *KEYFILE, - gnutls_openpgp_crt_fmt_t); - int gnutls_certificate_set_openpgp_key_mem (mhd_gtls_cert_credentials_t res, - const gnutls_datum_t * CERT, - const gnutls_datum_t * KEY, - gnutls_openpgp_crt_fmt_t); - - int - gnutls_certificate_set_openpgp_keyring_mem - (mhd_gtls_cert_credentials_t c, const unsigned char *data, - size_t dlen, gnutls_openpgp_crt_fmt_t); - - int - gnutls_certificate_set_openpgp_keyring_file - (mhd_gtls_cert_credentials_t c, const char *file, - gnutls_openpgp_crt_fmt_t); - - /* - * TLS/IA stuff - */ - typedef enum - { - GNUTLS_IA_APPLICATION_PAYLOAD = 0, - GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED = 1, - GNUTLS_IA_FINAL_PHASE_FINISHED = 2 - } gnutls_ia_apptype_t; - - /* - * TLS/IA credential - */ - typedef int (*gnutls_ia_avp_func) (mhd_gtls_session_t session, void *ptr, - const char *last, size_t lastlen, - char **next, size_t * nextlen); - - typedef struct gnutls_ia_server_credentials_st - *gnutls_ia_server_credentials_t; - typedef struct gnutls_ia_client_credentials_st - *gnutls_ia_client_credentials_t; - - /* Allocate and free TLS/IA credentials. */ - extern void - gnutls_ia_free_client_credentials (gnutls_ia_client_credentials_t sc); - extern int - gnutls_ia_allocate_client_credentials (gnutls_ia_client_credentials_t * - sc); - - extern void - gnutls_ia_free_server_credentials (gnutls_ia_server_credentials_t sc); - extern int - gnutls_ia_allocate_server_credentials (gnutls_ia_server_credentials_t * - sc); - - /* Client TLS/IA credential functions. */ - extern void - gnutls_ia_set_client_avp_function (gnutls_ia_client_credentials_t cred, - gnutls_ia_avp_func avp_func); - extern void - gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred, - void *ptr); - extern void *gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t - cred); - - /* Server TLS/IA credential functions. */ - extern void - gnutls_ia_set_server_avp_function (gnutls_ia_server_credentials_t cred, - gnutls_ia_avp_func avp_func); - extern void - gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred, - void *ptr); - extern void *gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t - cred); - - /* TLS/IA handshake. */ - extern int gnutls_ia_handshake_p (mhd_gtls_session_t session); - - extern int gnutls_ia_handshake (mhd_gtls_session_t session); - - /* TLS/IA low level interface. */ - extern int - gnutls_ia_permute_inner_secret (mhd_gtls_session_t session, - size_t session_keys_size, - const char *session_keys); - extern int gnutls_ia_endphase_send (mhd_gtls_session_t session, - int final_p); - - extern int gnutls_ia_verify_endphase (mhd_gtls_session_t session, - const char *checksum); - - extern ssize_t gnutls_ia_send (mhd_gtls_session_t session, - const char *data, size_t sizeofdata); - extern ssize_t gnutls_ia_recv (mhd_gtls_session_t session, - char *data, size_t sizeofdata); - - /* Utility stuff. */ - extern int gnutls_ia_generate_challenge (mhd_gtls_session_t session, - size_t buffer_size, char *buffer); - extern void gnutls_ia_extract_inner_secret (mhd_gtls_session_t session, - char *buffer); - - /* Define whether inner phases are wanted. */ - extern void gnutls_ia_enable (mhd_gtls_session_t session, - int allow_skip_on_resume); - - int gnutls_global_init_extra (void); - -/* returns libgnutls-extra version (call it with a NULL argument) - */ - const char *gnutls_extra_check_version (const char *req_version); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/daemon/https/opencdk/Makefile.am b/src/daemon/https/opencdk/Makefile.am @@ -1,14 +0,0 @@ -AM_CPPFLAGS = \ --I$(top_srcdir)/src/include \ --I$(top_srcdir)/lib \ --I$(top_srcdir)/lgl \ --I$(GCRYPT_CPPFLAGS) - -noinst_LTLIBRARIES = libopencdk.la - -libopencdk_la_LDFLAGS = -lgcrypt - -libopencdk_la_SOURCES = armor.c filters.h main.c seskey.c types.h \ - cipher.c kbnode.c main.h packet.h dummy.c sig-check.c verify.c \ - compress.c keydb.c misc.c pubkey.c stream.c write-packet.c \ - context.h literal.c new-packet.c read-packet.c stream.h opencdk.h diff --git a/src/daemon/https/opencdk/README b/src/daemon/https/opencdk/README @@ -1,5 +0,0 @@ -This is a stripped down mirror of the files in OpenCDK -src/. To avoid to link proc-packets.c, dummy.c is included. - -In Makefile.am libminiopencdk_la_SOURCES contains the list -of all needed files. diff --git a/src/daemon/https/opencdk/armor.c b/src/daemon/https/opencdk/armor.c @@ -1,763 +0,0 @@ -/* armor.c - Armor filters - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - * - * ChangeLog for basic BASE64 code (base64_encode, base64_decode): - * Original author: Eric S. Raymond (Fetchmail) - * Heavily modified by Brendan Cully <brendan@kublai.com> (Mutt) - * Modify the code for generic use by Timo Schulz <twoaday@freakmail.de> - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <sys/stat.h> - -#include "opencdk.h" -#include "main.h" -#include "filters.h" - -#ifdef __MINGW32__ -# define LF "\r\n" -#else -# define LF "\n" -#endif - -#define CRCINIT 0xB704CE - -#define BAD -1 -#define b64val(c) index64[(unsigned int)(c)] - -static u32 crc_table[] = { - 0x000000, 0x864CFB, 0x8AD50D, 0x0C99F6, 0x93E6E1, 0x15AA1A, 0x1933EC, - 0x9F7F17, - 0xA18139, 0x27CDC2, 0x2B5434, 0xAD18CF, 0x3267D8, 0xB42B23, 0xB8B2D5, - 0x3EFE2E, - 0xC54E89, 0x430272, 0x4F9B84, 0xC9D77F, 0x56A868, 0xD0E493, 0xDC7D65, - 0x5A319E, - 0x64CFB0, 0xE2834B, 0xEE1ABD, 0x685646, 0xF72951, 0x7165AA, 0x7DFC5C, - 0xFBB0A7, - 0x0CD1E9, 0x8A9D12, 0x8604E4, 0x00481F, 0x9F3708, 0x197BF3, 0x15E205, - 0x93AEFE, - 0xAD50D0, 0x2B1C2B, 0x2785DD, 0xA1C926, 0x3EB631, 0xB8FACA, 0xB4633C, - 0x322FC7, - 0xC99F60, 0x4FD39B, 0x434A6D, 0xC50696, 0x5A7981, 0xDC357A, 0xD0AC8C, - 0x56E077, - 0x681E59, 0xEE52A2, 0xE2CB54, 0x6487AF, 0xFBF8B8, 0x7DB443, 0x712DB5, - 0xF7614E, - 0x19A3D2, 0x9FEF29, 0x9376DF, 0x153A24, 0x8A4533, 0x0C09C8, 0x00903E, - 0x86DCC5, - 0xB822EB, 0x3E6E10, 0x32F7E6, 0xB4BB1D, 0x2BC40A, 0xAD88F1, 0xA11107, - 0x275DFC, - 0xDCED5B, 0x5AA1A0, 0x563856, 0xD074AD, 0x4F0BBA, 0xC94741, 0xC5DEB7, - 0x43924C, - 0x7D6C62, 0xFB2099, 0xF7B96F, 0x71F594, 0xEE8A83, 0x68C678, 0x645F8E, - 0xE21375, - 0x15723B, 0x933EC0, 0x9FA736, 0x19EBCD, 0x8694DA, 0x00D821, 0x0C41D7, - 0x8A0D2C, - 0xB4F302, 0x32BFF9, 0x3E260F, 0xB86AF4, 0x2715E3, 0xA15918, 0xADC0EE, - 0x2B8C15, - 0xD03CB2, 0x567049, 0x5AE9BF, 0xDCA544, 0x43DA53, 0xC596A8, 0xC90F5E, - 0x4F43A5, - 0x71BD8B, 0xF7F170, 0xFB6886, 0x7D247D, 0xE25B6A, 0x641791, 0x688E67, - 0xEEC29C, - 0x3347A4, 0xB50B5F, 0xB992A9, 0x3FDE52, 0xA0A145, 0x26EDBE, 0x2A7448, - 0xAC38B3, - 0x92C69D, 0x148A66, 0x181390, 0x9E5F6B, 0x01207C, 0x876C87, 0x8BF571, - 0x0DB98A, - 0xF6092D, 0x7045D6, 0x7CDC20, 0xFA90DB, 0x65EFCC, 0xE3A337, 0xEF3AC1, - 0x69763A, - 0x578814, 0xD1C4EF, 0xDD5D19, 0x5B11E2, 0xC46EF5, 0x42220E, 0x4EBBF8, - 0xC8F703, - 0x3F964D, 0xB9DAB6, 0xB54340, 0x330FBB, 0xAC70AC, 0x2A3C57, 0x26A5A1, - 0xA0E95A, - 0x9E1774, 0x185B8F, 0x14C279, 0x928E82, 0x0DF195, 0x8BBD6E, 0x872498, - 0x016863, - 0xFAD8C4, 0x7C943F, 0x700DC9, 0xF64132, 0x693E25, 0xEF72DE, 0xE3EB28, - 0x65A7D3, - 0x5B59FD, 0xDD1506, 0xD18CF0, 0x57C00B, 0xC8BF1C, 0x4EF3E7, 0x426A11, - 0xC426EA, - 0x2AE476, 0xACA88D, 0xA0317B, 0x267D80, 0xB90297, 0x3F4E6C, 0x33D79A, - 0xB59B61, - 0x8B654F, 0x0D29B4, 0x01B042, 0x87FCB9, 0x1883AE, 0x9ECF55, 0x9256A3, - 0x141A58, - 0xEFAAFF, 0x69E604, 0x657FF2, 0xE33309, 0x7C4C1E, 0xFA00E5, 0xF69913, - 0x70D5E8, - 0x4E2BC6, 0xC8673D, 0xC4FECB, 0x42B230, 0xDDCD27, 0x5B81DC, 0x57182A, - 0xD154D1, - 0x26359F, 0xA07964, 0xACE092, 0x2AAC69, 0xB5D37E, 0x339F85, 0x3F0673, - 0xB94A88, - 0x87B4A6, 0x01F85D, 0x0D61AB, 0x8B2D50, 0x145247, 0x921EBC, 0x9E874A, - 0x18CBB1, - 0xE37B16, 0x6537ED, 0x69AE1B, 0xEFE2E0, 0x709DF7, 0xF6D10C, 0xFA48FA, - 0x7C0401, - 0x42FA2F, 0xC4B6D4, 0xC82F22, 0x4E63D9, 0xD11CCE, 0x575035, 0x5BC9C3, - 0xDD8538 -}; - -static const char *armor_begin[] = { - "BEGIN PGP MESSAGE", - "BEGIN PGP PUBLIC KEY BLOCK", - "BEGIN PGP PRIVATE KEY BLOCK", - "BEGIN PGP SIGNATURE", - NULL -}; - -static const char *armor_end[] = { - "END PGP MESSAGE", - "END PGP PUBLIC KEY BLOCK", - "END PGP PRIVATE KEY BLOCK", - "END PGP SIGNATURE", - NULL -}; - -static const char *valid_headers[] = { - "Comment", - "Version", - "MessageID", - "Hash", - "Charset", - NULL -}; - -static char b64chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static int index64[128] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 -}; - - -/* encode a raw binary buffer to a null-terminated base64 strings */ -static int -base64_encode (char *out, const byte * in, size_t len, size_t olen) -{ - if (!out || !in) - return CDK_Inv_Value; - - while (len >= 3 && olen > 10) - { - *out++ = b64chars[in[0] >> 2]; - *out++ = b64chars[((in[0] << 4) & 0x30) | (in[1] >> 4)]; - *out++ = b64chars[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; - *out++ = b64chars[in[2] & 0x3f]; - olen -= 4; - len -= 3; - in += 3; - } - - /* clean up remainder */ - if (len > 0 && olen > 4) - { - byte fragment = 0; - *out++ = b64chars[in[0] >> 2]; - fragment = (in[0] << 4) & 0x30; - if (len > 1) - fragment |= in[1] >> 4; - *out++ = b64chars[fragment]; - *out++ = (len < 2) ? '=' : b64chars[(in[1] << 2) & 0x3c]; - *out++ = '='; - } - *out = '\0'; - return 0; -} - - -/* Convert '\0'-terminated base64 string to raw byte buffer. - Returns length of returned buffer, or -1 on error. */ -static int -base64_decode (byte * out, const char *in) -{ - size_t len; - byte digit1, digit2, digit3, digit4; - - if (!out || !in) - return -1; - - len = 0; - do - { - digit1 = in[0]; - if (digit1 > 127 || b64val (digit1) == BAD) - return -1; - digit2 = in[1]; - if (digit2 > 127 || b64val (digit2) == BAD) - return -1; - digit3 = in[2]; - if (digit3 > 127 || ((digit3 != '=') && (b64val (digit3) == BAD))) - return -1; - digit4 = in[3]; - if (digit4 > 127 || ((digit4 != '=') && (b64val (digit4) == BAD))) - return -1; - in += 4; - - /* digits are already sanity-checked */ - *out++ = (b64val (digit1) << 2) | (b64val (digit2) >> 4); - len++; - if (digit3 != '=') - { - *out++ = ((b64val (digit2) << 4) & 0xf0) | (b64val (digit3) >> 2); - len++; - if (digit4 != '=') - { - *out++ = ((b64val (digit3) << 6) & 0xc0) | b64val (digit4); - len++; - } - } - } - while (*in && digit4 != '='); - - return len; -} - - -/* Return the compression algorithm in @r_zipalgo. - If the parameter is not set after execution, - the stream is not compressed. */ -static int -compress_get_algo (cdk_stream_t inp, int *r_zipalgo) -{ - byte plain[512]; - char buf[128]; - int nread, pkttype; - - *r_zipalgo = 0; - cdk_stream_seek (inp, 0); - while (!cdk_stream_eof (inp)) - { - nread = _cdk_stream_gets (inp, buf, DIM (buf) - 1); - if (!nread || nread == -1) - break; - if (nread == 1 && !cdk_stream_eof (inp) - && (nread = _cdk_stream_gets (inp, buf, DIM (buf) - 1)) > 0) - { - base64_decode (plain, buf); - if (!(*plain & 0x80)) - break; - pkttype = *plain & 0x40 ? (*plain & 0x3f) : ((*plain >> 2) & 0xf); - if (pkttype == CDK_PKT_COMPRESSED && r_zipalgo) - { - _cdk_log_debug ("armor compressed (algo=%d)\n", *(plain + 1)); - *r_zipalgo = *(plain + 1); - } - break; - } - } - return 0; -} - - -static int -check_armor (cdk_stream_t inp, int *r_zipalgo) -{ - char buf[4096]; - size_t nread; - int check; - - check = 0; - nread = cdk_stream_read (inp, buf, DIM (buf) - 1); - if (nread > 0) - { - buf[nread] = '\0'; - if (strstr (buf, "-----BEGIN PGP")) - { - compress_get_algo (inp, r_zipalgo); - check = 1; - } - cdk_stream_seek (inp, 0); - } - return check; -} - - -static int -is_armored (int ctb) -{ - int pkttype = 0; - - if (!(ctb & 0x80)) - return 1; /* invalid packet: assume it is armored */ - pkttype = ctb & 0x40 ? (ctb & 0x3f) : ((ctb >> 2) & 0xf); - switch (pkttype) - { - case CDK_PKT_MARKER: - case CDK_PKT_SYMKEY_ENC: - case CDK_PKT_ONEPASS_SIG: - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_SECRET_KEY: - case CDK_PKT_PUBKEY_ENC: - case CDK_PKT_SIGNATURE: - case CDK_PKT_LITERAL: - case CDK_PKT_COMPRESSED: - case CDK_PKT_ENCRYPTED: - return 0; /* seems to be a regular packet: not armored */ - } - return 1; -} - - -static u32 -update_crc (u32 crc, const byte * buf, size_t buflen) -{ - int j; - - if (!crc) - crc = CRCINIT; - - for (j = 0; j < buflen; j++) - crc = (crc << 8) ^ crc_table[0xff & ((crc >> 16) ^ buf[j])]; - crc &= 0xffffff; - return crc; -} - - -static cdk_error_t -armor_encode (void *opaque, FILE * in, FILE * out) -{ - armor_filter_t *afx = opaque; - struct stat statbuf; - char crcbuf[5], buf[128], raw[49]; - byte crcbuf2[3]; - size_t nread = 0; - const char *lf; - - if (!afx) - return CDK_Inv_Value; - if (afx->idx < 0 || afx->idx > DIM (armor_begin) || - afx->idx2 < 0 || afx->idx2 > DIM (armor_end)) - return CDK_Inv_Value; - - _cdk_log_debug ("armor filter: encode\n"); - - memset (crcbuf, 0, sizeof (crcbuf)); - - lf = afx->le ? afx->le : LF; - fprintf (out, "-----%s-----%s", armor_begin[afx->idx], lf); - fprintf (out, "Version: OpenPrivacy " PACKAGE_VERSION "%s", lf); - if (afx->hdrlines) - fwrite (afx->hdrlines, 1, strlen (afx->hdrlines), out); - fprintf (out, "%s", lf); - - if (fstat (fileno (in), &statbuf)) - return CDK_General_Error; - - while (!feof (in)) - { - nread = fread (raw, 1, DIM (raw) - 1, in); - if (!nread) - break; - if (ferror (in)) - return CDK_File_Error; - afx->crc = update_crc (afx->crc, (byte *) raw, nread); - base64_encode (buf, (byte *) raw, nread, DIM (buf) - 1); - fprintf (out, "%s%s", buf, lf); - } - - crcbuf2[0] = afx->crc >> 16; - crcbuf2[1] = afx->crc >> 8; - crcbuf2[2] = afx->crc; - crcbuf[0] = b64chars[crcbuf2[0] >> 2]; - crcbuf[1] = b64chars[((crcbuf2[0] << 4) & 0x30) | (crcbuf2[1] >> 4)]; - crcbuf[2] = b64chars[((crcbuf2[1] << 2) & 0x3c) | (crcbuf2[2] >> 6)]; - crcbuf[3] = b64chars[crcbuf2[2] & 0x3f]; - fprintf (out, "=%s%s", crcbuf, lf); - fprintf (out, "-----%s-----%s", armor_end[afx->idx2], lf); - - return 0; -} - - -/** - * cdk_armor_filter_use: - * @inp: the stream to check - * - * Check if the stream contains armored data. - **/ -int -cdk_armor_filter_use (cdk_stream_t inp) -{ - int c, check; - int zipalgo; - - zipalgo = 0; - c = cdk_stream_getc (inp); - if (c == EOF) - return 0; /* EOF, doesn't matter whether armored or not */ - cdk_stream_seek (inp, 0); - check = is_armored (c); - if (check) - { - check = check_armor (inp, &zipalgo); - if (zipalgo) - _cdk_stream_set_compress_algo (inp, zipalgo); - } - return check; -} - - -static int -search_header (const char *buf, const char **array) -{ - const char *s; - int i; - - if (strlen (buf) < 5 || strncmp (buf, "-----", 5)) - return -1; - for (i = 0; (s = array[i]); i++) - { - if (!strncmp (s, buf + 5, strlen (s))) - return i; - } - return -1; -} - - -const char * -_cdk_armor_get_lineend (void) -{ - return LF; -} - - -static cdk_error_t -armor_decode (void *opaque, FILE * in, FILE * out) -{ - armor_filter_t *afx = opaque; - const char *s; - char buf[127]; - byte raw[128], crcbuf[4]; - u32 crc2 = 0; - size_t nread = 0; - int i, pgp_data = 0; - cdk_error_t rc = 0; - - if (!afx) - return CDK_Inv_Value; - - _cdk_log_debug ("armor filter: decode\n"); - - fseek (in, 0, SEEK_SET); - /* Search the begin of the message */ - while (!feof (in) && !pgp_data) - { - s = fgets (buf, DIM (buf) - 1, in); - if (!s) - break; - afx->idx = search_header (buf, armor_begin); - if (afx->idx >= 0) - pgp_data = 1; - } - - if (feof (in) || !pgp_data) - return CDK_Armor_Error; /* no data found */ - - /* Parse header until the empty line is reached */ - while (!feof (in)) - { - s = fgets (buf, DIM (buf) - 1, in); - if (!s) - return CDK_EOF; - if (strlen (s) == strlen (LF)) - { - rc = 0; - break; /* empty line */ - } - /* From RFC2440: OpenPGP should consider improperly formatted Armor - Headers to be corruption of the ASCII Armor. A colon and a single - space separate the key and value. */ - if (!strstr (buf, ": ")) - return CDK_Armor_Error; - rc = CDK_General_Error; - for (i = 0; (s = valid_headers[i]); i++) - { - if (!strncmp (s, buf, strlen (s))) - rc = 0; - } - if (rc) - { - /* From RFC2440: Unknown keys should be reported to the user, - but OpenPGP should continue to process the message. */ - _cdk_log_info ("unknown header: `%s'\n", buf); - rc = 0; - } - } - - /* Read the data body */ - while (!feof (in)) - { - s = fgets (buf, DIM (buf) - 1, in); - if (!s) - break; - buf[strlen (buf) - strlen (LF)] = '\0'; - if (buf[0] == '=' && strlen (s) == 5) - { /* CRC */ - memset (crcbuf, 0, sizeof (crcbuf)); - base64_decode (crcbuf, buf + 1); - crc2 = (crcbuf[0] << 16) | (crcbuf[1] << 8) | crcbuf[2]; - break; /* stop here */ - } - else - { - nread = base64_decode (raw, buf); - if (nread == -1 || nread == 0) - break; - afx->crc = update_crc (afx->crc, raw, nread); - fwrite (raw, 1, nread, out); - } - } - - /* Search the tail of the message */ - s = fgets (buf, DIM (buf) - 1, in); - if (s) - { - buf[strlen (buf) - strlen (LF)] = '\0'; - rc = CDK_General_Error; - afx->idx2 = search_header (buf, armor_end); - if (afx->idx2 >= 0) - rc = 0; - } - - /* This catches error when no tail was found or the header is - different then the tail line. */ - if (rc || afx->idx != afx->idx2) - rc = CDK_Armor_Error; - - afx->crc_okay = (afx->crc == crc2) ? 1 : 0; - if (!afx->crc_okay && !rc) - { - _cdk_log_debug ("file crc=%08lX afx_crc=%08lX\n", crc2, afx->crc); - rc = CDK_Armor_CRC_Error; - } - - return rc; -} - - -/** - * cdk_file_armor: - * @hd: Handle - * @file: Name of the file to protect. - * @output: Output filename. - * - * Protect a file with ASCII armor. - **/ -cdk_error_t -cdk_file_armor (cdk_ctx_t hd, const char *file, const char *output) -{ - cdk_stream_t inp, out; - cdk_error_t rc; - - rc = _cdk_check_args (hd->opt.overwrite, file, output); - if (rc) - return rc; - - rc = cdk_stream_open (file, &inp); - if (rc) - return rc; - - rc = cdk_stream_new (output, &out); - if (rc) - { - cdk_stream_close (inp); - return rc; - } - - cdk_stream_set_armor_flag (out, CDK_ARMOR_MESSAGE); - if (hd->opt.compress) - rc = cdk_stream_set_compress_flag (out, hd->compress.algo, - hd->compress.level); - if (!rc) - rc = cdk_stream_set_literal_flag (out, 0, file); - if (!rc) - rc = cdk_stream_kick_off (inp, out); - if (!rc) - rc = _cdk_stream_get_errno (out); - - cdk_stream_close (out); - cdk_stream_close (inp); - return rc; -} - - -/** - * cdk_file_dearmor: - * @file: Name of the file to unprotect. - * @output: Output filename. - * - * Remove ASCII armor from a file. - **/ -cdk_error_t -cdk_file_dearmor (const char *file, const char *output) -{ - cdk_stream_t inp, out; - cdk_error_t rc; - int zipalgo; - - rc = _cdk_check_args (1, file, output); - if (rc) - return rc; - - rc = cdk_stream_open (file, &inp); - if (rc) - return rc; - - rc = cdk_stream_create (output, &out); - if (rc) - { - cdk_stream_close (inp); - return rc; - } - - if (cdk_armor_filter_use (inp)) - { - rc = cdk_stream_set_literal_flag (inp, 0, NULL); - zipalgo = cdk_stream_is_compressed (inp); - if (zipalgo) - rc = cdk_stream_set_compress_flag (inp, zipalgo, 0); - if (!rc) - rc = cdk_stream_set_armor_flag (inp, 0); - if (!rc) - rc = cdk_stream_kick_off (inp, out); - if (!rc) - rc = _cdk_stream_get_errno (inp); - } - - cdk_stream_close (inp); - cdk_stream_close (out); - return rc; -} - - -int -_cdk_filter_armor (void *opaque, int ctl, FILE * in, FILE * out) -{ - if (ctl == STREAMCTL_READ) - return armor_decode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return armor_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - armor_filter_t *afx = opaque; - if (afx) - { - _cdk_log_debug ("free armor filter\n"); - afx->idx = afx->idx2 = 0; - afx->crc = afx->crc_okay = 0; - return 0; - } - } - return CDK_Inv_Mode; -} - - -/** - * cdk_armor_encode_buffer: - * @inbuf: the raw input buffer - * @inlen: raw buffer len - * @outbuf: the destination buffer for the base64 output - * @outlen: destination buffer len - * @nwritten: actual length of the base64 data - * @type: the base64 file type. - * - * Encode the given buffer into base64 format. - **/ -cdk_error_t -cdk_armor_encode_buffer (const byte * inbuf, size_t inlen, - char *outbuf, size_t outlen, - size_t * nwritten, int type) -{ - const char *head, *tail, *le; - byte tempbuf[48]; - char tempout[128]; - size_t pos, off, len, rest; - - if (!inbuf || !nwritten) - return CDK_Inv_Value; - if (type > CDK_ARMOR_SIGNATURE) - return CDK_Inv_Mode; - - head = armor_begin[type]; - tail = armor_end[type]; - le = _cdk_armor_get_lineend (); - pos = strlen (head) + 10 + 2 + 2 + strlen (tail) + 10 + 2 + 5 + 2; - /* The output data is 4/3 times larger, plus a line end for each line. */ - pos += (4 * inlen / 3) + 2 * (4 * inlen / 3 / 64); - - if (outbuf && outlen < pos) - return CDK_Too_Short; - - /* Only return the size of the output. */ - if (!outbuf) - { - *nwritten = pos; - return 0; - } - - pos = 0; - memset (outbuf, 0, outlen); - memcpy (outbuf + pos, "-----", 5); - pos += 5; - memcpy (outbuf + pos, head, strlen (head)); - pos += strlen (head); - memcpy (outbuf + pos, "-----", 5); - pos += 5; - memcpy (outbuf + pos, le, strlen (le)); - pos += strlen (le); - memcpy (outbuf + pos, le, strlen (le)); - pos += strlen (le); - rest = inlen; - for (off = 0; off < inlen;) - { - if (rest > 48) - { - memcpy (tempbuf, inbuf + off, 48); - off += 48; - len = 48; - } - else - { - memcpy (tempbuf, inbuf + off, rest); - off += rest; - len = rest; - } - rest -= len; - base64_encode (tempout, tempbuf, len, DIM (tempout) - 1); - memcpy (outbuf + pos, tempout, strlen (tempout)); - pos += strlen (tempout); - memcpy (outbuf + pos, le, strlen (le)); - pos += strlen (le); - } - - memcpy (outbuf + pos, "-----", 5); - pos += 5; - memcpy (outbuf + pos, tail, strlen (tail)); - pos += strlen (tail); - memcpy (outbuf + pos, "-----", 5); - pos += 5; - memcpy (outbuf + pos, le, strlen (le)); - pos += strlen (le); - *nwritten = pos; - return 0; -} diff --git a/src/daemon/https/opencdk/cipher.c b/src/daemon/https/opencdk/cipher.c @@ -1,528 +0,0 @@ -/* cipher.c - Cipher filters - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <assert.h> -#include <sys/stat.h> - -#include "opencdk.h" -#include "main.h" -#include "filters.h" - - -/* The maximal cipher block size in octets. */ -#define MAX_CIPHER_BLKSIZE 16 - - -static off_t -fp_get_length (FILE * fp) -{ - struct stat statbuf; - - if (fstat (fileno (fp), &statbuf)) - return (off_t) - 1; - return statbuf.st_size; -} - - -static cdk_error_t -hash_encode (void *opaque, FILE * in, FILE * out) -{ - md_filter_t *mfx = opaque; - byte buf[BUFSIZE]; - gcry_error_t err; - int nread; - - if (!mfx) - return CDK_Inv_Value; - - _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo); - - if (!mfx->md) - { - err = gcry_md_open (&mfx->md, mfx->digest_algo, 0); - if (err) - return map_gcry_error (err); - } - - while (!feof (in)) - { - nread = fread (buf, 1, BUFSIZE, in); - if (!nread) - break; - gcry_md_write (mfx->md, buf, nread); - } - - wipemem (buf, sizeof (buf)); - return 0; -} - - -cdk_error_t -_cdk_filter_hash (void *opaque, int ctl, FILE * in, FILE * out) -{ - if (ctl == STREAMCTL_READ) - return hash_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - md_filter_t *mfx = opaque; - if (mfx) - { - _cdk_log_debug ("free hash filter\n"); - gcry_md_close (mfx->md); - mfx->md = NULL; - return 0; - } - } - return CDK_Inv_Mode; -} - - -static cdk_error_t -write_header (cipher_filter_t * cfx, FILE * out) -{ - cdk_pkt_encrypted_t ed; - cdk_packet_t pkt; - cdk_error_t rc; - cdk_dek_t dek = cfx->dek; - byte temp[MAX_CIPHER_BLKSIZE + 2]; - size_t blocksize; - int use_mdc, nprefix; - gcry_error_t err; - - blocksize = gcry_cipher_get_algo_blklen (dek->algo); - if (blocksize < 8 || blocksize > 16) - return CDK_Inv_Algo; - - /* It might be possible the receiver does not understand the MDC - output and thus we offer to supress the MDC packet. */ - use_mdc = dek->use_mdc; - if (blocksize == 8) - use_mdc = 0; - - /* We need to increase the data length because the MDC packet will - be also included. It has a fixed length of 22 octets. */ - if (use_mdc && cfx->datalen) - cfx->datalen += 22; - - cdk_pkt_alloc (&pkt, CDK_PKT_ENCRYPTED_MDC); - ed = pkt->pkt.encrypted; - if (!cfx->blkmode.on) - { - ed->len = cfx->datalen; - ed->extralen = blocksize + 2; - } - else - cfx->blkmode.nleft = DEF_BLOCKSIZE; - - if (use_mdc) - { - ed->mdc_method = GCRY_MD_SHA1; - err = gcry_md_open (&cfx->mdc, GCRY_MD_SHA1, 0); - if (err) - return map_gcry_error (err); - } - - /* When we use partial bodies, the MDC feature or a blocksize - larger than 8, we force the use of the new packet format. */ - if (cfx->blkmode.on || use_mdc || blocksize != 8) - pkt->old_ctb = 0; - else - pkt->old_ctb = 1; - pkt->pkttype = use_mdc ? CDK_PKT_ENCRYPTED_MDC : CDK_PKT_ENCRYPTED; - rc = _cdk_pkt_write_fp (out, pkt); - cdk_pkt_release (pkt); - if (rc) - return rc; - - nprefix = blocksize; - gcry_randomize (temp, nprefix, GCRY_STRONG_RANDOM); - temp[nprefix] = temp[nprefix - 2]; - temp[nprefix + 1] = temp[nprefix - 1]; - err = gcry_cipher_open (&cfx->hd, dek->algo, GCRY_CIPHER_MODE_CFB, - use_mdc ? 0 : GCRY_CIPHER_ENABLE_SYNC); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setiv (cfx->hd, NULL, 0); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setkey (cfx->hd, dek->key, dek->keylen); - if (err) - return map_gcry_error (err); - if (cfx->mdc) - gcry_md_write (cfx->mdc, temp, nprefix + 2); - gcry_cipher_encrypt (cfx->hd, temp, nprefix + 2, NULL, 0); - gcry_cipher_sync (cfx->hd); - fwrite (temp, 1, nprefix + 2, out); - if (cfx->blkmode.on) - { - cfx->blkmode.nleft -= (nprefix + 2); - if (use_mdc) - cfx->blkmode.nleft--; /* 1 byte version */ - } - return rc; -} - - -static cdk_error_t -write_mdc_packet (FILE * out, cipher_filter_t * cfx) -{ - byte pktdata[22]; - int dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); - - if (!out || !cfx) - return CDK_Inv_Value; - if (dlen != 20) - return CDK_Inv_Algo; - - /* We must hash the prefix of the MDC packet here */ - pktdata[0] = 0xD3; - pktdata[1] = 0x14; - gcry_md_write (cfx->mdc, pktdata, 2); - gcry_md_final (cfx->mdc); - memcpy (pktdata + 2, gcry_md_read (cfx->mdc, GCRY_MD_SHA1), dlen); - gcry_cipher_encrypt (cfx->hd, pktdata, dlen + 2, NULL, 0); - fwrite (pktdata, 1, dlen + 2, out); - wipemem (pktdata, sizeof (pktdata)); - return 0; -} - - -static inline int -num2bits (size_t n) -{ - size_t i; - - for (i = 0; n > 1; i++) - n >>= 1; - return i; -} - - -static cdk_error_t -write_partial_block (FILE * in, FILE * out, off_t * r_len, - cipher_filter_t * cfx) -{ - gcry_error_t err; - byte buf[DEF_BLOCKSIZE]; - size_t n; - int nread; - - if (!out || !cfx) - return CDK_Inv_Value; - - if (!cfx->blkmode.nleft && *r_len > 0) - { - if (*r_len > DEF_BLOCKSIZE) - { - /*_cdk_log_debug ("write_partial_block: size %lu block %d\n", - *r_len, DEF_BLOCKSIZE);*/ - fputc ((0xE0 | DEF_BLOCKBITS), out); - cfx->blkmode.nleft = DEF_BLOCKSIZE; - (*r_len) -= DEF_BLOCKSIZE; - } - else if (*r_len > 512) - { - n = num2bits (*r_len); - cfx->blkmode.nleft = (1 << n); - /*_cdk_log_debug ("write_partial_block: size %lu bits %d block %d\n", - *r_len, n, (1<<n));*/ - fputc ((0xE0 | n), out); - (*r_len) -= cfx->blkmode.nleft; - } - else - { - size_t pktlen = *r_len; - - /* If we use the MDC mode, we need to increase the final - partial body length to hold the mdc packet itself. */ - if (cfx->mdc) - pktlen += 22; - - if (pktlen < 192) - fputc (pktlen, out); - else if (pktlen < 8384) - { - pktlen -= 192; - fputc ((pktlen / 256) + 192, out); - fputc ((pktlen % 256), out); - } - cfx->blkmode.nleft = pktlen; - /*_cdk_log_debug ("write_partial_block: end %d block\n", pktlen);*/ - (*r_len) -= pktlen; - } - } - else - (*r_len) -= cfx->blkmode.nleft; - - n = cfx->blkmode.nleft < DIM (buf) ? cfx->blkmode.nleft : DIM (buf); - nread = fread (buf, 1, n, in); - if (!nread) - return CDK_EOF; - if (cfx->mdc) - gcry_md_write (cfx->mdc, buf, nread); - err = gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); - if (err) - return map_gcry_error (err); - fwrite (buf, 1, nread, out); - cfx->blkmode.nleft -= nread; - return 0; -} - - -static cdk_error_t -cipher_encode_file (void *opaque, FILE * in, FILE * out) -{ - cipher_filter_t *cfx = opaque; - byte buf[BUFSIZE]; - off_t len, len2; - int nread; - cdk_error_t rc; - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - len = len2 = fp_get_length (in); - if (len == (off_t) - 1) - return CDK_File_Error; - while (!feof (in)) - { - if (cfx->blkmode.on) - { - rc = write_partial_block (in, out, &len2, cfx); - if (rc == CDK_EOF) - break; - if (rc) - { - wipemem (buf, sizeof (buf)); - return rc; - } - continue; - } - nread = fread (buf, 1, DIM (buf), in); - if (!nread) - break; - if (cfx->mdc) - gcry_md_write (cfx->mdc, buf, nread); - gcry_cipher_encrypt (cfx->hd, buf, nread, NULL, 0); - fwrite (buf, 1, nread, out); - } - if (cfx->mdc) - rc = write_mdc_packet (out, cfx); - else - rc = 0; - - wipemem (buf, sizeof (buf)); - return rc; -} - - -static cdk_error_t -read_header (cipher_filter_t * cfx, FILE * in) -{ - cdk_dek_t dek; - byte temp[32]; - int blocksize, nprefix; - int i, c; - gcry_error_t err; - - if (!cfx || !in) - return CDK_Inv_Value; - - dek = cfx->dek; - blocksize = gcry_cipher_get_algo_blklen (dek->algo); - if (blocksize < 8 || blocksize > 16) - return CDK_Inv_Algo; - - nprefix = blocksize; - if (cfx->datalen > 0 && cfx->datalen < (nprefix + 2)) - return CDK_Inv_Value; - if (cfx->mdc_method) - { - err = gcry_md_open (&cfx->mdc, cfx->mdc_method, 0); - if (err) - return map_gcry_error (err); - } - err = gcry_cipher_open (&cfx->hd, dek->algo, GCRY_CIPHER_MODE_CFB, - cfx->mdc_method ? 0 : GCRY_CIPHER_ENABLE_SYNC); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setiv (cfx->hd, NULL, 0); - if (err) - return map_gcry_error (err); - err = gcry_cipher_setkey (cfx->hd, dek->key, dek->keylen); - if (err) - return map_gcry_error (err); - - for (i = 0; i < (nprefix + 2); i++) - { - c = fgetc (in); - if (c == EOF) - return CDK_File_Error; - temp[i] = c; - } - gcry_cipher_decrypt (cfx->hd, temp, nprefix + 2, NULL, 0); - gcry_cipher_sync (cfx->hd); - i = nprefix; - if (temp[i - 2] != temp[i] || temp[i - 1] != temp[i + 1]) - return CDK_Chksum_Error; - if (cfx->mdc) - gcry_md_write (cfx->mdc, temp, nprefix + 2); - if (cfx->blkmode.on) - cfx->blkmode.size -= (nprefix + 2); - return 0; -} - - -static cdk_error_t -finalize_mdc (gcry_md_hd_t md, const byte * buf, size_t nread) -{ - byte mdcbuf[20]; - int dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); - cdk_error_t rc; - - if (dlen != 20) - return CDK_Inv_Algo; - - if (buf[nread - dlen - 2] == 0xD3 && buf[nread - dlen - 1] == 0x14) - { - gcry_md_write (md, buf, nread - dlen); - gcry_md_final (md); - memcpy (mdcbuf, gcry_md_read (md, GCRY_MD_SHA1), dlen); - if (memcmp (mdcbuf, buf + nread - dlen, dlen)) - rc = CDK_Bad_MDC; - else - rc = CDK_Success; - wipemem (mdcbuf, sizeof (mdcbuf)); - return rc; - } - - return CDK_Inv_Packet; -} - - -static cdk_error_t -cipher_decode_file (void *opaque, FILE * in, FILE * out) -{ - cipher_filter_t *cfx = opaque; - cdk_error_t rc; - byte buf[BUFSIZE]; - int nread, nreq; - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - while (!feof (in)) - { - /*_cdk_log_debug ("partial on=%d size=%lu\n", - cfx->blkmode.on, cfx->blkmode.size);*/ - nreq = cfx->blkmode.on ? cfx->blkmode.size : DIM (buf); - nread = fread (buf, 1, nreq, in); - if (!nread) - break; - gcry_cipher_decrypt (cfx->hd, buf, nread, NULL, 0); - if (feof (in) && cfx->mdc) - { - rc = finalize_mdc (cfx->mdc, buf, nread); - if (rc) - { - wipemem (buf, sizeof (buf)); - return rc; - } - /* We need to correct the size here to avoid the MDC - packet will be written to the output. */ - nread -= 22; - } - else if (cfx->mdc) - gcry_md_write (cfx->mdc, buf, nread); - fwrite (buf, 1, nread, out); - if (cfx->blkmode.on) - { - cfx->blkmode.size = _cdk_pkt_read_len (in, &cfx->blkmode.on); - if (cfx->blkmode.size == (size_t) EOF) - return CDK_Inv_Packet; - } - } - - wipemem (buf, sizeof (buf)); - return 0; -} - - -static cdk_error_t -cipher_decode (void *opaque, FILE * in, FILE * out) -{ - cipher_filter_t *cfx = opaque; - cdk_error_t rc; - - _cdk_log_debug ("cipher filter: decode\n"); - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - rc = read_header (cfx, in); - if (!rc) - rc = cipher_decode_file (cfx, in, out); - return rc; -} - - -static cdk_error_t -cipher_encode (void *opaque, FILE * in, FILE * out) -{ - cipher_filter_t *cfx = opaque; - cdk_error_t rc; - - _cdk_log_debug ("cipher filter: encode\n"); - - if (!cfx || !in || !out) - return CDK_Inv_Value; - - cfx->datalen = fp_get_length (in); - if (cfx->datalen < BUFSIZE && cfx->blkmode.on) - cfx->blkmode.on = 0; - rc = write_header (cfx, out); - if (!rc) - rc = cipher_encode_file (cfx, in, out); - return rc; -} - - -cdk_error_t -_cdk_filter_cipher (void *opaque, int ctl, FILE * in, FILE * out) -{ - if (ctl == STREAMCTL_READ) - return cipher_decode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return cipher_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - cipher_filter_t *cfx = opaque; - if (cfx) - { - _cdk_log_debug ("free cipher filter\n"); - gcry_md_close (cfx->mdc); - cfx->mdc = NULL; - gcry_cipher_close (cfx->hd); - cfx->hd = NULL; - return 0; - } - } - return CDK_Inv_Mode; -} diff --git a/src/daemon/https/opencdk/compress.c b/src/daemon/https/opencdk/compress.c @@ -1,238 +0,0 @@ -/* compress.c - Compression filters - * Copyright (C) 2002, 2003 Timo Schulz - * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <time.h> -#ifdef HAVE_LIBZ -# include <zlib.h> -#endif - -#include "opencdk.h" -#include "main.h" -#include "filters.h" - -#ifdef HAVE_LIBZ -static int -compress_data (z_stream * zs, int flush, byte * inbuf, size_t insize, - FILE * out) -{ - int nbytes, zrc; - byte buf[4096]; - - zs->next_in = inbuf; - zs->avail_in = insize; - - do - { - zs->next_out = buf; - zs->avail_out = DIM (buf); - - zrc = deflate (zs, flush); - if (zrc == Z_STREAM_END && flush == Z_FINISH) - ; - else if (zrc != Z_OK) - break; - nbytes = DIM (buf) - zs->avail_out; - fwrite (buf, 1, nbytes, out); - } - while (zs->avail_out == 0 || (flush == Z_FINISH && zrc != Z_STREAM_END)); - return zrc; -} - - -static int -decompress_data (compress_filter_t * zfx, z_stream * zs, - FILE * in, size_t * ret_len) -{ - int nread, nold; - int rc, zrc; - - rc = 0; - nread = 0; - while (zs->avail_out != 0) - { - if (!zs->avail_in) - { - nread = fread (zfx->inbuf, 1, zfx->inbufsize, in); - zs->next_in = zfx->inbuf; - zs->avail_in = nread; - } - nold = zs->avail_out; - zrc = inflate (zs, Z_SYNC_FLUSH); - if (zrc != Z_OK && zrc != Z_STREAM_END) - { - rc = CDK_Zlib_Error; - break; - } - *ret_len = zfx->outbufsize - zs->avail_out; - if (nold == zs->avail_out) - break; - if (zrc == Z_STREAM_END) - { - rc = EOF; /* eof */ - break; - } - } - if (!nread && feof (in)) - rc = -1; - return rc; -} - - -static cdk_error_t -compress_decode (void *opaque, FILE * in, FILE * out) -{ - compress_filter_t *zfx = opaque; - z_stream *zs; - size_t nbytes; - int zrc; - cdk_error_t rc = 0; - - _cdk_log_debug ("compress filter: decode (algo=%d)\n", zfx->algo); - - if (!zfx || !in || !out) - return CDK_Inv_Value; - - zs = cdk_calloc (1, sizeof *zs); - if (!zs) - return CDK_Out_Of_Core; - if (zfx->algo == CDK_COMPRESS_ZIP) - zrc = inflateInit2 (zs, -13); - else - zrc = inflateInit (zs); - if (zrc != Z_OK) - return CDK_Zlib_Error; - - zfx->outbufsize = 8192; - zfx->inbufsize = 2048; - memset (zfx->inbuf, 0, sizeof zfx->inbuf); - zs->avail_in = 0; - - nbytes = 0; - while (rc != -1) - { - zs->next_out = zfx->outbuf; - zs->avail_out = 8192; - rc = decompress_data (zfx, zs, in, &nbytes); - fwrite (zfx->outbuf, 1, nbytes, out); - } - inflateEnd (zs); - cdk_free (zs); - if (rc == CDK_EOF) - rc = 0; - return rc; -} - - -static cdk_error_t -compress_encode (void *opaque, FILE * in, FILE * out) -{ - compress_filter_t *zfx = opaque; - z_stream *zs; - struct cdk_pkt_compressed_s cd; - struct cdk_packet_s pkt; - int zrc, nread; - cdk_error_t rc; - - _cdk_log_debug ("compress filter: encode\n"); - - if (!zfx || !in || !out) - return CDK_Inv_Value; - - if (!zfx->algo) - zfx->algo = CDK_COMPRESS_ZIP; - - memset (&cd, 0, sizeof (cd)); - cd.len = 0; - cd.algorithm = zfx->algo; - pkt.pkttype = CDK_PKT_COMPRESSED; - pkt.pkt.compressed = &cd; - rc = _cdk_pkt_write_fp (out, &pkt); - if (rc) - return rc; - - zs = cdk_calloc (1, sizeof *zs); - if (!zs) - return CDK_Out_Of_Core; - if (zfx->algo == CDK_COMPRESS_ZIP) - rc = deflateInit2 (zs, zfx->level, Z_DEFLATED, -13, 8, - Z_DEFAULT_STRATEGY); - else - rc = deflateInit (zs, zfx->level); - if (rc != Z_OK) - { - cdk_free (zs); - return CDK_Zlib_Error; - } - zfx->outbufsize = 8192; - memset (zfx->outbuf, 0, sizeof zfx->outbuf); - - while (!feof (in)) - { - nread = fread (zfx->outbuf, 1, zfx->outbufsize, in); - if (!nread) - break; - zrc = compress_data (zs, Z_NO_FLUSH, zfx->outbuf, nread, out); - if (zrc) - { - rc = CDK_Zlib_Error; - break; - } - } - if (!rc) - { - nread = 0; - zrc = compress_data (zs, Z_FINISH, zfx->outbuf, nread, out); - if (zrc != Z_STREAM_END) - rc = CDK_Zlib_Error; - } - deflateEnd (zs); - cdk_free (zs); - return rc; -} - - -cdk_error_t -_cdk_filter_compress (void *opaque, int ctl, FILE * in, FILE * out) -{ - if (ctl == STREAMCTL_READ) - return compress_decode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return compress_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - compress_filter_t *zfx = opaque; - if (zfx) - { - _cdk_log_debug ("free compress filter\n"); - zfx->level = 0; - zfx->algo = 0; - return 0; - } - } - return CDK_Inv_Mode; -} - -#else -cdk_error_t -_cdk_filter_compress (void *opaque, int ctl, FILE * in, FILE * out) -{ - return CDK_Not_Implemented; -} -#endif /* HAVE_LIBZ */ diff --git a/src/daemon/https/opencdk/context.h b/src/daemon/https/opencdk/context.h @@ -1,120 +0,0 @@ -/* context.h - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifndef CDK_CONTEXT_H -#define CDK_CONTEXT_H - -#include "types.h" - -struct cdk_listkey_s { - unsigned init:1; - cdk_stream_t inp; - cdk_keydb_hd_t db; - int type; - union { - char *patt; - cdk_strlist_t fpatt; - } u; - cdk_strlist_t t; -}; - - -struct cdk_s2k_s { - int mode; - byte hash_algo; - byte salt[8]; - u32 count; -}; - - -struct cdk_ctx_s { - int cipher_algo; - int digest_algo; - struct { - int algo; - int level; - } compress; - struct { - int mode; - int digest_algo; - } _s2k; - struct { - unsigned blockmode:1; - unsigned armor:1; - unsigned textmode:1; - unsigned compress:1; - unsigned mdc:1; - unsigned overwrite; - unsigned force_digest:1; - } opt; - struct { - cdk_verify_result_t verify; - } result; - struct { - cdk_pkt_seckey_t sk; - unsigned on:1; - } cache; - cdk_dek_t dek; - struct { - cdk_keydb_hd_t sec; - cdk_keydb_hd_t pub; - unsigned int close_db:1; - } db; - char *(*passphrase_cb) (void *opaque, const char *prompt); - void * passphrase_cb_value; -}; - -struct cdk_prefitem_s { - byte type; - byte value; -}; - -struct cdk_desig_revoker_s { - struct cdk_desig_revoker_s * next; - byte r_class; - byte algid; - byte fpr[KEY_FPR_LEN]; -}; - -struct cdk_subpkt_s { - struct cdk_subpkt_s * next; - u32 size; - byte type; - byte d[1]; -}; - -struct cdk_keylist_s { - struct cdk_keylist_s * next; - union { - cdk_pkt_pubkey_t pk; - cdk_pkt_seckey_t sk; - } key; - int version; - int type; -}; - -struct cdk_dek_s { - int algo; - int keylen; - int use_mdc; - byte key[32]; /* 256-bit */ -}; - -struct cdk_strlist_s { - struct cdk_strlist_s * next; - char d[1]; -}; - -#endif /* CDK_CONTEXT_H */ diff --git a/src/daemon/https/opencdk/dummy.c b/src/daemon/https/opencdk/dummy.c @@ -1,15 +0,0 @@ -#include <stdio.h> -#include <string.h> - -#include "opencdk.h" -#include "main.h" -#include "filters.h" -#include "packet.h" - -cdk_error_t -_cdk_proc_packets (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t data, - const char *output, cdk_stream_t outstream, - gcry_md_hd_t md) -{ - return 0; -} diff --git a/src/daemon/https/opencdk/filters.h b/src/daemon/https/opencdk/filters.h @@ -1,95 +0,0 @@ -/* filters.h - Filter structs - * Copyright (C) 2002, 2003 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifndef CDK_FILTERS_H -#define CDK_FILTERS_H - -enum { - STREAMCTL_READ = 0, - STREAMCTL_WRITE = 1, - STREAMCTL_FREE = 2 -}; - -typedef struct { - gcry_cipher_hd_t hd; - gcry_md_hd_t mdc; - int mdc_method; - cdk_dek_t dek; - u32 datalen; - struct { - size_t on; - off_t size; - off_t nleft; - } blkmode; - cdk_stream_t s; -} cipher_filter_t; - -typedef struct { - int digest_algo; - gcry_md_hd_t md; -} md_filter_t; - -typedef struct { - const char *le; /* line endings */ - const char *hdrlines; - u32 crc; - int crc_okay; - int idx, idx2; -} armor_filter_t; - -typedef struct { - cdk_lit_format_t mode; - char *orig_filename; /* This original name of the input file. */ - char *filename; - gcry_md_hd_t md; - struct { - size_t on; - off_t size; - } blkmode; -} literal_filter_t; - -typedef struct { - size_t inbufsize; - byte inbuf[8192]; - size_t outbufsize; - byte outbuf[8192]; - int algo; /* compress algo */ - int level; -} compress_filter_t; - -typedef struct { - const char * lf; -} text_filter_t; - - -/*-- armor.c -*/ -int _cdk_filter_armor( void * opaque, int ctl, FILE * in, FILE * out ); - -/*-- cipher.c --*/ -cdk_error_t _cdk_filter_hash( void * opaque, int ctl, FILE * in, FILE * out ); -cdk_error_t _cdk_filter_cipher( void * opaque, int ctl, - FILE * in, FILE * out ); - -/*-- literal.c --*/ -int _cdk_filter_literal( void * opaque, int ctl, FILE * in, FILE * out ); -int _cdk_filter_text( void * opaque, int ctl, FILE * in, FILE * out ); - -/*-- compress.c --*/ -cdk_error_t _cdk_filter_compress( void * opaque, int ctl, - FILE * in, FILE * out ); - -#endif /* CDK_FILTERS_H */ - - diff --git a/src/daemon/https/opencdk/kbnode.c b/src/daemon/https/opencdk/kbnode.c @@ -1,581 +0,0 @@ -/* kbnode.c - keyblock node utility functions - * Copyright (C) 1998-2001 Free Software Foundation, Inc. - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" - - -/** - * cdk_kbnode_new: - * @pkt: the packet to add - * - * Allocate a new key node and add the packet. - **/ -cdk_kbnode_t -cdk_kbnode_new (cdk_packet_t pkt) -{ - cdk_kbnode_t n; - - n = cdk_calloc (1, sizeof *n); - if (!n) - return NULL; - n->pkt = pkt; - return n; -} - - -void -_cdk_kbnode_clone (cdk_kbnode_t node) -{ - /* Mark the node as clone which means that the packet - will not be freed, just the node itself. */ - if (node) - node->is_cloned = 1; -} - - -/** - * cdk_kbnode_release: - * @n: the key node - * - * Release the memory of the node. - **/ -void -cdk_kbnode_release (cdk_kbnode_t node) -{ - cdk_kbnode_t n2; - - while (node) - { - n2 = node->next; - if (!node->is_cloned) - cdk_pkt_release (node->pkt); - cdk_free (node); - node = n2; - } -} - - -/** - * cdk_kbnode_delete: - * @node: the key node - * - * Mark the given node as deleted. - **/ -void -cdk_kbnode_delete (cdk_kbnode_t node) -{ - if (node) - node->is_deleted = 1; -} - - -/* Append NODE to ROOT. ROOT must exist! */ -void -_cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node) -{ - cdk_kbnode_t n1; - - for (n1 = root; n1->next; n1 = n1->next) - ; - n1->next = node; -} - - -/** - * cdk_kbnode_insert: - * @root: the root key node - * @node: the node to add - * @pkttype: packet type - * - * Insert @node into the list after @root but before a packet which is not of - * type @pkttype (only if @pkttype != 0). - **/ -void -cdk_kbnode_insert (cdk_kbnode_t root, cdk_kbnode_t node, int pkttype) -{ - if (!pkttype) - { - node->next = root->next; - root->next = node; - } - else - { - cdk_kbnode_t n1; - - for (n1 = root; n1->next; n1 = n1->next) - if (pkttype != n1->next->pkt->pkttype) - { - node->next = n1->next; - n1->next = node; - return; - } - /* No such packet, append */ - node->next = NULL; - n1->next = node; - } -} - - -/** - * cdk_kbnode_find_prev: - * @root: the root key node - * @node: the key node - * @pkttype: packet type - * - * Find the previous node (if @pkttype = 0) or the previous node - * with pkttype @pkttype in the list starting with @root of @node. - **/ -cdk_kbnode_t -cdk_kbnode_find_prev (cdk_kbnode_t root, cdk_kbnode_t node, int pkttype) -{ - cdk_kbnode_t n1; - - for (n1 = NULL; root && root != node; root = root->next) - { - if (!pkttype || root->pkt->pkttype == pkttype) - n1 = root; - } - return n1; -} - - -/** - * cdk_kbnode_find_next: - * @node: the key node - * @pkttype: packet type - * - * Ditto, but find the next packet. The behaviour is trivial if - * @pkttype is 0 but if it is specified, the next node with a packet - * of this type is returned. The function has some knowledge about - * the valid ordering of packets: e.g. if the next signature packet - * is requested, the function will not return one if it encounters - * a user-id. - **/ -cdk_kbnode_t -cdk_kbnode_find_next (cdk_kbnode_t node, int pkttype) -{ - for (node = node->next; node; node = node->next) - { - if (!pkttype) - return node; - else if (pkttype == CDK_PKT_USER_ID && - (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || - node->pkt->pkttype == CDK_PKT_SECRET_KEY)) - return NULL; - else if (pkttype == CDK_PKT_SIGNATURE && - (node->pkt->pkttype == CDK_PKT_USER_ID || - node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || - node->pkt->pkttype == CDK_PKT_SECRET_KEY)) - return NULL; - else if (node->pkt->pkttype == pkttype) - return node; - } - return NULL; -} - - -/** - * cdk_kbnode_find: - * @node: the key node - * @pkttype: packet type - * - * Try to find the next node with the packettype @pkttype. - **/ -cdk_kbnode_t -cdk_kbnode_find (cdk_kbnode_t node, int pkttype) -{ - for (; node; node = node->next) - { - if (node->pkt->pkttype == pkttype) - return node; - } - return NULL; -} - - -/** - * cdk_kbnode_find_packet: - * @node: the key node - * @pkttype: packet type - * - * Same as cdk_kbnode_find but it returns the packet instead of the node. - **/ -cdk_packet_t -cdk_kbnode_find_packet (cdk_kbnode_t node, int pkttype) -{ - cdk_kbnode_t res; - - res = cdk_kbnode_find (node, pkttype); - return res ? res->pkt : NULL; -} - - -/**************** - * Walk through a list of kbnodes. This function returns - * the next kbnode for each call; before using the function the first - * time, the caller must set CONTEXT to NULL (This has simply the effect - * to start with ROOT). - */ -cdk_kbnode_t -cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t * context, int all) -{ - cdk_kbnode_t n; - - do - { - if (!*context) - { - *context = root; - n = root; - } - else - { - n = (*context)->next; - *context = n; - } - } - while (!all && n && n->is_deleted); - return n; -} - - -/** - * cdk_kbnode_commit: - * @root: the nodes - * - * Commit changes made to the kblist at ROOT. Note that ROOT my change, - * and it is therefore passed by reference. - * The function has the effect of removing all nodes marked as deleted. - * returns true if any node has been changed - */ -int -cdk_kbnode_commit (cdk_kbnode_t * root) -{ - cdk_kbnode_t n, nl; - int changed = 0; - - for (n = *root, nl = NULL; n; n = nl->next) - { - if (n->is_deleted) - { - if (n == *root) - *root = nl = n->next; - else - nl->next = n->next; - if (!n->is_cloned) - cdk_pkt_release (n->pkt); - cdk_free (n); - changed = 1; - } - else - nl = n; - } - return changed; -} - - -/** - * cdk_kbnode_remove: - * @root: the root node - * @node: the node to delete - * - * Remove a node from the root node. - */ -void -cdk_kbnode_remove (cdk_kbnode_t * root, cdk_kbnode_t node) -{ - cdk_kbnode_t n, nl; - - for (n = *root, nl = NULL; n; n = nl->next) - { - if (n == node) - { - if (n == *root) - *root = nl = n->next; - else - nl->next = n->next; - if (!n->is_cloned) - cdk_pkt_release (n->pkt); - cdk_free (n); - } - else - nl = n; - } -} - - - -/** - * cdk_cdknode_move: - * @root: root node - * @node: the node to move - * @where: destination place where to move the node. - * - * Move NODE behind right after WHERE or to the beginning if WHERE is NULL. - */ -void -cdk_kbnode_move (cdk_kbnode_t * root, cdk_kbnode_t node, cdk_kbnode_t where) -{ - cdk_kbnode_t tmp, prev; - - if (!root || !*root || !node) - return; - for (prev = *root; prev && prev->next != node; prev = prev->next) - ; - if (!prev) - return; /* Node is not in the list */ - - if (!where) - { /* Move node before root */ - if (node == *root) - return; - prev->next = node->next; - node->next = *root; - *root = node; - return; - } - if (node == where) /* Move it after where. */ - return; - tmp = node->next; - node->next = where->next; - where->next = node; - prev->next = tmp; -} - - -/** - * cdk_kbnode_get_packet: - * @node: the key node - * - * Return the packet which is stored inside the node in @node. - **/ -cdk_packet_t -cdk_kbnode_get_packet (cdk_kbnode_t node) -{ - if (node) - return node->pkt; - return NULL; -} - - -/** - * cdk_kbnode_read_from_mem: - * @ret_node: the new key node - * @buf: the buffer which stores the key sequence - * @buflen: the length of the buffer - * - * Try to read a key node from the memory buffer @buf. - **/ -cdk_error_t -cdk_kbnode_read_from_mem (cdk_kbnode_t * ret_node, - const byte * buf, size_t buflen) -{ - cdk_stream_t inp; - cdk_error_t rc; - - if (!buflen || !ret_node || !buf) - return CDK_Inv_Value; - - *ret_node = NULL; - rc = cdk_stream_tmp_from_mem (buf, buflen, &inp); - if (rc) - return rc; - rc = cdk_keydb_get_keyblock (inp, ret_node); - cdk_stream_close (inp); - return rc; -} - -/** - * cdk_kbnode_write_to_mem_alloc: - * @node: the key node - * @r_buf: buffer to hold the raw data - * @r_buflen: buffer length of the allocated raw data. - * - * The function acts similar to cdk_kbnode_write_to_mem but - * it allocates the buffer to avoid the lengthy second run. - */ -cdk_error_t -cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, - byte ** r_buf, size_t * r_buflen) -{ - cdk_kbnode_t n; - cdk_stream_t s; - cdk_error_t rc; - size_t len; - - if (!node) - return CDK_Inv_Value; - - *r_buf = NULL; - *r_buflen = 0; - - rc = cdk_stream_tmp_new (&s); - if (rc) - return rc; - - for (n = node; n; n = n->next) - { - /* Skip all packets which cannot occur in a key composition. */ - if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY && - n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY && - n->pkt->pkttype != CDK_PKT_SECRET_KEY && - n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY && - n->pkt->pkttype != CDK_PKT_SIGNATURE && - n->pkt->pkttype != CDK_PKT_USER_ID && - n->pkt->pkttype != CDK_PKT_ATTRIBUTE) - continue; - rc = cdk_pkt_write (s, n->pkt); - if (rc) - { - cdk_stream_close (s); - return rc; - } - } - - cdk_stream_seek (s, 0); - len = cdk_stream_get_length (s); - *r_buf = cdk_calloc (1, len); - *r_buflen = cdk_stream_read (s, *r_buf, len); - cdk_stream_close (s); - return 0; -} - - -/** - * cdk_kbnode_write_to_mem: - * @node: the key node - * @buf: the buffer to store the node data - * @r_nbytes: the new length of the buffer. - * - * Try to write the contents of the key node to the buffer @buf and - * return the length of it in @r_nbytes. If buf is zero, only the - * length of the node is calculated and returned in @r_nbytes. - * Whenever it is possible, the cdk_kbnode_write_to_mem_alloc should be used. - **/ -cdk_error_t -cdk_kbnode_write_to_mem (cdk_kbnode_t node, byte * buf, size_t * r_nbytes) -{ - cdk_kbnode_t n; - cdk_stream_t s; - size_t len; - cdk_error_t rc; - - if (!node) - return CDK_Inv_Value; - - rc = cdk_stream_tmp_new (&s); - if (rc) - return rc; - - for (n = node; n; n = n->next) - { - /* Skip all packets which cannot occur in a key composition. */ - if (n->pkt->pkttype != CDK_PKT_PUBLIC_KEY && - n->pkt->pkttype != CDK_PKT_PUBLIC_SUBKEY && - n->pkt->pkttype != CDK_PKT_SECRET_KEY && - n->pkt->pkttype != CDK_PKT_SECRET_SUBKEY && - n->pkt->pkttype != CDK_PKT_SIGNATURE && - n->pkt->pkttype != CDK_PKT_USER_ID && - n->pkt->pkttype != CDK_PKT_ATTRIBUTE) - continue; - rc = cdk_pkt_write (s, n->pkt); - if (rc) - { - cdk_stream_close (s); - return rc; - } - } - - cdk_stream_seek (s, 0); - len = cdk_stream_get_length (s); - if (!buf) - { - *r_nbytes = len; /* Only return the length of the buffer */ - cdk_stream_close (s); - return 0; - } - if (*r_nbytes < len) - rc = CDK_Too_Short; - if (!rc) - *r_nbytes = cdk_stream_read (s, buf, len); - cdk_stream_close (s); - return rc; -} - - -/** - * cdk_kbnode_hash: - * @node: the key node - * @hashctx: opaque pointer to the hash context - * @is_v4: OpenPGP signature (yes=1, no=0) - * @pkttype: packet type to hash (if zero use the packet type from the node) - * @flags: flags which depend on the operation - * - * Hash the key node contents. Two modes are supported. If the packet - * type is used (!= 0) then the function searches the first node with - * this type. Otherwise the node is seen as a single node and the type - * is extracted from it. - **/ -cdk_error_t -cdk_kbnode_hash (cdk_kbnode_t node, gcry_md_hd_t md, int is_v4, - int pkttype, int flags) -{ - cdk_packet_t pkt; - - if (!node || !md) - return CDK_Inv_Value; - if (!pkttype) - { - pkt = cdk_kbnode_get_packet (node); - pkttype = pkt->pkttype; - } - else - { - pkt = cdk_kbnode_find_packet (node, pkttype); - if (!pkt) - return CDK_Inv_Packet; - } - - switch (pkttype) - { - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - _cdk_hash_pubkey (pkt->pkt.public_key, md, flags & 1); - break; - - case CDK_PKT_USER_ID: - _cdk_hash_userid (pkt->pkt.user_id, is_v4, md); - break; - - case CDK_PKT_SIGNATURE: - _cdk_hash_sig_data (pkt->pkt.signature, md); - break; - - default: - return CDK_Inv_Mode; - } - return 0; -} diff --git a/src/daemon/https/opencdk/keydb.c b/src/daemon/https/opencdk/keydb.c @@ -1,2303 +0,0 @@ -/* keydb.c - Key database routines - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <sys/stat.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <ctype.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" -#include "filters.h" -#include "stream.h" - - -#define KEYID_CMP(a, b) ((a[0]) == (b[0]) && (a[1]) == (b[1])) -#define KEYDB_CACHE_ENTRIES 8 - - -/* Internal key index structure. */ -struct key_idx_s -{ - off_t offset; - u32 keyid[2]; - byte fpr[KEY_FPR_LEN]; -}; -typedef struct key_idx_s *key_idx_t; - - -/* Internal handle for the search operation. */ -struct cdk_dbsearch_s -{ - union - { - char *pattern; /* A search is performed by pattern. */ - u32 keyid[2]; /* A search by keyid. */ - byte fpr[KEY_FPR_LEN]; /* A search by fingerprint. */ - } u; - int type; -}; -typedef struct cdk_dbsearch_s *cdk_dbsearch_t; - -/* Internal key cache to associate a key with an file offset. */ -struct key_table_s -{ - struct key_table_s *next; - off_t offset; - cdk_dbsearch_t desc; -}; -typedef struct key_table_s *key_table_t; - -/* Internal key database handle. */ -struct cdk_keydb_hd_s -{ - int type; /* type of the key db handle. */ - int fp_ref; /* 1=means it is a reference and shall not be closed. */ - cdk_stream_t fp; - cdk_stream_t idx; - cdk_dbsearch_t dbs; - char *name; /* name of the underlying file or NULL. */ - char *idx_name; /* name of the index file or NULL. */ - struct key_table_s *cache; - size_t ncache; - unsigned int secret:1; /* contain secret keys. */ - unsigned int isopen:1; /* the underlying stream is opened. */ - unsigned int no_cache:1; /* disable the index cache. */ - unsigned int search:1; /* handle is in search mode. */ - - /* structure to store some stats about the keydb. */ - struct - { - size_t new_keys; /* amount of new keys that were imported. */ - } stats; -}; - - -static void keydb_cache_free (key_table_t cache); -static int keydb_search_copy (cdk_dbsearch_t * r_dst, cdk_dbsearch_t src); -static void keydb_search_free (cdk_dbsearch_t dbs); -static int classify_data (const byte * buf, size_t len); -static cdk_kbnode_t find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk); - - -static char * -keydb_idx_mkname (const char *file) -{ - char *fname, *fmt; - - fmt = "%s.idx"; - fname = cdk_calloc (1, strlen (file) + strlen (fmt) + 1); - if (!fname) - return NULL; - sprintf (fname, fmt, file); - return fname; -} - - -/* This functions builds an index of the keyring into a separate file - with the name keyring.ext.idx. It contains the offset of all public- - and public subkeys. The format of the file is: - -------- - 4 octets offset of the packet - 8 octets keyid - 20 octets fingerprint - -------- - We store the keyid and the fingerprint due to the fact we can't get - the keyid from a v3 fingerprint directly. -*/ -static cdk_error_t -keydb_idx_build (const char *file) -{ - cdk_packet_t pkt; - cdk_stream_t inp, out = NULL; - byte buf[4 + 8 + KEY_FPR_LEN]; - char *idx_name; - u32 keyid[2]; - cdk_error_t rc; - - if (!file) - return CDK_Inv_Value; - - rc = cdk_stream_open (file, &inp); - if (rc) - return rc; - - idx_name = keydb_idx_mkname (file); - if (!idx_name) - { - cdk_stream_close (inp); - return CDK_Out_Of_Core; - } - rc = cdk_stream_create (idx_name, &out); - cdk_free (idx_name); - if (rc) - { - cdk_stream_close (inp); - return rc; - } - - cdk_pkt_new (&pkt); - while (!cdk_stream_eof (inp)) - { - off_t pos = cdk_stream_tell (inp); - - rc = cdk_pkt_read (inp, pkt); - if (rc) - { - _cdk_log_debug ("index build failed packet off=%lu\n", pos); - /* FIXME: The index is incomplete */ - break; - } - if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || - pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) - { - _cdk_u32tobuf (pos, buf); - cdk_pk_get_keyid (pkt->pkt.public_key, keyid); - _cdk_u32tobuf (keyid[0], buf + 4); - _cdk_u32tobuf (keyid[1], buf + 8); - cdk_pk_get_fingerprint (pkt->pkt.public_key, buf + 12); - cdk_stream_write (out, buf, 4 + 8 + KEY_FPR_LEN); - } - cdk_pkt_free (pkt); - } - - cdk_pkt_release (pkt); - - cdk_stream_close (out); - cdk_stream_close (inp); - return rc; -} - - -/** - * cdk_keydb_idx_rebuild: - * @hd: key database handle - * - * Rebuild the key index files for the given key database. - **/ -cdk_error_t -cdk_keydb_idx_rebuild (cdk_keydb_hd_t db) -{ - struct stat stbuf; - char *tmp_idx_name; - cdk_error_t rc; - int err; - - if (!db || !db->name) - return CDK_Inv_Value; - if (db->secret) - return 0; - - tmp_idx_name = keydb_idx_mkname (db->name); - if (!tmp_idx_name) - return CDK_Out_Of_Core; - err = stat (tmp_idx_name, &stbuf); - cdk_free (tmp_idx_name); - /* This function expects an existing index which can be rebuild, - if no index exists we do not build one and just return. */ - if (err) - return 0; - - cdk_stream_close (db->idx); - db->idx = NULL; - if (!db->idx_name) - { - db->idx_name = keydb_idx_mkname (db->name); - if (!db->idx_name) - return CDK_Out_Of_Core; - } - rc = keydb_idx_build (db->name); - if (!rc) - rc = cdk_stream_open (db->idx_name, &db->idx); - return rc; -} - - -static cdk_error_t -keydb_idx_parse (cdk_stream_t inp, key_idx_t * r_idx) -{ - key_idx_t idx; - byte buf[4]; - - if (!inp || !r_idx) - return CDK_Inv_Value; - - idx = cdk_calloc (1, sizeof *idx); - if (!idx) - return CDK_Out_Of_Core; - - while (!cdk_stream_eof (inp)) - { - if (cdk_stream_read (inp, buf, 4) == CDK_EOF) - break; - idx->offset = _cdk_buftou32 (buf); - cdk_stream_read (inp, buf, 4); - idx->keyid[0] = _cdk_buftou32 (buf); - cdk_stream_read (inp, buf, 4); - idx->keyid[1] = _cdk_buftou32 (buf); - cdk_stream_read (inp, idx->fpr, KEY_FPR_LEN); - break; - } - *r_idx = idx; - return cdk_stream_eof (inp) ? CDK_EOF : 0; -} - - -static cdk_error_t -keydb_idx_search (cdk_stream_t inp, u32 * keyid, const byte * fpr, - off_t * r_off) -{ - key_idx_t idx; - - if (!inp || !r_off) - return CDK_Inv_Value; - if ((keyid && fpr) || (!keyid && !fpr)) - return CDK_Inv_Mode; - - /* We need an initialize the offset var with a value - because it might be possible the returned offset will - be 0 and then we cannot differ between the begin and an EOF. */ - *r_off = 0xFFFFFFFF; - cdk_stream_seek (inp, 0); - while (keydb_idx_parse (inp, &idx) != CDK_EOF) - { - if (keyid && KEYID_CMP (keyid, idx->keyid)) - { - *r_off = idx->offset; - break; - } - else if (fpr && !memcmp (idx->fpr, fpr, KEY_FPR_LEN)) - { - *r_off = idx->offset; - break; - } - cdk_free (idx); - idx = NULL; - } - cdk_free (idx); - return *r_off != 0xFFFFFFFF ? 0 : CDK_EOF; -} - - -/** - * cdk_keydb_new_from_mem: - * @r_hd: The keydb output handle. - * @data: The raw key data. - * @datlen: The length of the raw data. - * - * Create a new keyring db handle from the contents of a buffer. - */ -cdk_error_t -cdk_keydb_new_from_mem (cdk_keydb_hd_t * r_db, int secret, - const void *data, size_t datlen) -{ - cdk_keydb_hd_t db; - cdk_error_t rc; - - if (!r_db) - return CDK_Inv_Value; - *r_db = NULL; - db = calloc (1, sizeof *db); - rc = cdk_stream_tmp_from_mem (data, datlen, &db->fp); - if (!db->fp) - { - cdk_free (db); - return rc; - } - if (cdk_armor_filter_use (db->fp)) - cdk_stream_set_armor_flag (db->fp, 0); - db->type = CDK_DBTYPE_DATA; - db->secret = secret; - *r_db = db; - return 0; -} - - -/** - * cdk_keydb_new_from_stream: - * @r_hd: the output keydb handle - * @secret: does the stream contain secret key data - * @in: the input stream to use - * - * This function creates a new keydb handle based on the given - * stream. The stream is not closed in cdk_keydb_free() and it - * is up to the caller to close it. No decoding is done. - */ -cdk_error_t -cdk_keydb_new_from_stream (cdk_keydb_hd_t * r_hd, int secret, cdk_stream_t in) -{ - cdk_keydb_hd_t hd; - - if (!r_hd) - return CDK_Inv_Value; - *r_hd = NULL; - - hd = calloc (1, sizeof *hd); - hd->fp = in; - hd->fp_ref = 1; - hd->type = CDK_DBTYPE_STREAM; - hd->secret = secret; - *r_hd = hd; - - /* We do not push any filters and thus we expect that the format - of the stream has the format the user wanted. */ - - return 0; -} - - -cdk_error_t -cdk_keydb_new_from_file (cdk_keydb_hd_t * r_hd, int secret, const char *fname) -{ - cdk_keydb_hd_t hd; - - if (!r_hd) - return CDK_Inv_Value; - *r_hd = NULL; - hd = calloc (1, sizeof *hd); - hd->name = cdk_strdup (fname); - if (!hd->name) - { - cdk_free (hd); - return CDK_Out_Of_Core; - } - hd->type = secret ? CDK_DBTYPE_SK_KEYRING : CDK_DBTYPE_PK_KEYRING; - hd->secret = secret; - *r_hd = hd; - return 0; -} - - - -/** - * cdk_keydb_new: - * @r_hd: handle to store the new keydb object - * @type: type of the keyring - * @data: data which depends on the keyring type - * @count: length of the data - * - * Create a new keydb object - **/ -cdk_error_t -cdk_keydb_new (cdk_keydb_hd_t * r_hd, int type, void *data, size_t count) -{ - switch (type) - { - case CDK_DBTYPE_PK_KEYRING: - case CDK_DBTYPE_SK_KEYRING: - return cdk_keydb_new_from_file (r_hd, type == CDK_DBTYPE_SK_KEYRING, - (const char *) data); - - case CDK_DBTYPE_DATA: - return cdk_keydb_new_from_mem (r_hd, 0, data, count); - - case CDK_DBTYPE_STREAM: - return cdk_keydb_new_from_stream (r_hd, 0, (cdk_stream_t) data); - - default: - return CDK_Inv_Mode; - } - return CDK_Inv_Mode; -} - - -/** - * cdk_keydb_free: - * @hd: the keydb object - * - * Free the keydb object. - **/ -void -cdk_keydb_free (cdk_keydb_hd_t hd) -{ - if (!hd) - return; - - if (hd->name) - { - cdk_free (hd->name); - hd->name = NULL; - } - - if (hd->fp && !hd->fp_ref) - { - cdk_stream_close (hd->fp); - hd->fp = NULL; - } - - if (hd->idx) - { - cdk_stream_close (hd->idx); - hd->idx = NULL; - } - - hd->isopen = 0; - hd->no_cache = 0; - hd->secret = 0; - keydb_cache_free (hd->cache); - hd->cache = NULL; - keydb_search_free (hd->dbs); - hd->dbs = NULL; - cdk_free (hd); -} - - -cdk_error_t -_cdk_keydb_open (cdk_keydb_hd_t hd, cdk_stream_t * ret_kr) -{ - cdk_error_t rc, ec; - - if (!hd || !ret_kr) - return CDK_Inv_Value; - - rc = 0; - if ((hd->type == CDK_DBTYPE_DATA || hd->type == CDK_DBTYPE_STREAM) - && hd->fp) - cdk_stream_seek (hd->fp, 0); - else if (hd->type == CDK_DBTYPE_PK_KEYRING || - hd->type == CDK_DBTYPE_SK_KEYRING) - { - if (!hd->isopen && hd->name) - { - rc = cdk_stream_open (hd->name, &hd->fp); - if (rc) - goto leave; - if (cdk_armor_filter_use (hd->fp)) - cdk_stream_set_armor_flag (hd->fp, 0); - hd->isopen = 1; - /* We disable the index cache for smaller keyrings. */ - if (cdk_stream_get_length (hd->fp) < 524288) - { - hd->no_cache = 1; - goto leave; - } - cdk_free (hd->idx_name); - hd->idx_name = keydb_idx_mkname (hd->name); - if (!hd->idx_name) - { - rc = CDK_Out_Of_Core; - goto leave; - } - ec = cdk_stream_open (hd->idx_name, &hd->idx); - if (ec && !hd->secret) - { - rc = keydb_idx_build (hd->name); - if (!rc) - rc = cdk_stream_open (hd->idx_name, &hd->idx); - if (!rc) - _cdk_log_debug ("create key index table\n"); - else - { - /* This is no real error, it just means we can't create - the index at the given directory. maybe we've no write - access. in this case, we simply disable the index. */ - _cdk_log_debug ("disable key index table err=%d\n", rc); - rc = 0; - hd->no_cache = 1; - } - } - } - else - { - /* We use the cache to search keys, so we always rewind the - STREAM. Except when the _NEXT search mode is used because - this mode is an enumeration and no seeking is needed. */ - if (!hd->search || - (hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT)) - cdk_stream_seek (hd->fp, 0); - } - } - else - return CDK_Inv_Mode; - -leave: - if (rc) - { - cdk_stream_close (hd->fp); - hd->fp = NULL; - } - *ret_kr = hd->fp; - return rc; -} - - -static int -find_by_keyid (cdk_kbnode_t knode, cdk_dbsearch_t ks) -{ - cdk_kbnode_t node; - u32 keyid[2]; - - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || - node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || - node->pkt->pkttype == CDK_PKT_SECRET_KEY || - node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY) - { - _cdk_pkt_get_keyid (node->pkt, keyid); - switch (ks->type) - { - case CDK_DBSEARCH_SHORT_KEYID: - if (keyid[1] == ks->u.keyid[1]) - return 1; - break; - - case CDK_DBSEARCH_KEYID: - if (KEYID_CMP (keyid, ks->u.keyid)) - return 1; - break; - - default: - _cdk_log_debug ("find_by_keyid: invalid mode = %d\n", ks->type); - return 0; - } - } - } - return 0; -} - - -static int -find_by_fpr (cdk_kbnode_t knode, cdk_dbsearch_t ks) -{ - cdk_kbnode_t node; - byte fpr[KEY_FPR_LEN]; - - if (ks->type != CDK_DBSEARCH_FPR) - return 0; - - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || - node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || - node->pkt->pkttype == CDK_PKT_SECRET_KEY || - node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY) - { - _cdk_pkt_get_fingerprint (node->pkt, fpr); - if (!memcmp (ks->u.fpr, fpr, KEY_FPR_LEN)) - return 1; - break; - } - } - - return 0; -} - - -static int -find_by_pattern (cdk_kbnode_t knode, cdk_dbsearch_t ks) -{ - cdk_kbnode_t node; - size_t uidlen; - char *name; - - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype != CDK_PKT_USER_ID) - continue; - if (node->pkt->pkt.user_id->attrib_img != NULL) - continue; /* Skip attribute packets. */ - uidlen = node->pkt->pkt.user_id->len; - name = node->pkt->pkt.user_id->name; - switch (ks->type) - { - case CDK_DBSEARCH_EXACT: - if (name && - (strlen (ks->u.pattern) == uidlen && - !strncmp (ks->u.pattern, name, uidlen))) - return 1; - break; - - case CDK_DBSEARCH_SUBSTR: - if (uidlen > 65536) - break; - if (name && strlen (ks->u.pattern) > uidlen) - break; - if (name && _cdk_memistr (name, uidlen, ks->u.pattern)) - return 1; - break; - - default: /* Invalid mode */ - return 0; - } - } - return 0; -} - - -static void -keydb_search_free (cdk_dbsearch_t dbs) -{ - if (!dbs) - return; - if (dbs->type == CDK_DBSEARCH_EXACT || dbs->type == CDK_DBSEARCH_SUBSTR) - cdk_free (dbs->u.pattern); - dbs->type = 0; - cdk_free (dbs); -} - - -static void -keydb_cache_free (key_table_t cache) -{ - key_table_t c2; - - while (cache) - { - c2 = cache->next; - cache->offset = 0; - keydb_search_free (cache->desc); - cdk_free (cache); - cache = c2; - } -} - - -static key_table_t -keydb_cache_find (key_table_t cache, cdk_dbsearch_t desc) -{ - key_table_t t; - - for (t = cache; t; t = t->next) - { - if (t->desc->type != desc->type) - continue; - switch (t->desc->type) - { - case CDK_DBSEARCH_SHORT_KEYID: - case CDK_DBSEARCH_KEYID: - if (KEYID_CMP (t->desc->u.keyid, desc->u.keyid)) - return t; - break; - - case CDK_DBSEARCH_EXACT: - if (strlen (t->desc->u.pattern) == strlen (desc->u.pattern) && - !strcmp (t->desc->u.pattern, desc->u.pattern)) - return t; - break; - - case CDK_DBSEARCH_SUBSTR: - if (strstr (t->desc->u.pattern, desc->u.pattern)) - return t; - break; - - case CDK_DBSEARCH_FPR: - if (!memcmp (t->desc->u.fpr, desc->u.fpr, KEY_FPR_LEN)) - return t; - break; - } - } - - return NULL; -} - - -static cdk_error_t -keydb_cache_add (cdk_keydb_hd_t hd, cdk_dbsearch_t dbs, off_t offset) -{ - key_table_t k; - - if (!hd) - return CDK_Inv_Value; - - if (hd->ncache > KEYDB_CACHE_ENTRIES) - return 0; /* FIXME: we should replace the last entry. */ - k = cdk_calloc (1, sizeof *k); - if (!k) - return CDK_Out_Of_Core; - k->offset = offset; - keydb_search_copy (&k->desc, dbs); - k->next = hd->cache; - hd->cache = k; - hd->ncache++; - _cdk_log_debug ("cache: add entry off=%d type=%d\n", offset, dbs->type); - return 0; -} - - -static cdk_error_t -keydb_search_copy (cdk_dbsearch_t * r_dst, cdk_dbsearch_t src) -{ - cdk_dbsearch_t dst; - - if (!r_dst || !src) - return CDK_Inv_Value; - - *r_dst = NULL; - dst = cdk_calloc (1, sizeof *dst); - if (!dst) - return CDK_Out_Of_Core; - dst->type = src->type; - switch (src->type) - { - case CDK_DBSEARCH_EXACT: - case CDK_DBSEARCH_SUBSTR: - dst->u.pattern = cdk_strdup (src->u.pattern); - if (!dst->u.pattern) - return CDK_Out_Of_Core; - break; - - case CDK_DBSEARCH_SHORT_KEYID: - case CDK_DBSEARCH_KEYID: - dst->u.keyid[0] = src->u.keyid[0]; - dst->u.keyid[1] = src->u.keyid[1]; - break; - - case CDK_DBSEARCH_FPR: - memcpy (dst->u.fpr, src->u.fpr, KEY_FPR_LEN); - break; - } - *r_dst = dst; - return 0; -} - - -/** - * cdk_keydb_search_start: - * @db: key database handle - * @type: specifies the search type - * @desc: description which depends on the type - * - * Create a new keydb search object. - **/ -cdk_error_t -cdk_keydb_search_start (cdk_keydb_hd_t db, int type, void *desc) -{ - cdk_dbsearch_t dbs; - u32 *keyid; - char *p, tmp[3]; - int i; - - if (!db) - return CDK_Inv_Value; - if (type != CDK_DBSEARCH_NEXT && !desc) - return CDK_Inv_Mode; - - dbs = cdk_calloc (1, sizeof *dbs); - if (!dbs) - return CDK_Out_Of_Core; - dbs->type = type; - switch (type) - { - case CDK_DBSEARCH_EXACT: - case CDK_DBSEARCH_SUBSTR: - cdk_free (dbs->u.pattern); - dbs->u.pattern = cdk_strdup (desc); - if (!dbs->u.pattern) - { - cdk_free (dbs); - return CDK_Out_Of_Core; - } - break; - - case CDK_DBSEARCH_SHORT_KEYID: - keyid = desc; - dbs->u.keyid[1] = keyid[0]; - break; - - case CDK_DBSEARCH_KEYID: - keyid = desc; - dbs->u.keyid[0] = keyid[0]; - dbs->u.keyid[1] = keyid[1]; - break; - - case CDK_DBSEARCH_FPR: - memcpy (dbs->u.fpr, desc, KEY_FPR_LEN); - break; - - case CDK_DBSEARCH_NEXT: - break; - - case CDK_DBSEARCH_AUTO: - /* Override the type with the actual db search type. */ - dbs->type = classify_data (desc, strlen (desc)); - switch (dbs->type) - { - case CDK_DBSEARCH_SUBSTR: - case CDK_DBSEARCH_EXACT: - cdk_free (dbs->u.pattern); - p = dbs->u.pattern = cdk_strdup (desc); - if (!p) - { - cdk_free (dbs); - return CDK_Out_Of_Core; - } - break; - - case CDK_DBSEARCH_SHORT_KEYID: - case CDK_DBSEARCH_KEYID: - p = desc; - if (!strncmp (p, "0x", 2)) - p += 2; - if (strlen (p) == 8) - { - dbs->u.keyid[0] = 0; - dbs->u.keyid[1] = strtoul (p, NULL, 16); - } - else if (strlen (p) == 16) - { - dbs->u.keyid[0] = strtoul (p, NULL, 16); - dbs->u.keyid[1] = strtoul (p + 8, NULL, 16); - } - else - { /* Invalid key ID object. */ - cdk_free (dbs); - return CDK_Inv_Mode; - } - break; - - case CDK_DBSEARCH_FPR: - p = desc; - if (strlen (p) != 2 * KEY_FPR_LEN) - { - cdk_free (dbs); - return CDK_Inv_Mode; - } - for (i = 0; i < KEY_FPR_LEN; i++) - { - tmp[0] = p[2 * i]; - tmp[1] = p[2 * i + 1]; - tmp[2] = 0x00; - dbs->u.fpr[i] = strtoul (tmp, NULL, 16); - } - break; - } - break; - - default: - cdk_free (dbs); - _cdk_log_debug ("cdk_keydb_search_start: invalid mode = %d\n", type); - return CDK_Inv_Mode; - } - - keydb_search_free (db->dbs); - db->dbs = dbs; - return 0; -} - - -static cdk_error_t -keydb_pos_from_cache (cdk_keydb_hd_t hd, cdk_dbsearch_t ks, - int *r_cache_hit, off_t * r_off) -{ - key_table_t c; - - if (!hd || !r_cache_hit || !r_off) - return CDK_Inv_Value; - - /* Reset the values. */ - *r_cache_hit = 0; - *r_off = 0; - - c = keydb_cache_find (hd->cache, ks); - if (c != NULL) - { - _cdk_log_debug ("cache: found entry in cache.\n"); - *r_cache_hit = 1; - *r_off = c->offset; - return 0; - } - - /* No index cache available so we just return here. */ - if (!hd->idx) - return 0; - - if (hd->idx) - { - if (ks->type == CDK_DBSEARCH_KEYID) - { - if (keydb_idx_search (hd->idx, ks->u.keyid, NULL, r_off)) - return CDK_Error_No_Key; - _cdk_log_debug ("cache: found keyid entry in idx table.\n"); - *r_cache_hit = 1; - } - else if (ks->type == CDK_DBSEARCH_FPR) - { - if (keydb_idx_search (hd->idx, NULL, ks->u.fpr, r_off)) - return CDK_Error_No_Key; - _cdk_log_debug ("cache: found fpr entry in idx table.\n"); - *r_cache_hit = 1; - } - } - - return 0; -} - - -/** - * cdk_keydb_search: - * @hd: the keydb object - * @ks: the keydb search object - * @ret_key: kbnode object to store the key - * - * Search for a key in the given keyring. The search mode is handled - * via @ks. If the key was found, @ret_key contains the key data. - **/ -cdk_error_t -cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t * ret_key) -{ - cdk_stream_t kr; - cdk_kbnode_t knode; - cdk_dbsearch_t ks; - cdk_error_t rc = 0; - off_t pos = 0, off = 0; - int key_found = 0, cache_hit = 0; - - if (!hd || !ret_key) - return CDK_Inv_Value; - - *ret_key = NULL; - kr = NULL; - hd->search = 1; - rc = _cdk_keydb_open (hd, &kr); - if (rc) - return rc; - - if (!hd->no_cache) - { - /* It is possible the index is not up-to-date and thus we do - not find the requesed key. In this case, we reset cache hit - and continue our normal search procedure. */ - rc = keydb_pos_from_cache (hd, hd->dbs, &cache_hit, &off); - if (rc) - cache_hit = 0; - } - - knode = NULL; - ks = hd->dbs; - while (!key_found && !rc) - { - if (cache_hit && ks->type != CDK_DBSEARCH_NEXT) - cdk_stream_seek (kr, off); - pos = cdk_stream_tell (kr); - rc = cdk_keydb_get_keyblock (kr, &knode); - if (rc) - { - if (rc == CDK_EOF) - break; - else - return rc; - } - - switch (ks->type) - { - case CDK_DBSEARCH_SHORT_KEYID: - case CDK_DBSEARCH_KEYID: - key_found = find_by_keyid (knode, ks); - break; - - case CDK_DBSEARCH_FPR: - key_found = find_by_fpr (knode, ks); - break; - - case CDK_DBSEARCH_EXACT: - case CDK_DBSEARCH_SUBSTR: - key_found = find_by_pattern (knode, ks); - break; - - case CDK_DBSEARCH_NEXT: - key_found = knode ? 1 : 0; - break; - } - - if (key_found) - { - if (!keydb_cache_find (hd->cache, ks)) - keydb_cache_add (hd, ks, pos); - break; - } - - cdk_kbnode_release (knode); - knode = NULL; - } - - hd->search = 0; - if (key_found && rc == CDK_EOF) - rc = 0; - else if (rc == CDK_EOF && !key_found) - rc = CDK_Error_No_Key; - *ret_key = key_found ? knode : NULL; - return rc; -} - - -cdk_error_t -cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, u32 * keyid, cdk_kbnode_t * ret_key) -{ - cdk_error_t rc; - - if (!hd || !keyid || !ret_key) - return CDK_Inv_Value; - - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid); - if (!rc) - rc = cdk_keydb_search (hd, ret_key); - return rc; -} - - -cdk_error_t -cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const byte * fpr, - cdk_kbnode_t * r_key) -{ - cdk_error_t rc; - - if (!hd || !fpr || !r_key) - return CDK_Inv_Value; - - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_FPR, (byte *) fpr); - if (!rc) - rc = cdk_keydb_search (hd, r_key); - return rc; -} - - -cdk_error_t -cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt, - cdk_kbnode_t * ret_key) -{ - cdk_error_t rc; - - if (!hd || !patt || !ret_key) - return CDK_Inv_Value; - - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_SUBSTR, (char *) patt); - if (!rc) - rc = cdk_keydb_search (hd, ret_key); - return rc; -} - - -static int -keydb_check_key (cdk_packet_t pkt) -{ - cdk_pkt_pubkey_t pk; - int is_sk, valid; - - if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || - pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) - { - pk = pkt->pkt.public_key; - is_sk = 0; - } - else if (pkt->pkttype == CDK_PKT_SECRET_KEY || - pkt->pkttype == CDK_PKT_SECRET_SUBKEY) - { - pk = pkt->pkt.secret_key->pk; - is_sk = 1; - } - else /* No key object. */ - return 0; - valid = !pk->is_revoked && !pk->has_expired; - if (is_sk) - return valid; - return valid && !pk->is_invalid; -} - - -/* Find the first kbnode with the requested packet type - that represents a valid key. */ -static cdk_kbnode_t -kbnode_find_valid (cdk_kbnode_t root, int pkttype) -{ - cdk_kbnode_t n; - - for (n = root; n; n = n->next) - { - if (n->pkt->pkttype != pkttype) - continue; - if (keydb_check_key (n->pkt)) - return n; - } - - return NULL; -} - - -static cdk_kbnode_t -keydb_find_byusage (cdk_kbnode_t root, int req_usage, int is_pk) -{ - cdk_kbnode_t node, key; - int req_type; - long timestamp; - - req_type = is_pk ? CDK_PKT_PUBLIC_KEY : CDK_PKT_SECRET_KEY; - if (!req_usage) - return kbnode_find_valid (root, req_type); - - node = cdk_kbnode_find (root, req_type); - if (node && !keydb_check_key (node->pkt)) - return NULL; - - key = NULL; - timestamp = 0; - /* We iteratre over the all nodes and search for keys or - subkeys which match the usage and which are not invalid. - A timestamp is used to figure out the newest valid key. */ - for (node = root; node; node = node->next) - { - if (is_pk && (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || - node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) - && keydb_check_key (node->pkt) - && (node->pkt->pkt.public_key->pubkey_usage & req_usage)) - { - if (node->pkt->pkt.public_key->timestamp > timestamp) - key = node; - } - if (!is_pk && (node->pkt->pkttype == CDK_PKT_SECRET_KEY || - node->pkt->pkttype == CDK_PKT_SECRET_SUBKEY) - && keydb_check_key (node->pkt) - && (node->pkt->pkt.secret_key->pk->pubkey_usage & req_usage)) - { - if (node->pkt->pkt.secret_key->pk->timestamp > timestamp) - key = node; - } - - } - return key; -} - - -static cdk_kbnode_t -keydb_find_bykeyid (cdk_kbnode_t root, const u32 * keyid, int search_mode) -{ - cdk_kbnode_t node; - u32 kid[2]; - - for (node = root; node; node = node->next) - { - if (!_cdk_pkt_get_keyid (node->pkt, kid)) - continue; - if (search_mode == CDK_DBSEARCH_SHORT_KEYID && kid[1] == keyid[1]) - return node; - else if (kid[0] == keyid[0] && kid[1] == keyid[1]) - return node; - } - return NULL; -} - - -cdk_error_t -_cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char *name, - cdk_seckey_t * ret_sk, int usage) -{ - cdk_kbnode_t knode = NULL; - cdk_kbnode_t node, sk_node, pk_node; - cdk_pkt_seckey_t sk; - cdk_error_t rc; - const char *s; - int pkttype; - - if (!ret_sk || !usage) - return CDK_Inv_Value; - if (!hd) - return CDK_Error_No_Keyring; - - *ret_sk = NULL; - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_AUTO, (char *) name); - if (rc) - return rc; - - rc = cdk_keydb_search (hd, &knode); - if (rc) - return rc; - - sk_node = keydb_find_byusage (knode, usage, 0); - if (!sk_node) - { - cdk_kbnode_release (knode); - return CDK_Unusable_Key; - } - - /* We clone the node with the secret key to avoid that the - packet will be released. */ - _cdk_kbnode_clone (sk_node); - sk = sk_node->pkt->pkt.secret_key; - - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_USER_ID) - { - s = node->pkt->pkt.user_id->name; - if (sk && !sk->pk->uid && _cdk_memistr (s, strlen (s), name)) - { - _cdk_copy_userid (&sk->pk->uid, node->pkt->pkt.user_id); - break; - } - } - } - - /* To find the self signature, we need the primary public key because - the selected secret key might be different from the primary key. */ - pk_node = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY); - if (!pk_node) - { - cdk_kbnode_release (knode); - return CDK_Unusable_Key; - } - node = find_selfsig_node (knode, pk_node->pkt->pkt.secret_key->pk); - if (sk->pk->uid && node) - _cdk_copy_signature (&sk->pk->uid->selfsig, node->pkt->pkt.signature); - - /* We only release the outer packet. */ - _cdk_pkt_detach_free (sk_node->pkt, &pkttype, (void *) &sk); - cdk_kbnode_release (knode); - *ret_sk = sk; - return rc; -} - - -cdk_error_t -_cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char *name, - cdk_pubkey_t * ret_pk, int usage) -{ - cdk_kbnode_t knode, node, pk_node; - cdk_pkt_pubkey_t pk; - const char *s; - cdk_error_t rc; - - if (!ret_pk || !usage) - return CDK_Inv_Value; - if (!hd) - return CDK_Error_No_Keyring; - - *ret_pk = NULL; - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_AUTO, (char *) name); - if (!rc) - rc = cdk_keydb_search (hd, &knode); - if (rc) - return rc; - - node = keydb_find_byusage (knode, usage, 1); - if (!node) - { - cdk_kbnode_release (knode); - return CDK_Unusable_Key; - } - - pk = NULL; - _cdk_copy_pubkey (&pk, node->pkt->pkt.public_key); - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_USER_ID) - { - s = node->pkt->pkt.user_id->name; - if (pk && !pk->uid && _cdk_memistr (s, strlen (s), name)) - { - _cdk_copy_userid (&pk->uid, node->pkt->pkt.user_id); - break; - } - } - } - - /* Same as in the sk code, the selected key can be a sub key - and thus we need the primary key to find the self sig. */ - pk_node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); - if (!pk_node) - { - cdk_kbnode_release (knode); - return CDK_Unusable_Key; - } - node = find_selfsig_node (knode, pk_node->pkt->pkt.public_key); - if (pk->uid && node) - _cdk_copy_signature (&pk->uid->selfsig, node->pkt->pkt.signature); - cdk_kbnode_release (knode); - - *ret_pk = pk; - return rc; -} - - -/** - * cdk_keydb_get_pk: - * @hd: key db handle - * @keyid: keyid of the key - * @r_pk: the allocated public key - * - * Perform a key database search by keyid and return the raw public - * key without any signatures or user id's. - **/ -cdk_error_t -cdk_keydb_get_pk (cdk_keydb_hd_t hd, u32 * keyid, cdk_pubkey_t * r_pk) -{ - cdk_kbnode_t knode = NULL, node; - cdk_pubkey_t pk; - cdk_error_t rc; - size_t s_type; - int pkttype; - - if (!keyid || !r_pk) - return CDK_Inv_Value; - if (!hd) - return CDK_Error_No_Keyring; - - *r_pk = NULL; - s_type = !keyid[0] ? CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID; - rc = cdk_keydb_search_start (hd, s_type, keyid); - if (rc) - return rc; - rc = cdk_keydb_search (hd, &knode); - if (rc) - return rc; - - node = keydb_find_bykeyid (knode, keyid, s_type); - if (!node) - { - cdk_kbnode_release (knode); - return CDK_Error_No_Key; - } - - /* See comment in cdk_keydb_get_sk() */ - _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &pk); - *r_pk = pk; - _cdk_kbnode_clone (node); - cdk_kbnode_release (knode); - - return rc; -} - - -/** - * cdk_keydb_get_sk: - * @hd: key db handle - * @keyid: the keyid of the key - * @ret_sk: the allocated secret key - * - * Perform a key database search by keyid and return - * only the raw secret key without the additional nodes, - * like the user id or the signatures. - **/ -cdk_error_t -cdk_keydb_get_sk (cdk_keydb_hd_t hd, u32 * keyid, cdk_seckey_t * ret_sk) -{ - cdk_kbnode_t snode, node; - cdk_seckey_t sk; - cdk_error_t rc; - int pkttype; - - if (!keyid || !ret_sk) - return CDK_Inv_Value; - if (!hd) - return CDK_Error_No_Keyring; - - *ret_sk = NULL; - rc = cdk_keydb_get_bykeyid (hd, keyid, &snode); - if (rc) - return rc; - - node = keydb_find_bykeyid (snode, keyid, CDK_DBSEARCH_KEYID); - if (!node) - { - cdk_kbnode_release (snode); - return CDK_Error_No_Key; - } - - /* We need to release the packet itself but not its contents - and thus we detach the openpgp packet and release the structure. */ - _cdk_pkt_detach_free (node->pkt, &pkttype, (void *) &sk); - _cdk_kbnode_clone (node); - cdk_kbnode_release (snode); - - *ret_sk = sk; - return 0; -} - - -static int -is_selfsig (cdk_kbnode_t node, const u32 * keyid) -{ - cdk_pkt_signature_t sig; - - if (node->pkt->pkttype != CDK_PKT_SIGNATURE) - return 0; - sig = node->pkt->pkt.signature; - if ((sig->sig_class >= 0x10 && sig->sig_class <= 0x13) && - sig->keyid[0] == keyid[0] && sig->keyid[1] == keyid[1]) - return 1; - - return 0; -} - - -/* Find the newest self signature for the public key @pk - and return the signature node. */ -static cdk_kbnode_t -find_selfsig_node (cdk_kbnode_t key, cdk_pkt_pubkey_t pk) -{ - cdk_kbnode_t n, sig; - unsigned int ts; - u32 keyid[2]; - - cdk_pk_get_keyid (pk, keyid); - sig = NULL; - ts = 0; - for (n = key; n; n = n->next) - { - if (is_selfsig (n, keyid) && n->pkt->pkt.signature->timestamp > ts) - { - ts = n->pkt->pkt.signature->timestamp; - sig = n; - } - } - - return sig; -} - - - -static cdk_error_t -keydb_merge_selfsig (cdk_kbnode_t key, u32 * keyid) -{ - cdk_kbnode_t node, kbnode, unode; - cdk_subpkt_t s = NULL; - cdk_pkt_signature_t sig = NULL; - cdk_pkt_userid_t uid = NULL; - const byte *symalg = NULL, *hashalg = NULL, *compalg = NULL; - size_t nsymalg = 0, nhashalg = 0, ncompalg = 0, n = 0; - size_t key_usage = 0, key_expire = 0; - - if (!key) - return CDK_Inv_Value; - - for (node = key; node; node = node->next) - { - if (!is_selfsig (node, keyid)) - continue; - unode = cdk_kbnode_find_prev (key, node, CDK_PKT_USER_ID); - if (!unode) - return CDK_Error_No_Key; - uid = unode->pkt->pkt.user_id; - sig = node->pkt->pkt.signature; - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PRIMARY_UID); - if (s) - uid->is_primary = 1; - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_FEATURES); - if (s && s->size == 1 && s->d[0] & 0x01) - uid->mdc_feature = 1; - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_EXPIRE); - if (s && s->size == 4) - key_expire = _cdk_buftou32 (s->d); - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_KEY_FLAGS); - if (s) - { - if (s->d[0] & 0x03) /* cert + sign data */ - key_usage |= CDK_KEY_USG_SIGN; - if (s->d[0] & 0x0C) /* encrypt comm. + storage */ - key_usage |= CDK_KEY_USG_ENCR; - if (s->d[0] & 0x20) - key_usage |= CDK_KEY_USG_AUTH; - } - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_SYM); - if (s) - { - symalg = s->d; - nsymalg = s->size; - n += s->size + 1; - } - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_HASH); - if (s) - { - hashalg = s->d; - nhashalg = s->size; - n += s->size + 1; - } - s = cdk_subpkt_find (sig->hashed, CDK_SIGSUBPKT_PREFS_ZIP); - if (s) - { - compalg = s->d; - ncompalg = s->size; - n += s->size + 1; - } - if (uid->prefs != NULL) - cdk_free (uid->prefs); - if (!n || !hashalg || !compalg || !symalg) - uid->prefs = NULL; - else - { - uid->prefs = cdk_calloc (1, sizeof (*uid->prefs) * (n + 1)); - if (!uid->prefs) - return CDK_Out_Of_Core; - n = 0; - for (; nsymalg; nsymalg--, n++) - { - uid->prefs[n].type = CDK_PREFTYPE_SYM; - uid->prefs[n].value = *symalg++; - } - for (; nhashalg; nhashalg--, n++) - { - uid->prefs[n].type = CDK_PREFTYPE_HASH; - uid->prefs[n].value = *hashalg++; - } - for (; ncompalg; ncompalg--, n++) - { - uid->prefs[n].type = CDK_PREFTYPE_ZIP; - uid->prefs[n].value = *compalg++; - } - - uid->prefs[n].type = CDK_PREFTYPE_NONE; /* end of list marker */ - uid->prefs[n].value = 0; - uid->prefs_size = n; - } - } - - /* Now we add the extracted information to the primary key. */ - kbnode = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY); - if (kbnode) - { - cdk_pkt_pubkey_t pk = kbnode->pkt->pkt.public_key; - if (uid && uid->prefs && n) - { - if (pk->prefs != NULL) - cdk_free (pk->prefs); - pk->prefs = _cdk_copy_prefs (uid->prefs); - pk->prefs_size = n; - } - if (key_expire) - { - pk->expiredate = pk->timestamp + key_expire; - pk->has_expired = pk->expiredate > (u32) time (NULL) ? 0 : 1; - } - - if (key_usage) - pk->pubkey_usage = key_usage; - pk->is_invalid = 0; - } - - return 0; -} - - -static cdk_error_t -keydb_parse_allsigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, int check) -{ - cdk_kbnode_t node, kb; - cdk_pkt_signature_t sig; - cdk_pkt_pubkey_t pk; - cdk_subpkt_t s = NULL; - u32 expiredate = 0, curtime = (u32) time (NULL); - u32 keyid[2]; - - if (!knode) - return CDK_Inv_Value; - if (check && !hd) - return CDK_Inv_Mode; - - kb = cdk_kbnode_find (knode, CDK_PKT_SECRET_KEY); - if (kb) - return 0; - - /* Reset */ - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_USER_ID) - node->pkt->pkt.user_id->is_revoked = 0; - else if (node->pkt->pkttype == CDK_PKT_PUBLIC_KEY || - node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) - node->pkt->pkt.public_key->is_revoked = 0; - } - - kb = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); - if (!kb) - return CDK_Wrong_Format; - cdk_pk_get_keyid (kb->pkt->pkt.public_key, keyid); - - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_SIGNATURE) - { - sig = node->pkt->pkt.signature; - /* Revocation certificates for primary keys */ - if (sig->sig_class == 0x20) - { - kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY); - if (kb) - { - kb->pkt->pkt.public_key->is_revoked = 1; - if (check) - _cdk_pk_check_sig (hd, kb, node, NULL); - } - else - return CDK_Error_No_Key; - } - /* Revocation certificates for subkeys */ - else if (sig->sig_class == 0x28) - { - kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY); - if (kb) - { - kb->pkt->pkt.public_key->is_revoked = 1; - if (check) - _cdk_pk_check_sig (hd, kb, node, NULL); - } - else - return CDK_Error_No_Key; - } - /* Revocation certifcates for user ID's */ - else if (sig->sig_class == 0x30) - { - if (sig->keyid[0] != keyid[0] || sig->keyid[1] != keyid[1]) - continue; /* revokes an earlier signature, no userID. */ - kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_USER_ID); - if (kb) - { - kb->pkt->pkt.user_id->is_revoked = 1; - if (check) - _cdk_pk_check_sig (hd, kb, node, NULL); - } - else - return CDK_Error_No_Key; - } - /* Direct certificates for primary keys */ - else if (sig->sig_class == 0x1F) - { - kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_KEY); - if (kb) - { - pk = kb->pkt->pkt.public_key; - pk->is_invalid = 0; - s = cdk_subpkt_find (node->pkt->pkt.signature->hashed, - CDK_SIGSUBPKT_KEY_EXPIRE); - if (s) - { - expiredate = _cdk_buftou32 (s->d); - pk->expiredate = pk->timestamp + expiredate; - pk->has_expired = pk->expiredate > curtime ? 0 : 1; - } - if (check) - _cdk_pk_check_sig (hd, kb, node, NULL); - } - else - return CDK_Error_No_Key; - } - /* Direct certificates for subkeys */ - else if (sig->sig_class == 0x18) - { - kb = cdk_kbnode_find_prev (knode, node, CDK_PKT_PUBLIC_SUBKEY); - if (kb) - { - pk = kb->pkt->pkt.public_key; - pk->is_invalid = 0; - s = cdk_subpkt_find (node->pkt->pkt.signature->hashed, - CDK_SIGSUBPKT_KEY_EXPIRE); - if (s) - { - expiredate = _cdk_buftou32 (s->d); - pk->expiredate = pk->timestamp + expiredate; - pk->has_expired = pk->expiredate > curtime ? 0 : 1; - } - if (check) - _cdk_pk_check_sig (hd, kb, node, NULL); - } - else - return CDK_Error_No_Key; - } - } - } - node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); - if (node && node->pkt->pkt.public_key->version == 3) - { - /* v3 public keys have no additonal signatures for the key directly. - we say the key is valid when we have at least a self signature. */ - pk = node->pkt->pkt.public_key; - for (node = knode; node; node = node->next) - { - if (is_selfsig (node, keyid)) - { - pk->is_invalid = 0; - break; - } - } - } - if (node && (node->pkt->pkt.public_key->is_revoked || - node->pkt->pkt.public_key->has_expired)) - { - /* If the primary key has been revoked, mark all subkeys as invalid - because without a primary key they are not useable */ - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) - node->pkt->pkt.public_key->is_invalid = 1; - } - } - - return 0; -} - - -cdk_error_t -cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * r_knode) -{ - cdk_packet_t pkt; - cdk_kbnode_t knode, node; - cdk_desig_revoker_t revkeys; - cdk_error_t rc; - u32 keyid[2], main_keyid[2]; - off_t old_off; - int key_seen, got_key; - - if (!inp || !r_knode) - return CDK_Inv_Value; - - /* Reset all values. */ - keyid[0] = keyid[1] = 0; - main_keyid[0] = main_keyid[1] = 0; - revkeys = NULL; - knode = NULL; - key_seen = got_key = 0; - - *r_knode = NULL; - rc = CDK_EOF; - while (!cdk_stream_eof (inp)) - { - cdk_pkt_new (&pkt); - old_off = cdk_stream_tell (inp); - rc = cdk_pkt_read (inp, pkt); - if (rc) - { - cdk_pkt_release (pkt); - if (rc == CDK_EOF) - break; - else - { /* Release all packets we reached so far. */ - _cdk_log_debug ("keydb_get_keyblock: error %d\n", rc); - cdk_kbnode_release (knode); - return rc; - } - } - if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || - pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || - pkt->pkttype == CDK_PKT_SECRET_KEY || - pkt->pkttype == CDK_PKT_SECRET_SUBKEY) - { - if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY || - pkt->pkttype == CDK_PKT_SECRET_KEY)) - { - /* The next key starts here so set the file pointer - and leave the loop. */ - cdk_stream_seek (inp, old_off); - cdk_pkt_release (pkt); - break; - } - if (pkt->pkttype == CDK_PKT_PUBLIC_KEY || - pkt->pkttype == CDK_PKT_SECRET_KEY) - { - _cdk_pkt_get_keyid (pkt, main_keyid); - key_seen = 1; - } - else if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || - pkt->pkttype == CDK_PKT_SECRET_SUBKEY) - { - if (pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY) - { - pkt->pkt.public_key->main_keyid[0] = main_keyid[0]; - pkt->pkt.public_key->main_keyid[1] = main_keyid[1]; - } - else - { - pkt->pkt.secret_key->main_keyid[0] = main_keyid[0]; - pkt->pkt.secret_key->main_keyid[1] = main_keyid[1]; - } - } - /* We save this for the signature */ - _cdk_pkt_get_keyid (pkt, keyid); - got_key = 1; - } - else if (pkt->pkttype == CDK_PKT_USER_ID) - ; - else if (pkt->pkttype == CDK_PKT_SIGNATURE) - { - pkt->pkt.signature->key[0] = keyid[0]; - pkt->pkt.signature->key[1] = keyid[1]; - if (pkt->pkt.signature->sig_class == 0x1F && - pkt->pkt.signature->revkeys) - revkeys = pkt->pkt.signature->revkeys; - } - node = cdk_kbnode_new (pkt); - if (!knode) - knode = node; - else - _cdk_kbnode_add (knode, node); - } - - if (got_key) - { - keydb_merge_selfsig (knode, main_keyid); - rc = keydb_parse_allsigs (knode, NULL, 0); - if (revkeys) - { - node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); - if (node) - node->pkt->pkt.public_key->revkeys = revkeys; - } - } - else - cdk_kbnode_release (knode); - *r_knode = got_key ? knode : NULL; - - /* It is possible that we are in an EOF condition after we - successfully read a keyblock. For example if the requested - key is the last in the file. */ - if (rc == CDK_EOF && got_key) - rc = 0; - return rc; -} - - -/* Return the type of the given data. In case it cannot be classified, - a substring search will be performed. */ -static int -classify_data (const byte * buf, size_t len) -{ - int type; - int i; - - if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) - { /* Skip hex prefix. */ - buf += 2; - len -= 2; - } - - /* The length of the data does not match either a keyid or a fingerprint. */ - if (len != 8 && len != 16 && len != 40) - return CDK_DBSEARCH_SUBSTR; - - for (i = 0; i < len; i++) - { - if (!isxdigit (buf[i])) - return CDK_DBSEARCH_SUBSTR; - } - if (i != len) - return CDK_DBSEARCH_SUBSTR; - switch (len) - { - case 8: - type = CDK_DBSEARCH_SHORT_KEYID; - break; - case 16: - type = CDK_DBSEARCH_KEYID; - break; - case 40: - type = CDK_DBSEARCH_FPR; - break; - default: - type = CDK_DBSEARCH_SUBSTR; - break; - } - - return type; -} - - -/** - * cdk_keydb_export: - * @hd: the keydb handle - * @out: the output stream - * @remusr: the list of key pattern to export - * - * Export a list of keys to the given output stream. - * Use string list with names for pattering searching. - * This procedure strips local signatures. - **/ -cdk_error_t -cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr) -{ - cdk_kbnode_t knode, node; - cdk_strlist_t r; - cdk_error_t rc; - int old_ctb; - - for (r = remusr; r; r = r->next) - { - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_AUTO, r->d); - if (rc) - return rc; - rc = cdk_keydb_search (hd, &knode); - if (rc) - return rc; - node = cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY); - if (!node) - return CDK_Error_No_Key; - - /* If the key is a version 3 key, use the old packet - format for the output. */ - if (node->pkt->pkt.public_key->version == 3) - old_ctb = 1; - else - old_ctb = 0; - - for (node = knode; node; node = node->next) - { - /* No specified format; skip them */ - if (node->pkt->pkttype == CDK_PKT_RING_TRUST) - continue; - /* We never export local signed signatures */ - if (node->pkt->pkttype == CDK_PKT_SIGNATURE && - !node->pkt->pkt.signature->flags.exportable) - continue; - /* Filter out invalid signatures */ - if (node->pkt->pkttype == CDK_PKT_SIGNATURE && - !KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo)) - continue; - - /* Adjust the ctb flag if needed. */ - node->pkt->old_ctb = old_ctb; - rc = cdk_pkt_write (out, node->pkt); - if (rc) - { - cdk_kbnode_release (knode); - return rc; - } - } - cdk_kbnode_release (knode); - knode = NULL; - } - return 0; -} - - -static cdk_packet_t -find_key_packet (cdk_kbnode_t knode, int *r_is_sk) -{ - cdk_packet_t pkt; - - pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY); - if (!pkt) - { - pkt = cdk_kbnode_find_packet (knode, CDK_PKT_SECRET_KEY); - if (r_is_sk) - *r_is_sk = pkt ? 1 : 0; - } - return pkt; -} - - -/* Return 1 if the is allowd in a key node. */ -static int -is_key_node (cdk_kbnode_t node) -{ - switch (node->pkt->pkttype) - { - case CDK_PKT_SIGNATURE: - case CDK_PKT_SECRET_KEY: - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_SECRET_SUBKEY: - case CDK_PKT_PUBLIC_SUBKEY: - case CDK_PKT_USER_ID: - case CDK_PKT_ATTRIBUTE: - return 1; - - default: - return 0; - } - - return 0; -} - - -cdk_error_t -cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode) -{ - cdk_kbnode_t node, chk; - cdk_packet_t pkt; - cdk_stream_t out; - cdk_error_t rc; - u32 keyid[2]; - - if (!hd || !knode) - return CDK_Inv_Value; - - pkt = find_key_packet (knode, NULL); - if (!pkt) - return CDK_Inv_Packet; - - _cdk_pkt_get_keyid (pkt, keyid); - chk = NULL; - cdk_keydb_get_bykeyid (hd, keyid, &chk); - if (chk) - { /* FIXME: search for new signatures */ - cdk_kbnode_release (chk); - return 0; - } - - /* We append data to the stream so we need to close - the stream here to re-open it later. */ - if (hd->fp) - { - cdk_stream_close (hd->fp); - hd->fp = NULL; - } - - rc = _cdk_stream_append (hd->name, &out); - if (rc) - return rc; - - for (node = knode; node; node = node->next) - { - if (node->pkt->pkttype == CDK_PKT_RING_TRUST) - continue; /* No uniformed syntax for this packet */ - if (node->pkt->pkttype == CDK_PKT_SIGNATURE && - !node->pkt->pkt.signature->flags.exportable) - { - _cdk_log_debug ("key db import: skip local signature\n"); - continue; - } - - if (!is_key_node (node)) - { - _cdk_log_debug ("key db import: skip invalid node of type %d\n", - node->pkt->pkttype); - continue; - } - - rc = cdk_pkt_write (out, node->pkt); - if (rc) - { - cdk_stream_close (out); - return rc; - } - } - - cdk_stream_close (out); - if (!hd->no_cache) - cdk_keydb_idx_rebuild (hd); - hd->stats.new_keys++; - - return 0; -} - - -cdk_error_t -_cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, const char *id) -{ - cdk_kbnode_t knode = NULL, unode = NULL; - cdk_error_t rc; - int check; - - if (!hd) - return CDK_Inv_Value; - - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid); - if (rc) - return rc; - rc = cdk_keydb_search (hd, &knode); - if (rc) - return rc; - - rc = cdk_keydb_search_start (hd, CDK_DBSEARCH_EXACT, (char *) id); - if (!rc) - rc = cdk_keydb_search (hd, &unode); - if (rc) - { - cdk_kbnode_release (knode); - return rc; - } - - check = 0; - cdk_keydb_search_start (hd, CDK_DBSEARCH_KEYID, keyid); - if (unode && find_by_keyid (unode, hd->dbs)) - check++; - cdk_kbnode_release (unode); - - cdk_keydb_search_start (hd, CDK_DBSEARCH_EXACT, (char *) id); - if (knode && find_by_pattern (knode, hd->dbs)) - check++; - cdk_kbnode_release (knode); - - return check == 2 ? 0 : CDK_Inv_Value; -} - - -/** - * cdk_keydb_check_sk: - * @hd: the key db handle - * @keyid: the 64-bit keyid - * - * Check if a secret key with the given key ID is available - * in the key database. - **/ -cdk_error_t -cdk_keydb_check_sk (cdk_keydb_hd_t hd, u32 * keyid) -{ - cdk_stream_t db; - cdk_packet_t pkt; - cdk_error_t rc; - u32 kid[2]; - - if (!hd || !keyid) - return CDK_Inv_Value; - if (!hd->secret) - return CDK_Inv_Mode; - - rc = _cdk_keydb_open (hd, &db); - if (rc) - return rc; - cdk_pkt_new (&pkt); - while (!cdk_pkt_read (db, pkt)) - { - if (pkt->pkttype != CDK_PKT_SECRET_KEY && - pkt->pkttype != CDK_PKT_SECRET_SUBKEY) - { - cdk_pkt_free (pkt); - continue; - } - cdk_sk_get_keyid (pkt->pkt.secret_key, kid); - if (KEYID_CMP (kid, keyid)) - { - cdk_pkt_release (pkt); - return 0; - } - cdk_pkt_free (pkt); - } - cdk_pkt_release (pkt); - return CDK_Error_No_Key; -} - - -/** - * cdk_listkey_start: - * @r_ctx: pointer to store the new context - * @db: the key database handle - * @patt: string pattern - * @fpatt: recipients from a stringlist to show - * - * Prepare a key listing with the given parameters. Two modes are supported. - * The first mode uses string pattern to determine if the key should be - * returned or not. The other mode uses a string list to request the key - * which should be listed. - **/ -cdk_error_t -cdk_listkey_start (cdk_listkey_t * r_ctx, cdk_keydb_hd_t db, - const char *patt, cdk_strlist_t fpatt) -{ - cdk_listkey_t ctx; - cdk_stream_t inp; - cdk_error_t rc; - - if (!r_ctx || !db) - return CDK_Inv_Value; - if ((patt && fpatt) || (!patt && !fpatt)) - return CDK_Inv_Mode; - rc = _cdk_keydb_open (db, &inp); - if (rc) - return rc; - ctx = cdk_calloc (1, sizeof *ctx); - if (!ctx) - return CDK_Out_Of_Core; - ctx->db = db; - ctx->inp = inp; - if (patt) - { - ctx->u.patt = cdk_strdup (patt); - if (!ctx->u.patt) - return CDK_Out_Of_Core; - } - else if (fpatt) - { - cdk_strlist_t l; - for (l = fpatt; l; l = l->next) - cdk_strlist_add (&ctx->u.fpatt, l->d); - } - ctx->type = patt ? 1 : 0; - ctx->init = 1; - *r_ctx = ctx; - return 0; -} - - -/** - * cdk_listkey_close: - * @ctx: the list key context - * - * Free the list key context. - **/ -void -cdk_listkey_close (cdk_listkey_t ctx) -{ - if (!ctx) - return; - - if (ctx->type) - cdk_free (ctx->u.patt); - else - cdk_strlist_free (ctx->u.fpatt); - cdk_free (ctx); -} - - -/** - * cdk_listkey_next: - * @ctx: list key context - * @r_key: the pointer to the new key node object - * - * Retrieve the next key from the pattern of the key list context. - **/ -cdk_error_t -cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t * ret_key) -{ - if (!ctx || !ret_key) - return CDK_Inv_Value; - if (!ctx->init) - return CDK_Inv_Mode; - - if (ctx->type && ctx->u.patt[0] == '*') - return cdk_keydb_get_keyblock (ctx->inp, ret_key); - else if (ctx->type) - { - cdk_kbnode_t node; - struct cdk_dbsearch_s ks; - cdk_error_t rc; - - for (;;) - { - rc = cdk_keydb_get_keyblock (ctx->inp, &node); - if (rc) - return rc; - memset (&ks, 0, sizeof (ks)); - ks.type = CDK_DBSEARCH_SUBSTR; - ks.u.pattern = ctx->u.patt; - if (find_by_pattern (node, &ks)) - { - *ret_key = node; - return 0; - } - cdk_kbnode_release (node); - node = NULL; - } - } - else - { - if (!ctx->t) - ctx->t = ctx->u.fpatt; - else if (ctx->t->next) - ctx->t = ctx->t->next; - else - return CDK_EOF; - return cdk_keydb_get_bypattern (ctx->db, ctx->t->d, ret_key); - } - return CDK_General_Error; -} - - -int -_cdk_keydb_is_secret (cdk_keydb_hd_t db) -{ - return db->secret; -} diff --git a/src/daemon/https/opencdk/literal.c b/src/daemon/https/opencdk/literal.c @@ -1,307 +0,0 @@ -/* Literal.c - Literal packet filters - * Copyright (C) 2002, 2003 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <time.h> - -#include "opencdk.h" -#include "main.h" -#include "filters.h" - - -/* Duplicate the string @s but strip of possible - relative folder names of it. */ -static char * -dup_trim_filename (const char *s) -{ - char *p = NULL; - - p = strrchr (s, '/'); - if (!p) - p = strrchr (s, '\\'); - if (!p) - return cdk_strdup (s); - return cdk_strdup (p + 1); -} - - -static cdk_error_t -literal_decode (void *opaque, FILE * in, FILE * out) -{ - literal_filter_t *pfx = opaque; - cdk_stream_t si, so; - cdk_packet_t pkt; - cdk_pkt_literal_t pt; - byte buf[BUFSIZE]; - size_t nread; - int bufsize; - cdk_error_t rc; - - _cdk_log_debug ("literal filter: decode\n"); - - if (!pfx || !in || !out) - return CDK_Inv_Value; - - rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si); - if (rc) - return rc; - - cdk_pkt_new (&pkt); - rc = cdk_pkt_read (si, pkt); - if (rc || pkt->pkttype != CDK_PKT_LITERAL) - { - cdk_pkt_release (pkt); - cdk_stream_close (si); - return !rc ? CDK_Inv_Packet : rc; - } - - rc = _cdk_stream_fpopen (out, STREAMCTL_WRITE, &so); - if (rc) - { - cdk_pkt_release (pkt); - cdk_stream_close (si); - return rc; - } - - pt = pkt->pkt.literal; - pfx->mode = pt->mode; - - if (pfx->filename && pt->namelen > 0) - { - /* The name in the literal packet is more authorative. */ - cdk_free (pfx->filename); - pfx->filename = dup_trim_filename (pt->name); - } - else if (!pfx->filename && pt->namelen > 0) - pfx->filename = dup_trim_filename (pt->name); - else if (!pt->namelen && !pfx->filename && pfx->orig_filename) - { - /* In this case, we need to derrive the output file name - from the original name and cut off the OpenPGP extension. - If this is not possible, we return an error. */ - if (!stristr (pfx->orig_filename, ".gpg") && - !stristr (pfx->orig_filename, ".pgp") && - !stristr (pfx->orig_filename, ".asc")) - { - cdk_pkt_release (pkt); - cdk_stream_close (si); - cdk_stream_close (so); - _cdk_log_debug - ("literal filter: no file name and no PGP extension\n"); - return CDK_Inv_Mode; - } - _cdk_log_debug ("literal filter: derrive file name from original\n"); - pfx->filename = dup_trim_filename (pfx->orig_filename); - pfx->filename[strlen (pfx->filename) - 4] = '\0'; - } - - while (!feof (in)) - { - _cdk_log_debug ("literal_decode: part on %d size %lu\n", - pfx->blkmode.on, pfx->blkmode.size); - if (pfx->blkmode.on) - bufsize = pfx->blkmode.size; - else - bufsize = pt->len < DIM (buf) ? pt->len : DIM (buf); - nread = cdk_stream_read (pt->buf, buf, bufsize); - if (nread == EOF) - { - rc = CDK_File_Error; - break; - } - if (pfx->md) - gcry_md_write (pfx->md, buf, nread); - cdk_stream_write (so, buf, nread); - pt->len -= nread; - if (pfx->blkmode.on) - { - pfx->blkmode.size = _cdk_pkt_read_len (in, &pfx->blkmode.on); - if (pfx->blkmode.size == (size_t) EOF) - return CDK_Inv_Packet; - } - if (pt->len <= 0 && !pfx->blkmode.on) - break; - } - - cdk_stream_close (si); - cdk_stream_close (so); - cdk_pkt_release (pkt); - return rc; -} - - -static char -intmode_to_char (int mode) -{ - switch (mode) - { - case CDK_LITFMT_BINARY: - return 'b'; - case CDK_LITFMT_TEXT: - return 't'; - case CDK_LITFMT_UNICODE: - return 'u'; - default: - return 'b'; - } - - return 'b'; -} - - -static cdk_error_t -literal_encode (void *opaque, FILE * in, FILE * out) -{ - literal_filter_t *pfx = opaque; - cdk_pkt_literal_t pt; - cdk_stream_t si; - cdk_packet_t pkt; - size_t filelen; - cdk_error_t rc; - - _cdk_log_debug ("literal filter: encode\n"); - - if (!pfx || !in || !out) - return CDK_Inv_Value; - if (!pfx->filename) - { - pfx->filename = cdk_strdup ("_CONSOLE"); - if (!pfx->filename) - return CDK_Out_Of_Core; - } - - rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si); - if (rc) - return rc; - - filelen = strlen (pfx->filename); - cdk_pkt_new (&pkt); - pt = pkt->pkt.literal = cdk_calloc (1, sizeof *pt + filelen - 1); - if (!pt) - { - cdk_pkt_release (pkt); - cdk_stream_close (si); - return CDK_Out_Of_Core; - } - memcpy (pt->name, pfx->filename, filelen); - pt->namelen = filelen; - pt->name[pt->namelen] = '\0'; - pt->timestamp = (u32) time (NULL); - pt->mode = intmode_to_char (pfx->mode); - pt->len = cdk_stream_get_length (si); - pt->buf = si; - pkt->old_ctb = 1; - pkt->pkttype = CDK_PKT_LITERAL; - pkt->pkt.literal = pt; - rc = _cdk_pkt_write_fp (out, pkt); - - cdk_pkt_release (pkt); - cdk_stream_close (si); - return rc; -} - - -int -_cdk_filter_literal (void *opaque, int ctl, FILE * in, FILE * out) -{ - if (ctl == STREAMCTL_READ) - return literal_decode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return literal_encode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - literal_filter_t *pfx = opaque; - if (pfx) - { - _cdk_log_debug ("free literal filter\n"); - cdk_free (pfx->filename); - pfx->filename = NULL; - cdk_free (pfx->orig_filename); - pfx->orig_filename = NULL; - return 0; - } - } - return CDK_Inv_Mode; -} - - -static int -text_encode (void *opaque, FILE * in, FILE * out) -{ - const char *s; - char buf[2048]; - - if (!in || !out) - return CDK_Inv_Value; - - /* FIXME: This code does not work for very long lines. */ - while (!feof (in)) - { - s = fgets (buf, DIM (buf) - 1, in); - if (!s) - break; - _cdk_trim_string (buf, 1); - fwrite (buf, 1, strlen (buf), out); - } - - return 0; -} - - -static int -text_decode (void *opaque, FILE * in, FILE * out) -{ - text_filter_t *tfx = opaque; - const char *s; - char buf[2048]; - - if (!tfx || !in || !out) - return CDK_Inv_Value; - - while (!feof (in)) - { - s = fgets (buf, DIM (buf) - 1, in); - if (!s) - break; - _cdk_trim_string (buf, 0); - fwrite (buf, 1, strlen (buf), out); - fwrite (tfx->lf, 1, strlen (tfx->lf), out); - } - - return 0; -} - - -int -_cdk_filter_text (void *opaque, int ctl, FILE * in, FILE * out) -{ - if (ctl == STREAMCTL_READ) - return text_encode (opaque, in, out); - else if (ctl == STREAMCTL_WRITE) - return text_decode (opaque, in, out); - else if (ctl == STREAMCTL_FREE) - { - text_filter_t *tfx = opaque; - if (tfx) - { - _cdk_log_debug ("free text filter\n"); - tfx->lf = NULL; - } - } - return CDK_Inv_Mode; -} diff --git a/src/daemon/https/opencdk/main.c b/src/daemon/https/opencdk/main.c @@ -1,779 +0,0 @@ -/* main.c - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <errno.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#ifdef _WIN32 -#include <windows.h> -#endif - -#include "opencdk.h" -#include "main.h" -#include "packet.h" - - -/* Set a default cipher algorithm and a digest algorithm. - Even if AES and SHA-256 are not 'MUST' in the latest - OpenPGP draft, AES seems to be a good choice. */ -#define DEFAULT_CIPHER_ALGO GCRY_CIPHER_AES -#define DEFAULT_DIGEST_ALGO GCRY_MD_SHA256 - -/* The site of the secure memory which is allocated in gcrypt. */ -#define SECMEM_SIZE 16384 - - -/* Hooks to custom memory allocation functions. */ -static void *(*alloc_func) (size_t n) = gcry_xmalloc; -static void *(*alloc_secure_func) (size_t n) = gcry_malloc_secure; -static void *(*realloc_func) (void *p, size_t n) = gcry_realloc; -static void *(*calloc_func) (size_t m, size_t n) = gcry_calloc; -static void (*free_func) (void *) = gcry_free; -static int malloc_hooks = 0; -static int secmem_init = 0; - -/* Global settings for the logging. */ -static cdk_log_fnc_t log_handler = NULL; -static void *log_handler_value = NULL; -static int log_level = CDK_LOG_NONE; - - -/** - * cdk_strerror: - * @ec: the error number - * - * Return an error text for the given id. - **/ -const char * -cdk_strerror (int ec) -{ - static char buf[20]; - - switch (ec) - { - case CDK_EOF: - return "End Of File"; - case CDK_Success: - return "No error"; - case CDK_General_Error: - return "General error"; - case CDK_File_Error: - return strerror (errno); - case CDK_Bad_Sig: - return "Bad signature"; - case CDK_Inv_Packet: - return "Invalid packet"; - case CDK_Inv_Algo: - return "Invalid algorithm"; - case CDK_Not_Implemented: - return "This is not implemented yet"; - case CDK_Armor_Error: - return "ASCII armor error"; - case CDK_Armor_CRC_Error: - return "ASCII armored damaged (CRC error)"; - case CDK_MPI_Error: - return "Invalid or missformed MPI"; - case CDK_Inv_Value: - return "Invalid parameter or value"; - case CDK_Error_No_Key: - return "No key available or not found"; - case CDK_Chksum_Error: - return "Check for key does not match"; - case CDK_Time_Conflict: - return "Time conflict"; - case CDK_Zlib_Error: - return "ZLIB error"; - case CDK_Weak_Key: - return "Weak key was detected"; - case CDK_Out_Of_Core: - return "Out of core!!"; - case CDK_Wrong_Seckey: - return "Wrong secret key"; - case CDK_Wrong_Format: - return "Data has wrong format"; - case CDK_Bad_MDC: - return "Manipulated MDC detected"; - case CDK_Inv_Mode: - return "Invalid mode"; - case CDK_Error_No_Keyring: - return "No keyring available"; - case CDK_Inv_Packet_Ver: - return "Invalid version for packet"; - case CDK_Too_Short: - return "Buffer or object is too short"; - case CDK_Unusable_Key: - return "Unusable public key"; - case CDK_No_Data: - return "No data"; - case CDK_No_Passphrase: - return "No passphrase supplied"; - case CDK_Network_Error: - return "A network error occurred"; - default: - sprintf (buf, "ec=%d", ec); - return buf; - } - return NULL; -} - - -static void -out_of_core (size_t n) -{ - fprintf (stderr, "\n ** fatal error: out of memory (%d bytes) **\n", n); -} - - -/** - * cdk_set_malloc_hooks: - * @new_alloc_func: malloc replacement - * @new_alloc_secure_func: secure malloc replacement - * @new_realloc_func: realloc replacement - * @new_calloc_func: calloc replacement - * @new_free_func: free replacement - * - * Set private memory hooks for the library. - */ -void -cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n), - void *(*new_alloc_secure_func) (size_t n), - void *(*new_realloc_func) (void *p, size_t n), - void *(*new_calloc_func) (size_t m, size_t n), - void (*new_free_func) (void *)) -{ - alloc_func = new_alloc_func; - alloc_secure_func = new_alloc_secure_func; - realloc_func = new_realloc_func; - calloc_func = new_calloc_func; - free_func = new_free_func; - malloc_hooks = 1; -} - - -/** - * cdk_malloc_hook_initialized: - * - * Return if the malloc hooks are already initialized. - **/ -int -cdk_malloc_hook_initialized (void) -{ - return malloc_hooks; -} - - -void * -cdk_malloc (size_t size) -{ - void *p = alloc_func (size); - if (!p) - out_of_core (size); - return p; -} - - -/** - * cdk_calloc: - * @n: amount of elements - * @m: size of one element - * - * Safe wrapper around the c-function calloc. - **/ -void * -cdk_calloc (size_t n, size_t m) -{ - void *p = calloc_func (n, m); - if (!p) - out_of_core (m); - return p; -} - - -/* Things which need to be done after the secure memory initialisation. */ -static void -_secmem_finish (void) -{ - gcry_control (GCRYCTL_DROP_PRIVS); -} - - -/* Initialize the secure memory. */ -static void -_secmem_init (size_t size) -{ - if (secmem_init == 1) - return; - if (size >= SECMEM_SIZE) - size = SECMEM_SIZE; - - /* Check if no other library has already initialized gcrypt. */ - if (!gcry_control (GCRYCTL_ANY_INITIALIZATION_P)) - { - _cdk_log_debug ("init: libgcrypt initialize.\n"); - gcry_control (GCRYCTL_INIT_SECMEM, size, 0); - gcry_control (GCRYCTL_USE_SECURE_RNDPOOL); - gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0); - secmem_init = 1; - } -} - - -/* Things which needs to be done to deinit the secure memory. */ -static void -_secmem_end (void) -{ - gcry_control (GCRYCTL_TERM_SECMEM); - secmem_init = 0; -} - - -/* The Windows system needs to startup the Winsock interface first - before we can use any socket related function. */ -#ifdef _WIN32 -static void -init_sockets (void) -{ - static int initialized = 0; - WSADATA wsdata; - - if (initialized) - return; - if (WSAStartup (0x202, &wsdata)) - _cdk_log_debug ("winsock init failed.\n"); - - initialized = 1; -} - -static void -deinit_sockets (void) -{ - WSACleanup (); -} -#else -void -init_sockets (void) -{ -} -void -deinit_sockets (void) -{ -} -#endif - - -/** - * cdk_lib_startup: - * - * Prepare the internal structures of the library. - * This function should be called before any other CDK function. - */ -void -cdk_lib_startup (void) -{ - _secmem_init (SECMEM_SIZE); - _secmem_finish (); - init_sockets (); -} - - -/** - * cdk_lib_shutdown: - * - * Shutdown the library and free all internal and globally used - * memory and structures. This function should be called in the - * exit handler of the calling program. - */ -void -cdk_lib_shutdown (void) -{ - deinit_sockets (); - _secmem_end (); -} - -/** - * cdk_salloc: - * @size: how much bytes should be allocated. - * @clear: shall the buffer cleared after the allocation? - * - * Allocated the requested amount of bytes in 'secure' memory. - */ -void * -cdk_salloc (size_t size, int clear) -{ - void *p; - - if (!secmem_init) - _secmem_init (SECMEM_SIZE); - - p = alloc_secure_func (size); - if (!p) - out_of_core (size); - if (clear) - memset (p, 0, size); - return p; -} - - -void * -cdk_realloc (void *ptr, size_t size) -{ - void *p = realloc_func (ptr, size); - if (!p) - out_of_core (size); - return p; -} - - -char * -cdk_strdup (const char *ptr) -{ - char *p = cdk_malloc (strlen (ptr) + 1); - if (p) - strcpy (p, ptr); - return p; -} - - -void -cdk_free (void *ptr) -{ - if (ptr) - free_func (ptr); -} - - -/* Internal logging routine. */ -static void -_cdk_logv (int level, const char *fmt, va_list arg_ptr) -{ - - if (log_handler) - log_handler (log_handler_value, level, fmt, arg_ptr); - else - { - if (level == CDK_LOG_NONE) - return; - if (level == CDK_LOG_DEBUG) - fputs ("DBG: ", stderr); - vfprintf (stderr, fmt, arg_ptr); - } -} - - -/** - * cdk_set_log_handler: - * @logfnc: the function pointer - * @opaque: a private values for the function - * - * Set a custom handler for logging. - **/ -void -cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque) -{ - log_handler = logfnc; - log_handler_value = opaque; -} - - -/** - * cdk_set_log_level: - * @lvl: the level - * - * Set the verbosity level. - **/ -void -cdk_set_log_level (int level) -{ - log_level = level; -} - - -/* Return the current log level of the lib. */ -int -_cdk_get_log_level (void) -{ - return log_level; -} - - -void -_cdk_log_info (const char *fmt, ...) -{ - va_list arg; - - if (log_level == CDK_LOG_NONE) - return; - va_start (arg, fmt); - _cdk_logv (CDK_LOG_INFO, fmt, arg); - va_end (arg); -} - - -void -_cdk_log_debug (const char *fmt, ...) -{ - va_list arg; - - if (log_level < CDK_LOG_DEBUG) - return; - va_start (arg, fmt); - _cdk_logv (CDK_LOG_DEBUG, fmt, arg); - va_end (arg); -} - - -/* Use the passphrase callback in the handle HD or - return NULL if there is no valid callback. */ -char * -_cdk_passphrase_get (cdk_ctx_t hd, const char *prompt) -{ - if (!hd || !hd->passphrase_cb) - return NULL; - return hd->passphrase_cb (hd->passphrase_cb_value, prompt); -} - - -static void -handle_set_cipher (cdk_ctx_t hd, int cipher) -{ - if (!hd) - return; - if (gcry_cipher_test_algo (cipher)) - cipher = DEFAULT_CIPHER_ALGO; - hd->cipher_algo = cipher; -} - - -static void -handle_set_digest (cdk_ctx_t hd, int digest) -{ - if (!hd) - return; - if (gcry_md_test_algo (digest)) - digest = DEFAULT_DIGEST_ALGO; - hd->digest_algo = digest; -} - - -static void -handle_set_s2k (cdk_ctx_t hd, int mode, int digest, int cipher) -{ - if (!hd) - return; - if (gcry_cipher_test_algo (cipher)) - cipher = DEFAULT_CIPHER_ALGO; - if (gcry_md_test_algo (digest)) - digest = DEFAULT_DIGEST_ALGO; - if (mode != CDK_S2K_SIMPLE && - mode != CDK_S2K_SALTED && mode != CDK_S2K_ITERSALTED) - mode = CDK_S2K_ITERSALTED; - hd->_s2k.mode = mode; - hd->_s2k.digest_algo = digest; -} - - -static void -handle_set_compress (cdk_ctx_t hd, int algo, int level) -{ - if (!hd) - return; - if (algo < 0 || algo > 2) - algo = 0; - hd->compress.algo = algo; - if (!algo) - hd->opt.compress = 0; - else - { - if (level > 0 && level < 10) - hd->compress.level = level; - else - hd->compress.level = 6; - } -} - - -/** - * cdk_handle_control: - * @hd: session handle - * @action: flag which indicates whether put or get is requested - * @cmd: command id - * - * Perform various control operations for the current session. - **/ -int -cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...) -{ - va_list arg_ptr; - int set = action == CDK_CTLF_SET, val = 0; - - if (!hd) - return -1; - - if (action != CDK_CTLF_SET && action != CDK_CTLF_GET) - return -1; - va_start (arg_ptr, cmd); - switch (cmd) - { - case CDK_CTL_ARMOR: - if (set) - hd->opt.armor = va_arg (arg_ptr, int); - else - val = hd->opt.armor; - break; - - case CDK_CTL_CIPHER: - if (set) - handle_set_cipher (hd, va_arg (arg_ptr, int)); - else - val = hd->cipher_algo; - break; - - case CDK_CTL_DIGEST: - if (set) - handle_set_digest (hd, va_arg (arg_ptr, int)); - else - val = hd->digest_algo; - break; - - case CDK_CTL_OVERWRITE: - if (set) - hd->opt.overwrite = va_arg (arg_ptr, int); - else - val = hd->opt.overwrite; - break; - - case CDK_CTL_COMPRESS: - if (set) - { - int algo = va_arg (arg_ptr, int); - int level = va_arg (arg_ptr, int); - handle_set_compress (hd, algo, level); - } - else - val = hd->compress.algo; - break; - - case CDK_CTL_S2K: - if (set) - { - int mode = va_arg (arg_ptr, int); - int digest = va_arg (arg_ptr, int); - int cipher = va_arg (arg_ptr, int); - handle_set_s2k (hd, mode, digest, cipher); - } - else - val = hd->_s2k.mode; - break; - - case CDK_CTL_FORCE_DIGEST: - if (set) - hd->opt.force_digest = va_arg (arg_ptr, int); - else - val = hd->opt.force_digest; - break; - - case CDK_CTL_BLOCKMODE_ON: - if (set) - hd->opt.blockmode = va_arg (arg_ptr, int); - else - val = hd->opt.blockmode; - break; - - default: - val = -1; - break; - } - va_end (arg_ptr); - return val; -} - - - -/** - * cdk_handle_new: - * @r_ctx: context to store the handle - * - * create a new session handle. - **/ -cdk_error_t -cdk_handle_new (cdk_ctx_t * r_ctx) -{ - cdk_ctx_t c; - - if (!r_ctx) - return CDK_Inv_Value; - - c = cdk_calloc (1, sizeof *c); - if (!c) - return CDK_Out_Of_Core; - - /* For S2K use the iterated and salted mode and use the - default digest and cipher algorithms. Because the MDC - feature will be used, the default cipher should use a - blocksize of 128 bits. */ - c->_s2k.mode = CDK_S2K_ITERSALTED; - c->_s2k.digest_algo = DEFAULT_DIGEST_ALGO; - - c->opt.mdc = 1; - c->opt.compress = 1; - c->opt.armor = 0; - c->opt.textmode = 0; - - c->digest_algo = DEFAULT_DIGEST_ALGO; - c->cipher_algo = DEFAULT_CIPHER_ALGO; - - c->compress.algo = CDK_COMPRESS_ZIP; - c->compress.level = 6; - - *r_ctx = c; - return 0; -} - - -/** - * cdk_handle_set_keyring: - * @hd: session handle - * @type: public=0 or secret=1 keyring type - * @kringname: file name of the keyring which shall be used. - * - * Convenient function to set the keyring for the current session. - */ -cdk_error_t -cdk_handle_set_keyring (cdk_ctx_t hd, int type, const char *kringname) -{ - cdk_keydb_hd_t db; - cdk_error_t err; - - err = cdk_keydb_new_from_file (&db, type, kringname); - if (err) - return err; - - if (!type) - hd->db.pub = db; - else - hd->db.sec = db; - hd->db.close_db = 1; - return 0; -} - - -/** - * cdk_handle_set_keydb: - * @hd: session handle - * @db: the database handle - * - * set the key database handle. - * the function automatically detects whether this is a public or - * secret keyring and the right handle is set. - **/ -void -cdk_handle_set_keydb (cdk_ctx_t hd, cdk_keydb_hd_t db) -{ - if (!hd) - return; - if (_cdk_keydb_is_secret (db)) - hd->db.sec = db; - else - hd->db.pub = db; -} - - -/** - * cdk_handle_get_keydb: - * @hd: session handle - * @type: type of the keyring - * - * Return the keydb handle from the session handle. - * The caller should not free these handles. - **/ -cdk_keydb_hd_t -cdk_handle_get_keydb (cdk_ctx_t hd, int type) -{ - if (!hd) - return NULL; - if (type == CDK_DBTYPE_PK_KEYRING) - return hd->db.pub; - else if (type == CDK_DBTYPE_SK_KEYRING) - return hd->db.sec; - return NULL; -} - - -/** - * cdk_handle_set_passphrase_cb: - * @hd: session handle - * @cb: callback function - * @cb_value: the opaque value for the cb function - * - * set the passphrase callback. - **/ -void -cdk_handle_set_passphrase_cb (cdk_ctx_t hd, - char *(*cb) (void *opa, const char *prompt), - void *cb_value) -{ - if (!hd) - return; - hd->passphrase_cb = cb; - hd->passphrase_cb_value = cb_value; -} - - -/** - * cdk_handle_verify_get_result: - * @hd: the session handle - * - * Return the verify result for the current session. - * Do not free the pointer. - **/ -cdk_verify_result_t -cdk_handle_verify_get_result (cdk_ctx_t hd) -{ - return hd->result.verify; -} - - -/** - * cdk_handle_free: - * @hd: the handle - * - * Release the main handle. - **/ -void -cdk_handle_free (cdk_ctx_t hd) -{ - if (!hd) - return; - _cdk_result_verify_free (hd->result.verify); - - /* If cdk_handle_set_keyring() were used, we need to free the key db - handles here because the handles are not controlled by the user. */ - if (hd->db.close_db) - { - if (hd->db.pub) - cdk_keydb_free (hd->db.pub); - if (hd->db.sec) - cdk_keydb_free (hd->db.sec); - hd->db.pub = hd->db.sec = NULL; - } - cdk_free (hd->dek); - cdk_free (hd); -} diff --git a/src/daemon/https/opencdk/main.h b/src/daemon/https/opencdk/main.h @@ -1,183 +0,0 @@ -/* main.h - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifndef CDK_MAIN_H -#define CDK_MAIN_H - -#include <gcrypt.h> -#include "types.h" - -/* The general size of a buffer for the variou modules. */ -#define BUFSIZE 8192 - -/* This is the default block size for the partial length packet mode. */ -#define DEF_BLOCKSIZE 8192 -#define DEF_BLOCKBITS 13 /* 2^13 = 8192 */ - -/* For now SHA-1 is used to create fingerprint for keys. - But if this will ever change, it is a good idea to - have a constant for it to avoid to change it in all files. */ -#define KEY_FPR_LEN 20 - -#include "context.h" - -/* The maximal amount of bits a multi precsion integer can have. */ -#define MAX_MPI_BITS 16384 -#define MAX_MPI_BYTES (MAX_MPI_BITS/8) - - -/* Because newer DSA variants are not limited to SHA-1, we must consider - that SHA-512 is used and increase the buffer size of the digest. */ -#define MAX_DIGEST_LEN 64 - -/* Helper to find out if the signature were made over a user ID - or if the signature revokes a previous user ID. */ -#define IS_UID_SIG(s) (((s)->sig_class & ~3) == 0x10) -#define IS_UID_REV(s) ((s)->sig_class == 0x30) - -#define DEBUG_PKT (_cdk_get_log_level () == (CDK_LOG_DEBUG+1)) - -/* Helper to find out if a key has the requested capability. */ -#define KEY_CAN_ENCRYPT(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_ENCR) -#define KEY_CAN_SIGN(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_SIGN) -#define KEY_CAN_AUTH(a) (_cdk_pk_algo_usage ((a)) & CDK_KEY_USG_AUTH) - -/* Helper macro to make sure the buffer is overwritten. */ -#define wipemem(_ptr,_len) do { \ - volatile char *_vptr = (volatile char *)(_ptr); \ - size_t _vlen = (_len); \ - while (_vlen) \ - { \ - *_vptr = 0; \ - _vptr++; \ - _vlen--; \ - } } while (0) - -/*-- armor.c --*/ -const char * _cdk_armor_get_lineend (void); - -/*-- main.c --*/ -int _cdk_get_log_level (void); -void _cdk_log_info (const char * fmt, ...); -void _cdk_log_debug (const char * fmt, ...); -char * _cdk_passphrase_get (cdk_ctx_t hd, const char *prompt); - -/*-- misc.c --*/ -int _cdk_check_args( int overwrite, const char * in, const char * out ); -u32 _cdk_buftou32 (const byte * buf); -void _cdk_u32tobuf (u32 u, byte * buf); -const char *_cdk_memistr (const char * buf, size_t buflen, const char * sub); -cdk_error_t _cdk_map_gcry_error (gcry_error_t err); -#define map_gcry_error(err) _cdk_map_gcry_error (err) - -/* Helper to provide case insentensive strstr version. */ -#define stristr(haystack, needle) \ - _cdk_memistr((haystack), strlen (haystack), (needle)) - -/*-- proc-packet.c --*/ -cdk_error_t _cdk_proc_packets (cdk_ctx_t hd, cdk_stream_t inp, - cdk_stream_t data, - const char *output, cdk_stream_t outstream, - gcry_md_hd_t md); -cdk_error_t _cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx); - -/*-- pubkey.c --*/ -u32 _cdk_pkt_get_keyid (cdk_packet_t pkt, u32 * keyid); -cdk_error_t _cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte *fpr); -int _cdk_pk_algo_usage (int algo); -int _cdk_pk_test_algo (int algo, unsigned int usage); -int _cdk_sk_get_csum (cdk_pkt_seckey_t sk); - -/*-- new-packet.c --*/ -byte * _cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t * r_nbytes); -cdk_error_t _cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src); -void _cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx); - -/*-- sig-check.c --*/ -cdk_error_t _cdk_sig_check (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig, - gcry_md_hd_t digest, int * r_expired); -cdk_error_t _cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t hd); -cdk_error_t _cdk_hash_userid (cdk_pkt_userid_t uid, int sig_version, gcry_md_hd_t md); -cdk_error_t _cdk_hash_pubkey (cdk_pkt_pubkey_t pk, gcry_md_hd_t md, - int use_fpr); -cdk_error_t _cdk_pk_check_sig (cdk_keydb_hd_t hd, - cdk_kbnode_t knode, - cdk_kbnode_t snode, int *is_selfsig); - -/*-- kbnode.c --*/ -void _cdk_kbnode_add (cdk_kbnode_t root, cdk_kbnode_t node); -void _cdk_kbnode_clone (cdk_kbnode_t node); - -/*-- sesskey.c --*/ -cdk_error_t _cdk_digest_encode_pkcs1 (byte **r_md, size_t *r_mdlen, - int pk_algo, - const byte * md, - int digest_algo, unsigned nbits); -cdk_error_t _cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk); - -/*-- keydb.c --*/ -int _cdk_keydb_is_secret (cdk_keydb_hd_t db); -cdk_error_t _cdk_keydb_get_pk_byusage (cdk_keydb_hd_t hd, const char * name, - cdk_pkt_pubkey_t * ret_pk, int usage); -cdk_error_t _cdk_keydb_get_sk_byusage (cdk_keydb_hd_t hd, const char * name, - cdk_pkt_seckey_t * ret_sk, int usage); -cdk_error_t _cdk_keydb_check_userid (cdk_keydb_hd_t hd, u32 * keyid, - const char * id); - -/*-- sign.c --*/ -int _cdk_sig_hash_for (cdk_pkt_pubkey_t pk); -void _cdk_trim_string (char * s, int canon); -cdk_error_t _cdk_sig_create (cdk_pkt_pubkey_t pk, cdk_pkt_signature_t sig); -cdk_error_t _cdk_sig_complete (cdk_pkt_signature_t sig, cdk_pkt_seckey_t sk, - gcry_md_hd_t hd); - -/*-- stream.c --*/ -void _cdk_stream_set_compress_algo (cdk_stream_t s, int algo); -cdk_error_t _cdk_stream_open_mode (const char *file, const char *mode, - cdk_stream_t *ret_s); -void * _cdk_stream_get_opaque( cdk_stream_t s, int fid ); -const char * _cdk_stream_get_fname( cdk_stream_t s ); -FILE * _cdk_stream_get_fp( cdk_stream_t s ); -int _cdk_stream_gets( cdk_stream_t s, char * buf, size_t count ); -cdk_error_t _cdk_stream_append( const char * file, cdk_stream_t * ret_s ); -int _cdk_stream_get_errno( cdk_stream_t s ); -cdk_error_t _cdk_stream_set_blockmode( cdk_stream_t s, size_t nbytes ); -int _cdk_stream_get_blockmode( cdk_stream_t s ); -int _cdk_stream_puts( cdk_stream_t s, const char * buf ); -cdk_error_t _cdk_stream_fpopen (FILE * fp, unsigned write_mode, - cdk_stream_t *ret_out); - -/*-- verify.c --*/ -void _cdk_result_verify_free (cdk_verify_result_t res); -cdk_verify_result_t _cdk_result_verify_new (void); - - -/*-- read-packet.c --*/ -size_t _cdk_pkt_read_len (FILE * inp, size_t *ret_partial); - -/*-- write-packet.c --*/ -cdk_error_t _cdk_pkt_write_fp( FILE * out, cdk_packet_t pkt ); - -/*-- seskey.c --*/ -cdk_error_t _cdk_s2k_copy (cdk_s2k_t *r_dst, cdk_s2k_t src); - -cdk_error_t cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, - gcry_mpi_t *r_enc); -cdk_error_t cdk_dek_decode_pkcs1 (cdk_dek_t * ret_dek, gcry_mpi_t esk); -cdk_error_t cdk_dek_extract (cdk_dek_t * ret_dek, cdk_ctx_t hd, - cdk_pkt_pubkey_enc_t enc, - cdk_pkt_seckey_t sk ); - -#endif /* CDK_MAIN_H */ diff --git a/src/daemon/https/opencdk/misc.c b/src/daemon/https/opencdk/misc.c @@ -1,571 +0,0 @@ -/* misc.c - * Copyright (C) 2002, 2003 Timo Schulz - * Copyright (C) 1998-2002, 2007 Free Software Foundation, Inc. - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <sys/stat.h> - -#include "opencdk.h" -#include "main.h" - - -u32 -_cdk_buftou32 (const byte * buf) -{ - u32 u; - - if (!buf) - return 0; - u = buf[0] << 24; - u |= buf[1] << 16; - u |= buf[2] << 8; - u |= buf[3]; - return u; -} - - -void -_cdk_u32tobuf (u32 u, byte * buf) -{ - if (!buf) - return; - buf[0] = u >> 24; - buf[1] = u >> 16; - buf[2] = u >> 8; - buf[3] = u; -} - - -static const char * -parse_version_number (const char *s, int *number) -{ - int val = 0; - - if (*s == '0' && isdigit (s[1])) - return NULL; - /* leading zeros are not allowed */ - for (; isdigit (*s); s++) - { - val *= 10; - val += *s - '0'; - } - *number = val; - return val < 0 ? NULL : s; -} - - -static const char * -parse_version_string (const char *s, int *major, int *minor, int *micro) -{ - s = parse_version_number (s, major); - if (!s || *s != '.') - return NULL; - s++; - s = parse_version_number (s, minor); - if (!s || *s != '.') - return NULL; - s++; - s = parse_version_number (s, micro); - if (!s) - return NULL; - return s; /* patchlevel */ -} - - -/** - * cdk_check_version: - * @req_version: The requested version - * - * Check that the the version of the library is at minimum the requested - * one and return the version string; return NULL if the condition is - * not satisfied. If a NULL is passed to this function, no check is done, - *but the version string is simply returned. - **/ -const char * -cdk_check_version (const char *req_version) -{ - const char *ver = VERSION; - int my_major, my_minor, my_micro; - int rq_major, rq_minor, rq_micro; - const char *my_plvl, *rq_plvl; - - if (!req_version) - return ver; - my_plvl = parse_version_string (ver, &my_major, &my_minor, &my_micro); - if (!my_plvl) - return NULL; - /* very strange our own version is bogus */ - rq_plvl = parse_version_string (req_version, &rq_major, &rq_minor, - &rq_micro); - if (!rq_plvl) - return NULL; /* req version string is invalid */ - if (my_major > rq_major - || (my_major == rq_major && my_minor > rq_minor) - || (my_major == rq_major && my_minor == rq_minor - && my_micro > rq_micro) - || (my_major == rq_major && my_minor == rq_minor - && my_micro == rq_micro && strcmp (my_plvl, rq_plvl) >= 0)) - return ver; - return NULL; -} - - -/** - * cdk_strlist_free: - * @sl: the string list - * - * Release the string list object. - **/ -void -cdk_strlist_free (cdk_strlist_t sl) -{ - cdk_strlist_t sl2; - - for (; sl; sl = sl2) - { - sl2 = sl->next; - cdk_free (sl); - } -} - - -/** - * cdk_strlist_add: - * @list: destination string list - * @string: the string to add - * - * Add the given list to the string list. - **/ -cdk_strlist_t -cdk_strlist_add (cdk_strlist_t * list, const char *string) -{ - cdk_strlist_t sl; - - if (!string) - return NULL; - - sl = cdk_calloc (1, sizeof *sl + strlen (string) + 1); - if (!sl) - return NULL; - strcpy (sl->d, string); - sl->next = *list; - *list = sl; - return sl; -} - - -/** - * cdk_strlist_next: - * @root: the opaque string list. - * @r_str: optional argument to store the string data. - * - * Return the next string list node from @root. The optional - * argument @r_str return the data of the current (!) node. - **/ -cdk_strlist_t -cdk_strlist_next (cdk_strlist_t root, const char **r_str) -{ - cdk_strlist_t node; - - if (root && r_str) - *r_str = root->d; - for (node = root->next; node; node = node->next) - return node; - - return NULL; -} - - -const char * -_cdk_memistr (const char *buf, size_t buflen, const char *sub) -{ - const byte *t, *s; - size_t n; - - for (t = (byte *) buf, n = buflen, s = (byte *) sub; n; t++, n--) - { - if (toupper (*t) == toupper (*s)) - { - for (buf = t++, buflen = n--, s++; - n && toupper (*t) == toupper ((byte) * s); t++, s++, n--) - ; - if (!*s) - return buf; - t = (byte *) buf; - n = buflen; - s = (byte *) sub; - } - } - - return NULL; -} - - -/** - * cdk_utf8_encode: - * @string: - * - * Encode the given string in utf8 and return it. - **/ -char * -cdk_utf8_encode (const char *string) -{ - const byte *s; - char *buffer; - byte *p; - size_t length; - - /* FIXME: We should use iconv if possible for utf8 issues. */ - for (s = (const byte *) string, length = 0; *s; s++) - { - length++; - if (*s & 0x80) - length++; - } - - buffer = cdk_calloc (1, length + 1); - for (p = (byte *) buffer, s = (byte *) string; *s; s++) - { - if (*s & 0x80) - { - *p++ = 0xc0 | ((*s >> 6) & 3); - *p++ = 0x80 | (*s & 0x3f); - } - else - *p++ = *s; - } - *p = 0; - return buffer; -} - - -/** - * cdk_utf8_decode: - * @string: the string to decode - * @length: the length of the string - * @delim: the delimiter - * - * Decode the given utf8 string and return the native representation. - **/ -char * -cdk_utf8_decode (const char *string, size_t length, int delim) -{ - int nleft; - int i; - byte encbuf[8]; - int encidx; - const byte *s; - size_t n; - byte *buffer = NULL, *p = NULL; - unsigned long val = 0; - size_t slen; - int resync = 0; - - /* 1. pass (p==NULL): count the extended utf-8 characters */ - /* 2. pass (p!=NULL): create string */ - for (;;) - { - for (slen = length, nleft = encidx = 0, n = 0, s = (byte *) string; - slen; s++, slen--) - { - if (resync) - { - if (!(*s < 128 || (*s >= 0xc0 && *s <= 0xfd))) - { - /* still invalid */ - if (p) - { - sprintf ((char *) p, "\\x%02x", *s); - p += 4; - } - n += 4; - continue; - } - resync = 0; - } - if (!nleft) - { - if (!(*s & 0x80)) - { /* plain ascii */ - if (*s < 0x20 || *s == 0x7f || *s == delim || - (delim && *s == '\\')) - { - n++; - if (p) - *p++ = '\\'; - switch (*s) - { - case '\n': - n++; - if (p) - *p++ = 'n'; - break; - case '\r': - n++; - if (p) - *p++ = 'r'; - break; - case '\f': - n++; - if (p) - *p++ = 'f'; - break; - case '\v': - n++; - if (p) - *p++ = 'v'; - break; - case '\b': - n++; - if (p) - *p++ = 'b'; - break; - case 0: - n++; - if (p) - *p++ = '0'; - break; - default: - n += 3; - if (p) - { - sprintf ((char *) p, "x%02x", *s); - p += 3; - } - break; - } - } - else - { - if (p) - *p++ = *s; - n++; - } - } - else if ((*s & 0xe0) == 0xc0) - { /* 110x xxxx */ - val = *s & 0x1f; - nleft = 1; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xf0) == 0xe0) - { /* 1110 xxxx */ - val = *s & 0x0f; - nleft = 2; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xf8) == 0xf0) - { /* 1111 0xxx */ - val = *s & 0x07; - nleft = 3; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xfc) == 0xf8) - { /* 1111 10xx */ - val = *s & 0x03; - nleft = 4; - encidx = 0; - encbuf[encidx++] = *s; - } - else if ((*s & 0xfe) == 0xfc) - { /* 1111 110x */ - val = *s & 0x01; - nleft = 5; - encidx = 0; - encbuf[encidx++] = *s; - } - else - { /* invalid encoding: print as \xnn */ - if (p) - { - sprintf ((char *) p, "\\x%02x", *s); - p += 4; - } - n += 4; - resync = 1; - } - } - else if (*s < 0x80 || *s >= 0xc0) - { /* invalid */ - if (p) - { - for (i = 0; i < encidx; i++) - { - sprintf ((char *) p, "\\x%02x", encbuf[i]); - p += 4; - } - sprintf ((char *) p, "\\x%02x", *s); - p += 4; - } - n += 4 + 4 * encidx; - nleft = 0; - encidx = 0; - resync = 1; - } - else - { - encbuf[encidx++] = *s; - val <<= 6; - val |= *s & 0x3f; - if (!--nleft) - { /* ready native set */ - if (val >= 0x80 && val < 256) - { - n++; /* we can simply print this character */ - if (p) - *p++ = val; - } - else - { /* we do not have a translation: print utf8 */ - if (p) - { - for (i = 0; i < encidx; i++) - { - sprintf ((char *) p, "\\x%02x", encbuf[i]); - p += 4; - } - } - n += encidx * 4; - encidx = 0; - } - } - } - - } - if (!buffer) /* allocate the buffer after the first pass */ - buffer = p = cdk_malloc (n + 1); - else - { - *p = 0; /* make a string */ - return (char *) buffer; - } - } -} - - -/* Map the gcrypt error to a valid opencdk error constant. */ -cdk_error_t -_cdk_map_gcry_error (gcry_error_t err) -{ - /* FIXME: We need to catch them all. */ - switch (gpg_err_code (err)) - { - case GPG_ERR_NO_ERROR: - return CDK_Success; - case GPG_ERR_INV_VALUE: - return CDK_Inv_Value; - case GPG_ERR_GENERAL: - return CDK_General_Error; - case GPG_ERR_INV_PACKET: - return CDK_Inv_Packet; - case GPG_ERR_TOO_SHORT: - return CDK_Too_Short; - case GPG_ERR_TOO_LARGE: - return CDK_Inv_Value; - case GPG_ERR_NO_PUBKEY: - case GPG_ERR_NO_SECKEY: - return CDK_Error_No_Key; - case GPG_ERR_BAD_SIGNATURE: - return CDK_Bad_Sig; - case GPG_ERR_NO_DATA: - return CDK_No_Data; - default: - break; - } - - return (cdk_error_t) err; -} - - -/* Remove all trailing white spaces from the string. */ -void -_cdk_trim_string (char *s, int canon) -{ - while (s && *s && - (s[strlen (s) - 1] == '\t' || - s[strlen (s) - 1] == '\r' || - s[strlen (s) - 1] == '\n' || s[strlen (s) - 1] == ' ')) - s[strlen (s) - 1] = '\0'; - if (canon) - strcat (s, "\r\n"); -} - - -int -_cdk_check_args (int overwrite, const char *in, const char *out) -{ - struct stat stbuf; - - if (!in || !out) - return CDK_Inv_Value; - if (strlen (in) == strlen (out) && strcmp (in, out) == 0) - return CDK_Inv_Mode; - if (!overwrite && !stat (out, &stbuf)) - return CDK_Inv_Mode; - return 0; -} - -#ifdef _WIN32 -#include <io.h> -#include <fcntl.h> - -FILE * -my_tmpfile (void) -{ - /* Because the tmpfile() version of wine is not really useful, - we implement our own version to avoid problems with 'make check'. */ - static const char *letters = "abcdefghijklmnopqrstuvwxyz"; - char buf[512], rnd[24]; - FILE *fp; - int fd, i; - - gcry_create_nonce (rnd, DIM (rnd)); - for (i = 0; i < DIM (rnd) - 1; i++) - { - char c = letters[(unsigned char) rnd[i] % 26]; - rnd[i] = c; - } - rnd[DIM (rnd) - 1] = 0; - if (!GetTempPath (464, buf)) - return NULL; - strcat (buf, "_cdk_"); - strcat (buf, rnd); - - /* We need to make sure the file will be deleted when it is closed. */ - fd = _open (buf, _O_CREAT | _O_EXCL | _O_TEMPORARY | - _O_RDWR | _O_BINARY, _S_IREAD | _S_IWRITE); - if (fd == -1) - return NULL; - fp = fdopen (fd, "w+b"); - if (fp != NULL) - return fp; - _close (fd); - return NULL; -} -#else -FILE * -my_tmpfile (void) -{ - return tmpfile (); -} -#endif diff --git a/src/daemon/https/opencdk/new-packet.c b/src/daemon/https/opencdk/new-packet.c @@ -1,874 +0,0 @@ -/* new-packet.c - packet handling (freeing, copying, ...) - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <string.h> -#include <stdio.h> -#include <assert.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" - - -/* Release an array of MPI values. */ -void -_cdk_free_mpibuf (size_t n, gcry_mpi_t * array) -{ - while (n--) - { - gcry_mpi_release (array[n]); - array[n] = NULL; - } -} - - -/** - * cdk_pkt_new: - * @r_pkt: the new packet - * - * Allocate a new packet. - **/ -cdk_error_t -cdk_pkt_new (cdk_packet_t * r_pkt) -{ - cdk_packet_t pkt; - - if (!r_pkt) - return CDK_Inv_Value; - pkt = cdk_calloc (1, sizeof *pkt); - if (!pkt) - return CDK_Out_Of_Core; - *r_pkt = pkt; - return 0; -} - - -static void -free_symkey_enc (cdk_pkt_symkey_enc_t enc) -{ - if (!enc) - return; - cdk_s2k_free (enc->s2k); - cdk_free (enc); -} - - -static void -free_pubkey_enc (cdk_pkt_pubkey_enc_t enc) -{ - size_t nenc; - - if (!enc) - return; - - nenc = cdk_pk_get_nenc (enc->pubkey_algo); - _cdk_free_mpibuf (nenc, enc->mpi); - cdk_free (enc); -} - - -static void -free_literal (cdk_pkt_literal_t pt) -{ - if (!pt) - return; - /* The buffer which is referenced in this packet is closed - elsewhere. To close it here would cause a double close. */ - cdk_free (pt); -} - - -void -_cdk_free_userid (cdk_pkt_userid_t uid) -{ - if (!uid) - return; - - cdk_free (uid->prefs); - uid->prefs = NULL; - cdk_free (uid->attrib_img); - uid->attrib_img = NULL; - cdk_free (uid); -} - - -void -_cdk_free_signature (cdk_pkt_signature_t sig) -{ - cdk_desig_revoker_t r; - size_t nsig; - - if (!sig) - return; - - nsig = cdk_pk_get_nsig (sig->pubkey_algo); - _cdk_free_mpibuf (nsig, sig->mpi); - - cdk_subpkt_free (sig->hashed); - sig->hashed = NULL; - cdk_subpkt_free (sig->unhashed); - sig->unhashed = NULL; - while (sig->revkeys) - { - r = sig->revkeys->next; - cdk_free (sig->revkeys); - sig->revkeys = r; - } - cdk_free (sig); -} - - -void -cdk_pk_release (cdk_pubkey_t pk) -{ - size_t npkey; - - if (!pk) - return; - - npkey = cdk_pk_get_npkey (pk->pubkey_algo); - _cdk_free_userid (pk->uid); - pk->uid = NULL; - cdk_free (pk->prefs); - pk->prefs = NULL; - _cdk_free_mpibuf (npkey, pk->mpi); - cdk_free (pk); -} - - -void -cdk_sk_release (cdk_seckey_t sk) -{ - size_t nskey; - - if (!sk) - return; - - nskey = cdk_pk_get_nskey (sk->pubkey_algo); - _cdk_free_mpibuf (nskey, sk->mpi); - cdk_free (sk->encdata); - sk->encdata = NULL; - cdk_pk_release (sk->pk); - sk->pk = NULL; - cdk_s2k_free (sk->protect.s2k); - sk->protect.s2k = NULL; - cdk_free (sk); -} - - -static void -free_encrypted (cdk_pkt_encrypted_t enc) -{ - if (!enc) - return; - - /* This is just a reference for the filters to know where - the encrypted data starts and to read from the sream. It - us closed elsewhere and to close it here would double close it. */ - /*cdk_stream_close (enc->buf); */ - enc->buf = NULL; - cdk_free (enc); -} - - -/* Detach the openpgp packet from the packet structure - and release the packet structure itself. */ -void -_cdk_pkt_detach_free (cdk_packet_t pkt, int *r_pkttype, void **ctx) -{ - /* For now we just allow this for keys. */ - switch (pkt->pkttype) - { - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - *ctx = pkt->pkt.public_key; - break; - - case CDK_PKT_SECRET_KEY: - case CDK_PKT_SECRET_SUBKEY: - *ctx = pkt->pkt.secret_key; - break; - - default: - *r_pkttype = 0; - return; - } - - /* The caller might expect a specific packet type and - is not interested to store it for later use. */ - if (r_pkttype) - *r_pkttype = pkt->pkttype; - - cdk_free (pkt); -} - - -void -cdk_pkt_free (cdk_packet_t pkt) -{ - if (!pkt) - return; - - switch (pkt->pkttype) - { - case CDK_PKT_ATTRIBUTE: - case CDK_PKT_USER_ID: - _cdk_free_userid (pkt->pkt.user_id); - break; - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - cdk_pk_release (pkt->pkt.public_key); - break; - case CDK_PKT_SECRET_KEY: - case CDK_PKT_SECRET_SUBKEY: - cdk_sk_release (pkt->pkt.secret_key); - break; - case CDK_PKT_SIGNATURE: - _cdk_free_signature (pkt->pkt.signature); - break; - case CDK_PKT_PUBKEY_ENC: - free_pubkey_enc (pkt->pkt.pubkey_enc); - break; - case CDK_PKT_SYMKEY_ENC: - free_symkey_enc (pkt->pkt.symkey_enc); - break; - case CDK_PKT_MDC: - cdk_free (pkt->pkt.mdc); - break; - case CDK_PKT_ENCRYPTED: - case CDK_PKT_ENCRYPTED_MDC: - free_encrypted (pkt->pkt.encrypted); - break; - case CDK_PKT_ONEPASS_SIG: - cdk_free (pkt->pkt.onepass_sig); - break; - case CDK_PKT_LITERAL: - free_literal (pkt->pkt.literal); - break; - case CDK_PKT_COMPRESSED: - cdk_free (pkt->pkt.compressed); - break; - default: - break; - } - - /* Reset the packet type to avoid, when cdk_pkt_release() will be - used, that the second cdk_pkt_free() call will double free the data. */ - pkt->pkttype = 0; -} - - -/** - * cdk_pkt_release: - * @pkt: the packet - * - * Free the contents of the given package and - * release the memory of the structure. - **/ -void -cdk_pkt_release (cdk_packet_t pkt) -{ - if (!pkt) - return; - cdk_pkt_free (pkt); - cdk_free (pkt); -} - - -/** - * cdk_pkt_alloc: - * @r_pkt: output is the new packet - * @pkttype: the requested packet type - * - * Allocate a new packet structure with the given packet type. - **/ -cdk_error_t -cdk_pkt_alloc (cdk_packet_t * r_pkt, int pkttype) -{ - cdk_packet_t pkt; - int rc; - - if (!r_pkt) - return CDK_Inv_Value; - - rc = cdk_pkt_new (&pkt); - if (rc) - return rc; - - switch (pkttype) - { - case CDK_PKT_USER_ID: - pkt->pkt.user_id = cdk_calloc (1, sizeof pkt->pkt.user_id); - if (!pkt->pkt.user_id) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); - if (!pkt->pkt.public_key) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_SECRET_KEY: - case CDK_PKT_SECRET_SUBKEY: - pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key); - pkt->pkt.secret_key->pk = - cdk_calloc (1, sizeof *pkt->pkt.secret_key->pk); - if (!pkt->pkt.secret_key || !pkt->pkt.secret_key->pk) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_SIGNATURE: - pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature); - if (!pkt->pkt.signature) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_SYMKEY_ENC: - pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc); - if (!pkt->pkt.symkey_enc) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_PUBKEY_ENC: - pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc); - if (!pkt->pkt.pubkey_enc) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_MDC: - pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc); - if (!pkt->pkt.mdc) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_ENCRYPTED_MDC: - case CDK_PKT_ENCRYPTED: - pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc); - if (!pkt->pkt.symkey_enc) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_ONEPASS_SIG: - pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig); - if (!pkt->pkt.onepass_sig) - return CDK_Out_Of_Core; - break; - - case CDK_PKT_LITERAL: - /* FIXME: We would need the size of the file name to allocate extra - bytes, otherwise the result would be useless. */ - pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal); - if (!pkt->pkt.literal) - return CDK_Out_Of_Core; - break; - } - pkt->pkttype = pkttype; - *r_pkt = pkt; - return 0; -} - - -cdk_prefitem_t -_cdk_copy_prefs (const cdk_prefitem_t prefs) -{ - size_t n = 0; - struct cdk_prefitem_s *new_prefs; - - if (!prefs) - return NULL; - - for (n = 0; prefs[n].type; n++) - ; - new_prefs = cdk_calloc (1, sizeof *new_prefs * (n + 1)); - if (!new_prefs) - return NULL; - for (n = 0; prefs[n].type; n++) - { - new_prefs[n].type = prefs[n].type; - new_prefs[n].value = prefs[n].value; - } - new_prefs[n].type = CDK_PREFTYPE_NONE; - new_prefs[n].value = 0; - return new_prefs; -} - - -cdk_error_t -_cdk_copy_userid (cdk_pkt_userid_t * dst, cdk_pkt_userid_t src) -{ - cdk_pkt_userid_t u; - - if (!dst || !src) - return CDK_Inv_Value; - - *dst = NULL; - u = cdk_calloc (1, sizeof *u + strlen (src->name) + 1); - if (!u) - return CDK_Out_Of_Core; - memcpy (u, src, sizeof *u); - memcpy (u->name, src->name, strlen (src->name)); - u->prefs = _cdk_copy_prefs (src->prefs); - if (src->selfsig) - _cdk_copy_signature (&u->selfsig, src->selfsig); - *dst = u; - - return 0; -} - - -cdk_error_t -_cdk_copy_pubkey (cdk_pkt_pubkey_t * dst, cdk_pkt_pubkey_t src) -{ - cdk_pkt_pubkey_t k; - int i; - - if (!dst || !src) - return CDK_Inv_Value; - - *dst = NULL; - k = cdk_calloc (1, sizeof *k); - if (!k) - return CDK_Out_Of_Core; - memcpy (k, src, sizeof *k); - if (src->uid) - _cdk_copy_userid (&k->uid, src->uid); - if (src->prefs) - k->prefs = _cdk_copy_prefs (src->prefs); - for (i = 0; i < cdk_pk_get_npkey (src->pubkey_algo); i++) - k->mpi[i] = gcry_mpi_copy (src->mpi[i]); - *dst = k; - - return 0; -} - - -cdk_error_t -_cdk_copy_seckey (cdk_pkt_seckey_t * dst, cdk_pkt_seckey_t src) -{ - cdk_pkt_seckey_t k; - int i; - - if (!dst || !src) - return CDK_Inv_Value; - - *dst = NULL; - k = cdk_calloc (1, sizeof *k); - if (!k) - return CDK_Out_Of_Core; - memcpy (k, src, sizeof *k); - _cdk_copy_pubkey (&k->pk, src->pk); - - if (src->encdata) - { - k->encdata = cdk_calloc (1, src->enclen + 1); - if (!k->encdata) - return CDK_Out_Of_Core; - memcpy (k->encdata, src->encdata, src->enclen); - } - - _cdk_s2k_copy (&k->protect.s2k, src->protect.s2k); - - for (i = 0; i < cdk_pk_get_nskey (src->pubkey_algo); i++) - { - k->mpi[i] = gcry_mpi_copy (src->mpi[i]); - gcry_mpi_set_flag (k->mpi[i], GCRYMPI_FLAG_SECURE); - } - - *dst = k; - return 0; -} - - -cdk_error_t -_cdk_copy_pk_to_sk (cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk) -{ - if (!pk || !sk) - return CDK_Inv_Value; - - sk->version = pk->version; - sk->expiredate = pk->expiredate; - sk->pubkey_algo = pk->pubkey_algo; - sk->has_expired = pk->has_expired; - sk->is_revoked = pk->is_revoked; - sk->main_keyid[0] = pk->main_keyid[0]; - sk->main_keyid[1] = pk->main_keyid[1]; - sk->keyid[0] = pk->keyid[0]; - sk->keyid[1] = pk->keyid[1]; - - return 0; -} - - -cdk_error_t -_cdk_copy_signature (cdk_pkt_signature_t * dst, cdk_pkt_signature_t src) -{ - cdk_pkt_signature_t s; - - if (!dst || !src) - return CDK_Inv_Value; - - *dst = NULL; - s = cdk_calloc (1, sizeof *s); - if (!s) - return CDK_Out_Of_Core; - memcpy (s, src, sizeof *src); - _cdk_subpkt_copy (&s->hashed, src->hashed); - _cdk_subpkt_copy (&s->unhashed, src->unhashed); - /* FIXME: Copy MPI parts */ - *dst = s; - - return 0; -} - - -cdk_error_t -_cdk_pubkey_compare (cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b) -{ - int na, nb, i; - - if (a->timestamp != b->timestamp || a->pubkey_algo != b->pubkey_algo) - return -1; - if (a->version < 4 && a->expiredate != b->expiredate) - return -1; - na = cdk_pk_get_npkey (a->pubkey_algo); - nb = cdk_pk_get_npkey (b->pubkey_algo); - if (na != nb) - return -1; - - for (i = 0; i < na; i++) - { - if (gcry_mpi_cmp (a->mpi[i], b->mpi[i])) - return -1; - } - - return 0; -} - - -/** - * cdk_subpkt_free: - * @ctx: the sub packet node to free - * - * Release the context. - **/ -void -cdk_subpkt_free (cdk_subpkt_t ctx) -{ - cdk_subpkt_t s; - - while (ctx) - { - s = ctx->next; - cdk_free (ctx); - ctx = s; - } -} - - -/** - * cdk_subpkt_find: - * @ctx: the sub packet node - * @type: the packet type to find - * - * Find the given packet type in the node. If no packet with this - * type was found, return null otherwise pointer to the node. - **/ -cdk_subpkt_t -cdk_subpkt_find (cdk_subpkt_t ctx, size_t type) -{ - return cdk_subpkt_find_nth (ctx, type, 0); -} - -/** - * cdk_subpkt_type_count: - * @ctx: The sub packet context - * @type: The sub packet type. - * - * Return the amount of sub packets with this type. - **/ -size_t -cdk_subpkt_type_count (cdk_subpkt_t ctx, size_t type) -{ - cdk_subpkt_t s; - size_t count; - - count = 0; - for (s = ctx; s; s = s->next) - { - if (s->type == type) - count++; - } - - return count; -} - - -/** - * cdk_subpkt_find_nth: - * @ctx: The sub packet context - * @type: The sub packet type - * @index: The nth packet to retrieve, 0 means the first - * - * Return the nth sub packet of the given type. - **/ -cdk_subpkt_t -cdk_subpkt_find_nth (cdk_subpkt_t ctx, size_t type, size_t idx) -{ - cdk_subpkt_t s; - size_t pos; - - pos = 0; - for (s = ctx; s; s = s->next) - { - if (s->type == type && pos++ == idx) - return s; - } - - return NULL; -} - - -/** - * cdk_subpkt_new: - * @size: the size of the new context - * - * Create a new sub packet node with the size of @size. - **/ -cdk_subpkt_t -cdk_subpkt_new (size_t size) -{ - cdk_subpkt_t s; - - if (!size) - return NULL; - s = cdk_calloc (1, sizeof *s + size + 1); - if (!s) - return NULL; - return s; -} - - -/** - * cdk_subpkt_get_data: - * @ctx: the sub packet node - * @r_type: pointer store the packet type - * @r_nbytes: pointer to store the packet size - * - * Extract the data from the given sub packet. The type is returned - * in @r_type and the size in @r_nbytes. - **/ -const byte * -cdk_subpkt_get_data (cdk_subpkt_t ctx, size_t * r_type, size_t * r_nbytes) -{ - if (!ctx || !r_nbytes) - return NULL; - if (r_type) - *r_type = ctx->type; - *r_nbytes = ctx->size; - return ctx->d; -} - - -/** - * cdk_subpkt_add: - * @root: the root node - * @node: the node to add - * - * Add the node in @node to the root node @root. - **/ -cdk_error_t -cdk_subpkt_add (cdk_subpkt_t root, cdk_subpkt_t node) -{ - cdk_subpkt_t n1; - - if (!root) - return CDK_Inv_Value; - for (n1 = root; n1->next; n1 = n1->next) - ; - n1->next = node; - return 0; -} - - -byte * -_cdk_subpkt_get_array (cdk_subpkt_t s, int count, size_t * r_nbytes) -{ - cdk_subpkt_t list; - byte *buf; - size_t n, nbytes; - - if (!s) - { - if (r_nbytes) - *r_nbytes = 0; - return NULL; - } - - for (n = 0, list = s; list; list = list->next) - { - n++; /* type */ - n += list->size; - if (list->size < 192) - n++; - else if (list->size < 8384) - n += 2; - else - n += 5; - } - buf = cdk_calloc (1, n + 1); - if (!buf) - return NULL; - - n = 0; - for (list = s; list; list = list->next) - { - nbytes = 1 + list->size; /* type */ - if (nbytes < 192) - buf[n++] = nbytes; - else if (nbytes < 8384) - { - buf[n++] = nbytes / 256 + 192; - buf[n++] = nbytes % 256; - } - else - { - buf[n++] = 0xFF; - buf[n++] = nbytes >> 24; - buf[n++] = nbytes >> 16; - buf[n++] = nbytes >> 8; - buf[n++] = nbytes; - } - buf[n++] = list->type; - memcpy (buf + n, list->d, list->size); - n += list->size; - } - - if (count) - { - cdk_free (buf); - buf = NULL; - } - if (r_nbytes) - *r_nbytes = n; - return buf; -} - - -cdk_error_t -_cdk_subpkt_copy (cdk_subpkt_t * r_dst, cdk_subpkt_t src) -{ - cdk_subpkt_t root, p, node; - - if (!src || !r_dst) - return CDK_Inv_Value; - - root = NULL; - for (p = src; p; p = p->next) - { - node = cdk_subpkt_new (p->size); - if (node) - { - memcpy (node->d, p->d, p->size); - node->type = p->type; - node->size = p->size; - } - if (!root) - root = node; - else - cdk_subpkt_add (root, node); - } - *r_dst = root; - return 0; -} - - -/** - * cdk_subpkt_init: - * @node: the sub packet node - * @type: type of the packet which data should be initialized - * @buf: the buffer with the actual data - * @buflen: the size of the data - * - * Set the packet data of the given root and set the type of it. - **/ -void -cdk_subpkt_init (cdk_subpkt_t node, size_t type, - const void *buf, size_t buflen) -{ - if (!node) - return; - node->type = type; - node->size = buflen; - memcpy (node->d, buf, buflen); -} - - -/* FIXME: We need to think of a public interface for it. */ -const byte * -cdk_key_desig_revoker_walk (cdk_desig_revoker_t root, - cdk_desig_revoker_t * ctx, - int *r_class, int *r_algid) -{ - cdk_desig_revoker_t n; - - if (!*ctx) - { - *ctx = root; - n = root; - } - else - { - n = (*ctx)->next; - *ctx = n; - } - - if (n && r_class && r_algid) - { - *r_class = n->r_class; - *r_algid = n->algid; - } - - return n ? n->fpr : NULL; -} - - -/** - * cdk_subpkt_find_next: - * @root: the base where to begin the iteration - * @type: the type to find or 0 for the next node. - * - * Try to find the next node after @root with type. - * If type is 0, the next node will be returned. - **/ -cdk_subpkt_t -cdk_subpkt_find_next (cdk_subpkt_t root, size_t type) -{ - cdk_subpkt_t node; - - for (node = root->next; node; node = node->next) - { - if (!type) - return node; - else if (node->type == type) - return node; - } - - return NULL; -} diff --git a/src/daemon/https/opencdk/opencdk.h b/src/daemon/https/opencdk/opencdk.h @@ -1,1169 +0,0 @@ -/* opencdk.h - Open Crypto Development Kit (OpenCDK) - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * Copyright (C) 2006, 2007 Free Software Foundation, Inc. - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ - -#ifndef OPENCDK_H -#define OPENCDK_H - -#include <stddef.h> /* for size_t */ -#include <stdarg.h> -#include <gcrypt.h> - -/* The OpenCDK version as a string. */ -#define OPENCDK_VERSION "0.6.6" - -/* The OpenCDK version as integer components major.minor.path */ -#define OPENCDK_VERSION_MAJOR 0 -#define OPENCDK_VERSION_MINOR 6 -#define OPENCDK_VERSION_PATCH 6 - -#ifdef __cplusplus -extern "C" { -#if 0 -} -#endif -#endif - -/* General contexts */ - -/* 'Session' handle to support the various options and run-time - information. */ -struct cdk_ctx_s; -typedef struct cdk_ctx_s *cdk_ctx_t; - -/* A generic context to store list of strings. */ -struct cdk_strlist_s; -typedef struct cdk_strlist_s *cdk_strlist_t; - -/* Context used to list keys of a keyring. */ -struct cdk_listkey_s; -typedef struct cdk_listkey_s *cdk_listkey_t; - -/* Opaque Data Encryption Key (DEK) context. */ -struct cdk_dek_s; -typedef struct cdk_dek_s *cdk_dek_t; - -/* Opaque String to Key (S2K) handle. */ -struct cdk_s2k_s; -typedef struct cdk_s2k_s *cdk_s2k_t; - -/* Abstract I/O object, a stream, which is used for most operations. */ -struct cdk_stream_s; -typedef struct cdk_stream_s *cdk_stream_t; - -/* Opaque handle for the user ID preferences. */ -struct cdk_prefitem_s; -typedef struct cdk_prefitem_s *cdk_prefitem_t; - -/* Node to store a single key node packet. */ -struct cdk_kbnode_s; -typedef struct cdk_kbnode_s *cdk_kbnode_t; - -/* Key database handle. */ -struct cdk_keydb_hd_s; -typedef struct cdk_keydb_hd_s *cdk_keydb_hd_t; - -/* Context to store a list of recipient keys. */ -struct cdk_keylist_s; -typedef struct cdk_keylist_s *cdk_keylist_t; - -/* Context to encapsulate a single sub packet of a signature. */ -struct cdk_subpkt_s; -typedef struct cdk_subpkt_s *cdk_subpkt_t; - -/* Context used to generate key pairs. */ -struct cdk_keygen_ctx_s; -typedef struct cdk_keygen_ctx_s *cdk_keygen_ctx_t; - -/* Handle for a single designated revoker. */ -struct cdk_desig_revoker_s; -typedef struct cdk_desig_revoker_s *cdk_desig_revoker_t; - -/* Alias for backward compatibility. */ -typedef gcry_mpi_t cdk_mpi_t; - - -/* All valid error constants. */ -typedef enum { - CDK_EOF = -1, - CDK_Success = 0, - CDK_General_Error = 1, - CDK_File_Error = 2, - CDK_Bad_Sig = 3, - CDK_Inv_Packet = 4, - CDK_Inv_Algo = 5, - CDK_Not_Implemented = 6, - CDK_Armor_Error = 8, - CDK_Armor_CRC_Error = 9, - CDK_MPI_Error = 10, - CDK_Inv_Value = 11, - CDK_Error_No_Key = 12, - CDK_Chksum_Error = 13, - CDK_Time_Conflict = 14, - CDK_Zlib_Error = 15, - CDK_Weak_Key = 16, - CDK_Out_Of_Core = 17, - CDK_Wrong_Seckey = 18, - CDK_Bad_MDC = 19, - CDK_Inv_Mode = 20, - CDK_Error_No_Keyring = 21, - CDK_Wrong_Format = 22, - CDK_Inv_Packet_Ver = 23, - CDK_Too_Short = 24, - CDK_Unusable_Key = 25, - CDK_No_Data = 26, - CDK_No_Passphrase = 27, - CDK_Network_Error = 28 -} cdk_error_t; - - -enum cdk_control_flags { - CDK_CTLF_SET = 0, /* Value to set an option */ - CDK_CTLF_GET = 1, /* Value to get an option */ - CDK_CTL_DIGEST = 10, /* Option to set the digest algorithm. */ - CDK_CTL_CIPHER = 11, /* Option to set the cipher algorithm. */ - CDK_CTL_ARMOR = 12, /* Option to enable armor output. */ - CDK_CTL_COMPRESS = 13, /* Option to enable compression. */ - CDK_CTL_COMPAT = 14, /* Option to switch in compat mode. */ - CDK_CTL_OVERWRITE = 15, /* Option to enable file overwritting. */ - CDK_CTL_S2K = 16, /* Option to set S2K values. */ - CDK_CTL_FORCE_DIGEST = 19, /* Force the use of a digest algorithm. */ - CDK_CTL_BLOCKMODE_ON = 20 /* Enable partial body lengths */ -}; - - -/* Specifies all valid log levels. */ -enum cdk_log_level_t { - CDK_LOG_NONE = 0, /* No log message will be shown. */ - CDK_LOG_INFO = 1, - CDK_LOG_DEBUG = 2, - CDK_LOG_DEBUG_PKT = 3 -}; - - -/* All valid compression algorithms in OpenPGP */ -enum cdk_compress_algo_t { - CDK_COMPRESS_NONE = 0, - CDK_COMPRESS_ZIP = 1, - CDK_COMPRESS_ZLIB = 2, - CDK_COMPRESS_BZIP2 = 3 /* Not supported in this version */ -}; - - -/* All valid public key algorithms valid in OpenPGP */ -enum cdk_pubkey_algo_t { - CDK_PK_RSA = 1, - CDK_PK_RSA_E = 2, /* RSA-E and RSA-S are deprecated use RSA instead */ - CDK_PK_RSA_S = 3, /* and use the key flags in the self signatures. */ - CDK_PK_ELG_E = 16, - CDK_PK_DSA = 17 -}; - - -/* All valid message digest algorithms in OpenPGP. */ -enum cdk_digest_algo_t { - CDK_MD_NONE = 0, - CDK_MD_MD5 = 1, - CDK_MD_SHA1 = 2, - CDK_MD_RMD160 = 3, - CDK_MD_SHA256 = 8, - CDK_MD_SHA384 = 9, - CDK_MD_SHA512 = 10, - CDK_MD_SHA224 = 11 /* This algorithm is NOT available. */ -}; - - -/* All valid symmetric cipher algorithms in OpenPGP */ -enum cdk_cipher_algo_t { - CDK_CIPHER_NONE = 0, - CDK_CIPHER_IDEA = 1, /* This algorithm is NOT available */ - CDK_CIPHER_3DES = 2, - CDK_CIPHER_CAST5 = 3, - CDK_CIPHER_BLOWFISH = 4, - CDK_CIPHER_AES = 7, - CDK_CIPHER_AES192 = 8, - CDK_CIPHER_AES256 = 9, - CDK_CIPHER_TWOFISH = 10 -}; - - -/* The valid 'String-To-Key' modes */ -enum cdk_s2k_type_t { - CDK_S2K_SIMPLE = 0, - CDK_S2K_SALTED = 1, - CDK_S2K_ITERSALTED = 3 -}; - - -/* The different kind of user ID preferences. */ -enum cdk_pref_type_t { - CDK_PREFTYPE_NONE = 0, - CDK_PREFTYPE_SYM = 1, /* Symmetric ciphers */ - CDK_PREFTYPE_HASH = 2, /* Message digests */ - CDK_PREFTYPE_ZIP = 3 /* Compression algorithms */ -}; - - -/* All valid sub packet types. */ -enum cdk_sig_subpacket_t { - CDK_SIGSUBPKT_NONE = 0, - CDK_SIGSUBPKT_SIG_CREATED = 2, - CDK_SIGSUBPKT_SIG_EXPIRE = 3, - CDK_SIGSUBPKT_EXPORTABLE = 4, - CDK_SIGSUBPKT_TRUST = 5, - CDK_SIGSUBPKT_REGEXP = 6, - CDK_SIGSUBPKT_REVOCABLE = 7, - CDK_SIGSUBPKT_KEY_EXPIRE = 9, - CDK_SIGSUBPKT_PREFS_SYM = 11, - CDK_SIGSUBPKT_REV_KEY = 12, - CDK_SIGSUBPKT_ISSUER = 16, - CDK_SIGSUBPKT_NOTATION = 20, - CDK_SIGSUBPKT_PREFS_HASH = 21, - CDK_SIGSUBPKT_PREFS_ZIP = 22, - CDK_SIGSUBPKT_KS_FLAGS = 23, - CDK_SIGSUBPKT_PREF_KS = 24, - CDK_SIGSUBPKT_PRIMARY_UID = 25, - CDK_SIGSUBPKT_POLICY = 26, - CDK_SIGSUBPKT_KEY_FLAGS = 27, - CDK_SIGSUBPKT_SIGNERS_UID = 28, - CDK_SIGSUBPKT_REVOC_REASON = 29, - CDK_SIGSUBPKT_FEATURES = 30 -}; - - -/* All valid armor types. */ -enum cdk_armor_type_t { - CDK_ARMOR_MESSAGE = 0, - CDK_ARMOR_PUBKEY = 1, - CDK_ARMOR_SECKEY = 2, - CDK_ARMOR_SIGNATURE = 3, - CDK_ARMOR_CLEARSIG = 4 -}; - -enum cdk_keydb_flag_t { - /* Valid database search modes */ - CDK_DBSEARCH_EXACT = 1, /* Exact string search */ - CDK_DBSEARCH_SUBSTR = 2, /* Sub string search */ - CDK_DBSEARCH_SHORT_KEYID = 3, /* 32-bit keyid search */ - CDK_DBSEARCH_KEYID = 4, /* 64-bit keyid search */ - CDK_DBSEARCH_FPR = 5, /* 160-bit fingerprint search */ - CDK_DBSEARCH_NEXT = 6, /* Enumerate all keys */ - CDK_DBSEARCH_AUTO = 7, /* Try to classify the string */ - /* Valid database types */ - CDK_DBTYPE_PK_KEYRING = 100, /* A file with one or more public keys */ - CDK_DBTYPE_SK_KEYRING = 101, /* A file with one or more secret keys */ - CDK_DBTYPE_DATA = 102, /* A buffer with at least one public key */ - CDK_DBTYPE_STREAM = 103 /* A stream is used to read keys from */ -}; - - -/* All valid modes for cdk_data_transform() */ -enum cdk_crypto_mode_t { - CDK_CRYPTYPE_NONE = 0, - CDK_CRYPTYPE_ENCRYPT = 1, - CDK_CRYPTYPE_DECRYPT = 2, - CDK_CRYPTYPE_SIGN = 3, - CDK_CRYPTYPE_VERIFY = 4, - CDK_CRYPTYPE_EXPORT = 5, - CDK_CRYPTYPE_IMPORT = 6 -}; - - -/* A list of valid public key usages. */ -enum cdk_key_usage_t { - CDK_KEY_USG_ENCR = 1, /* Key can be used for encryption. */ - CDK_KEY_USG_SIGN = 2, /* Key can be used for signing and certifying. */ - CDK_KEY_USG_AUTH = 4 /* Key can be used for authentication. */ -}; - - -/* Valid flags for keys. */ -enum cdk_key_flag_t { - CDK_KEY_VALID = 0, - CDK_KEY_INVALID = 1, /* Missing or wrong self signature */ - CDK_KEY_EXPIRED = 2, /* Key is expired. */ - CDK_KEY_REVOKED = 4, /* Key has been revoked. */ - CDK_KEY_NOSIGNER = 8 -}; - - -/* Trust values and flags for keys and user IDs */ -enum cdk_trust_flag_t { - CDK_TRUST_UNKNOWN = 0, - CDK_TRUST_EXPIRED = 1, - CDK_TRUST_UNDEFINED = 2, - CDK_TRUST_NEVER = 3, - CDK_TRUST_MARGINAL = 4, - CDK_TRUST_FULLY = 5, - CDK_TRUST_ULTIMATE = 6, - /* trust flags */ - CDK_TFLAG_REVOKED = 32, - CDK_TFLAG_SUB_REVOKED = 64, - CDK_TFLAG_DISABLED = 128 -}; - - -/* Signature states and the signature modes. */ -enum cdk_signature_stat_t { - /* Signature status */ - CDK_SIGSTAT_NONE = 0, - CDK_SIGSTAT_GOOD = 1, - CDK_SIGSTAT_BAD = 2, - CDK_SIGSTAT_NOKEY = 3, - CDK_SIGSTAT_VALID = 4, /* True if made with a valid key. */ - /* FIXME: We need indicators for revoked/expires signatures. */ - - /* Signature modes */ - CDK_SIGMODE_NORMAL = 100, - CDK_SIGMODE_DETACHED = 101, - CDK_SIGMODE_CLEAR = 102 -}; - - -/* Key flags. */ -typedef enum { - CDK_FLAG_KEY_REVOKED = 256, - CDK_FLAG_KEY_EXPIRED = 512, - CDK_FLAG_SIG_EXPIRED = 1024 -} cdk_key_flags_t; - - -/* Possible format for the literal data. */ -typedef enum { - CDK_LITFMT_BINARY = 0, - CDK_LITFMT_TEXT = 1, - CDK_LITFMT_UNICODE= 2 -} cdk_lit_format_t; - -/* Valid OpenPGP packet types and their IDs */ -typedef enum { - CDK_PKT_RESERVED = 0, - CDK_PKT_PUBKEY_ENC = 1, - CDK_PKT_SIGNATURE = 2, - CDK_PKT_SYMKEY_ENC = 3, - CDK_PKT_ONEPASS_SIG = 4, - CDK_PKT_SECRET_KEY = 5, - CDK_PKT_PUBLIC_KEY = 6, - CDK_PKT_SECRET_SUBKEY = 7, - CDK_PKT_COMPRESSED = 8, - CDK_PKT_ENCRYPTED = 9, - CDK_PKT_MARKER = 10, - CDK_PKT_LITERAL = 11, - CDK_PKT_RING_TRUST = 12, - CDK_PKT_USER_ID = 13, - CDK_PKT_PUBLIC_SUBKEY = 14, - CDK_PKT_OLD_COMMENT = 16, - CDK_PKT_ATTRIBUTE = 17, - CDK_PKT_ENCRYPTED_MDC = 18, - CDK_PKT_MDC = 19 -} cdk_packet_type_t; - -/* Define the maximal number of multiprecion integers for - a public key. */ -#define MAX_CDK_PK_PARTS 4 - -/* Define the maximal number of multiprecision integers for - a signature/encrypted blob issued by a secret key. */ -#define MAX_CDK_DATA_PARTS 2 - - -/* Helper macro to figure out if the packet is encrypted */ -#define CDK_PKT_IS_ENCRYPTED(pkttype) (\ - ((pkttype)==CDK_PKT_ENCRYPTED_MDC) \ - || ((pkttype)==CDK_PKT_ENCRYPTED)) - - -struct cdk_pkt_signature_s { - unsigned char version; - unsigned char sig_class; - unsigned int timestamp; - unsigned int expiredate; - unsigned int keyid[2]; - unsigned char pubkey_algo; - unsigned char digest_algo; - unsigned char digest_start[2]; - unsigned short hashed_size; - cdk_subpkt_t hashed; - unsigned short unhashed_size; - cdk_subpkt_t unhashed; - gcry_mpi_t mpi[MAX_CDK_DATA_PARTS]; - cdk_desig_revoker_t revkeys; - struct { - unsigned exportable:1; - unsigned revocable:1; - unsigned policy_url:1; - unsigned notation:1; - unsigned expired:1; - unsigned checked:1; - unsigned valid:1; - unsigned missing_key:1; - } flags; - unsigned int key[2]; /* only valid for key signatures */ -}; -typedef struct cdk_pkt_signature_s *cdk_pkt_signature_t; - - -struct cdk_pkt_userid_s { - unsigned int len; - unsigned is_primary:1; - unsigned is_revoked:1; - unsigned mdc_feature:1; - cdk_prefitem_t prefs; - size_t prefs_size; - unsigned char * attrib_img; /* Tag 17 if not null */ - size_t attrib_len; - cdk_pkt_signature_t selfsig; - char name[1]; -}; -typedef struct cdk_pkt_userid_s *cdk_pkt_userid_t; - - -struct cdk_pkt_pubkey_s { - unsigned char version; - unsigned char pubkey_algo; - unsigned char fpr[20]; - unsigned int keyid[2]; - unsigned int main_keyid[2]; - unsigned int timestamp; - unsigned int expiredate; - gcry_mpi_t mpi[MAX_CDK_PK_PARTS]; - unsigned is_revoked:1; - unsigned is_invalid:1; - unsigned has_expired:1; - int pubkey_usage; - cdk_pkt_userid_t uid; - cdk_prefitem_t prefs; - size_t prefs_size; - cdk_desig_revoker_t revkeys; -}; -typedef struct cdk_pkt_pubkey_s *cdk_pkt_pubkey_t; - -/* Alias to define a generic public key context. */ -typedef cdk_pkt_pubkey_t cdk_pubkey_t; - - -struct cdk_pkt_seckey_s { - cdk_pkt_pubkey_t pk; - unsigned int expiredate; - int version; - int pubkey_algo; - unsigned int keyid[2]; - unsigned int main_keyid[2]; - unsigned char s2k_usage; - struct { - unsigned char algo; - unsigned char sha1chk; /* SHA1 is used instead of a 16 bit checksum */ - cdk_s2k_t s2k; - unsigned char iv[16]; - unsigned char ivlen; - } protect; - unsigned short csum; - gcry_mpi_t mpi[MAX_CDK_PK_PARTS]; - unsigned char * encdata; - size_t enclen; - unsigned char is_protected; - unsigned is_primary:1; - unsigned has_expired:1; - unsigned is_revoked:1; -}; -typedef struct cdk_pkt_seckey_s *cdk_pkt_seckey_t; - -/* Alias to define a generic secret key context. */ -typedef cdk_pkt_seckey_t cdk_seckey_t; - - -struct cdk_pkt_onepass_sig_s { - unsigned char version; - unsigned int keyid[2]; - unsigned char sig_class; - unsigned char digest_algo; - unsigned char pubkey_algo; - unsigned char last; -}; -typedef struct cdk_pkt_onepass_sig_s * cdk_pkt_onepass_sig_t; - - -struct cdk_pkt_pubkey_enc_s { - unsigned char version; - unsigned int keyid[2]; - int throw_keyid; - unsigned char pubkey_algo; - gcry_mpi_t mpi[MAX_CDK_DATA_PARTS]; -}; -typedef struct cdk_pkt_pubkey_enc_s * cdk_pkt_pubkey_enc_t; - - -struct cdk_pkt_symkey_enc_s { - unsigned char version; - unsigned char cipher_algo; - cdk_s2k_t s2k; - unsigned char seskeylen; - unsigned char seskey[32]; -}; -typedef struct cdk_pkt_symkey_enc_s *cdk_pkt_symkey_enc_t; - - -struct cdk_pkt_encrypted_s { - unsigned int len; - int extralen; - unsigned char mdc_method; - cdk_stream_t buf; -}; -typedef struct cdk_pkt_encrypted_s *cdk_pkt_encrypted_t; - - -struct cdk_pkt_mdc_s { - unsigned char hash[20]; -}; -typedef struct cdk_pkt_mdc_s *cdk_pkt_mdc_t; - - -struct cdk_pkt_literal_s { - unsigned int len; - cdk_stream_t buf; - int mode; - unsigned int timestamp; - int namelen; - char name[1]; -}; -typedef struct cdk_pkt_literal_s *cdk_pkt_literal_t; - - -struct cdk_pkt_compressed_s { - unsigned int len; - int algorithm; - cdk_stream_t buf; -}; -typedef struct cdk_pkt_compressed_s *cdk_pkt_compressed_t; - - -/* Structure which represents a single OpenPGP packet. */ -struct cdk_packet_s { - size_t pktlen; /* real packet length */ - size_t pktsize; /* length with all headers */ - int old_ctb; /* 1 if RFC1991 mode is used */ - cdk_packet_type_t pkttype; - union { - cdk_pkt_mdc_t mdc; - cdk_pkt_userid_t user_id; - cdk_pkt_pubkey_t public_key; - cdk_pkt_seckey_t secret_key; - cdk_pkt_signature_t signature; - cdk_pkt_pubkey_enc_t pubkey_enc; - cdk_pkt_symkey_enc_t symkey_enc; - cdk_pkt_compressed_t compressed; - cdk_pkt_encrypted_t encrypted; - cdk_pkt_literal_t literal; - cdk_pkt_onepass_sig_t onepass_sig; - } pkt; -}; -typedef struct cdk_packet_s *cdk_packet_t; - -/* memory routines */ -typedef void (*cdk_log_fnc_t) (void *, int, const char *, va_list); - -/* Set the log level. */ -void cdk_set_log_level (int lvl); - -/* Set a custom log handler which is used for logging. */ -void cdk_set_log_handler (cdk_log_fnc_t logfnc, void *opaque); - -/* Return a human readable error description of the given error coe. */ -const char* cdk_strerror (int ec); - -/* Allow the user to set custom hooks for memory allocation. - If this function is not used, the standard allocation functions - will be used. Extra care must be taken for the 'secure' alloc - function. */ -void cdk_set_malloc_hooks (void *(*new_alloc_func) (size_t n), - void *(*new_alloc_secure_func) (size_t n), - void *(*new_realloc_func) (void *p, size_t n), - void *(*new_calloc_func) (size_t m, size_t n), - void (*new_free_func) (void *)); - -/* Return 1 if the malloc hooks were already set via the function above. */ -int cdk_malloc_hook_initialized (void); - -/* Standard memory wrapper. */ -void *cdk_malloc (size_t size); -void *cdk_calloc (size_t n, size_t m); -void *cdk_realloc (void * ptr, size_t size); -void *cdk_salloc (size_t size, int clear); -char *cdk_strdup (const char * ptr); -void cdk_free (void * ptr); - -/* Startup routines. */ - -/* This function has to be called before any other - CDK function is executed. */ -void cdk_lib_startup (void); - -/* This function should be called before the application exists - to allow the lib to cleanup its internal structures. */ -void cdk_lib_shutdown (void); - -/* Session handle routines */ -cdk_error_t cdk_handle_new (cdk_ctx_t *r_ctx); -void cdk_handle_free (cdk_ctx_t c); - -/* Set the key database handle for the given session handle. - The type of the key db handle (public or secret) decides - which session key db handle to use. */ -void cdk_handle_set_keydb (cdk_ctx_t hd, cdk_keydb_hd_t db); - -/* Convenient function to avoid to open a key db first. - The user can directly use the file name, the rest is - done internally. */ -cdk_error_t cdk_handle_set_keyring (cdk_ctx_t hd, int type, - const char *kringname); - -/* Return keydb handle stored in the session handle. */ -cdk_keydb_hd_t cdk_handle_get_keydb (cdk_ctx_t hd, int type); -int cdk_handle_control (cdk_ctx_t hd, int action, int cmd, ...); - -/* Set a passphrase callback for the given session handle. */ -void cdk_handle_set_passphrase_cb (cdk_ctx_t hd, - char *(*cb) (void *opa, const char *prompt), - void *cb_value); - -/* shortcuts for some controls */ - -/* Enable or disable armor output. */ -#define cdk_handle_set_armor(a, val) \ - cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_ARMOR, (val)) - -/* Set the compression algorithm and level. 0 means disable compression. */ -#define cdk_handle_set_compress(a, algo, level) \ - cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_COMPRESS, (algo), (level)) - -/* Activate partial bodies for the output. This is needed if the length - of the data is not known in advance or for the use with sockets - or pipes. */ -#define cdk_handle_set_blockmode(a, val) \ - cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_BLOCKMODE_ON, (val)) - -/* Set the symmetric cipher for encryption. */ -#define cdk_handle_set_cipher(a, val) \ - cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_CIPHER, (val)) - -/* Set the digest for the PK signing operation. */ -#define cdk_handle_set_digest(a, val) \ - cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_DIGEST, (val)) - -/* Set the mode and the digest for the S2K operation. */ -#define cdk_handle_set_s2k(a, val1, val2) \ - cdk_handle_control ((a), CDK_CTLF_SET, CDK_CTL_S2K, (val1), (val2)) - - -/* This context holds all information of the verification process. */ -struct cdk_verify_result_s { - int sig_ver; /* Version of the signature. */ - int sig_status; /* The status (GOOD, BAD) of the signature */ - int sig_flags; /* May contain expired or revoked flags */ - unsigned int keyid[2]; /* The issuer key ID */ - unsigned int created; /* Timestamp when the sig was created. */ - unsigned int expires; - int pubkey_algo; - int digest_algo; - char *user_id; /* NULL or user ID which issued the signature. */ - char *policy_url; /* If set, the policy the sig was created under. */ - size_t sig_len; /* Size of the signature data inbits. */ - unsigned char *sig_data; /* Raw signature data. */ -}; -typedef struct cdk_verify_result_s *cdk_verify_result_t; - -/* Return the verify result. Do not free the data. */ -cdk_verify_result_t cdk_handle_verify_get_result (cdk_ctx_t hd); - -/* Raw packet routines. */ - -/* Allocate a new packet or a new packet with the given packet type. */ -cdk_error_t cdk_pkt_new (cdk_packet_t *r_pkt); -cdk_error_t cdk_pkt_alloc (cdk_packet_t *r_pkt, int pkttype); - -/* Only release the contents of the packet but not @PKT itself. */ -void cdk_pkt_free (cdk_packet_t pkt); - -/* Release the packet contents and the packet structure @PKT itself. */ -void cdk_pkt_release (cdk_packet_t pkt); - -/* Read or write the given output from or to the stream. */ -cdk_error_t cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt); -cdk_error_t cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt); - -/* Sub packet routines */ -cdk_subpkt_t cdk_subpkt_new (size_t size); -void cdk_subpkt_free (cdk_subpkt_t ctx); -cdk_subpkt_t cdk_subpkt_find (cdk_subpkt_t ctx, size_t type); -cdk_subpkt_t cdk_subpkt_find_next (cdk_subpkt_t root, size_t type); -size_t cdk_subpkt_type_count (cdk_subpkt_t ctx, size_t type); -cdk_subpkt_t cdk_subpkt_find_nth (cdk_subpkt_t ctx, size_t type, size_t index); -cdk_error_t cdk_subpkt_add (cdk_subpkt_t root, cdk_subpkt_t node); -const unsigned char * cdk_subpkt_get_data (cdk_subpkt_t ctx, - size_t * r_type, size_t *r_nbytes); -void cdk_subpkt_init (cdk_subpkt_t node, size_t type, - const void *buf, size_t buflen); - -/* Designated Revoker routines */ -const unsigned char* cdk_key_desig_revoker_walk (cdk_desig_revoker_t root, - cdk_desig_revoker_t * ctx, - int *r_class, int *r_algid); - -#define is_RSA(a) ((a) == CDK_PK_RSA \ - || (a) == CDK_PK_RSA_E \ - || (a) == CDK_PK_RSA_S) -#define is_ELG(a) ((a) == CDK_PK_ELG_E) -#define is_DSA(a) ((a) == CDK_PK_DSA) - -/* Encrypt the given session key @SK with the public key @PK - and write the contents into the packet @PKE. */ -cdk_error_t cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke, - gcry_mpi_t sk); - -/* Decrypt the given encrypted session key in @PKE with the secret key - @SK and store it in @R_SK. */ -cdk_error_t cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke, - gcry_mpi_t *r_sk); - -/* Sign the given message digest @MD with the secret key @SK and - store the signature in the packet @SIG. */ -cdk_error_t cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, - const unsigned char *md); - -/* Verify the given signature in @SIG with the public key @PK - and compare it against the message digest @MD. */ -cdk_error_t cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, - const unsigned char *md); - -/* Use cdk_pk_get_npkey() and cdk_pk_get_nskey to find out how much - multiprecision integers a key consists of. */ - -/* Return a multi precision integer of the public key with the index @IDX - in the buffer @BUF. @R_NWRITTEN will contain the length in octets. - Optional @R_NBITS may contain the size in bits. */ -cdk_error_t cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx, - unsigned char *buf, size_t buflen, - size_t *r_nwritten, size_t *r_nbits); - -/* Same as the function above but of the secret key. */ -cdk_error_t cdk_sk_get_mpi (cdk_seckey_t sk, size_t idx, - unsigned char * buf, size_t buflen, - size_t *r_nwritten, size_t *r_nbits); - -/* Helper to get the exact number of multi precision integers - for the given object. */ -int cdk_pk_get_nbits (cdk_pubkey_t pk); -int cdk_pk_get_npkey (int algo); -int cdk_pk_get_nskey (int algo); -int cdk_pk_get_nsig (int algo); -int cdk_pk_get_nenc (int algo); - -/* Fingerprint and key ID routines. */ - -/* Calculate the fingerprint of the given public key. - the FPR parameter must be at least 20 octets to hold the SHA1 hash. */ -cdk_error_t cdk_pk_get_fingerprint (cdk_pubkey_t pk, unsigned char *fpr); - -/* Same as above, but with additional sanity checks of the buffer size. */ -cdk_error_t cdk_pk_to_fingerprint (cdk_pubkey_t pk, - unsigned char *fpr, size_t fprlen, - size_t *r_nout); - -/* Derive the keyid from the fingerprint. This is only possible for - modern, version 4 keys. */ -unsigned int cdk_pk_fingerprint_get_keyid (const unsigned char *fpr, - size_t fprlen, - unsigned int *keyid); - -/* Various functions to get the keyid from the specific packet type. */ -unsigned int cdk_pk_get_keyid (cdk_pubkey_t pk, unsigned int *keyid); -unsigned int cdk_sk_get_keyid (cdk_seckey_t sk, unsigned int *keyid); -unsigned int cdk_sig_get_keyid (cdk_pkt_signature_t sig, - unsigned int *keyid); - -/* Key release functions. */ -void cdk_pk_release (cdk_pubkey_t pk); -void cdk_sk_release (cdk_seckey_t sk); - -/* Secret key related functions. */ -cdk_error_t cdk_sk_unprotect (cdk_seckey_t sk, const char *pw); -cdk_error_t cdk_sk_protect (cdk_seckey_t sk, const char *pw); - -/* Create a public key with the data from the secret key @SK. */ -cdk_error_t cdk_pk_from_secret_key (cdk_seckey_t sk, - cdk_pubkey_t *ret_pk); - -/* Sexp conversion of keys. */ -cdk_error_t cdk_pubkey_to_sexp (cdk_pubkey_t pk, - char **sexp, size_t *len); -cdk_error_t cdk_seckey_to_sexp (cdk_seckey_t sk, - char **sexp, size_t *len); - - -/* Data Encryption Key (DEK) routines */ -cdk_error_t cdk_dek_new (cdk_dek_t *r_dek); -void cdk_dek_free (cdk_dek_t dek); - -/* Set the symmetric cipher algorithm which shall be used for this - DEK object. */ -cdk_error_t cdk_dek_set_cipher (cdk_dek_t dek, int cipher_algo); - -/* Return the symmetric cipher which is used for this DEK object. */ -cdk_error_t cdk_dek_get_cipher (cdk_dek_t dek, int *r_cipher_algo); - - -/* Set the session key for the given DEK object. - If @KEY and @KEYLEN are both NULL/0, a random key will be generated - and stored in the DEK object. */ -cdk_error_t cdk_dek_set_key (cdk_dek_t dek, const unsigned char *key, - size_t keylen); - -/* Enable the MDC feature for the current DEK object. */ -void cdk_dek_set_mdc_flag (cdk_dek_t dek, int val); - -/* Return if the MDC feature is enabled for the current DEK object.*/ -int cdk_dek_get_mdc_flag (cdk_dek_t dek); - -/* Transform the given passphrase into a DEK. - If @rndsalt is set, a random salt will be generated. */ -cdk_error_t cdk_dek_from_passphrase (cdk_dek_t *ret_dek, int cipher_algo, - cdk_s2k_t s2k, int rndsalt, - const char *passphrase); - -/* String to Key routines. */ -cdk_error_t cdk_s2k_new (cdk_s2k_t *ret_s2k, int mode, int digest_algo, - const unsigned char *salt); -void cdk_s2k_free (cdk_s2k_t s2k); - -cdk_error_t cdk_file_armor (cdk_ctx_t hd, const char *file, - const char *output); -cdk_error_t cdk_file_dearmor (const char * file, const char *output); -int cdk_armor_filter_use (cdk_stream_t inp); - -/* Protect the inbuf with ASCII armor of the specified type. - If @outbuf and @outlen are NULL, the function returns the calculated - size of the base64 encoded data in @nwritten. */ -cdk_error_t cdk_armor_encode_buffer (const unsigned char *inbuf, size_t inlen, - char *outbuf, size_t outlen, - size_t *nwritten, int type); - - -/* This context contain user callbacks for different stream operations. - Some of these callbacks might be NULL to indicate that the callback - is not used. */ -struct cdk_stream_cbs_s -{ - cdk_error_t (*open)(void *); - cdk_error_t (*release)(void *); - int (*read)(void *, void *buf, size_t); - int (*write)(void *, const void *buf, size_t); - int (*seek)(void *, off_t); -}; -typedef struct cdk_stream_cbs_s *cdk_stream_cbs_t; - - -int cdk_stream_is_compressed (cdk_stream_t s); - -/* Return a stream object which is associated to a socket. */ -cdk_error_t cdk_stream_sockopen (const char *host, unsigned short port, - cdk_stream_t *ret_out); - -/* Return a stream object which is associated to an existing file. */ -cdk_error_t cdk_stream_open (const char * file, cdk_stream_t * ret_s); - -/* Return a stream object which is associated to a file which will - be created when the stream is closed. */ -cdk_error_t cdk_stream_new (const char * file, cdk_stream_t * ret_s); - -/* Return a stream object with custom callback functions for the - various core operations. */ -cdk_error_t cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa, - cdk_stream_t *ret_s); -cdk_error_t cdk_stream_create (const char * file, cdk_stream_t * ret_s); -cdk_error_t cdk_stream_tmp_new (cdk_stream_t *r_out); -cdk_error_t cdk_stream_tmp_from_mem (const void * buf, size_t buflen, - cdk_stream_t *r_out); -void cdk_stream_tmp_set_mode (cdk_stream_t s, int val); -cdk_error_t cdk_stream_flush (cdk_stream_t s); -cdk_error_t cdk_stream_enable_cache (cdk_stream_t s, int val); -cdk_error_t cdk_stream_filter_disable (cdk_stream_t s, int type); -cdk_error_t cdk_stream_close (cdk_stream_t s); -off_t cdk_stream_get_length (cdk_stream_t s); -int cdk_stream_read (cdk_stream_t s, void * buf, size_t count); -int cdk_stream_write (cdk_stream_t s, const void * buf, size_t count); -int cdk_stream_putc (cdk_stream_t s, int c); -int cdk_stream_getc (cdk_stream_t s); -int cdk_stream_eof (cdk_stream_t s); -off_t cdk_stream_tell (cdk_stream_t s); -cdk_error_t cdk_stream_seek (cdk_stream_t s, off_t offset); -cdk_error_t cdk_stream_set_armor_flag (cdk_stream_t s, int type); - -/* Push the literal filter for the given stream. */ -cdk_error_t cdk_stream_set_literal_flag (cdk_stream_t s, - cdk_lit_format_t mode, - const char * fname); - -cdk_error_t cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, - int use_mdc); -cdk_error_t cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level); -cdk_error_t cdk_stream_set_hash_flag (cdk_stream_t s, int algo); -cdk_error_t cdk_stream_set_text_flag (cdk_stream_t s, const char * lf); -cdk_error_t cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out); -cdk_error_t cdk_stream_mmap (cdk_stream_t s, unsigned char **ret_buf, - size_t *ret_buflen); -cdk_error_t cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len, - unsigned char **ret_buf, size_t *ret_buflen); - -/* Read from the stream but restore the file pointer after reading - the requested amount of bytes. */ -int cdk_stream_peek (cdk_stream_t inp, unsigned char *buf, size_t buflen); - -/* A wrapper around the various new_from_XXX functions. Because - the function does not support all combinations, the dedicated - functions should be preferred. */ -cdk_error_t cdk_keydb_new (cdk_keydb_hd_t *r_hd, int type, void *data, - size_t count); - -/* Create a new key db handle from a memory buffer. */ -cdk_error_t cdk_keydb_new_from_mem (cdk_keydb_hd_t *r_hd, int secret, - const void *data, size_t datlen); - -/* Create a new key db which uses an existing file. */ -cdk_error_t cdk_keydb_new_from_file (cdk_keydb_hd_t *r_hd, int secret, - const char *fname); - -/* Uses a stream as the key db input. For searching it is important - that the seek function is supported on the stream. Furthermore, - the stream is not closed in cdk_keydb_free(). The caller must do it. */ -cdk_error_t cdk_keydb_new_from_stream (cdk_keydb_hd_t *r_hd, int secret, - cdk_stream_t in); - -/* Check that a secret key with the given key ID is available. */ -cdk_error_t cdk_keydb_check_sk (cdk_keydb_hd_t hd, unsigned int *keyid); - -/* Prepare the key db search. */ -cdk_error_t cdk_keydb_search_start (cdk_keydb_hd_t hd, int type, void *desc); - -/* Return a key which matches a valid description given in - cdk_keydb_search_start(). */ -cdk_error_t cdk_keydb_search (cdk_keydb_hd_t hd, cdk_kbnode_t *ret_key); - -/* Release the key db handle and all its resources. */ -void cdk_keydb_free (cdk_keydb_hd_t hd); - -/* The following functions will try to find a key in the given key - db handle either by keyid, by fingerprint or by some pattern. */ -cdk_error_t cdk_keydb_get_bykeyid (cdk_keydb_hd_t hd, unsigned int *keyid, - cdk_kbnode_t *ret_pk); -cdk_error_t cdk_keydb_get_byfpr (cdk_keydb_hd_t hd, const unsigned char *fpr, - cdk_kbnode_t *ret_pk); -cdk_error_t cdk_keydb_get_bypattern (cdk_keydb_hd_t hd, const char *patt, - cdk_kbnode_t *ret_pk); - -/* These function, in contrast to most other key db functions, only - return the public or secret key packet without the additional - signatures and user IDs. */ -cdk_error_t cdk_keydb_get_pk (cdk_keydb_hd_t khd, unsigned int * keyid, - cdk_pubkey_t *ret_pk); -cdk_error_t cdk_keydb_get_sk (cdk_keydb_hd_t khd, unsigned int * keyid, - cdk_seckey_t *ret_sk); - -/* Try to read the next key block from the given input stream. - The key will be returned in @RET_KEY on success. */ -cdk_error_t cdk_keydb_get_keyblock (cdk_stream_t inp, cdk_kbnode_t * ret_key); - -/* Rebuild the key db index if possible. */ -cdk_error_t cdk_keydb_idx_rebuild (cdk_keydb_hd_t hd); - -/* Export one or more keys from the given key db handle into - the stream @OUT. The export is done by substring search and - uses the string list @REMUSR for the pattern. */ -cdk_error_t cdk_keydb_export (cdk_keydb_hd_t hd, cdk_stream_t out, - cdk_strlist_t remusr); - -/* Import the given key node @knode into the key db. */ -cdk_error_t cdk_keydb_import (cdk_keydb_hd_t hd, cdk_kbnode_t knode); - - -/* List or enumerate keys from a given key db handle. */ - -/* Start the key list process. Either use @PATT for a pattern search - or @FPATT for a list of pattern. */ -cdk_error_t cdk_listkey_start (cdk_listkey_t *r_ctx, cdk_keydb_hd_t db, - const char *patt, cdk_strlist_t fpatt); -void cdk_listkey_close (cdk_listkey_t ctx); - -/* Return the next key which matches the pattern. */ -cdk_error_t cdk_listkey_next (cdk_listkey_t ctx, cdk_kbnode_t *ret_key); - -cdk_kbnode_t cdk_kbnode_new (cdk_packet_t pkt); -cdk_error_t cdk_kbnode_read_from_mem (cdk_kbnode_t * ret_node, - const unsigned char * buf, - size_t buflen); -cdk_error_t cdk_kbnode_write_to_mem (cdk_kbnode_t node, - unsigned char * buf, size_t * r_nbytes); -cdk_error_t cdk_kbnode_write_to_mem_alloc (cdk_kbnode_t node, - unsigned char **r_buf, - size_t *r_buflen); - -void cdk_kbnode_release (cdk_kbnode_t node); -cdk_kbnode_t cdk_kbnode_walk (cdk_kbnode_t root, cdk_kbnode_t * ctx, int all); -cdk_packet_t cdk_kbnode_find_packet (cdk_kbnode_t node, int pkttype); -cdk_packet_t cdk_kbnode_get_packet (cdk_kbnode_t node); -cdk_kbnode_t cdk_kbnode_find (cdk_kbnode_t node, int pkttype); -cdk_kbnode_t cdk_kbnode_find_prev (cdk_kbnode_t root, cdk_kbnode_t node, - int pkttype); -cdk_kbnode_t cdk_kbnode_find_next (cdk_kbnode_t node, int pkttype); -cdk_error_t cdk_kbnode_hash (cdk_kbnode_t node, gcry_md_hd_t md, int is_v4, - int pkttype, int flags); - -/* Check each signature in the key node and return a summary of the - key status in @r_status. Values of cdk_key_flag_t are used. */ -cdk_error_t cdk_pk_check_sigs (cdk_kbnode_t knode, cdk_keydb_hd_t hd, - int *r_status); - -/* Check the self signature of the key to make sure it is valid. */ -cdk_error_t cdk_pk_check_self_sig (cdk_kbnode_t knode, int *r_status); - -/* Return a matching algorithm from the given public key list. - @PREFTYPE can be either sym-cipher/compress/digest. */ -int cdk_pklist_select_algo (cdk_keylist_t pkl, int preftype); - -/* Return 0 or 1 if the given key list is able to understand the - MDC feature. */ -int cdk_pklist_use_mdc (cdk_keylist_t pkl); -cdk_error_t cdk_pklist_build (cdk_keylist_t *ret_pkl, cdk_keydb_hd_t hd, - cdk_strlist_t remusr, int use); -void cdk_pklist_release (cdk_keylist_t pkl); - -/* Encrypt the given DEK key with the list of public keys given - in @PKL. The result will be written to the stream output @OUT. */ -cdk_error_t cdk_pklist_encrypt (cdk_keylist_t pkl, cdk_dek_t dek, - cdk_stream_t out); - -/* Secret key lists */ -cdk_error_t cdk_sklist_build (cdk_keylist_t * ret_skl, - cdk_keydb_hd_t db, cdk_ctx_t hd, - cdk_strlist_t locusr, - int unlock, unsigned int use); -void cdk_sklist_release (cdk_keylist_t skl); -cdk_error_t cdk_sklist_write (cdk_keylist_t skl, cdk_stream_t outp, - gcry_md_hd_t mdctx, - int sigclass, int sigver); -cdk_error_t cdk_sklist_write_onepass (cdk_keylist_t skl, cdk_stream_t outp, - int sigclass, int mdalgo); - -/* Encrypt the given stream @INP with the recipients given in @REMUSR. - If @REMUSR is NULL, symmetric encryption will be used. The output - will be written to @OUT. */ -cdk_error_t cdk_stream_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr, - cdk_stream_t inp, cdk_stream_t out); - -/* Decrypt the @INP stream into @OUT. */ -cdk_error_t cdk_stream_decrypt (cdk_ctx_t hd, cdk_stream_t inp, - cdk_stream_t out); - -/* Same as the function above but it works on files. */ -cdk_error_t cdk_file_encrypt (cdk_ctx_t hd, cdk_strlist_t remusr, - const char *file, const char *output); -cdk_error_t cdk_file_decrypt (cdk_ctx_t hd, const char * file, - const char *output); - -/* Generic function to transform data. The mode can be either sign, - verify, encrypt, decrypt, import or export. The meanings of the - parameters are similar to the functions above. - @OUTBUF will contain the output and @OUTSIZE the length of it. */ -cdk_error_t cdk_data_transform (cdk_ctx_t hd, enum cdk_crypto_mode_t mode, - cdk_strlist_t locusr, cdk_strlist_t remusr, - const void * inbuf, size_t insize, - unsigned char ** outbuf, size_t * outsize, - int modval); - -/* Sign the stream @INP. Optionally, the output will be encrypted - if @REMUSR is not NULL and the @ENCRYPTFLAG is set. - The output will be written to @OUT. - @LOCUSR contains one ore more pattern for the secret key(s) to use. */ -cdk_error_t cdk_stream_sign (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out, - cdk_strlist_t locusr, cdk_strlist_t remusr, - int encryptflag, int sigmode); - -/* Same as the function above but it works on files. */ -cdk_error_t cdk_file_sign (cdk_ctx_t hd, cdk_strlist_t locusr, - cdk_strlist_t remusr, - const char *file, const char *output, - int sigmode, int encryptflag); - -cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp, - cdk_stream_t data, - cdk_stream_t out); - -/* Verify the given file @FILE. For a detached signature, @DATA_FILE - contains the actual file data and @FILE is only the signature. - If the @OUTPUT is not NULL, the plaintext will be written to this file. */ -cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file, - const char *data_file, const char *output); - -int cdk_trustdb_get_validity (cdk_stream_t inp, cdk_pkt_userid_t id, - int *r_val); -int cdk_trustdb_get_ownertrust (cdk_stream_t inp, cdk_pubkey_t pk, - int *r_val, int *r_flags); - -void cdk_strlist_free (cdk_strlist_t sl); -cdk_strlist_t cdk_strlist_add (cdk_strlist_t * list, const char * string); -cdk_strlist_t cdk_strlist_next (cdk_strlist_t root, const char **r_str); -const char * cdk_check_version (const char * req_version); -/* UTF8 */ -char* cdk_utf8_encode (const char * string); -char* cdk_utf8_decode (const char * string, size_t length, int delim); - -/* Try to receive the key, which has the key ID @KEYID, from the - keyserver host @HOST and the port @PORT. */ -cdk_error_t cdk_keyserver_recv_key (const char *host, int port, - const unsigned char *keyid, int kid_type, - cdk_kbnode_t *r_key); - -cdk_error_t cdk_keygen_new (cdk_keygen_ctx_t * r_hd); -void cdk_keygen_free (cdk_keygen_ctx_t hd); - -/* Set the preferences of the given type for the new key. - @ARRAY is an array which list of algorithm IDs. */ -cdk_error_t cdk_keygen_set_prefs (cdk_keygen_ctx_t hd, - enum cdk_pref_type_t type, - const unsigned char * array, size_t n); -cdk_error_t cdk_keygen_set_algo_info (cdk_keygen_ctx_t hd, int type, - int usage, enum cdk_pubkey_algo_t algo, - unsigned int bits); -int cdk_keygen_set_keyserver_flags (cdk_keygen_ctx_t hd, int no_modify, - const char *pref_url); -int cdk_keygen_set_expire_date (cdk_keygen_ctx_t hd, int type, - long timestamp); - -/* Set the user ID specifc parts for the new key. - It is suggested to use a name in the form of - 'First Name' 'Last Name' <email-address@host.domain> */ -void cdk_keygen_set_name (cdk_keygen_ctx_t hd, const char * name); -void cdk_keygen_set_passphrase (cdk_keygen_ctx_t hd, const char * pass); -cdk_error_t cdk_keygen_start (cdk_keygen_ctx_t hd); -cdk_error_t cdk_keygen_save (cdk_keygen_ctx_t hd, - const char * pubf, - const char * secf); - -#ifdef __cplusplus -} -#endif - -#endif /* OPENCDK_H */ - diff --git a/src/daemon/https/opencdk/packet.h b/src/daemon/https/opencdk/packet.h @@ -1,40 +0,0 @@ -/* packet.h - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifndef CDK_PACKET_H -#define CDK_PACKET_H - -struct cdk_kbnode_s -{ - struct cdk_kbnode_s *next; - cdk_packet_t pkt; - unsigned int is_deleted:1; - unsigned int is_cloned:1; -}; - -/*-- new-packet.c --*/ -void _cdk_free_mpibuf (size_t n, gcry_mpi_t *array); -void _cdk_free_userid (cdk_pkt_userid_t uid); -void _cdk_free_signature( cdk_pkt_signature_t sig ); -cdk_prefitem_t _cdk_copy_prefs( const cdk_prefitem_t prefs ); -int _cdk_copy_userid( cdk_pkt_userid_t *dst, cdk_pkt_userid_t src ); -int _cdk_copy_pubkey( cdk_pkt_pubkey_t* dst, cdk_pkt_pubkey_t src ); -int _cdk_copy_seckey( cdk_pkt_seckey_t* dst, cdk_pkt_seckey_t src ); -int _cdk_copy_pk_to_sk( cdk_pkt_pubkey_t pk, cdk_pkt_seckey_t sk ); -int _cdk_copy_signature( cdk_pkt_signature_t* dst, cdk_pkt_signature_t src ); -int _cdk_pubkey_compare( cdk_pkt_pubkey_t a, cdk_pkt_pubkey_t b ); - -#endif /* CDK_PACKET_H */ - diff --git a/src/daemon/https/opencdk/pubkey.c b/src/daemon/https/opencdk/pubkey.c @@ -1,1380 +0,0 @@ -/* pubkey.c - Public key API - * Copyright (C) 2007 Free Software Foundation, Inc. - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <stdio.h> -#include <gcrypt.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" - - -/* Convert the given secret key into a gcrypt SEXP object. */ -static int -seckey_to_sexp (gcry_sexp_t * r_skey, cdk_seckey_t sk) -{ - gcry_sexp_t sexp = NULL; - gcry_mpi_t *mpk = NULL, *msk = NULL; - gcry_error_t err; - cdk_pubkey_t pk; - const char *fmt; - - if (!r_skey || !sk || !sk->pk) - return CDK_Inv_Value; - - pk = sk->pk; - mpk = pk->mpi; - msk = sk->mpi; - - *r_skey = NULL; - if (is_RSA (sk->pubkey_algo)) - { - fmt = "(private-key(openpgp-rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))"; - err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], - msk[0], msk[1], msk[2], msk[3]); - } - else if (is_ELG (sk->pubkey_algo)) - { - fmt = "(private-key(openpgp-elg(p%m)(g%m)(y%m)(x%m)))"; - err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], - mpk[2], msk[0]); - } - else if (is_DSA (sk->pubkey_algo)) - { - fmt = "(private-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)(x%m)))"; - err = gcry_sexp_build (&sexp, NULL, fmt, mpk[0], mpk[1], mpk[2], - mpk[3], msk[0]); - } - else - return CDK_Inv_Algo; - if (err) - return map_gcry_error (err); - *r_skey = sexp; - return 0; -} - - -/* Convert the given public key to a gcrypt SEXP object. */ -static cdk_error_t -pubkey_to_sexp (gcry_sexp_t * r_key_sexp, cdk_pubkey_t pk) -{ - gcry_mpi_t *m; - gcry_error_t err; - const char *fmt = NULL; - cdk_error_t rc = 0; - - if (!r_key_sexp || !pk) - return CDK_Inv_Value; - - m = pk->mpi; - if (is_RSA (pk->pubkey_algo)) - { - fmt = "(public-key(openpgp-rsa(n%m)(e%m)))"; - err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1]); - if (err) - rc = map_gcry_error (err); - } - else if (is_ELG (pk->pubkey_algo)) - { - fmt = "(public-key(openpgp-elg(p%m)(g%m)(y%m)))"; - err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2]); - if (err) - rc = map_gcry_error (err); - } - else if (is_DSA (pk->pubkey_algo)) - { - fmt = "(public-key(openpgp-dsa(p%m)(q%m)(g%m)(y%m)))"; - err = gcry_sexp_build (r_key_sexp, NULL, fmt, m[0], m[1], m[2], m[3]); - if (err) - rc = map_gcry_error (err); - } - else - rc = CDK_Inv_Algo; - return rc; -} - - -static cdk_error_t -enckey_to_sexp (gcry_sexp_t * r_sexp, gcry_mpi_t esk) -{ - gcry_error_t err; - - if (!r_sexp || !esk) - return CDK_Inv_Value; - err = gcry_sexp_build (r_sexp, NULL, "%m", esk); - if (err) - return map_gcry_error (err); - return 0; -} - - -static cdk_error_t -digest_to_sexp (gcry_sexp_t * r_md_sexp, int digest_algo, - const byte * md, size_t mdlen) -{ - gcry_mpi_t m; - gcry_error_t err; - - if (!r_md_sexp || !md) - return CDK_Inv_Value; - - if (!mdlen) - mdlen = gcry_md_get_algo_dlen (digest_algo); - if (!mdlen) - return CDK_Inv_Algo; - - err = gcry_mpi_scan (&m, GCRYMPI_FMT_USG, md, mdlen, &mdlen); - if (err) - return map_gcry_error (err); - - err = gcry_sexp_build (r_md_sexp, NULL, "%m", m); - gcry_mpi_release (m); - if (err) - return map_gcry_error (err); - return 0; -} - - -static cdk_error_t -sexp_to_mpi (gcry_sexp_t sexp, const char *val, gcry_mpi_t * ret_buf) -{ - gcry_sexp_t list; - - if (!sexp || !val || !ret_buf) - return CDK_Inv_Value; - - list = gcry_sexp_find_token (sexp, val, 0); - if (!list) - return CDK_Inv_Value; - - *ret_buf = gcry_sexp_nth_mpi (list, 1, 0); - gcry_sexp_release (list); - if (!*ret_buf) - return CDK_Inv_Value; - return 0; -} - - -static cdk_error_t -sexp_to_sig (cdk_pkt_signature_t sig, gcry_sexp_t sexp) -{ - if (!sig || !sexp) - return CDK_Inv_Value; - - /* ElGamal signatures are not supported any longer. */ - if (is_ELG (sig->pubkey_algo)) - { - _cdk_log_debug ("sexp_to_sig: unsupported signature type (ElGamal)\n"); - return CDK_Not_Implemented; - } - - if (is_RSA (sig->pubkey_algo)) - return sexp_to_mpi (sexp, "s", &sig->mpi[0]); - else if (is_DSA (sig->pubkey_algo)) - { - cdk_error_t rc; - - rc = sexp_to_mpi (sexp, "r", &sig->mpi[0]); - if (!rc) - rc = sexp_to_mpi (sexp, "s", &sig->mpi[1]); - return rc; - } - return CDK_Inv_Algo; -} - - -static cdk_error_t -sig_to_sexp (gcry_sexp_t * r_sig_sexp, cdk_pkt_signature_t sig) -{ - gcry_error_t err; - cdk_error_t rc; - const char *fmt; - - if (!r_sig_sexp || !sig) - return CDK_Inv_Value; - if (is_ELG (sig->pubkey_algo)) - return CDK_Not_Implemented; - - rc = 0; - if (is_RSA (sig->pubkey_algo)) - { - fmt = "(sig-val(openpgp-rsa(s%m)))"; - err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0]); - if (err) - rc = map_gcry_error (err); - } - else if (is_DSA (sig->pubkey_algo)) - { - fmt = "(sig-val(openpgp-dsa(r%m)(s%m)))"; - err = gcry_sexp_build (r_sig_sexp, NULL, fmt, sig->mpi[0], sig->mpi[1]); - if (err) - rc = map_gcry_error (err); - } - else - rc = CDK_Inv_Algo; - return rc; -} - - -static cdk_error_t -sexp_to_pubenc (cdk_pkt_pubkey_enc_t enc, gcry_sexp_t sexp) -{ - if (!sexp || !enc) - return CDK_Inv_Value; - - if (is_RSA (enc->pubkey_algo)) - return sexp_to_mpi (sexp, "a", &enc->mpi[0]); - else if (is_ELG (enc->pubkey_algo)) - { - cdk_error_t rc = sexp_to_mpi (sexp, "a", &enc->mpi[0]); - if (!rc) - rc = sexp_to_mpi (sexp, "b", &enc->mpi[1]); - return rc; - } - return CDK_Inv_Algo; -} - - -static cdk_error_t -pubenc_to_sexp (gcry_sexp_t * r_sexp, cdk_pkt_pubkey_enc_t enc) -{ - gcry_sexp_t sexp = NULL; - gcry_error_t err; - const char *fmt; - - if (!r_sexp || !enc) - return CDK_Inv_Value; - - *r_sexp = NULL; - if (is_RSA (enc->pubkey_algo)) - { - fmt = "(enc-val(openpgp-rsa((a%m))))"; - err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0]); - } - else if (is_ELG (enc->pubkey_algo)) - { - fmt = "(enc-val(openpgp-elg((a%m)(b%m))))"; - err = gcry_sexp_build (&sexp, NULL, fmt, enc->mpi[0], enc->mpi[1]); - } - else - return CDK_Inv_Algo; - if (err) - return map_gcry_error (err); - *r_sexp = sexp; - return 0; -} - - -static int -is_unprotected (cdk_seckey_t sk) -{ - if (sk->is_protected && !sk->mpi[0]) - return 0; - return 1; -} - - -/** - * cdk_pk_encrypt: - * @pk: the public key - * @pke: the public key encrypted packet - * @esk: the actual session key - * - * Encrypt the session key in @esk and write its encrypted content - * into the @pke struct. - **/ -cdk_error_t -cdk_pk_encrypt (cdk_pubkey_t pk, cdk_pkt_pubkey_enc_t pke, gcry_mpi_t esk) -{ - gcry_sexp_t s_data = NULL, s_pkey = NULL, s_ciph = NULL; - gcry_error_t err; - cdk_error_t rc; - - if (!pk || !esk || !pke) - return CDK_Inv_Value; - - if (!KEY_CAN_ENCRYPT (pk->pubkey_algo)) - return CDK_Inv_Algo; - - rc = enckey_to_sexp (&s_data, esk); - if (!rc) - rc = pubkey_to_sexp (&s_pkey, pk); - if (!rc) - { - err = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); - if (err) - return map_gcry_error (err); - } - if (!rc) - rc = sexp_to_pubenc (pke, s_ciph); - - gcry_sexp_release (s_data); - gcry_sexp_release (s_pkey); - gcry_sexp_release (s_ciph); - return rc; -} - - -/** - * cdk_pk_decrypt: - * @sk: the secret key - * @pke: public key encrypted packet - * @r_sk: the object to store the plain session key - * - * Decrypt the encrypted session key from @pke into @r_sk. - **/ -cdk_error_t -cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke, gcry_mpi_t * r_sk) -{ - gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL; - cdk_error_t rc; - gcry_error_t err; - - if (!sk || !r_sk || !pke) - return CDK_Inv_Value; - - if (!is_unprotected (sk)) - return CDK_Inv_Mode; - - *r_sk = NULL; - rc = seckey_to_sexp (&s_skey, sk); - if (rc) - return rc; - - rc = pubenc_to_sexp (&s_data, pke); - if (rc) - { - gcry_sexp_release (s_skey); - return rc; - } - - err = gcry_pk_decrypt (&s_plain, s_data, s_skey); - if (err) - rc = map_gcry_error (err); - else - *r_sk = gcry_sexp_nth_mpi (s_plain, 0, 0); - - gcry_sexp_release (s_data); - gcry_sexp_release (s_skey); - gcry_sexp_release (s_plain); - return rc; -} - - -/** - * cdk_pk_sign: - * @sk: secret key - * @sig: signature - * @md: the message digest - * - * Sign the message digest from @md and write the result into @sig. - **/ -cdk_error_t -cdk_pk_sign (cdk_seckey_t sk, cdk_pkt_signature_t sig, const byte * md) -{ - gcry_sexp_t s_skey = NULL, s_sig = NULL, s_hash = NULL; - byte *encmd = NULL; - size_t enclen = 0; - int nbits; - cdk_error_t rc; - gcry_error_t err; - - if (!sk || !sk->pk || !sig || !md) - return CDK_Inv_Value; - - if (!is_unprotected (sk)) - return CDK_Inv_Mode; - - if (!KEY_CAN_SIGN (sig->pubkey_algo)) - return CDK_Inv_Algo; - - nbits = cdk_pk_get_nbits (sk->pk); - rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, sk->pk->pubkey_algo, md, - sig->digest_algo, nbits); - if (rc) - return rc; - - rc = seckey_to_sexp (&s_skey, sk); - if (!rc) - rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); - if (rc) - { - cdk_free (encmd); - gcry_sexp_release (s_skey); - return rc; - } - - err = gcry_pk_sign (&s_sig, s_hash, s_skey); - if (err) - rc = map_gcry_error (err); - else - { - rc = sexp_to_sig (sig, s_sig); - if (!rc) - { - sig->digest_start[0] = md[0]; - sig->digest_start[1] = md[1]; - } - } - - gcry_sexp_release (s_skey); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_sig); - cdk_free (encmd); - return rc; -} - - -/** - * cdk_pk_verify: - * @pk: the public key - * @sig: signature - * @md: the message digest - * - * Verify the signature in @sig and compare it with the message digest in @md. - **/ -cdk_error_t -cdk_pk_verify (cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md) -{ - gcry_sexp_t s_pkey = NULL, s_sig = NULL, s_hash = NULL; - byte *encmd = NULL; - size_t enclen; - cdk_error_t rc; - - if (!pk || !sig || !md) - return CDK_Inv_Value; - - rc = pubkey_to_sexp (&s_pkey, pk); - if (rc) - return rc; - - rc = sig_to_sexp (&s_sig, sig); - if (rc) - goto leave; - - rc = _cdk_digest_encode_pkcs1 (&encmd, &enclen, pk->pubkey_algo, md, - sig->digest_algo, cdk_pk_get_nbits (pk)); - if (rc) - goto leave; - - rc = digest_to_sexp (&s_hash, sig->digest_algo, encmd, enclen); - if (rc) - goto leave; - - if (gcry_pk_verify (s_sig, s_hash, s_pkey)) - rc = CDK_Bad_Sig; - -leave: - gcry_sexp_release (s_sig); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_pkey); - cdk_free (encmd); - return rc; -} - - -/** - * cdk_pk_get_nbits: - * @pk: the public key - * - * Return the length of the public key in bits. - * The meaning of length is actually the size of the 'prime' - * object in the key. For RSA keys the modulus, for ElG/DSA - * the size of the public prime. - **/ -int -cdk_pk_get_nbits (cdk_pubkey_t pk) -{ - if (!pk || !pk->mpi[0]) - return 0; - return gcry_mpi_get_nbits (pk->mpi[0]); -} - - -/** - * cdk_pk_get_npkey: - * @algo: The public key algorithm. - * - * Return the number of multiprecison integer forming an public - * key with the given algorithm. - */ -int -cdk_pk_get_npkey (int algo) -{ - size_t bytes; - - if (algo == 16) - algo = 20; /* FIXME: libgcrypt returns 0 for 16 */ - if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &bytes)) - return 0; - return bytes; -} - - -/** - * cdk_pk_get_nskey: - * @algo: the public key algorithm - * - * Return the number of multiprecision integers forming an - * secret key with the given algorithm. - **/ -int -cdk_pk_get_nskey (int algo) -{ - size_t bytes; - - if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &bytes)) - return 0; - bytes -= cdk_pk_get_npkey (algo); - return bytes; -} - - -/** - * cdk_pk_get_nbits: - * @algo: the public key algorithm - * - * Return the number of MPIs a signature consists of. - **/ -int -cdk_pk_get_nsig (int algo) -{ - size_t bytes; - - if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &bytes)) - return 0; - return bytes; -} - - -/** - * cdk_pk_get_nenc: - * @algo: the public key algorithm - * - * Return the number of MPI's the encrypted data consists of. - **/ -int -cdk_pk_get_nenc (int algo) -{ - size_t bytes; - - if (gcry_pk_algo_info (algo, GCRYCTL_GET_ALGO_NENCR, NULL, &bytes)) - return 0; - return bytes; -} - - -int -_cdk_pk_algo_usage (int algo) -{ - int usage; - - /* The ElGamal sign+encrypt algorithm is not supported any longer. */ - switch (algo) - { - case CDK_PK_RSA: - usage = CDK_KEY_USG_SIGN | CDK_KEY_USG_ENCR; - break; - case CDK_PK_RSA_E: - usage = CDK_KEY_USG_ENCR; - break; - case CDK_PK_RSA_S: - usage = CDK_KEY_USG_SIGN; - break; - case CDK_PK_ELG_E: - usage = CDK_KEY_USG_ENCR; - break; - case CDK_PK_DSA: - usage = CDK_KEY_USG_SIGN; - break; - default: - usage = 0; - } - return usage; -} - - -static cdk_error_t -mpi_to_buffer (gcry_mpi_t a, byte * buf, size_t buflen, - size_t * r_nwritten, size_t * r_nbits) -{ - size_t nbits; - - if (!a || !buf || !r_nwritten) - return CDK_Inv_Value; - - nbits = gcry_mpi_get_nbits (a); - if (r_nbits) - *r_nbits = nbits; - if ((nbits + 7) / 8 + 2 > buflen) - return CDK_Too_Short; - *r_nwritten = (nbits + 7) / 8 + 2; - if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, buflen, r_nwritten, a)) - return CDK_Wrong_Format; - return 0; -} - - -/** - * cdk_pk_get_mpi: - * @pk: public key - * @idx: index of the MPI to retrieve - * @buf: buffer to hold the raw data - * @r_nwritten: output how large the raw data is - * @r_nbits: size of the MPI in bits. - * - * Return the MPI with the given index of the public key. - **/ -cdk_error_t -cdk_pk_get_mpi (cdk_pubkey_t pk, size_t idx, - byte * buf, size_t buflen, size_t * r_nwritten, - size_t * r_nbits) -{ - if (!pk || !r_nwritten) - return CDK_Inv_Value; - if (idx > cdk_pk_get_npkey (pk->pubkey_algo)) - return CDK_Inv_Value; - return mpi_to_buffer (pk->mpi[idx], buf, buflen, r_nwritten, r_nbits); -} - - -/** - * cdk_sk_get_mpi: - * @sk: secret key - * @idx: index of the MPI to retrieve - * @buf: buffer to hold the raw data - * @r_nwritten: output length of the raw data - * @r_nbits: length of the MPI data in bits. - * - * Return the MPI of the given secret key with the - * index @idx. It is important to check if the key - * is protected and thus no real MPI data will be returned then. - **/ -cdk_error_t -cdk_sk_get_mpi (cdk_pkt_seckey_t sk, size_t idx, - byte * buf, size_t buflen, size_t * r_nwritten, - size_t * r_nbits) -{ - if (!sk || !r_nwritten) - return CDK_Inv_Value; - if (idx > cdk_pk_get_nskey (sk->pubkey_algo)) - return CDK_Inv_Value; - return mpi_to_buffer (sk->mpi[idx], buf, buflen, r_nwritten, r_nbits); -} - - -static u16 -checksum_mpi (gcry_mpi_t m) -{ - byte buf[MAX_MPI_BYTES + 2]; - size_t nread; - int i; - u16 chksum = 0; - - if (!m) - return 0; - if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), &nread, m)) - return 0; - for (i = 0; i < nread; i++) - chksum += buf[i]; - return chksum; -} - - -/** - * cdk_sk_unprotect: - * @sk: the secret key - * @pw: the passphrase - * - * Unprotect the given secret key with the passphrase. - **/ -cdk_error_t -cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw) -{ - gcry_cipher_hd_t hd; - cdk_dek_t dek = NULL; - byte *data = NULL; - u16 chksum = 0; - size_t ndata, nbits, nbytes; - int i, dlen, pos = 0, nskey; - cdk_error_t rc; - gcry_error_t err; - - if (!sk) - return CDK_Inv_Value; - - nskey = cdk_pk_get_nskey (sk->pubkey_algo); - if (!sk->is_protected) - { - chksum = 0; - for (i = 0; i < nskey; i++) - chksum += checksum_mpi (sk->mpi[i]); - if (chksum != sk->csum) - return CDK_Chksum_Error; - } - - rc = cdk_dek_from_passphrase (&dek, sk->protect.algo, - sk->protect.s2k, 0, pw); - if (rc) - return rc; - err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, - GCRY_CIPHER_ENABLE_SYNC); - if (!err) - err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen); - if (!err) - err = gcry_cipher_setkey (hd, dek->key, dek->keylen); - if (err) - { - cdk_free (dek); - return map_gcry_error (err); - } - cdk_dek_free (dek); - chksum = 0; - if (sk->version == 4) - { - ndata = sk->enclen; - data = cdk_salloc (ndata, 1); - if (!data) - return CDK_Out_Of_Core; - gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata); - if (sk->protect.sha1chk) - { - /* This is the new SHA1 checksum method to detect tampering - with the key as used by the Klima/Rosa attack */ - sk->csum = 0; - chksum = 1; - dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); - if (ndata < dlen) - { - cdk_free (data); - return CDK_Inv_Packet; - } - else - { - byte mdcheck[20]; - - gcry_md_hash_buffer (GCRY_MD_SHA1, mdcheck, data, ndata - dlen); - if (!memcmp (mdcheck, data + ndata - dlen, dlen)) - chksum = 0; /* Digest does match */ - } - } - else - { - for (i = 0; i < ndata - 2; i++) - chksum += data[i]; - sk->csum = data[ndata - 2] << 8 | data[ndata - 1]; - } - if (sk->csum == chksum) - { - for (i = 0; i < nskey; i++) - { - nbits = data[pos] << 8 | data[pos + 1]; - - if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data, - (nbits + 7) / 8 + 2, &nbytes)) - { - wipemem (data, sk->enclen); - cdk_free (data); - return CDK_Wrong_Format; - } - gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE); - pos += (nbits + 7) / 8 + 2; - } - } - wipemem (data, sk->enclen); - cdk_free (data); - } - else - { - byte buf[MAX_MPI_BYTES + 2]; - - chksum = 0; - for (i = 0; i < nskey; i++) - { - gcry_cipher_sync (hd); - gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), - &nbytes, sk->mpi[i]); - gcry_cipher_decrypt (hd, buf + 2, nbytes - 2, NULL, 0); - gcry_mpi_release (sk->mpi[i]); - if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, - buf, nbytes, &nbytes)) - return CDK_Wrong_Format; - chksum += checksum_mpi (sk->mpi[i]); - } - } - gcry_cipher_close (hd); - if (chksum != sk->csum) - return CDK_Chksum_Error; - sk->is_protected = 0; - return 0; -} - - -/** - * cdk_sk_protect: - * @sk: the secret key - * @pw: the passphrase to use - * - * Protect the given secret key with a passphrase. - **/ -cdk_error_t -cdk_sk_protect (cdk_pkt_seckey_t sk, const char *pw) -{ - gcry_cipher_hd_t hd = NULL; - cdk_dek_t dek = NULL; - cdk_s2k_t s2k; - byte *p = NULL, buf[MAX_MPI_BYTES + 2]; - size_t enclen = 0, nskey, i, nbytes; - size_t dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1); - gcry_error_t err; - cdk_error_t rc; - - nskey = cdk_pk_get_nskey (sk->pubkey_algo); - if (!nskey) - return CDK_Inv_Algo; - - rc = cdk_s2k_new (&s2k, CDK_S2K_ITERSALTED, GCRY_MD_SHA256, NULL); - if (!rc) - rc = cdk_dek_from_passphrase (&dek, GCRY_CIPHER_AES, s2k, 1, pw); - if (rc) - { - cdk_s2k_free (s2k); - return rc; - } - - for (i = 0; i < nskey; i++) - { - enclen += 2; - enclen += (gcry_mpi_get_nbits (sk->mpi[i]) + 7) / 8; - } - p = sk->encdata = cdk_calloc (1, enclen + dlen + 1); - if (!p) - { - cdk_s2k_free (s2k); - return CDK_Out_Of_Core; - } - - enclen = 0; - for (i = 0; i < nskey; i++) - { - if (gcry_mpi_print (GCRYMPI_FMT_PGP, buf, - DIM (buf), &nbytes, sk->mpi[i])) - { - cdk_free (p); - cdk_s2k_free (s2k); - return CDK_Wrong_Format; - } - memcpy (p + enclen, buf, nbytes); - enclen += nbytes; - } - - enclen += dlen; - sk->enclen = enclen; - sk->protect.s2k = s2k; - sk->protect.algo = GCRY_CIPHER_AES; - sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo); - gcry_randomize (sk->protect.iv, sk->protect.ivlen, GCRY_STRONG_RANDOM); - err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, - GCRY_CIPHER_ENABLE_SYNC); - if (err) - { - cdk_dek_free (dek); - rc = map_gcry_error (err); - goto leave; - } - - err = gcry_cipher_setkey (hd, dek->key, dek->keylen); - if (!err) - err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen); - cdk_dek_free (dek); - if (err) - { - rc = map_gcry_error (err); - goto leave; - } - - sk->protect.sha1chk = 1; - sk->is_protected = 1; - sk->csum = 0; - - gcry_md_hash_buffer (GCRY_MD_SHA1, buf, p, enclen - dlen); - memcpy (p + enclen - dlen, buf, dlen); - gcry_cipher_encrypt (hd, p, enclen, NULL, 0); - - /* FIXME: We should release all MPI's and set the elements to NULL. */ - -leave: - gcry_cipher_close (hd); - return rc; -} - - -/** - * cdk_pk_from_secret_key: - * @sk: the secret key - * @ret_pk: the new public key - * - * Create a new public key from a secret key. - **/ -cdk_error_t -cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t * ret_pk) -{ - if (!sk) - return CDK_Inv_Value; - return _cdk_copy_pubkey (ret_pk, sk->pk); -} - - -#if 0 /* FIXME: Code is not finished yet. */ -cdk_error_t -cdk_pk_revoke_cert_create (cdk_pkt_seckey_t sk, int code, const char *inf, - char **ret_revcert) -{ - gcry_md_hd_t md; - cdk_subpkt_t node; - cdk_pkt_signature_t sig; - char *p = NULL, *dat; - gcry_error_t err; - cdk_error_t rc = 0; - size_t n; - - if (!sk || !ret_revcert) - return CDK_Inv_Value; - if (code < 0 || code > 3) - return CDK_Inv_Value; - - sig = cdk_calloc (1, sizeof *sig); - if (!sig) - return CDK_Out_Of_Core; - _cdk_sig_create (sk->pk, sig); - n = 1; - if (inf) - { - n += strlen (p); - p = cdk_utf8_encode (inf); - } - dat = cdk_calloc (1, n + 1); - if (!dat) - { - _cdk_free_signature (sig); - return CDK_Out_Of_Core; - } - dat[0] = code; - if (inf) - memcpy (dat + 1, p, strlen (p)); - cdk_free (p); - - node = cdk_subpkt_new (n); - if (node) - { - cdk_subpkt_init (node, CDK_SIGSUBPKT_REVOC_REASON, dat, n); - cdk_subpkt_add (sig->hashed, node); - } - cdk_free (dat); - - err = gcry_md_open (&md, GCRY_MD_SHA1, 0); - if (err) - rc = map_gcry_error (err); - else - _cdk_hash_pubkey (sk->pk, md, 0); - _cdk_free_signature (sig); - - return rc; -} -#endif - -int -_cdk_sk_get_csum (cdk_pkt_seckey_t sk) -{ - u16 csum = 0, i; - - if (!sk) - return 0; - for (i = 0; i < cdk_pk_get_nskey (sk->pubkey_algo); i++) - csum += checksum_mpi (sk->mpi[i]); - return csum; -} - - -/** - * cdk_pk_get_fingerprint: - * @pk: the public key - * @fpr: the buffer to hold the fingerprint - * - * Return the fingerprint of the given public key. - * The buffer must be at least 20 octets. - * This function should be considered deprecated and - * the new cdk_pk_to_fingerprint() should be used whenever - * possible to avoid overflows. - **/ -cdk_error_t -cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr) -{ - gcry_md_hd_t hd; - int md_algo; - int dlen = 0; - gcry_error_t err; - - if (!pk || !fpr) - return CDK_Inv_Value; - - if (pk->version < 4 && is_RSA (pk->pubkey_algo)) - md_algo = GCRY_MD_MD5; /* special */ - else - md_algo = GCRY_MD_SHA1; - dlen = gcry_md_get_algo_dlen (md_algo); - err = gcry_md_open (&hd, md_algo, 0); - if (err) - return map_gcry_error (err); - _cdk_hash_pubkey (pk, hd, 1); - gcry_md_final (hd); - memcpy (fpr, gcry_md_read (hd, md_algo), dlen); - gcry_md_close (hd); - if (dlen == 16) - memset (fpr + 16, 0, 4); - return 0; -} - - -/** - * cdk_pk_to_fingerprint: - * @pk: the public key - * @fprbuf: buffer to save the fingerprint - * @fprbuflen: buffer size - * @r_nout: actual length of the fingerprint. - * - * Calculate a fingerprint of the given key and - * return it in the given byte array. - **/ -cdk_error_t -cdk_pk_to_fingerprint (cdk_pubkey_t pk, - byte * fprbuf, size_t fprbuflen, size_t * r_nout) -{ - size_t key_fprlen; - cdk_error_t err; - - if (!pk) - return CDK_Inv_Value; - - if (pk->version < 4) - key_fprlen = 16; - else - key_fprlen = 20; - - /* Only return the required buffer size for the fingerprint. */ - if (!fprbuf && !fprbuflen && r_nout) - { - *r_nout = key_fprlen; - return 0; - } - - if (!fprbuf || key_fprlen > fprbuflen) - return CDK_Too_Short; - - err = cdk_pk_get_fingerprint (pk, fprbuf); - if (r_nout) - *r_nout = key_fprlen; - - return err; -} - - -/** - * cdk_pk_fingerprint_get_keyid: - * @fpr: the key fingerprint - * @fprlen: the length of the fingerprint - * - * Derive the key ID from the key fingerprint. - * For version 3 keys, this is not working. - **/ -u32 -cdk_pk_fingerprint_get_keyid (const byte * fpr, size_t fprlen, u32 * keyid) -{ - u32 lowbits = 0; - - /* In this case we say the key is a V3 RSA key and we can't - use the fingerprint to get the keyid. */ - if (fpr && fprlen == 16) - { - keyid[0] = 0; - keyid[1] = 0; - return 0; - } - else if (keyid && fpr) - { - keyid[0] = _cdk_buftou32 (fpr + 12); - keyid[1] = _cdk_buftou32 (fpr + 16); - lowbits = keyid[1]; - } - else if (fpr) - lowbits = _cdk_buftou32 (fpr + 16); - return lowbits; -} - - -/** - * cdk_pk_get_keyid: - * @pk: the public key - * @keyid: buffer to store the key ID - * - * Calculate the key ID of the given public key. - **/ -u32 -cdk_pk_get_keyid (cdk_pubkey_t pk, u32 * keyid) -{ - u32 lowbits = 0; - byte buf[24]; - - if (pk && (!pk->keyid[0] || !pk->keyid[1])) - { - if (pk->version < 4 && is_RSA (pk->pubkey_algo)) - { - byte p[MAX_MPI_BYTES]; - size_t n; - - gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]); - pk->keyid[0] = - p[n - 8] << 24 | p[n - 7] << 16 | p[n - 6] << 8 | p[n - 5]; - pk->keyid[1] = - p[n - 4] << 24 | p[n - 3] << 16 | p[n - 2] << 8 | p[n - 1]; - } - else if (pk->version == 4) - { - cdk_pk_get_fingerprint (pk, buf); - pk->keyid[0] = _cdk_buftou32 (buf + 12); - pk->keyid[1] = _cdk_buftou32 (buf + 16); - } - } - lowbits = pk ? pk->keyid[1] : 0; - if (keyid && pk) - { - keyid[0] = pk->keyid[0]; - keyid[1] = pk->keyid[1]; - } - - return lowbits; -} - - -/** - * cdk_sk_get_keyid: - * @sk: the secret key - * @keyid: buffer to hold the key ID - * - * Calculate the key ID of the secret key, actually the public key. - **/ -u32 -cdk_sk_get_keyid (cdk_pkt_seckey_t sk, u32 * keyid) -{ - u32 lowbits = 0; - - if (sk && sk->pk) - { - lowbits = cdk_pk_get_keyid (sk->pk, keyid); - sk->keyid[0] = sk->pk->keyid[0]; - sk->keyid[1] = sk->pk->keyid[1]; - } - - return lowbits; -} - - -/** - * cdk_sig_get_keyid: - * @sig: the signature - * @keyid: buffer to hold the key ID - * - * Retrieve the key ID from the given signature. - **/ -u32 -cdk_sig_get_keyid (cdk_pkt_signature_t sig, u32 * keyid) -{ - u32 lowbits = sig ? sig->keyid[1] : 0; - - if (keyid && sig) - { - keyid[0] = sig->keyid[0]; - keyid[1] = sig->keyid[1]; - } - return lowbits; -} - - -/* Return the key ID from the given packet. - If this is not possible, 0 is returned */ -u32 -_cdk_pkt_get_keyid (cdk_packet_t pkt, u32 * keyid) -{ - u32 lowbits; - - if (!pkt) - return 0; - - switch (pkt->pkttype) - { - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - lowbits = cdk_pk_get_keyid (pkt->pkt.public_key, keyid); - break; - - case CDK_PKT_SECRET_KEY: - case CDK_PKT_SECRET_SUBKEY: - lowbits = cdk_sk_get_keyid (pkt->pkt.secret_key, keyid); - break; - - case CDK_PKT_SIGNATURE: - lowbits = cdk_sig_get_keyid (pkt->pkt.signature, keyid); - break; - - default: - lowbits = 0; - break; - } - - return lowbits; -} - - -/* Get the fingerprint of the packet if possible. */ -int -_cdk_pkt_get_fingerprint (cdk_packet_t pkt, byte * fpr) -{ - if (!pkt || !fpr) - return CDK_Inv_Value; - - switch (pkt->pkttype) - { - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - return cdk_pk_get_fingerprint (pkt->pkt.public_key, fpr); - - case CDK_PKT_SECRET_KEY: - case CDK_PKT_SECRET_SUBKEY: - return cdk_pk_get_fingerprint (pkt->pkt.secret_key->pk, fpr); - - default: - return CDK_Inv_Mode; - } - return 0; -} - - -/** - * cdk_pubkey_to_sexp: - * @pk: the public key - * @sexp: where to store the S-expression - * @len: the length of sexp - * - * Convert a public key to an S-expression. sexp is allocated by this - * function, but you have to cdk_free() it yourself. The S-expression - * is stored in canonical format as used by libgcrypt - * (GCRYSEXP_FMT_CANON). - **/ -cdk_error_t -cdk_pubkey_to_sexp (cdk_pubkey_t pk, char **sexp, size_t * len) -{ - char *buf; - size_t sexp_len; - gcry_sexp_t pk_sexp; - cdk_error_t rc; - - if (!pk || !sexp) - return CDK_Inv_Value; - - rc = pubkey_to_sexp (&pk_sexp, pk); - if (rc) - return rc; - - sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, NULL, 0); - if (!sexp_len) - return CDK_Wrong_Format; - - buf = (char *) cdk_malloc (sexp_len); - if (!buf) - { - gcry_sexp_release (pk_sexp); - return CDK_Out_Of_Core; - } - - sexp_len = gcry_sexp_sprint (pk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len); - gcry_sexp_release (pk_sexp); - if (!sexp_len) - { - cdk_free (buf); - return CDK_Wrong_Format; - } - - if (len) - *len = sexp_len; - *sexp = buf; - return CDK_Success; -} - - -/** - * cdk_seckey_to_sexp: - * @sk: the secret key - * @sexp: where to store the S-expression - * @len: the length of sexp - * - * Convert a public key to an S-expression. sexp is allocated by this - * function, but you have to cdk_free() it yourself. The S-expression - * is stored in canonical format as used by libgcrypt - * (GCRYSEXP_FMT_CANON). - **/ -cdk_error_t -cdk_seckey_to_sexp (cdk_pkt_seckey_t sk, char **sexp, size_t * len) -{ - char *buf; - size_t sexp_len; - gcry_sexp_t sk_sexp; - cdk_error_t rc; - - if (!sk || !sexp) - return CDK_Inv_Value; - - rc = seckey_to_sexp (&sk_sexp, sk); - if (rc) - return rc; - - sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, NULL, 0); - if (!sexp_len) - return CDK_Wrong_Format; - - buf = (char *) cdk_malloc (sexp_len); - if (!buf) - { - gcry_sexp_release (sk_sexp); - return CDK_Out_Of_Core; - } - - sexp_len = gcry_sexp_sprint (sk_sexp, GCRYSEXP_FMT_CANON, buf, sexp_len); - gcry_sexp_release (sk_sexp); - if (!sexp_len) - { - cdk_free (buf); - return CDK_Wrong_Format; - } - - if (len) - *len = sexp_len; - *sexp = buf; - - return CDK_Success; -} diff --git a/src/daemon/https/opencdk/read-packet.c b/src/daemon/https/opencdk/read-packet.c @@ -1,1179 +0,0 @@ -/* read-packet.c - Read OpenPGP packets - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <string.h> -#include <stdio.h> -#include <time.h> -#include <assert.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" -#include "types.h" - - -/* The version of the MDC packet considering the lastest OpenPGP draft. */ -#define MDC_PKT_VER 1 - -static int -stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread) -{ - *r_nread = cdk_stream_read (s, buf, buflen); - return *r_nread > 0 ? 0 : _cdk_stream_get_errno (s); -} - - -/* Try to read 4 octets from the stream. */ -static u32 -read_32 (cdk_stream_t s) -{ - byte buf[4]; - size_t nread; - - assert (s != NULL); - - stream_read (s, buf, 4, &nread); - if (nread != 4) - return (u32) - 1; - return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; -} - - -/* Try to read 2 octets from a stream. */ -static u16 -read_16 (cdk_stream_t s) -{ - byte buf[2]; - size_t nread; - - assert (s != NULL); - - stream_read (s, buf, 2, &nread); - if (nread != 2) - return (u16) - 1; - return buf[0] << 8 | buf[1]; -} - - -static int -read_s2k (cdk_stream_t inp, cdk_s2k_t s2k) -{ - size_t nread; - - if (!inp || !s2k) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_s2k:\n"); - - s2k->mode = cdk_stream_getc (inp); - if (cdk_stream_eof (inp)) - return CDK_Inv_Packet; - if (s2k->mode != CDK_S2K_SIMPLE && s2k->mode != CDK_S2K_SALTED && - s2k->mode != CDK_S2K_ITERSALTED) - return CDK_Inv_Packet; - s2k->hash_algo = cdk_stream_getc (inp); - if (s2k->mode == CDK_S2K_SIMPLE) /* No additional elements. */ - memset (s2k->salt, 0, sizeof (s2k->salt)); - else if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) - { - if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread)) - return CDK_Inv_Packet; - if (nread != DIM (s2k->salt)) - return CDK_Inv_Packet; - if (s2k->mode == CDK_S2K_ITERSALTED) - { - s2k->count = cdk_stream_getc (inp); - if (cdk_stream_eof (inp)) - return CDK_Inv_Packet; - } - } - else - return CDK_Inv_Mode; - return 0; -} - - -static cdk_error_t -read_mpi (cdk_stream_t inp, gcry_mpi_t * ret_m, int secure) -{ - gcry_mpi_t m; - gcry_error_t err; - byte buf[MAX_MPI_BYTES + 2]; - size_t nread, nbits; - cdk_error_t rc; - - if (!inp || !ret_m) - return CDK_Inv_Value; - - *ret_m = NULL; - nbits = read_16 (inp); - nread = (nbits + 7) / 8; - - if (nbits > MAX_MPI_BITS || nbits == 0) - { - _cdk_log_debug ("read_mpi: too large %d bits\n", nbits); - return CDK_MPI_Error; /* Sanity check */ - } - - rc = stream_read (inp, buf + 2, nread, &nread); - if (!rc && nread != ((nbits + 7) / 8)) - { - _cdk_log_debug ("read_mpi: too short %d < %d\n", nread, - (nbits + 7) / 8); - return CDK_MPI_Error; - } - - buf[0] = nbits >> 8; - buf[1] = nbits >> 0; - err = gcry_mpi_scan (&m, GCRYMPI_FMT_PGP, buf, nread + 2, &nread); - if (err) - return map_gcry_error (err); - if (secure) - gcry_mpi_set_flag (m, GCRYMPI_FLAG_SECURE); - *ret_m = m; - return rc; -} - - -/* Read the encoded packet length directly from the file - object INP and return it. Reset RET_PARTIAL if this is - the last packet in block mode. */ -size_t -_cdk_pkt_read_len (FILE * inp, size_t * ret_partial) -{ - int c1, c2; - size_t pktlen; - - c1 = fgetc (inp); - if (c1 == EOF) - return (size_t) EOF; - if (c1 < 224 || c1 == 255) - *ret_partial = 0; /* End of partial data */ - if (c1 < 192) - pktlen = c1; - else if (c1 >= 192 && c1 <= 223) - { - c2 = fgetc (inp); - if (c2 == EOF) - return (size_t) EOF; - pktlen = ((c1 - 192) << 8) + c2 + 192; - } - else if (c1 == 255) - { - pktlen = fgetc (inp) << 24; - pktlen |= fgetc (inp) << 16; - pktlen |= fgetc (inp) << 8; - pktlen |= fgetc (inp) << 0; - } - else - pktlen = 1 << (c1 & 0x1f); - return pktlen; -} - - -static cdk_error_t -read_encrypted (cdk_stream_t inp, size_t pktlen, cdk_pkt_encrypted_t enc, - int is_partial, int is_mdc) -{ - if (!inp || !enc) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_encrypted: %d octets\n", pktlen); - - if (is_mdc) - { - int version = cdk_stream_getc (inp); - if (version != MDC_PKT_VER) - return CDK_Inv_Packet; - enc->mdc_method = CDK_MD_SHA1; - pktlen--; - } - /* The packet must at least contain blocksize + 2 octets. */ - if (pktlen < 10) - return CDK_Inv_Packet; - if (is_partial) - _cdk_stream_set_blockmode (inp, pktlen); - enc->len = pktlen; - enc->buf = inp; - return 0; -} - - -static cdk_error_t -read_symkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_symkey_enc_t ske) -{ - cdk_s2k_t s2k; - size_t minlen; - size_t nread, nleft; - - if (!inp || !ske) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_symkey_enc: %d octets\n", pktlen); - - ske->version = cdk_stream_getc (inp); - if (ske->version != 4 || cdk_stream_eof (inp)) - return CDK_Inv_Packet; - - s2k = ske->s2k = cdk_calloc (1, sizeof *ske->s2k); - if (!ske->s2k) - return CDK_Out_Of_Core; - - ske->cipher_algo = cdk_stream_getc (inp); - s2k->mode = cdk_stream_getc (inp); - switch (s2k->mode) - { - case CDK_S2K_SIMPLE: - minlen = 0; - break; - case CDK_S2K_SALTED: - minlen = 8; - break; - case CDK_S2K_ITERSALTED: - minlen = 9; - break; - - default: - /* Invalid S2K mode. */ - return CDK_Inv_Packet; - } - - s2k->hash_algo = cdk_stream_getc (inp); - if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) - { - if (stream_read (inp, s2k->salt, DIM (s2k->salt), &nread)) - return CDK_Inv_Packet; - if (nread != DIM (s2k->salt)) - return CDK_Inv_Packet; - - if (s2k->mode == CDK_S2K_ITERSALTED) - s2k->count = cdk_stream_getc (inp); - } - - ske->seskeylen = pktlen - 4 - minlen; - /* We check if there is an encrypted session key and if it fits into - the buffer. The maximal key length is 256-bit. */ - if (ske->seskeylen > DIM (ske->seskey)) - return CDK_Inv_Packet; - nleft = ske->seskeylen; - for (nread = 0; nread < ske->seskeylen; nread++) - { - ske->seskey[nread] = cdk_stream_getc (inp); - if (cdk_stream_eof (inp) && --nleft > 0) - return CDK_Inv_Packet; - } - - return 0; -} - - -static cdk_error_t -read_pubkey_enc (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_enc_t pke) -{ - size_t i, nenc; - - if (!inp || !pke) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_pubkey_enc: %d octets\n", pktlen); - - if (pktlen < 12) - return CDK_Inv_Packet; - pke->version = cdk_stream_getc (inp); - if (pke->version < 2 || pke->version > 3) - return CDK_Inv_Packet; - pke->keyid[0] = read_32 (inp); - pke->keyid[1] = read_32 (inp); - if (!pke->keyid[0] && !pke->keyid[1]) - pke->throw_keyid = 1; /* RFC2440 "speculative" keyID */ - pke->pubkey_algo = cdk_stream_getc (inp); - nenc = cdk_pk_get_nenc (pke->pubkey_algo); - if (!nenc) - return CDK_Inv_Algo; - for (i = 0; i < nenc; i++) - { - cdk_error_t rc = read_mpi (inp, &pke->mpi[i], 0); - if (rc) - return rc; - } - - return 0; -} - - - -static cdk_error_t -read_mdc (cdk_stream_t inp, cdk_pkt_mdc_t mdc) -{ - size_t n; - cdk_error_t rc; - - if (!inp || !mdc) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_mdc:\n"); - - rc = stream_read (inp, mdc->hash, DIM (mdc->hash), &n); - if (rc) - return rc; - - return n != DIM (mdc->hash) ? CDK_Inv_Packet : 0; -} - - -static cdk_error_t -read_compressed (cdk_stream_t inp, size_t pktlen, cdk_pkt_compressed_t c) -{ - if (!inp || !c) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_compressed: %d octets\n", pktlen); - - c->algorithm = cdk_stream_getc (inp); - if (c->algorithm > 3) - return CDK_Inv_Packet; - - /* don't know the size, so we read until EOF */ - if (!pktlen) - { - c->len = 0; - c->buf = inp; - } - - /* FIXME: Support partial bodies. */ - return 0; -} - - -static cdk_error_t -read_public_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk) -{ - size_t i, ndays, npkey; - - if (!inp || !pk) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_public_key: %d octets\n", pktlen); - - pk->is_invalid = 1; /* default to detect missing self signatures */ - pk->is_revoked = 0; - pk->has_expired = 0; - - pk->version = cdk_stream_getc (inp); - if (pk->version < 2 || pk->version > 4) - return CDK_Inv_Packet_Ver; - pk->timestamp = read_32 (inp); - if (pk->version < 4) - { - ndays = read_16 (inp); - if (ndays) - pk->expiredate = pk->timestamp + ndays * 86400L; - } - - pk->pubkey_algo = cdk_stream_getc (inp); - npkey = cdk_pk_get_npkey (pk->pubkey_algo); - if (!npkey) - { - _cdk_log_debug ("invalid public key algorithm %d\n", pk->pubkey_algo); - return CDK_Inv_Algo; - } - for (i = 0; i < npkey; i++) - { - cdk_error_t rc = read_mpi (inp, &pk->mpi[i], 0); - if (rc) - return rc; - } - - /* These values are just for the first run and should be - replaced with the actual key flags from the self signature. */ - pk->pubkey_usage = _cdk_pk_algo_usage (pk->pubkey_algo); - return 0; -} - - -static cdk_error_t -read_public_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_pubkey_t pk) -{ - if (!inp || !pk) - return CDK_Inv_Value; - return read_public_key (inp, pktlen, pk); -} - - -static cdk_error_t -read_secret_key (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk) -{ - size_t p1, p2, nread; - int i, nskey; - int rc; - - if (!inp || !sk || !sk->pk) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_secret_key: %d octets\n", pktlen); - - p1 = cdk_stream_tell (inp); - rc = read_public_key (inp, pktlen, sk->pk); - if (rc) - return rc; - - sk->s2k_usage = cdk_stream_getc (inp); - sk->protect.sha1chk = 0; - if (sk->s2k_usage == 254 || sk->s2k_usage == 255) - { - sk->protect.sha1chk = (sk->s2k_usage == 254); - sk->protect.algo = cdk_stream_getc (inp); - sk->protect.s2k = cdk_calloc (1, sizeof *sk->protect.s2k); - if (!sk->protect.s2k) - return CDK_Out_Of_Core; - rc = read_s2k (inp, sk->protect.s2k); - if (rc) - return rc; - sk->protect.ivlen = gcry_cipher_get_algo_blklen (sk->protect.algo); - if (!sk->protect.ivlen) - return CDK_Inv_Packet; - rc = stream_read (inp, sk->protect.iv, sk->protect.ivlen, &nread); - if (rc) - return rc; - if (nread != sk->protect.ivlen) - return CDK_Inv_Packet; - } - else - sk->protect.algo = sk->s2k_usage; - if (sk->protect.algo == GCRY_CIPHER_NONE) - { - sk->csum = 0; - nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo); - if (!nskey) - return CDK_Inv_Algo; - for (i = 0; i < nskey; i++) - { - rc = read_mpi (inp, &sk->mpi[i], 1); - if (rc) - return rc; - } - sk->csum = read_16 (inp); - sk->is_protected = 0; - } - else if (sk->pk->version < 4) - { - /* The length of each multiprecision integer is stored in plaintext. */ - nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo); - if (!nskey) - return CDK_Inv_Algo; - for (i = 0; i < nskey; i++) - { - rc = read_mpi (inp, &sk->mpi[i], 1); - if (rc) - return rc; - } - sk->csum = read_16 (inp); - sk->is_protected = 1; - } - else - { - /* We need to read the rest of the packet because we do not - have any information how long the encrypted mpi's are */ - p2 = cdk_stream_tell (inp); - p2 -= p1; - sk->enclen = pktlen - p2; - if (sk->enclen < 2) - return CDK_Inv_Packet; /* at least 16 bits for the checksum! */ - sk->encdata = cdk_calloc (1, sk->enclen + 1); - if (!sk->encdata) - return CDK_Out_Of_Core; - if (stream_read (inp, sk->encdata, sk->enclen, &nread)) - return CDK_Inv_Packet; - nskey = cdk_pk_get_nskey (sk->pk->pubkey_algo); - if (!nskey) - return CDK_Inv_Algo; - /* We mark each MPI entry with NULL to indicate a protected key. */ - for (i = 0; i < nskey; i++) - sk->mpi[i] = NULL; - sk->is_protected = 1; - } - - sk->is_primary = 1; - _cdk_copy_pk_to_sk (sk->pk, sk); - return 0; -} - - -static cdk_error_t -read_secret_subkey (cdk_stream_t inp, size_t pktlen, cdk_pkt_seckey_t sk) -{ - cdk_error_t rc; - - if (!inp || !sk || !sk->pk) - return CDK_Inv_Value; - - rc = read_secret_key (inp, pktlen, sk); - sk->is_primary = 0; - return rc; -} - - -static cdk_error_t -read_attribute (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t attr) -{ - const byte *p; - byte *buf; - size_t len, nread; - cdk_error_t rc; - - if (!inp || !attr || !pktlen) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_attribute: %d octets\n", pktlen); - - strcpy (attr->name, "[attribute]"); - attr->len = strlen (attr->name); - buf = cdk_calloc (1, pktlen); - if (!buf) - return CDK_Out_Of_Core; - rc = stream_read (inp, buf, pktlen, &nread); - if (rc) - { - cdk_free (buf); - return CDK_Inv_Packet; - } - p = buf; - len = *p++; - pktlen--; - if (len == 255) - { - len = _cdk_buftou32 (p); - p += 4; - pktlen -= 4; - } - else if (len >= 192) - { - if (pktlen < 2) - { - cdk_free (buf); - return CDK_Inv_Packet; - } - len = ((len - 192) << 8) + *p + 192; - p++; - pktlen--; - } - - if (*p != 1) /* Currently only 1, meaning an image, is defined. */ - { - cdk_free (buf); - return CDK_Inv_Packet; - } - p++; - len--; - - if (pktlen - (len + 1) > 0) - return CDK_Inv_Packet; - attr->attrib_img = cdk_calloc (1, len); - if (!attr->attrib_img) - { - cdk_free (buf); - return CDK_Out_Of_Core; - } - attr->attrib_len = len; - memcpy (attr->attrib_img, p, len); - cdk_free (buf); - return rc; -} - - -static cdk_error_t -read_user_id (cdk_stream_t inp, size_t pktlen, cdk_pkt_userid_t user_id) -{ - size_t nread; - cdk_error_t rc; - - if (!inp || !user_id) - return CDK_Inv_Value; - if (!pktlen) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("read_user_id: %lu octets\n", pktlen); - - user_id->len = pktlen; - rc = stream_read (inp, user_id->name, pktlen, &nread); - if (rc) - return rc; - if (nread != pktlen) - return CDK_Inv_Packet; - user_id->name[nread] = '\0'; - return rc; -} - - -static cdk_error_t -read_subpkt (cdk_stream_t inp, cdk_subpkt_t * r_ctx, size_t * r_nbytes) -{ - byte c, c1; - size_t size, nread, n; - cdk_subpkt_t node; - cdk_error_t rc; - - if (!inp || !r_nbytes) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_subpkt:\n"); - - n = 0; - *r_nbytes = 0; - c = cdk_stream_getc (inp); - n++; - if (c == 255) - { - size = read_32 (inp); - n += 4; - } - else if (c >= 192 && c < 255) - { - c1 = cdk_stream_getc (inp); - n++; - if (c1 == 0) - return 0; - size = ((c - 192) << 8) + c1 + 192; - } - else if (c < 192) - size = c; - else - return CDK_Inv_Packet; - - node = cdk_subpkt_new (size); - if (!node) - return CDK_Out_Of_Core; - node->size = size; - node->type = cdk_stream_getc (inp); - if (DEBUG_PKT) - _cdk_log_debug (" %d octets %d type\n", node->size, node->type); - n++; - node->size--; - rc = stream_read (inp, node->d, node->size, &nread); - n += nread; - if (rc) - return rc; - *r_nbytes = n; - if (!*r_ctx) - *r_ctx = node; - else - cdk_subpkt_add (*r_ctx, node); - return rc; -} - - -static cdk_error_t -read_onepass_sig (cdk_stream_t inp, size_t pktlen, cdk_pkt_onepass_sig_t sig) -{ - if (!inp || !sig) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_onepass_sig: %d octets\n", pktlen); - - if (pktlen != 13) - return CDK_Inv_Packet; - sig->version = cdk_stream_getc (inp); - if (sig->version != 3) - return CDK_Inv_Packet_Ver; - sig->sig_class = cdk_stream_getc (inp); - sig->digest_algo = cdk_stream_getc (inp); - sig->pubkey_algo = cdk_stream_getc (inp); - sig->keyid[0] = read_32 (inp); - sig->keyid[1] = read_32 (inp); - sig->last = cdk_stream_getc (inp); - return 0; -} - - -static cdk_error_t -parse_sig_subpackets (cdk_pkt_signature_t sig) -{ - cdk_subpkt_t node; - - /* Setup the standard packet entries, so we can use V4 - signatures similar to V3. */ - for (node = sig->unhashed; node; node = node->next) - { - if (node->type == CDK_SIGSUBPKT_ISSUER && node->size >= 8) - { - sig->keyid[0] = _cdk_buftou32 (node->d); - sig->keyid[1] = _cdk_buftou32 (node->d + 4); - } - else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0) - { - /* Sometimes this packet might be placed in the unhashed area */ - sig->flags.exportable = 0; - } - } - for (node = sig->hashed; node; node = node->next) - { - if (node->type == CDK_SIGSUBPKT_SIG_CREATED && node->size >= 4) - sig->timestamp = _cdk_buftou32 (node->d); - else if (node->type == CDK_SIGSUBPKT_SIG_EXPIRE && node->size >= 4) - { - sig->expiredate = _cdk_buftou32 (node->d); - if (sig->expiredate > 0 && sig->expiredate < (u32) time (NULL)) - sig->flags.expired = 1; - } - else if (node->type == CDK_SIGSUBPKT_POLICY) - sig->flags.policy_url = 1; - else if (node->type == CDK_SIGSUBPKT_NOTATION) - sig->flags.notation = 1; - else if (node->type == CDK_SIGSUBPKT_REVOCABLE && node->d[0] == 0) - sig->flags.revocable = 0; - else if (node->type == CDK_SIGSUBPKT_EXPORTABLE && node->d[0] == 0) - sig->flags.exportable = 0; - } - if (sig->sig_class == 0x1F) - { - cdk_desig_revoker_t r, rnode; - - for (node = sig->hashed; node; node = node->next) - { - if (node->type == CDK_SIGSUBPKT_REV_KEY) - { - if (node->size < 22) - continue; - rnode = cdk_calloc (1, sizeof *rnode); - if (!rnode) - return CDK_Out_Of_Core; - rnode->r_class = node->d[0]; - rnode->algid = node->d[1]; - memcpy (rnode->fpr, node->d + 2, KEY_FPR_LEN); - if (!sig->revkeys) - sig->revkeys = rnode; - else - { - for (r = sig->revkeys; r->next; r = r->next) - ; - r->next = rnode; - } - } - } - } - - return 0; -} - - -static cdk_error_t -read_signature (cdk_stream_t inp, size_t pktlen, cdk_pkt_signature_t sig) -{ - size_t nbytes; - size_t i, size, nsig; - cdk_error_t rc; - - if (!inp || !sig) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_signature: %d octets\n", pktlen); - - if (pktlen < 16) - return CDK_Inv_Packet; - sig->version = cdk_stream_getc (inp); - if (sig->version < 2 || sig->version > 4) - return CDK_Inv_Packet_Ver; - - sig->flags.exportable = 1; - sig->flags.revocable = 1; - - if (sig->version < 4) - { - if (cdk_stream_getc (inp) != 5) - return CDK_Inv_Packet; - sig->sig_class = cdk_stream_getc (inp); - sig->timestamp = read_32 (inp); - sig->keyid[0] = read_32 (inp); - sig->keyid[1] = read_32 (inp); - sig->pubkey_algo = cdk_stream_getc (inp); - sig->digest_algo = cdk_stream_getc (inp); - sig->digest_start[0] = cdk_stream_getc (inp); - sig->digest_start[1] = cdk_stream_getc (inp); - nsig = cdk_pk_get_nsig (sig->pubkey_algo); - if (!nsig) - return CDK_Inv_Algo; - for (i = 0; i < nsig; i++) - { - rc = read_mpi (inp, &sig->mpi[i], 0); - if (rc) - return rc; - } - } - else - { - sig->sig_class = cdk_stream_getc (inp); - sig->pubkey_algo = cdk_stream_getc (inp); - sig->digest_algo = cdk_stream_getc (inp); - sig->hashed_size = read_16 (inp); - size = sig->hashed_size; - sig->hashed = NULL; - while (size > 0) - { - rc = read_subpkt (inp, &sig->hashed, &nbytes); - if (rc) - return rc; - size -= nbytes; - } - sig->unhashed_size = read_16 (inp); - size = sig->unhashed_size; - sig->unhashed = NULL; - while (size > 0) - { - rc = read_subpkt (inp, &sig->unhashed, &nbytes); - if (rc) - return rc; - size -= nbytes; - } - - rc = parse_sig_subpackets (sig); - if (rc) - return rc; - - sig->digest_start[0] = cdk_stream_getc (inp); - sig->digest_start[1] = cdk_stream_getc (inp); - nsig = cdk_pk_get_nsig (sig->pubkey_algo); - if (!nsig) - return CDK_Inv_Algo; - for (i = 0; i < nsig; i++) - { - rc = read_mpi (inp, &sig->mpi[i], 0); - if (rc) - return rc; - } - } - - return 0; -} - - -static cdk_error_t -read_literal (cdk_stream_t inp, size_t pktlen, - cdk_pkt_literal_t * ret_pt, int is_partial) -{ - cdk_pkt_literal_t pt = *ret_pt; - size_t nread; - cdk_error_t rc; - - if (!inp || !pt) - return CDK_Inv_Value; - - if (DEBUG_PKT) - _cdk_log_debug ("read_literal: %d octets\n", pktlen); - - pt->mode = cdk_stream_getc (inp); - if (pt->mode != 0x62 && pt->mode != 0x74 && pt->mode != 0x75) - return CDK_Inv_Packet; - if (cdk_stream_eof (inp)) - return CDK_Inv_Packet; - - pt->namelen = cdk_stream_getc (inp); - if (pt->namelen > 0) - { - *ret_pt = pt = cdk_realloc (pt, sizeof *pt + pt->namelen + 1); - if (!pt) - return CDK_Out_Of_Core; - rc = stream_read (inp, pt->name, pt->namelen, &nread); - if (rc) - return rc; - if (nread != pt->namelen) - return CDK_Inv_Packet; - pt->name[pt->namelen] = '\0'; - } - pt->timestamp = read_32 (inp); - pktlen = pktlen - 6 - pt->namelen; - if (is_partial) - _cdk_stream_set_blockmode (inp, pktlen); - pt->buf = inp; - pt->len = pktlen; - return 0; -} - - -/* Read an old packet CTB and return the length of the body. */ -static void -read_old_length (cdk_stream_t inp, int ctb, size_t * r_len, size_t * r_size) -{ - int llen = ctb & 0x03; - - if (llen == 0) - { - *r_len = cdk_stream_getc (inp); - (*r_size)++; - } - else if (llen == 1) - { - *r_len = read_16 (inp); - (*r_size) += 2; - } - else if (llen == 2) - { - *r_len = read_32 (inp); - (*r_size) += 4; - } - else - { - *r_len = 0; - *r_size = 0; - } -} - - -/* Read a new CTB and decode the body length. */ -static void -read_new_length (cdk_stream_t inp, - size_t * r_len, size_t * r_size, size_t * r_partial) -{ - int c, c1; - - c = cdk_stream_getc (inp); - (*r_size)++; - if (c < 192) - *r_len = c; - else if (c >= 192 && c <= 223) - { - c1 = cdk_stream_getc (inp); - (*r_size)++; - *r_len = ((c - 192) << 8) + c1 + 192; - } - else if (c == 255) - { - *r_len = read_32 (inp); - (*r_size) += 4; - } - else - { - *r_len = 1 << (c & 0x1f); - *r_partial = 1; - } -} - - -/* Skip the current packet body. */ -static void -skip_packet (cdk_stream_t inp, size_t pktlen) -{ - byte buf[BUFSIZE]; - size_t nread, buflen = DIM (buf); - - while (pktlen > 0) - { - stream_read (inp, buf, pktlen > buflen ? buflen : pktlen, &nread); - pktlen -= nread; - } - - assert (pktlen == 0); -} - - -/** - * cdk_pkt_read: - * @inp: the input stream - * @pkt: allocated packet handle to store the packet - * - * Parse the next packet on the @inp stream and return its contents in @pkt. - **/ -cdk_error_t -cdk_pkt_read (cdk_stream_t inp, cdk_packet_t pkt) -{ - int use_mdc = 0; - int ctb, is_newctb; - int pkttype; - size_t pktlen = 0, pktsize = 0, is_partial = 0; - cdk_error_t rc; - - if (!inp || !pkt) - return CDK_Inv_Value; - - ctb = cdk_stream_getc (inp); - if (cdk_stream_eof (inp) || ctb == EOF) - return CDK_EOF; - else if (!ctb) - return CDK_Inv_Packet; - - pktsize++; - if (!(ctb & 0x80)) - { - _cdk_log_info ("cdk_pkt_read: no openpgp data found. " - "(ctb=%02X; fpos=%02X)\n", ctb, cdk_stream_tell (inp)); - return CDK_Inv_Packet; - } - - if (ctb & 0x40) /* RFC2440 packet format. */ - { - pkttype = ctb & 0x3f; - is_newctb = 1; - } - else /* the old RFC1991 packet format. */ - { - pkttype = ctb & 0x3f; - pkttype >>= 2; - is_newctb = 0; - } - - if (pkttype > 63) - { - _cdk_log_info ("cdk_pkt_read: unknown type %d\n", pkttype); - return CDK_Inv_Packet; - } - - if (is_newctb) - read_new_length (inp, &pktlen, &pktsize, &is_partial); - else - read_old_length (inp, ctb, &pktlen, &pktsize); - - pkt->pkttype = pkttype; - pkt->pktlen = pktlen; - pkt->pktsize = pktsize + pktlen; - pkt->old_ctb = is_newctb ? 0 : 1; - - rc = 0; - switch (pkt->pkttype) - { - case CDK_PKT_ATTRIBUTE: - pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id - + pkt->pktlen + 16 + 1); - if (!pkt->pkt.user_id) - return CDK_Out_Of_Core; - rc = read_attribute (inp, pktlen, pkt->pkt.user_id); - pkt->pkttype = CDK_PKT_ATTRIBUTE; - break; - - case CDK_PKT_USER_ID: - pkt->pkt.user_id = cdk_calloc (1, sizeof *pkt->pkt.user_id - + pkt->pktlen); - if (!pkt->pkt.user_id) - return CDK_Out_Of_Core; - rc = read_user_id (inp, pktlen, pkt->pkt.user_id); - break; - - case CDK_PKT_PUBLIC_KEY: - pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); - if (!pkt->pkt.public_key) - return CDK_Out_Of_Core; - rc = read_public_key (inp, pktlen, pkt->pkt.public_key); - break; - - case CDK_PKT_PUBLIC_SUBKEY: - pkt->pkt.public_key = cdk_calloc (1, sizeof *pkt->pkt.public_key); - if (!pkt->pkt.public_key) - return CDK_Out_Of_Core; - rc = read_public_subkey (inp, pktlen, pkt->pkt.public_key); - break; - - case CDK_PKT_SECRET_KEY: - pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key); - if (!pkt->pkt.secret_key) - return CDK_Out_Of_Core; - pkt->pkt.secret_key->pk = cdk_calloc (1, - sizeof *pkt->pkt.secret_key->pk); - if (!pkt->pkt.secret_key->pk) - return CDK_Out_Of_Core; - rc = read_secret_key (inp, pktlen, pkt->pkt.secret_key); - break; - - case CDK_PKT_SECRET_SUBKEY: - pkt->pkt.secret_key = cdk_calloc (1, sizeof *pkt->pkt.secret_key); - if (!pkt->pkt.secret_key) - return CDK_Out_Of_Core; - pkt->pkt.secret_key->pk = cdk_calloc (1, - sizeof *pkt->pkt.secret_key->pk); - if (!pkt->pkt.secret_key->pk) - return CDK_Out_Of_Core; - rc = read_secret_subkey (inp, pktlen, pkt->pkt.secret_key); - break; - - case CDK_PKT_LITERAL: - pkt->pkt.literal = cdk_calloc (1, sizeof *pkt->pkt.literal); - if (!pkt->pkt.literal) - return CDK_Out_Of_Core; - rc = read_literal (inp, pktlen, &pkt->pkt.literal, is_partial); - break; - - case CDK_PKT_ONEPASS_SIG: - pkt->pkt.onepass_sig = cdk_calloc (1, sizeof *pkt->pkt.onepass_sig); - if (!pkt->pkt.onepass_sig) - return CDK_Out_Of_Core; - rc = read_onepass_sig (inp, pktlen, pkt->pkt.onepass_sig); - break; - - case CDK_PKT_SIGNATURE: - pkt->pkt.signature = cdk_calloc (1, sizeof *pkt->pkt.signature); - if (!pkt->pkt.signature) - return CDK_Out_Of_Core; - rc = read_signature (inp, pktlen, pkt->pkt.signature); - break; - - case CDK_PKT_ENCRYPTED_MDC: - case CDK_PKT_ENCRYPTED: - pkt->pkt.encrypted = cdk_calloc (1, sizeof *pkt->pkt.encrypted); - if (!pkt->pkt.encrypted) - return CDK_Out_Of_Core; - use_mdc = (pkt->pkttype == CDK_PKT_ENCRYPTED_MDC) ? 1 : 0; - rc = read_encrypted (inp, pktlen, pkt->pkt.encrypted, - is_partial, use_mdc); - break; - - case CDK_PKT_SYMKEY_ENC: - pkt->pkt.symkey_enc = cdk_calloc (1, sizeof *pkt->pkt.symkey_enc); - if (!pkt->pkt.symkey_enc) - return CDK_Out_Of_Core; - rc = read_symkey_enc (inp, pktlen, pkt->pkt.symkey_enc); - break; - - case CDK_PKT_PUBKEY_ENC: - pkt->pkt.pubkey_enc = cdk_calloc (1, sizeof *pkt->pkt.pubkey_enc); - if (!pkt->pkt.pubkey_enc) - return CDK_Out_Of_Core; - rc = read_pubkey_enc (inp, pktlen, pkt->pkt.pubkey_enc); - break; - - case CDK_PKT_COMPRESSED: - pkt->pkt.compressed = cdk_calloc (1, sizeof *pkt->pkt.compressed); - if (!pkt->pkt.compressed) - return CDK_Out_Of_Core; - rc = read_compressed (inp, pktlen, pkt->pkt.compressed); - break; - - case CDK_PKT_MDC: - pkt->pkt.mdc = cdk_calloc (1, sizeof *pkt->pkt.mdc); - if (!pkt->pkt.mdc) - return CDK_Out_Of_Core; - rc = read_mdc (inp, pkt->pkt.mdc); - break; - - default: - /* Skip all packets we don't understand */ - skip_packet (inp, pktlen); - break; - } - - return rc; -} diff --git a/src/daemon/https/opencdk/seskey.c b/src/daemon/https/opencdk/seskey.c @@ -1,717 +0,0 @@ -/* seskey.c - Session key routines - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * Copyright (C) 1998-2000, 2002 Free Software Foundation, Inc. - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <assert.h> -#include <stdio.h> -#include <gcrypt.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" - - -/* We encode the MD in this way: - * - * 0 1 PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) - * - * PAD consists of FF bytes. - */ -static cdk_error_t -do_encode_md (byte ** r_frame, size_t * r_flen, const byte * md, int algo, - size_t len, unsigned nbits, const byte * asn, size_t asnlen) -{ - byte *frame = NULL; - size_t nframe = (nbits + 7) / 8; - size_t i, n = 0; - - if (!asn || !md || !r_frame || !r_flen) - return CDK_Inv_Value; - - if (len + asnlen + 4 > nframe) - return CDK_General_Error; - - frame = cdk_calloc (1, nframe); - if (!frame) - return CDK_Out_Of_Core; - frame[n++] = 0; - frame[n++] = 1; - i = nframe - len - asnlen - 3; - if (i < 0) - { - cdk_free (frame); - return CDK_Inv_Value; - } - memset (frame + n, 0xFF, i); - n += i; - frame[n++] = 0; - memcpy (frame + n, asn, asnlen); - n += asnlen; - memcpy (frame + n, md, len); - n += len; - if (n != nframe) - { - cdk_free (frame); - return CDK_Inv_Value; - } - *r_frame = frame; - *r_flen = n; - return 0; -} - - - -/* RFC2437 format: - * - * 0 2 RND(n bytes) 0 [A DEK(k bytes) CSUM(2 bytes)] - * - * RND - randomized bytes for padding. - * A - cipher algorithm. - * DEK - random session key. - * CKSUM - algebraic checksum of the DEK. - */ - -/** - * cdk_dek_encode_pkcs1 - * @dek: DEK object - * @nbits: size of the multi precision integer frame - * @r_enc: output of the encoded multiprecision integer - * - * Encode the given random session key in the DEK object - * into a multiprecision integer. - **/ -cdk_error_t -cdk_dek_encode_pkcs1 (cdk_dek_t dek, size_t nbits, gcry_mpi_t * r_enc) -{ - gcry_mpi_t a = NULL; - gcry_error_t err; - byte *p, *frame; - size_t n; - size_t nframe; - size_t i; - u16 chksum; - - if (!r_enc || !dek) - return CDK_Inv_Value; - - *r_enc = NULL; - chksum = 0; - for (i = 0; i < dek->keylen; i++) - chksum += dek->key[i]; - nframe = (nbits + 7) / 8; - frame = cdk_salloc (nframe + 1, 1); - if (!frame) - return CDK_Out_Of_Core; - n = 0; - frame[n++] = 0x00; - frame[n++] = 0x02; - i = nframe - 6 - dek->keylen; - p = gcry_random_bytes (i, GCRY_STRONG_RANDOM); - /* Replace zero bytes by new values */ - for (;;) - { - size_t j, k; - byte *pp; - - /* count the zero bytes */ - for (j = k = 0; j < i; j++) - { - if (!p[j]) - k++; - } - if (!k) - break; /* No zeroes remain. */ - k += k / 128; /* better get some more */ - pp = gcry_random_bytes (k, GCRY_STRONG_RANDOM); - for (j = 0; j < i && k; j++) - { - if (!p[j]) - p[j] = pp[--k]; - } - cdk_free (pp); - } - memcpy (frame + n, p, i); - cdk_free (p); - n += i; - frame[n++] = 0; - frame[n++] = dek->algo; - memcpy (frame + n, dek->key, dek->keylen); - n += dek->keylen; - frame[n++] = chksum >> 8; - frame[n++] = chksum; - err = gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe); - cdk_free (frame); - if (err) - return map_gcry_error (err); - *r_enc = a; - return 0; -} - - -/** - * cdk_dek_decode_pkcs1: - * @ret_dek: the decoded DEK object - * @esk: the pkcs#1 encoded session key. - * - * Decode the given multi precision integer in pkcs#1 and - * store it into the DEK object. - **/ -cdk_error_t -cdk_dek_decode_pkcs1 (cdk_dek_t * ret_dek, gcry_mpi_t esk) -{ - cdk_dek_t dek; - byte frame[MAX_MPI_BYTES + 2 + 1]; - size_t nframe, n; - u16 csum, csum2; - gcry_error_t err; - - if (!ret_dek || !esk) - return CDK_Inv_Value; - - *ret_dek = NULL; /* reset */ - nframe = DIM (frame) - 1; - err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, esk); - if (err) - return map_gcry_error (err); - dek = cdk_salloc (sizeof *dek, 1); - if (!dek) - return CDK_Out_Of_Core; - - /* Now get the DEK (data encryption key) from the frame - * - * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) - * - * (gcry_mpi_print already removed the leading zero). - * - * RND are non-zero randow bytes. - * A is the cipher algorithm - * DEK is the encryption key (session key) with length k - * CSUM - */ - n = 0; - if (frame[n] != 2) - { - cdk_free (dek); - return CDK_Inv_Mode; - } - for (n++; n < nframe && frame[n]; n++) - ; - n++; - dek->keylen = nframe - (n + 1) - 2; - dek->algo = frame[n++]; - if (dek->keylen != gcry_cipher_get_algo_keylen (dek->algo)) - { - _cdk_log_debug ("pkcs1 decode: invalid cipher keylen %d\n", - dek->keylen); - cdk_free (dek); - return CDK_Inv_Algo; - } - csum = frame[nframe - 2] << 8; - csum |= frame[nframe - 1]; - memcpy (dek->key, frame + n, dek->keylen); - csum2 = 0; - for (n = 0; n < dek->keylen; n++) - csum2 += dek->key[n]; - if (csum != csum2) - { - _cdk_log_debug ("pkcs decode: checksum does not match\n"); - cdk_free (dek); - return CDK_Chksum_Error; - } - *ret_dek = dek; - return 0; -} - - -/* Encode the given digest into a pkcs#1 compatible format. */ -cdk_error_t -_cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo, - const byte * md, int digest_algo, unsigned nbits) -{ - gcry_error_t err; - size_t dlen; - - if (!md || !r_md || !r_mdlen) - return CDK_Inv_Value; - - dlen = gcry_md_get_algo_dlen (digest_algo); - if (!dlen) - return CDK_Inv_Algo; - if (is_DSA (pk_algo)) /* DSS does not use a special encoding. */ - { - *r_md = cdk_malloc (dlen + 1); - if (!*r_md) - return CDK_Out_Of_Core; - *r_mdlen = dlen; - memcpy (*r_md, md, dlen); - return 0; - } - else - { - byte *asn; - size_t asnlen; - cdk_error_t rc; - - err = gcry_md_get_asnoid (digest_algo, NULL, &asnlen); - if (err) - return map_gcry_error (err); - asn = cdk_malloc (asnlen + 1); - if (!asn) - return CDK_Out_Of_Core; - err = gcry_md_get_asnoid (digest_algo, asn, &asnlen); - if (err) - { - cdk_free (asn); - return map_gcry_error (err); - } - rc = do_encode_md (r_md, r_mdlen, md, digest_algo, dlen, - nbits, asn, asnlen); - cdk_free (asn); - return rc; - } - return 0; -} - - -/* FIXME: The prompt should be provided in a more generic way. - Like: (keyid, algorithm, [user-id]) */ -static char * -passphrase_prompt (cdk_pkt_seckey_t sk) -{ - u32 keyid = cdk_pk_get_keyid (sk->pk, NULL); - int bits = cdk_pk_get_nbits (sk->pk), pk_algo = sk->pubkey_algo; - const char *algo = "???", *fmt; - char *p; - - if (is_RSA (pk_algo)) - algo = "RSA"; - else if (is_ELG (pk_algo)) - algo = "ELG"; - else if (is_DSA (pk_algo)) - algo = "DSA"; - - fmt = "%d-bit %s key, ID %08lX\nEnter Passphrase: "; - p = cdk_calloc (1, 64 + strlen (fmt) + strlen (algo) + 1); - if (!p) - return NULL; - sprintf (p, fmt, bits, algo, keyid); - return p; -} - - -/* Try to unprotect the secret key, if needed, automatically. - The passphrase callback is used to get the passphrase directly - from the user. */ -cdk_error_t -_cdk_sk_unprotect_auto (cdk_ctx_t hd, cdk_pkt_seckey_t sk) -{ - char *pw, *p; - cdk_error_t rc; - - if (!sk->is_protected) - return 0; - - p = passphrase_prompt (sk); - pw = _cdk_passphrase_get (hd, p); - cdk_free (p); - if (!pw) - return CDK_No_Passphrase; - - rc = cdk_sk_unprotect (sk, pw); - - wipemem (pw, strlen (pw)); - cdk_free (pw); - return rc; -} - - -/** - * cdk_dek_extract: - * @ret_dek: the raw DEK object - * @hd: the session handle - * @enc: the public key encrypted packet - * @sk: the secret key. - * - * Try to extract the DEK from the public key encrypted packet. - **/ -cdk_error_t -cdk_dek_extract (cdk_dek_t * ret_dek, cdk_ctx_t hd, - cdk_pkt_pubkey_enc_t enc, cdk_pkt_seckey_t sk) -{ - gcry_mpi_t skey = NULL; - cdk_dek_t dek; - cdk_error_t rc; - - if (!enc || !sk || !ret_dek) - return CDK_Inv_Value; - - /* FIXME: it is not very elegant that we need the session handle here. */ - if (sk->is_protected) - { - rc = _cdk_sk_unprotect_auto (hd, sk); - if (rc) - return rc; - } - - rc = cdk_pk_decrypt (sk, enc, &skey); - if (rc) - return rc; - - rc = cdk_dek_decode_pkcs1 (&dek, skey); - gcry_mpi_release (skey); - if (rc) - { - cdk_dek_free (dek); - dek = NULL; - } - *ret_dek = dek; - return rc; -} - - -/** - * cdk_dek_new: - * @r_dek: the new DEK object - * - * Create a new DEK object. - **/ -cdk_error_t -cdk_dek_new (cdk_dek_t * r_dek) -{ - cdk_dek_t dek; - - if (!r_dek) - return CDK_Inv_Value; - *r_dek = NULL; - dek = cdk_salloc (sizeof *dek, 1); - if (!dek) - return CDK_Out_Of_Core; - *r_dek = dek; - return 0; -} - - -/** - * cdk_dek_set_cipher: - * @dek: the DEK object - * @algo: the cipher algorithm to use - * - * Set the cipher for the given DEK object. - **/ -cdk_error_t -cdk_dek_set_cipher (cdk_dek_t dek, int algo) -{ - if (!dek) - return CDK_Inv_Value; - - if (!algo) - algo = GCRY_CIPHER_AES128; - if (gcry_cipher_test_algo (algo)) - return CDK_Inv_Algo; - dek->algo = algo; - dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); - return 0; -} - -cdk_error_t -cdk_dek_get_cipher (cdk_dek_t dek, int *r_algo) -{ - if (!dek || !r_algo) - return CDK_Inv_Value; - - - *r_algo = dek->algo; - return 0; -} - - -/** - * cdk_dek_set_key: - * @dek: the DEK object - * @key: the random session key - * @keylen: the length of the session key. - * - * Set the random session key for the given DEK object. - * If @key and @keylen is NULL (0) a random key will be generated. - * In any case, cdk_dek_set_cipher must be called first. - **/ -cdk_error_t -cdk_dek_set_key (cdk_dek_t dek, const byte * key, size_t keylen) -{ - gcry_cipher_hd_t hd; - size_t i; - - if (!dek) - return CDK_Inv_Value; - - /* The given key must be compatible with the symmetric - cipher algorithm set before. */ - if (keylen > 0 && keylen != dek->keylen) - return CDK_Inv_Mode; - - if (!key && !keylen) - { - gcry_error_t err; - - /* Used to generate a random session key. The extra code is used - to detect weak keys, if they are possible at all. */ - err = gcry_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, - GCRY_CIPHER_ENABLE_SYNC); - if (err) - return map_gcry_error (err); - gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM); - for (i = 0; i < 8; i++) - { - if (!gcry_cipher_setkey (hd, dek->key, dek->keylen)) - { - gcry_cipher_close (hd); - return 0; - } - gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM); - } - gcry_cipher_close (hd); - return CDK_Weak_Key; - } - - memcpy (dek->key, key, dek->keylen); - return 0; -} - - -/** - * cdk_dek_set_mdc_flag: - * @dek: the DEK object - * @val: value to enable or disable the use - * - * Enable or disable the MDC flag for the given DEK object. - **/ -void -cdk_dek_set_mdc_flag (cdk_dek_t dek, int val) -{ - if (dek) - dek->use_mdc = val; -} - - -int -cdk_dek_get_mdc_flag (cdk_dek_t dek) -{ - if (!dek) - return 0; - return dek->use_mdc; -} - - -/** - * cdk_dek_free: - * @dek: the DEK object - * - * Release the DEK object. - **/ -void -cdk_dek_free (cdk_dek_t dek) -{ - if (!dek) - return; - - /* Make sure sentensive data is overwritten. */ - wipemem (dek->key, sizeof (dek->key)); - cdk_free (dek); -} - - -/* Hash the passphrase to produce the a DEK. - If create is set, a random salt will be generated. */ -static cdk_error_t -hash_passphrase (cdk_dek_t dek, const char *pw, cdk_s2k_t s2k, int create) -{ - gcry_md_hd_t md; - byte zero[1] = { 0x00 }; - int pass, i; - int used = 0, pwlen; - gcry_error_t err; - - if (!dek || !pw || !s2k) - return CDK_Inv_Value; - - if (!s2k->hash_algo) - s2k->hash_algo = GCRY_MD_SHA1; - pwlen = strlen (pw); - - dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); - err = gcry_md_open (&md, s2k->hash_algo, 0); - if (err) - return map_gcry_error (err); - - for (pass = 0; used < dek->keylen; pass++) - { - if (pass) - { - gcry_md_reset (md); - for (i = 0; i < pass; i++) /* preset the hash context */ - gcry_md_write (md, zero, 1); - } - if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) - { - int len2 = pwlen + 8; - u32 count = len2; - if (create && !pass) - { - gcry_randomize (s2k->salt, 8, GCRY_STRONG_RANDOM); - if (s2k->mode == 3) - s2k->count = 96; /* 65536 iterations */ - } - if (s2k->mode == 3) - { - count = (16ul + (s2k->count & 15)) << ((s2k->count >> 4) + 6); - if (count < len2) - count = len2; - } - /* a little bit complicated because we need a ulong for count */ - while (count > len2) - { /* maybe iterated+salted */ - gcry_md_write (md, s2k->salt, 8); - gcry_md_write (md, pw, pwlen); - count -= len2; - } - if (count < 8) - gcry_md_write (md, s2k->salt, count); - else - { - gcry_md_write (md, s2k->salt, 8); - count -= 8; - gcry_md_write (md, pw, count); - } - } - else - gcry_md_write (md, pw, pwlen); - gcry_md_final (md); - i = gcry_md_get_algo_dlen (s2k->hash_algo); - if (i > dek->keylen - used) - i = dek->keylen - used; - memcpy (dek->key + used, gcry_md_read (md, s2k->hash_algo), i); - used += i; - } - gcry_md_close (md); - return 0; -} - - -/** - * cdk_dek_from_passphrase: - * @ret_dek: the new DEK. - * @cipher_algo: symmetric key algorithm to use - * @s2k: the S2K to use - * @rndsalt: 1=create random salt - * @pw: the passphrase. - * - * Transform a passphrase into a DEK object. - */ -cdk_error_t -cdk_dek_from_passphrase (cdk_dek_t * ret_dek, int cipher_algo, cdk_s2k_t s2k, - int rndsalt, const char *pw) -{ - cdk_dek_t dek; - cdk_error_t rc; - - if (!ret_dek) - return CDK_Inv_Value; - - *ret_dek = NULL; - rc = cdk_dek_new (&dek); - if (rc) - return rc; - rc = cdk_dek_set_cipher (dek, cipher_algo); - if (!rc) - rc = hash_passphrase (dek, pw, s2k, rndsalt); - if (rc) - { - cdk_dek_free (dek); - return rc; - } - - *ret_dek = dek; - return 0; -} - - -/** - * cdk_s2k_new: - * @ret_s2k: output for the new S2K object - * @mode: the S2K mode (simple, salted, iter+salted) - * @digest_algo: the hash algorithm - * @salt: random salt - * - * Create a new S2K object with the given parameter. - * The @salt parameter must be always 8 octets. - **/ -cdk_error_t -cdk_s2k_new (cdk_s2k_t * ret_s2k, int mode, int digest_algo, - const byte * salt) -{ - cdk_s2k_t s2k; - - if (!ret_s2k) - return CDK_Inv_Value; - - if (mode != 0x00 && mode != 0x01 && mode != 0x03) - return CDK_Inv_Mode; - - if (gcry_md_test_algo (digest_algo)) - return CDK_Inv_Algo; - - s2k = cdk_calloc (1, sizeof *s2k); - if (!s2k) - return CDK_Out_Of_Core; - s2k->mode = mode; - s2k->hash_algo = digest_algo; - if (salt) - memcpy (s2k->salt, salt, 8); - *ret_s2k = s2k; - return 0; -} - - -/** - * cdk_s2k_free: - * @s2k: the S2K object - * - * Release the given S2K object. - **/ -void -cdk_s2k_free (cdk_s2k_t s2k) -{ - cdk_free (s2k); -} - - -/* Make a copy of the source s2k into R_DST. */ -cdk_error_t -_cdk_s2k_copy (cdk_s2k_t * r_dst, cdk_s2k_t src) -{ - cdk_s2k_t dst; - cdk_error_t err; - - err = cdk_s2k_new (&dst, src->mode, src->hash_algo, src->salt); - if (err) - return err; - dst->count = src->count; - *r_dst = dst; - - return 0; -} diff --git a/src/daemon/https/opencdk/sig-check.c b/src/daemon/https/opencdk/sig-check.c @@ -1,489 +0,0 @@ -/* sig-check.c - Check signatures - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * Copyright (C) 1998-2002 Free Software Foundation, Inc. - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <time.h> -#include <gcrypt.h> -#include <assert.h> - -#include "opencdk.h" -#include "main.h" -#include "packet.h" - - -/* Hash all multi precision integers of the key PK with the given - message digest context MD. */ -static int -hash_mpibuf (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr) -{ - byte buf[MAX_MPI_BYTES]; /* FIXME: do not use hardcoded length. */ - size_t nbytes; - size_t i, npkey; - gcry_error_t err; - - /* We have to differ between two modes for v3 keys. To form the - fingerprint, we hash the MPI values without the length prefix. - But if we calculate the hash for verifying/signing we use all data. */ - npkey = cdk_pk_get_npkey (pk->pubkey_algo); - for (i = 0; i < npkey; i++) - { - err = gcry_mpi_print (GCRYMPI_FMT_PGP, buf, MAX_MPI_BYTES, - &nbytes, pk->mpi[i]); - if (err) - return map_gcry_error (err); - if (!usefpr || pk->version == 4) - gcry_md_write (md, buf, nbytes); - else /* without the prefix. */ - gcry_md_write (md, buf + 2, nbytes - 2); - } - return 0; -} - - -/* Hash an entire public key PK with the given message digest context - MD. The @usefpr param is only valid for version 3 keys because of - the different way to calculate the fingerprint. */ -cdk_error_t -_cdk_hash_pubkey (cdk_pubkey_t pk, gcry_md_hd_t md, int usefpr) -{ - byte buf[12]; - size_t i, n, npkey; - - if (!pk || !md) - return CDK_Inv_Value; - - if (usefpr && pk->version < 4 && is_RSA (pk->pubkey_algo)) - return hash_mpibuf (pk, md, 1); - - /* The version 4 public key packet does not have the 2 octets for - the expiration date. */ - n = pk->version < 4 ? 8 : 6; - npkey = cdk_pk_get_npkey (pk->pubkey_algo); - for (i = 0; i < npkey; i++) - n = n + (gcry_mpi_get_nbits (pk->mpi[i]) + 7) / 8 + 2; - - i = 0; - buf[i++] = 0x99; - buf[i++] = n >> 8; - buf[i++] = n >> 0; - buf[i++] = pk->version; - buf[i++] = pk->timestamp >> 24; - buf[i++] = pk->timestamp >> 16; - buf[i++] = pk->timestamp >> 8; - buf[i++] = pk->timestamp >> 0; - - if (pk->version < 4) - { - u16 a = 0; - - /* Convert the expiration date into days. */ - if (pk->expiredate) - a = (u16) ((pk->expiredate - pk->timestamp) / 86400L); - buf[i++] = a >> 8; - buf[i++] = a; - } - buf[i++] = pk->pubkey_algo; - gcry_md_write (md, buf, i); - return hash_mpibuf (pk, md, 0); -} - - -/* Hash the user ID @uid with the given message digest @md. - Use openpgp mode if @is_v4 is 1. */ -cdk_error_t -_cdk_hash_userid (cdk_pkt_userid_t uid, int is_v4, gcry_md_hd_t md) -{ - const byte *data; - byte buf[5]; - u32 dlen; - - if (!uid || !md) - return CDK_Inv_Value; - - if (!is_v4) - { - gcry_md_write (md, (byte *) uid->name, uid->len); - return 0; - } - - dlen = uid->attrib_img ? uid->attrib_len : uid->len; - data = uid->attrib_img ? uid->attrib_img : (byte *) uid->name; - buf[0] = uid->attrib_img ? 0xD1 : 0xB4; - buf[1] = dlen >> 24; - buf[2] = dlen >> 16; - buf[3] = dlen >> 8; - buf[4] = dlen >> 0; - gcry_md_write (md, buf, 5); - gcry_md_write (md, data, dlen); - return 0; -} - - -/* Hash all parts of the signature which are needed to derive - the correct message digest to verify the sig. */ -cdk_error_t -_cdk_hash_sig_data (cdk_pkt_signature_t sig, gcry_md_hd_t md) -{ - byte buf[4]; - - if (!sig || !md) - return CDK_Inv_Value; - - if (sig->version == 4) - gcry_md_putc (md, sig->version); - gcry_md_putc (md, sig->sig_class); - if (sig->version < 4) - { - buf[0] = sig->timestamp >> 24; - buf[1] = sig->timestamp >> 16; - buf[2] = sig->timestamp >> 8; - buf[3] = sig->timestamp >> 0; - gcry_md_write (md, buf, 4); - } - else - { - size_t n; - - gcry_md_putc (md, sig->pubkey_algo); - gcry_md_putc (md, sig->digest_algo); - if (sig->hashed != NULL) - { - byte *p = _cdk_subpkt_get_array (sig->hashed, 0, &n); - assert (p != NULL); - buf[0] = n >> 8; - buf[1] = n >> 0; - gcry_md_write (md, buf, 2); - gcry_md_write (md, p, n); - cdk_free (p); - sig->hashed_size = n; - n = sig->hashed_size + 6; - } - else - { - gcry_md_putc (md, 0x00); - gcry_md_putc (md, 0x00); - n = 6; - } - gcry_md_putc (md, sig->version); - gcry_md_putc (md, 0xFF); - buf[0] = n >> 24; - buf[1] = n >> 16; - buf[2] = n >> 8; - buf[3] = n >> 0; - gcry_md_write (md, buf, 4); - } - return 0; -} - - -/* Cache the signature result and store it inside the sig. */ -static void -cache_sig_result (cdk_pkt_signature_t sig, int res) -{ - sig->flags.checked = 0; - sig->flags.valid = 0; - if (res == 0) - { - sig->flags.checked = 1; - sig->flags.valid = 1; - } - else if (res == CDK_Bad_Sig) - { - sig->flags.checked = 1; - sig->flags.valid = 0; - } -} - - -/* Check the given signature @sig with the public key @pk. - Use the digest handle @digest. */ -cdk_error_t -_cdk_sig_check (cdk_pubkey_t pk, cdk_pkt_signature_t sig, - gcry_md_hd_t digest, int *r_expired) -{ - cdk_error_t rc; - byte md[MAX_DIGEST_LEN]; - time_t cur_time = (u32) time (NULL); - - if (!pk || !sig || !digest) - return CDK_Inv_Value; - - if (sig->flags.checked) - return sig->flags.valid ? 0 : CDK_Bad_Sig; - if (!KEY_CAN_SIGN (pk->pubkey_algo)) - return CDK_Inv_Algo; - if (pk->timestamp > sig->timestamp || pk->timestamp > cur_time) - return CDK_Time_Conflict; - - if (r_expired && pk->expiredate - && (pk->expiredate + pk->timestamp) > cur_time) - *r_expired = 1; - - _cdk_hash_sig_data (sig, digest); - gcry_md_final (digest); - memcpy (md, gcry_md_read (digest, sig->digest_algo), - gcry_md_get_algo_dlen (sig->digest_algo)); - - if (md[0] != sig->digest_start[0] || md[1] != sig->digest_start[1]) - return CDK_Chksum_Error; - - rc = cdk_pk_verify (pk, sig, md); - cache_sig_result (sig, rc); - return rc; -} - - -/* Check the given key signature. - @knode is the key node and @snode the signature node. */ -cdk_error_t -_cdk_pk_check_sig (cdk_keydb_hd_t keydb, - cdk_kbnode_t knode, cdk_kbnode_t snode, int *is_selfsig) -{ - gcry_md_hd_t md; - gcry_error_t err; - cdk_pubkey_t pk; - cdk_pkt_signature_t sig; - cdk_kbnode_t node; - cdk_error_t rc = 0; - int is_expired; - - if (!knode || !snode) - return CDK_Inv_Value; - - if (is_selfsig) - *is_selfsig = 0; - if (knode->pkt->pkttype != CDK_PKT_PUBLIC_KEY || - snode->pkt->pkttype != CDK_PKT_SIGNATURE) - return CDK_Inv_Value; - pk = knode->pkt->pkt.public_key; - sig = snode->pkt->pkt.signature; - - err = gcry_md_open (&md, sig->digest_algo, 0); - if (err) - return map_gcry_error (err); - - is_expired = 0; - if (sig->sig_class == 0x20) - { /* key revocation */ - cdk_kbnode_hash (knode, md, 0, 0, 0); - rc = _cdk_sig_check (pk, sig, md, &is_expired); - } - else if (sig->sig_class == 0x28) - { /* subkey revocation */ - node = cdk_kbnode_find_prev (knode, snode, CDK_PKT_PUBLIC_SUBKEY); - if (!node) - { /* no subkey for subkey revocation packet */ - rc = CDK_Error_No_Key; - goto fail; - } - cdk_kbnode_hash (knode, md, 0, 0, 0); - cdk_kbnode_hash (node, md, 0, 0, 0); - rc = _cdk_sig_check (pk, sig, md, &is_expired); - } - else if (sig->sig_class == 0x18 || sig->sig_class == 0x19) - { /* primary/secondary key binding */ - node = cdk_kbnode_find_prev (knode, snode, CDK_PKT_PUBLIC_SUBKEY); - if (!node) - { /* no subkey for subkey binding packet */ - rc = CDK_Error_No_Key; - goto fail; - } - cdk_kbnode_hash (knode, md, 0, 0, 0); - cdk_kbnode_hash (node, md, 0, 0, 0); - rc = _cdk_sig_check (pk, sig, md, &is_expired); - } - else if (sig->sig_class == 0x1F) - { /* direct key signature */ - cdk_kbnode_hash (knode, md, 0, 0, 0); - rc = _cdk_sig_check (pk, sig, md, &is_expired); - } - else - { /* all other classes */ - node = cdk_kbnode_find_prev (knode, snode, CDK_PKT_USER_ID); - if (!node) - { /* no user ID for key signature packet */ - rc = CDK_Error_No_Key; - goto fail; - } - cdk_kbnode_hash (knode, md, 0, 0, 0); - cdk_kbnode_hash (node, md, sig->version == 4, 0, 0); - if (pk->keyid[0] == sig->keyid[0] && pk->keyid[1] == sig->keyid[1]) - { - rc = _cdk_sig_check (pk, sig, md, &is_expired); - if (is_selfsig) - *is_selfsig = 1; - } - else if (keydb != NULL) - { - cdk_pubkey_t sig_pk; - - rc = cdk_keydb_get_pk (keydb, sig->keyid, &sig_pk); - if (!rc) - rc = _cdk_sig_check (sig_pk, sig, md, &is_expired); - cdk_pk_release (sig_pk); - } - } -fail: - gcry_md_close (md); - return rc; -} - - -/** - * cdk_pk_check_sigs: - * @key: the public key - * @hd: an optinal key database handle - * @r_status: variable to store the status of the key - * - * Check all signatures. When no key is available for checking, the - * sigstat is marked as 'NOKEY'. The @r_status contains the key flags - * which are or-ed or zero when there are no flags. - **/ -cdk_error_t -cdk_pk_check_sigs (cdk_kbnode_t key, cdk_keydb_hd_t keydb, int *r_status) -{ - cdk_pkt_signature_t sig; - cdk_kbnode_t node; - cdk_error_t rc; - u32 keyid; - int key_status, is_selfsig = 0; - int no_signer, n_sigs = 0; - - if (!key || !r_status) - return CDK_Inv_Value; - - *r_status = 0; - node = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY); - if (!node) - return CDK_Error_No_Key; - - key_status = 0; - /* Continue with the signature check but adjust the - key status flags accordingly. */ - if (node->pkt->pkt.public_key->is_revoked) - key_status |= CDK_KEY_REVOKED; - if (node->pkt->pkt.public_key->has_expired) - key_status |= CDK_KEY_EXPIRED; - - rc = 0; - no_signer = 0; - keyid = cdk_pk_get_keyid (node->pkt->pkt.public_key, NULL); - for (node = key; node; node = node->next) - { - if (node->pkt->pkttype != CDK_PKT_SIGNATURE) - continue; - sig = node->pkt->pkt.signature; - rc = _cdk_pk_check_sig (keydb, key, node, &is_selfsig); - if (IS_UID_SIG (sig)) - { - if (is_selfsig == 0) - n_sigs++; - } - if (rc && IS_UID_SIG (sig) && rc == CDK_Error_No_Key) - { - /* We do not consider it a problem when the signing key - is not avaiable. We just mark the signature accordingly - and contine. */ - sig->flags.missing_key = 1; - no_signer++; - } - else if (rc && rc != CDK_Error_No_Key) - { - /* It might be possible that a single signature has been - corrupted, thus we do not consider it a problem when - one ore more signatures are bad. But at least the self - signature has to be valid. */ - if (is_selfsig) - { - key_status |= CDK_KEY_INVALID; - break; - } - } - _cdk_log_debug ("signature %s: signer %08lX keyid %08lX\n", - rc == CDK_Bad_Sig ? "BAD" : "good", sig->keyid[1], - keyid); - } - - if (n_sigs == no_signer) - key_status |= CDK_KEY_NOSIGNER; - *r_status = key_status; - if (rc == CDK_Error_No_Key) - rc = 0; - return rc; -} - - -/** - * cdk_pk_check_self_sig: - * @key: the key node - * @r_status: output the status of the key. - * - * A convenient function to make sure the key is valid. - * Valid means the self signature is ok. - **/ -cdk_error_t -cdk_pk_check_self_sig (cdk_kbnode_t key, int *r_status) -{ - cdk_pkt_signature_t sig; - cdk_kbnode_t node; - cdk_error_t rc; - u32 keyid[2], sigid[2]; - int is_selfsig, sig_ok; - - if (!key || !r_status) - return CDK_Inv_Value; - - node = cdk_kbnode_find (key, CDK_PKT_PUBLIC_KEY); - if (!node) - return CDK_Error_No_Key; - /* FIXME: we should set expire/revoke here also but callers - expect CDK_KEY_VALID=0 if the key is okay. */ - cdk_pk_get_keyid (key->pkt->pkt.public_key, keyid); - sig_ok = 0; - for (node = key; node; node = node->next) - { - if (node->pkt->pkttype != CDK_PKT_SIGNATURE) - continue; - sig = node->pkt->pkt.signature; - if (!IS_UID_SIG (sig)) - continue; - cdk_sig_get_keyid (sig, sigid); - if (sigid[0] != keyid[0] || sigid[1] != keyid[1]) - continue; - /* FIXME: Now we check all self signatures. */ - rc = _cdk_pk_check_sig (NULL, key, node, &is_selfsig); - if (rc) - { - *r_status = CDK_KEY_INVALID; - return rc; - } - else /* For each valid self sig we increase this counter. */ - sig_ok++; - } - - /* A key without a self signature is not valid. */ - if (!sig_ok) - { - *r_status = CDK_KEY_INVALID; - return CDK_General_Error; - } - /* No flags indicate a valid key. */ - *r_status = CDK_KEY_VALID; - return 0; -} diff --git a/src/daemon/https/opencdk/stream.c b/src/daemon/https/opencdk/stream.c @@ -1,1446 +0,0 @@ -/* stream.c - The stream implementation - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <assert.h> -#include <stdio.h> -#include <sys/stat.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif - -#include "opencdk.h" -#include "main.h" -#include "filters.h" -#include "stream.h" -#include "types.h" - -/* This is the maximal amount of bytes we map. */ -#define MAX_MAP_SIZE 16777216 - -static int stream_flush (cdk_stream_t s); -static int stream_filter_write (cdk_stream_t s); -static int stream_cache_flush (cdk_stream_t s, FILE * fp); - -/* Customized tmpfile() version from misc.c */ -FILE *my_tmpfile (void); - - -/* FIXME: The read/write/putc/getc function cannot directly - return an error code. It is stored in an error variable - inside the string. Right now there is no code to - return the error code or to reset it. */ - -/** - * cdk_stream_open: - * @file: The file to open - * @ret_s: The new STREAM object - * - * Create a new stream based on an existing file. The stream is - * opened in read-only mode. - **/ -cdk_error_t -cdk_stream_open (const char *file, cdk_stream_t * ret_s) -{ - return _cdk_stream_open_mode (file, "rb", ret_s); -} - - -/* Helper function to allow to open a stream in different modes. */ -cdk_error_t -_cdk_stream_open_mode (const char *file, const char *mode, - cdk_stream_t * ret_s) -{ - cdk_stream_t s; - - if (!file || !ret_s) - return CDK_Inv_Value; - - _cdk_log_debug ("open stream `%s'\n", file); - *ret_s = NULL; - s = cdk_calloc (1, sizeof *s); - if (!s) - return CDK_Out_Of_Core; - s->fname = cdk_strdup (file); - if (!s->fname) - { - cdk_free (s); - return CDK_Out_Of_Core; - } - s->fp = fopen (file, mode); - if (!s->fp) - { - cdk_free (s->fname); - cdk_free (s); - return CDK_File_Error; - } - _cdk_log_debug ("open stream fd=%d\n", fileno (s->fp)); - s->flags.write = 0; - *ret_s = s; - return 0; -} - - -/** - * cdk_stream_new_from_cbs: - * @cbs: the callback context with all user callback functions - * @opa: opaque handle which is passed to all callbacks. - * @ret_s: the allocated stream - * - * This function creates a stream which uses user callback - * for the core operations (open, close, read, write, seek). - */ -cdk_error_t -cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs, void *opa, - cdk_stream_t * ret_s) -{ - cdk_stream_t s; - - if (!cbs || !opa || !ret_s) - return CDK_Inv_Value; - - *ret_s = NULL; - s = cdk_calloc (1, sizeof *s); - if (!s) - return CDK_Out_Of_Core; - - s->cbs.read = cbs->read; - s->cbs.write = cbs->write; - s->cbs.seek = cbs->seek; - s->cbs.release = cbs->release; - s->cbs.open = cbs->open; - s->cbs_hd = opa; - *ret_s = s; - - /* If there is a user callback for open, we need to call it - here because read/write expects an open stream. */ - if (s->cbs.open) - return s->cbs.open (s->cbs_hd); - return 0; -} - - -/** - * cdk_stream_new: Create a new stream into into the given file. - * @file: The name of the new file - * @ret_s: The new STREAM object - **/ -cdk_error_t -cdk_stream_new (const char *file, cdk_stream_t * ret_s) -{ - cdk_stream_t s; - - if (!ret_s) - return CDK_Inv_Value; - - _cdk_log_debug ("new stream `%s'\n", file ? file : "[temp]"); - *ret_s = NULL; - s = cdk_calloc (1, sizeof *s); - if (!s) - return CDK_Out_Of_Core; - s->flags.write = 1; - if (!file) - s->flags.temp = 1; - else - { - s->fname = cdk_strdup (file); - if (!s->fname) - { - cdk_free (s); - return CDK_Out_Of_Core; - } - } - s->fp = my_tmpfile (); - if (!s->fp) - { - cdk_free (s->fname); - cdk_free (s); - return CDK_File_Error; - } - _cdk_log_debug ("new stream fd=%d\n", fileno (s->fp)); - *ret_s = s; - return 0; -} - - -/** - * cdk_stream_create: create a new stream. - * @file: the filename - * @ret_s: the object - * - * The difference to cdk_stream_new is, that no filtering can be used with - * this kind of stream and everything is written directly to the stream. - **/ -cdk_error_t -cdk_stream_create (const char *file, cdk_stream_t * ret_s) -{ - cdk_stream_t s; - - if (!file || !ret_s) - return CDK_Inv_Value; - - _cdk_log_debug ("create stream `%s'\n", file); - *ret_s = NULL; - s = cdk_calloc (1, sizeof *s); - if (!s) - return CDK_Out_Of_Core; - s->flags.write = 1; - s->flags.filtrated = 1; - s->fname = cdk_strdup (file); - if (!s->fname) - { - cdk_free (s); - return CDK_Out_Of_Core; - } - s->fp = fopen (file, "w+b"); - if (!s->fp) - { - cdk_free (s->fname); - cdk_free (s); - return CDK_File_Error; - } - _cdk_log_debug ("stream create fd=%d\n", fileno (s->fp)); - *ret_s = s; - return 0; -} - - -/** - * cdk_stream_tmp_new: - * @r_out: the new temp stream. - * - * Allocate a new tempory stream which is not associated with a file. - */ -cdk_error_t -cdk_stream_tmp_new (cdk_stream_t * r_out) -{ - return cdk_stream_new (NULL, r_out); -} - - - -/** - * cdk_stream_tmp_from_mem: - * @buf: the buffer which shall be written to the temp stream. - * @buflen: how large the buffer is - * @r_out: the new stream with the given contents. - * - * Create a new tempory stream with the given contests. - */ -cdk_error_t -cdk_stream_tmp_from_mem (const void *buf, size_t buflen, cdk_stream_t * r_out) -{ - cdk_stream_t s; - cdk_error_t rc; - int nwritten; - - *r_out = NULL; - rc = cdk_stream_tmp_new (&s); - if (rc) - return rc; - - nwritten = cdk_stream_write (s, buf, buflen); - if (nwritten == EOF) - { - cdk_stream_close (s); - return s->error; - } - cdk_stream_seek (s, 0); - *r_out = s; - return 0; -} - - -cdk_error_t -_cdk_stream_fpopen (FILE * fp, unsigned write_mode, cdk_stream_t * ret_out) -{ - cdk_stream_t s; - - *ret_out = NULL; - s = cdk_calloc (1, sizeof *s); - if (!s) - return CDK_Out_Of_Core; - - _cdk_log_debug ("stream ref fd=%d\n", fileno (fp)); - s->fp = fp; - s->fp_ref = 1; - s->flags.filtrated = 1; - s->flags.write = write_mode; - - *ret_out = s; - return 0; -} - - -cdk_error_t -_cdk_stream_append (const char *file, cdk_stream_t * ret_s) -{ - cdk_stream_t s; - cdk_error_t rc; - - if (!ret_s) - return CDK_Inv_Value; - *ret_s = NULL; - - rc = _cdk_stream_open_mode (file, "a+b", &s); - if (rc) - return rc; - - /* In the append mode, we need to write to the flag. */ - s->flags.write = 1; - *ret_s = s; - return 0; -} - - -/** - * cdk_stream_is_compressed: - * @s: the stream - * - * Return 0 if the stream is uncompressed, otherwise the - * compression algorithm. - */ -int -cdk_stream_is_compressed (cdk_stream_t s) -{ - if (!s) - return 0; - return s->flags.compressed; -} - -void -_cdk_stream_set_compress_algo (cdk_stream_t s, int algo) -{ - if (!s) - return; - s->flags.compressed = algo; -} - - -cdk_error_t -cdk_stream_flush (cdk_stream_t s) -{ - cdk_error_t rc; - - if (!s) - return CDK_Inv_Value; - - /* The user callback does not support flush */ - if (s->cbs_hd) - return 0; - - /* For read-only streams, no flush is needed. */ - if (!s->flags.write) - return 0; - - if (!s->flags.filtrated) - { - if (!cdk_stream_get_length (s)) - return 0; - rc = cdk_stream_seek (s, 0); - if (!rc) - rc = stream_flush (s); - if (!rc) - rc = stream_filter_write (s); - s->flags.filtrated = 1; - if (rc) - { - s->error = rc; - return rc; - } - } - return 0; -} - - -void -cdk_stream_tmp_set_mode (cdk_stream_t s, int val) -{ - if (s && s->flags.temp) - s->fmode = val; -} - - -/** - * cdk_stream_close: Close a stream and flush all buffers. - * @s: The STREAM object. - * - * This function work different for read or write streams. When the - * stream is for reading, the filtering is already done and we can - * simply close the file and all buffers. - * But for the case it's a write stream, we need to apply all registered - * filters now. The file is closed in the filter function and not here. - **/ -cdk_error_t -cdk_stream_close (cdk_stream_t s) -{ - struct stream_filter_s *f, *f2; - cdk_error_t rc; - - if (!s) - return CDK_Inv_Value; - - _cdk_log_debug ("close stream ref=%d `%s'\n", - s->fp_ref, s->fname ? s->fname : "[temp]"); - - /* In the user callback mode, we call the release cb if possible - and just free the stream. */ - if (s->cbs_hd) - { - if (s->cbs.release) - rc = s->cbs.release (s->cbs_hd); - else - rc = 0; - cdk_free (s); - return rc; - } - - - rc = 0; - if (!s->flags.filtrated && !s->error) - rc = cdk_stream_flush (s); - if (!s->fp_ref && (s->fname || s->flags.temp)) - { - int err; - - _cdk_log_debug ("close stream fd=%d\n", fileno (s->fp)); - err = fclose (s->fp); - s->fp = NULL; - if (err) - rc = CDK_File_Error; - } - - /* Iterate over the filter list and use the cleanup flag to - free the allocated internal structures. */ - f = s->filters; - while (f) - { - f2 = f->next; - if (f->fnct) - f->fnct (f->opaque, STREAMCTL_FREE, NULL, NULL); - cdk_free (f); - f = f2; - } - - if (s->fname) - { - cdk_free (s->fname); - s->fname = NULL; - } - - cdk_free (s->cache.buf); - s->cache.alloced = 0; - - cdk_free (s); - return rc; -} - - -/** - * cdk_stream_eof: Return if the associated file handle was set to EOF. - * @s: The STREAM object. - * - * This function will only work with read streams. - **/ -int -cdk_stream_eof (cdk_stream_t s) -{ - return s ? s->flags.eof : -1; -} - - -const char * -_cdk_stream_get_fname (cdk_stream_t s) -{ - if (!s) - return NULL; - if (s->flags.temp) - return NULL; - return s->fname ? s->fname : NULL; -} - - -/* Return the underlying FP of the stream. - WARNING: This handle should not be closed. */ -FILE * -_cdk_stream_get_fp (cdk_stream_t s) -{ - return s ? s->fp : NULL; -} - - -int -_cdk_stream_get_errno (cdk_stream_t s) -{ - return s ? s->error : CDK_Inv_Value; -} - - -/** - * cdk_stream_get_length: Return the length of the associated file handle. - * @s: The STREAM object. - * - * This function should work for both read and write streams. For write - * streams an additional flush is used to write possible pending data. - **/ -off_t -cdk_stream_get_length (cdk_stream_t s) -{ - struct stat statbuf; - cdk_error_t rc; - - if (!s) - return (off_t) - 1; - - /* The user callback does not support stat. */ - if (s->cbs_hd) - return 0; - - rc = stream_flush (s); - if (rc) - { - s->error = rc; - return (off_t) - 1; - } - - if (fstat (fileno (s->fp), &statbuf)) - { - s->error = CDK_File_Error; - return (off_t) - 1; - } - - return statbuf.st_size; -} - - -static struct stream_filter_s * -filter_add2 (cdk_stream_t s) -{ - struct stream_filter_s *f; - - assert (s); - - f = cdk_calloc (1, sizeof *f); - if (!f) - return NULL; - f->next = s->filters; - s->filters = f; - return f; -} - - -static struct stream_filter_s * -filter_search (cdk_stream_t s, filter_fnct_t fnc) -{ - struct stream_filter_s *f; - - assert (s); - - for (f = s->filters; f; f = f->next) - { - if (f->fnct == fnc) - return f; - } - - return NULL; -} - - -struct stream_filter_s * -filter_add (cdk_stream_t s, filter_fnct_t fnc, int type) -{ - struct stream_filter_s *f; - - assert (s); - - s->flags.filtrated = 0; - f = filter_search (s, fnc); - if (f) - return f; - f = filter_add2 (s); - if (!f) - return NULL; - f->fnct = fnc; - f->flags.enabled = 1; - f->tmp = NULL; - f->type = type; - switch (type) - { - case fARMOR: - f->opaque = &f->u.afx; - break; - case fCIPHER: - f->opaque = &f->u.cfx; - break; - case fLITERAL: - f->opaque = &f->u.pfx; - break; - case fCOMPRESS: - f->opaque = &f->u.zfx; - break; - case fHASH: - f->opaque = &f->u.mfx; - break; - case fTEXT: - f->opaque = &f->u.tfx; - break; - default: - f->opaque = NULL; - } - - return f; -} - - -static int -stream_get_mode (cdk_stream_t s) -{ - assert (s); - - if (s->flags.temp) - return s->fmode; - return s->flags.write; -} - - -static filter_fnct_t -stream_id_to_filter (int type) -{ - switch (type) - { - case fARMOR: - return _cdk_filter_armor; - case fLITERAL: - return _cdk_filter_literal; - case fTEXT: - return _cdk_filter_text; - case fCIPHER: - return _cdk_filter_cipher; - case fCOMPRESS: - return _cdk_filter_compress; - default: - return NULL; - } -} - - -/** - * cdk_stream_filter_disable: Disable the filter with the type 'type' - * @s: The STREAM object - * @type: The numberic filter ID. - * - **/ -cdk_error_t -cdk_stream_filter_disable (cdk_stream_t s, int type) -{ - struct stream_filter_s *f; - filter_fnct_t fnc; - - if (!s) - return CDK_Inv_Value; - - fnc = stream_id_to_filter (type); - if (!fnc) - return CDK_Inv_Value; - f = filter_search (s, fnc); - if (f) - f->flags.enabled = 0; - return 0; -} - - -/* WARNING: tmp should not be closed by the caller. */ -static cdk_error_t -stream_fp_replace (cdk_stream_t s, FILE ** tmp) -{ - int rc; - - assert (s); - - _cdk_log_debug ("replace stream fd=%d with fd=%d\n", - fileno (s->fp), fileno (*tmp)); - rc = fclose (s->fp); - if (rc) - return CDK_File_Error; - s->fp = *tmp; - *tmp = NULL; - return 0; -} - - -/* This function is exactly like filter_read, except the fact that we can't - use tmpfile () all the time. That's why we open the real file when there - is no last filter. */ -static cdk_error_t -stream_filter_write (cdk_stream_t s) -{ - struct stream_filter_s *f; - cdk_error_t rc = 0; - - assert (s); - - if (s->flags.filtrated) - return CDK_Inv_Value; - - for (f = s->filters; f; f = f->next) - { - if (!f->flags.enabled) - continue; - /* if there is no next filter, create the final output file */ - _cdk_log_debug ("filter [write]: last filter=%d fname=%s\n", - f->next ? 1 : 0, s->fname); - if (!f->next && s->fname) - f->tmp = fopen (s->fname, "w+b"); - else - f->tmp = my_tmpfile (); - if (!f->tmp) - { - rc = CDK_File_Error; - break; - } - /* If there is no next filter, flush the cache. We also do this - when the next filter is the armor filter because this filter - is special and before it starts, all data should be written. */ - if ((!f->next || f->next->type == fARMOR) && s->cache.size) - { - rc = stream_cache_flush (s, f->tmp); - if (rc) - break; - } - rc = f->fnct (f->opaque, f->ctl, s->fp, f->tmp); - _cdk_log_debug ("filter [write]: type=%d rc=%d\n", f->type, rc); - if (!rc) - rc = stream_fp_replace (s, &f->tmp); - if (!rc) - rc = cdk_stream_seek (s, 0); - if (rc) - { - _cdk_log_debug ("filter [close]: fd=%d\n", fileno (f->tmp)); - fclose (f->tmp); - break; - } - } - return rc; -} - - -/* Here all data from the file handle is passed through all filters. - The scheme works like this: - Create a tempfile and use it for the output of the filter. Then the - original file handle will be closed and replace with the temp handle. - The file pointer will be set to the begin and the game starts again. */ -static cdk_error_t -stream_filter_read (cdk_stream_t s) -{ - struct stream_filter_s *f; - cdk_error_t rc = 0; - - assert (s); - - if (s->flags.filtrated) - return 0; - - for (f = s->filters; f; f = f->next) - { - if (!f->flags.enabled) - continue; - if (f->flags.error) - { - _cdk_log_debug ("filter %s [read]: has the error flag; skipped\n", - s->fname ? s->fname : "[temp]"); - continue; - } - - f->tmp = my_tmpfile (); - if (!f->tmp) - { - rc = CDK_File_Error; - break; - } - rc = f->fnct (f->opaque, f->ctl, s->fp, f->tmp); - _cdk_log_debug ("filter %s [read]: type=%d rc=%d\n", - s->fname ? s->fname : "[temp]", f->type, rc); - if (rc) - { - f->flags.error = 1; - break; - } - - f->flags.error = 0; - /* If the filter is read-only, do not replace the FP because - the contents were not altered in any way. */ - if (!f->flags.rdonly) - { - rc = stream_fp_replace (s, &f->tmp); - if (rc) - break; - } - else - { - fclose (f->tmp); - f->tmp = NULL; - } - rc = cdk_stream_seek (s, 0); - if (rc) - break; - /* Disable the filter after it was successfully used. The idea - is the following: let's say the armor filter was pushed and - later more filters were added. The second time the filter code - will be executed, only the new filter should be started but - not the old because we already used it. */ - f->flags.enabled = 0; - } - - return rc; -} - - -void * -_cdk_stream_get_opaque (cdk_stream_t s, int fid) -{ - struct stream_filter_s *f; - - if (!s) - return NULL; - - for (f = s->filters; f; f = f->next) - { - if (f->type == fid) - return f->opaque; - } - return NULL; -} - - -/** - * cdk_stream_read: Try to read count bytes from the STREAM object. - * @s: The STREAM object. - * @buf: The buffer to insert the readed bytes. - * @count: Request so much bytes. - * - * When this function is called the first time, it can take a while - * because all filters need to be processed. Please remember that you - * need to add the filters in reserved order. - **/ -int -cdk_stream_read (cdk_stream_t s, void *buf, size_t buflen) -{ - int nread; - int rc; - - if (!s) - { - s->error = CDK_Inv_Value; - return EOF; - } - - if (s->cbs_hd) - { - if (s->cbs.read) - return s->cbs.read (s->cbs_hd, buf, buflen); - return 0; - } - - if (s->flags.write && !s->flags.temp) - { - s->error = CDK_Inv_Mode; - return EOF; /* This is a write stream */ - } - - if (!s->flags.no_filter && !s->cache.on && !s->flags.filtrated) - { - rc = stream_filter_read (s); - if (rc) - { - s->error = rc; - if (feof (s->fp)) - s->flags.eof = 1; - return EOF; - } - s->flags.filtrated = 1; - } - if (!buf && !buflen) - return 0; - nread = fread (buf, 1, buflen, s->fp); - if (!nread) - nread = EOF; - if (feof (s->fp)) - { - s->error = 0; - s->flags.eof = 1; - } - return nread; -} - - -int -cdk_stream_getc (cdk_stream_t s) -{ - unsigned char buf[2]; - int nread; - - if (!s) - { - s->error = CDK_Inv_Value; - return EOF; - } - nread = cdk_stream_read (s, buf, 1); - if (nread == EOF) - { - s->error = CDK_File_Error; - return EOF; - } - return buf[0]; -} - - -/** - * cdk_stream_write: Try to write count bytes into the stream. - * @s: The STREAM object - * @buf: The buffer with the values to write. - * @count: The size of the buffer. - * - * In this function we simply write the bytes to the stream. We can't - * use the filters here because it would mean they have to support - * partial flushing. - **/ -int -cdk_stream_write (cdk_stream_t s, const void *buf, size_t count) -{ - int nwritten; - - if (!s) - { - s->error = CDK_Inv_Value; - return EOF; - } - - if (s->cbs_hd) - { - if (s->cbs.write) - return s->cbs.write (s->cbs_hd, buf, count); - return 0; - } - - if (!s->flags.write) - { - s->error = CDK_Inv_Mode; /* this is a read stream */ - return EOF; - } - - if (!buf && !count) - return stream_flush (s); - - if (s->cache.on) - { - /* We need to resize the buffer if the additional data wouldn't - fit into it. We allocate more memory to avoid to resize it the - next time the function is used. */ - if (s->cache.size + count > s->cache.alloced) - { - byte *old = s->cache.buf; - - s->cache.buf = - cdk_calloc (1, s->cache.alloced + count + STREAM_BUFSIZE); - s->cache.alloced += (count + STREAM_BUFSIZE); - memcpy (s->cache.buf, old, s->cache.size); - cdk_free (old); - _cdk_log_debug ("stream: enlarge cache to %d octets\n", - s->cache.alloced); - } - memcpy (s->cache.buf + s->cache.size, buf, count); - s->cache.size += count; - return count; - } - - nwritten = fwrite (buf, 1, count, s->fp); - if (!nwritten) - nwritten = EOF; - return nwritten; -} - - -int -cdk_stream_putc (cdk_stream_t s, int c) -{ - byte buf[2]; - int nwritten; - - if (!s) - { - s->error = CDK_Inv_Value; - return EOF; - } - buf[0] = c; - nwritten = cdk_stream_write (s, buf, 1); - if (nwritten == EOF) - return EOF; - return 0; -} - - -off_t -cdk_stream_tell (cdk_stream_t s) -{ - return s ? ftell (s->fp) : (off_t) - 1; -} - - -cdk_error_t -cdk_stream_seek (cdk_stream_t s, off_t offset) -{ - off_t len; - - if (!s) - return CDK_Inv_Value; - - if (s->cbs_hd) - { - if (s->cbs.seek) - return s->cbs.seek (s->cbs_hd, offset); - return 0; - } - - /* Set or reset the EOF flag. */ - len = cdk_stream_get_length (s); - if (len == offset) - s->flags.eof = 1; - else - s->flags.eof = 0; - - if (fseek (s->fp, offset, SEEK_SET)) - return CDK_File_Error; - return 0; -} - - -static cdk_error_t -stream_flush (cdk_stream_t s) -{ - assert (s); - - /* For some constellations it cannot be assured that the - return value is defined, thus we ignore it for now. */ - (void) fflush (s->fp); - return 0; -} - - -/** - * cdk_stream_set_armor_flag: - * @s: the stream object - * @type: the type of armor to use - * - * If the file is in read-mode, no armor type needs to be - * defined (armor_type=0) because the armor filter will be - * used for decoding existing armor data. - * For the write mode, @armor_type can be set to any valid - * armor type (message, key, sig). - **/ -cdk_error_t -cdk_stream_set_armor_flag (cdk_stream_t s, int armor_type) -{ - struct stream_filter_s *f; - - if (!s) - return CDK_Inv_Value; - f = filter_add (s, _cdk_filter_armor, fARMOR); - if (!f) - return CDK_Out_Of_Core; - f->u.afx.idx = f->u.afx.idx2 = armor_type; - f->ctl = stream_get_mode (s); - return 0; -} - - -/** - * cdk_stream_set_literal_flag: - * @s: the stream object - * @mode: the mode to use (binary, text, unicode) - * @fname: the file name to store in the packet. - * - * In read mode it kicks off the literal decoding routine to - * unwrap the data from the packet. The @mode parameter is ignored. - * In write mode the function can be used to wrap the stream data - * into a literal packet with the given mode and file name. - **/ -cdk_error_t -cdk_stream_set_literal_flag (cdk_stream_t s, cdk_lit_format_t mode, - const char *fname) -{ - struct stream_filter_s *f; - const char *orig_fname; - - _cdk_log_debug ("stream: enable literal mode.\n"); - - if (!s) - return CDK_Inv_Value; - - orig_fname = _cdk_stream_get_fname (s); - f = filter_add (s, _cdk_filter_literal, fLITERAL); - if (!f) - return CDK_Out_Of_Core; - f->u.pfx.mode = mode; - f->u.pfx.filename = fname ? cdk_strdup (fname) : NULL; - f->u.pfx.orig_filename = orig_fname ? cdk_strdup (orig_fname) : NULL; - f->ctl = stream_get_mode (s); - if (s->blkmode > 0) - { - f->u.pfx.blkmode.on = 1; - f->u.pfx.blkmode.size = s->blkmode; - } - return 0; -} - - -/** - * cdk_stream_set_cipher_flag: - * @s: the stream object - * @dek: the data encryption key - * @use_mdc: 1 means to use the MDC mode - * - * In read mode it kicks off the cipher filter to decrypt the data - * from the stream with the key given in @dek. - * In write mode the stream data will be encrypted with the DEK object - * and optionally, the @use_mdc parameter can be used to enable the MDC mode. - **/ -cdk_error_t -cdk_stream_set_cipher_flag (cdk_stream_t s, cdk_dek_t dek, int use_mdc) -{ - struct stream_filter_s *f; - - _cdk_log_debug ("stream: enable cipher mode\n"); - if (!s) - return CDK_Inv_Value; - f = filter_add (s, _cdk_filter_cipher, fCIPHER); - if (!f) - return CDK_Out_Of_Core; - dek->use_mdc = use_mdc; - f->ctl = stream_get_mode (s); - f->u.cfx.dek = dek; - f->u.cfx.mdc_method = use_mdc ? GCRY_MD_SHA1 : 0; - if (s->blkmode > 0) - { - f->u.cfx.blkmode.on = 1; - f->u.cfx.blkmode.size = s->blkmode; - } - return 0; -} - - -/** - * cdk_stream_set_compress_flag: - * @s: the stream object - * @algo: the compression algo - * @level: level of compression (0..9) - * - * In read mode it kicks off the decompression filter to retrieve - * the uncompressed data. - * In write mode the stream data will be compressed with the - * given algorithm at the given level. - **/ -cdk_error_t -cdk_stream_set_compress_flag (cdk_stream_t s, int algo, int level) -{ - struct stream_filter_s *f; - - if (!s) - return CDK_Inv_Value; - f = filter_add (s, _cdk_filter_compress, fCOMPRESS); - if (!f) - return CDK_Out_Of_Core; - f->ctl = stream_get_mode (s); - f->u.zfx.algo = algo; - f->u.zfx.level = level; - return 0; -} - - -/** - * cdk_stream_set_text_flag: - * @s: the stream object - * @lf: line ending - * - * Pushes the text filter to store the stream data in cannoncial format. - **/ -cdk_error_t -cdk_stream_set_text_flag (cdk_stream_t s, const char *lf) -{ - struct stream_filter_s *f; - - if (!s) - return CDK_Inv_Value; - f = filter_add (s, _cdk_filter_text, fTEXT); - if (!f) - return CDK_Out_Of_Core; - f->ctl = stream_get_mode (s); - f->u.tfx.lf = lf; - return 0; -} - - -/** - * cdk_stream_set_hash_flag: - * @s: the stream object - * @digest_algo: the digest algorithm to use - * - * This is for read-only streams. It pushes a digest filter to - * calculate the digest of the given stream data. - **/ -cdk_error_t -cdk_stream_set_hash_flag (cdk_stream_t s, int digest_algo) -{ - struct stream_filter_s *f; - - if (!s) - return CDK_Inv_Value; - if (stream_get_mode (s)) - return CDK_Inv_Mode; - f = filter_add (s, _cdk_filter_hash, fHASH); - if (!f) - return CDK_Out_Of_Core; - f->ctl = stream_get_mode (s); - f->u.mfx.digest_algo = digest_algo; - f->flags.rdonly = 1; - return 0; -} - - -/** - * cdk_stream_enable_cache: - * @s: the stream object - * @val: 1=on, 0=off - * - * Enable or disable the cache section of a stream object. - **/ -cdk_error_t -cdk_stream_enable_cache (cdk_stream_t s, int val) -{ - if (!s) - return CDK_Inv_Value; - if (!s->flags.write) - return CDK_Inv_Mode; - s->cache.on = val; - if (!s->cache.buf) - { - s->cache.buf = cdk_calloc (1, STREAM_BUFSIZE); - s->cache.alloced = STREAM_BUFSIZE; - _cdk_log_debug ("stream: allocate cache of %d octets\n", - STREAM_BUFSIZE); - } - return 0; -} - - -static int -stream_cache_flush (cdk_stream_t s, FILE * fp) -{ - int nwritten; - - assert (s); - - /* FIXME: We should find a way to use cdk_stream_write here. */ - if (s->cache.size > 0) - { - nwritten = fwrite (s->cache.buf, 1, s->cache.size, fp); - if (!nwritten) - return CDK_File_Error; - s->cache.size = 0; - s->cache.on = 0; - wipemem (s->cache.buf, s->cache.alloced); - } - return 0; -} - - -/** - * cdk_stream_kick_off: - * @inp: the input stream - * @out: the output stream. - * - * Passes the entire data from @inp into the output stream @out - * with all the activated filters. - */ -cdk_error_t -cdk_stream_kick_off (cdk_stream_t inp, cdk_stream_t out) -{ - byte buf[BUFSIZE]; - int nread, nwritten; - cdk_error_t rc; - - if (!inp || !out) - return CDK_Inv_Value; - rc = CDK_Success; - while (!cdk_stream_eof (inp)) - { - nread = cdk_stream_read (inp, buf, DIM (buf)); - if (!nread || nread == EOF) - break; - nwritten = cdk_stream_write (out, buf, nread); - if (!nwritten || nwritten == EOF) - { /* In case of errors, we leave the loop. */ - rc = inp->error; - break; - } - } - - wipemem (buf, sizeof (buf)); - return rc; -} - - -/** - * cdk_stream_mmap_part: - * @s: the stream - * @off: the offset where to start - * @len: how much bytes shall be mapped - * @ret_buf: the buffer to store the content - * @ret_buflen: length of the buffer - * - * Map the data of the given stream into a memory section. @ret_count - * contains the length of the buffer. - **/ -cdk_error_t -cdk_stream_mmap_part (cdk_stream_t s, off_t off, size_t len, - byte ** ret_buf, size_t * ret_buflen) -{ - off_t oldpos; - int n; - cdk_error_t rc; - - if (!s || !ret_buf || !ret_buflen) - return CDK_Inv_Value; - if (s->cbs_hd) - return CDK_Inv_Mode; - - *ret_buflen = 0; - *ret_buf = NULL; - oldpos = cdk_stream_tell (s); - rc = cdk_stream_flush (s); - if (!rc) - rc = cdk_stream_seek (s, off); - if (rc) - return rc; - if (!len) - len = cdk_stream_get_length (s); - if (!len || len > MAX_MAP_SIZE) - return 0; - *ret_buf = cdk_calloc (1, len + 1); - *ret_buflen = len; - n = cdk_stream_read (s, *ret_buf, len); - if (n != len) - *ret_buflen = n; - rc = cdk_stream_seek (s, oldpos); - return rc; -} - - -cdk_error_t -cdk_stream_mmap (cdk_stream_t inp, byte ** buf, size_t * buflen) -{ - off_t len; - - /* We need to make sure all data is flushed before we retrieve the size. */ - cdk_stream_flush (inp); - len = cdk_stream_get_length (inp); - return cdk_stream_mmap_part (inp, 0, len, buf, buflen); -} - - -/** - * cdk_stream_peek: - * @inp: the input stream handle - * @s: buffer - * @count: number of bytes to peek - * - * The function acts like cdk_stream_read with the difference that - * the file pointer is moved to the old position after the bytes were read. - **/ -int -cdk_stream_peek (cdk_stream_t inp, byte * buf, size_t buflen) -{ - off_t off; - int nbytes; - - if (!inp || !buf) - return 0; - if (inp->cbs_hd) - return 0; - - off = cdk_stream_tell (inp); - nbytes = cdk_stream_read (inp, buf, buflen); - if (nbytes == -1) - return 0; - if (cdk_stream_seek (inp, off)) - return 0; - return nbytes; -} - - -/* Try to read a line from the given stream. */ -int -_cdk_stream_gets (cdk_stream_t s, char *buf, size_t count) -{ - int c, i; - - assert (s); - - i = 0; - while (!cdk_stream_eof (s) && count > 0) - { - c = cdk_stream_getc (s); - if (c == EOF || c == '\r' || c == '\n') - { - buf[i++] = '\0'; - break; - } - buf[i++] = c; - count--; - } - return i; -} - - -/* Try to write string into the stream @s. */ -int -_cdk_stream_puts (cdk_stream_t s, const char *buf) -{ - return cdk_stream_write (s, buf, strlen (buf)); -} - - -/* Activate the block mode for the given stream. */ -cdk_error_t -_cdk_stream_set_blockmode (cdk_stream_t s, size_t nbytes) -{ - assert (s); - - _cdk_log_debug ("stream: activate block mode with blocksize %d\n", nbytes); - s->blkmode = nbytes; - return 0; -} - - -/* Return the block mode state of the given stream. */ -int -_cdk_stream_get_blockmode (cdk_stream_t s) -{ - return s ? s->blkmode : 0; -} diff --git a/src/daemon/https/opencdk/stream.h b/src/daemon/https/opencdk/stream.h @@ -1,88 +0,0 @@ -/* stream.h - internal definiton for the STREAM object - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifndef CDK_STREAM_H -#define CDK_STREAM_H - -/* The default buffer size for the stream. */ -#define STREAM_BUFSIZE 8192 - -enum { - fDUMMY = 0, - fARMOR = 1, - fCIPHER = 2, - fLITERAL = 3, - fCOMPRESS= 4, - fHASH = 5, - fTEXT = 6 -}; - -/* Type definition for the filter function. */ -typedef int (*filter_fnct_t) (void * opaque, int ctl, FILE * in, FILE * out); - -/* The stream filter context structure. */ -struct stream_filter_s -{ - struct stream_filter_s *next; - filter_fnct_t fnct; - void *opaque; - FILE *tmp; - union { - armor_filter_t afx; - cipher_filter_t cfx; - literal_filter_t pfx; - compress_filter_t zfx; - text_filter_t tfx; - md_filter_t mfx; - } u; - struct { - unsigned enabled:1; - unsigned rdonly:1; - unsigned error:1; - } flags; - unsigned type; - unsigned ctl; -}; - - -/* The stream context structure. */ -struct cdk_stream_s { - struct stream_filter_s *filters; - int fmode; - int error; - size_t blkmode; - struct { - unsigned filtrated:1; - unsigned eof:1; - unsigned write:1; - unsigned temp:1; - unsigned reset:1; - unsigned no_filter:1; - unsigned compressed:3; - } flags; - struct { - unsigned char *buf; - unsigned on:1; - size_t size; - size_t alloced; - } cache; - char *fname; - FILE *fp; - unsigned int fp_ref:1; - struct cdk_stream_cbs_s cbs; - void *cbs_hd; -}; - -#endif /* CDK_STREAM_H */ diff --git a/src/daemon/https/opencdk/types.h b/src/daemon/https/opencdk/types.h @@ -1,44 +0,0 @@ -/* types.h - Some type definitions - * Copyright (C) 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifndef CDK_TYPES_H -#define CDK_TYPES_H - -#include <gcrypt.h> - -#ifndef HAVE_BYTE_TYPEDEF -# undef byte - typedef unsigned char byte; -# define HAVE_BYTE_TYPEDEF -#endif - -#ifndef HAVE_U16_TYPEDEF -# undef u16 - typedef unsigned short u16; -# define HAVE_U16_TYPEDEF -#endif - -#ifndef HAVE_U32_TYPEDEF -# undef u32 - typedef unsigned int u32; -# define HAVE_U32_TYPEDEF -#endif - -#ifndef DIM -# define DIM(v) (sizeof (v)/sizeof ((v)[0])) -# define DIMof(type, member) DIM(((type *)0)->member) -#endif - -#endif /* CDK_TYPES_H */ diff --git a/src/daemon/https/opencdk/verify.c b/src/daemon/https/opencdk/verify.c @@ -1,306 +0,0 @@ -/* verify.c - Verify signatures - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <sys/stat.h> - -#include "opencdk.h" -#include "main.h" -#include "filters.h" -#include "packet.h" - - -/* Table of all supported digest algorithms and their names. */ -struct -{ - const char *name; - int algo; -} digest_table[] = -{ - { - "MD5", GCRY_MD_MD5}, - { - "SHA1", GCRY_MD_SHA1}, - { - "RIPEMD160", GCRY_MD_RMD160}, - { - "SHA256", GCRY_MD_SHA256}, - { - "SHA384", GCRY_MD_SHA384}, - { - "SHA512", GCRY_MD_SHA512}, - { - NULL, 0} -}; - - -static int file_verify_clearsign (cdk_ctx_t, const char *, const char *); - - -/** - * cdk_stream_verify: - * @hd: session handle - * @inp: the input stream - * @data: for detached signatures, this is the data stream @inp is the sig - * @out: where the output shall be written. - */ -cdk_error_t -cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t data, - cdk_stream_t out) -{ - /* FIXME: out is not currently used. */ - if (cdk_armor_filter_use (inp)) - cdk_stream_set_armor_flag (inp, 0); - return _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL); -} - - -/** - * cdk_file_verify: - * @hd: the session handle - * @file: the input file - * @data_file: for detached signature this is the data file and @file is the sig. - * @output: the output file - * - * Verify a signature. - **/ -cdk_error_t -cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file, - const char *output) -{ - struct stat stbuf; - cdk_stream_t inp, data; - char buf[4096]; - int n; - cdk_error_t rc; - - if (!hd || !file) - return CDK_Inv_Value; - if (output && !hd->opt.overwrite && !stat (output, &stbuf)) - return CDK_Inv_Mode; - - rc = cdk_stream_open (file, &inp); - if (rc) - return rc; - if (cdk_armor_filter_use (inp)) - { - n = cdk_stream_peek (inp, (byte *) buf, DIM (buf) - 1); - if (!n || n == -1) - return CDK_EOF; - buf[n] = '\0'; - if (strstr (buf, "BEGIN PGP SIGNED MESSAGE")) - { - cdk_stream_close (inp); - return file_verify_clearsign (hd, file, output); - } - cdk_stream_set_armor_flag (inp, 0); - } - - if (data_file) - { - rc = cdk_stream_open (data_file, &data); - if (rc) - { - cdk_stream_close (inp); - return rc; - } - } - else - data = NULL; - - rc = _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL); - - if (data != NULL) - cdk_stream_close (data); - cdk_stream_close (inp); - return rc; -} - - -void -_cdk_result_verify_free (cdk_verify_result_t res) -{ - if (!res) - return; - cdk_free (res->policy_url); - cdk_free (res->sig_data); - cdk_free (res); -} - - -cdk_verify_result_t -_cdk_result_verify_new (void) -{ - cdk_verify_result_t res; - - res = cdk_calloc (1, sizeof *res); - if (!res) - return NULL; - return res; -} - - -static cdk_error_t -file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output) -{ - cdk_stream_t inp = NULL, out = NULL, tmp = NULL; - gcry_md_hd_t md = NULL; - char buf[512], chk[512]; - const char *s; - int i, is_signed = 0, nbytes; - int digest_algo = 0; - gcry_error_t err; - cdk_error_t rc; - - if (output) - { - rc = cdk_stream_create (output, &out); - if (rc) - return rc; - } - - rc = cdk_stream_open (file, &inp); - if (rc) - { - if (output) - cdk_stream_close (out); - return rc; - } - - s = "-----BEGIN PGP SIGNED MESSAGE-----"; - while (!cdk_stream_eof (inp)) - { - nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); - if (!nbytes || nbytes == -1) - break; - if (!strncmp (buf, s, strlen (s))) - { - is_signed = 1; - break; - } - } - - if (cdk_stream_eof (inp) && !is_signed) - { - rc = CDK_Armor_Error; - goto leave; - } - - while (!cdk_stream_eof (inp)) - { - nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); - if (!nbytes || nbytes == -1) - break; - if (nbytes == 1) /* Empty line */ - break; - else if (!strncmp (buf, "Hash: ", 6)) - { - for (i = 0; digest_table[i].name; i++) - { - if (!strcmp (buf + 6, digest_table[i].name)) - { - digest_algo = digest_table[i].algo; - break; - } - } - } - } - - if (digest_algo && gcry_md_test_algo (digest_algo)) - { - rc = CDK_Inv_Algo; - goto leave; - } - - if (!digest_algo) - digest_algo = GCRY_MD_MD5; - - err = gcry_md_open (&md, digest_algo, 0); - if (err) - { - rc = map_gcry_error (err); - goto leave; - } - - s = "-----BEGIN PGP SIGNATURE-----"; - while (!cdk_stream_eof (inp)) - { - nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); - if (!nbytes || nbytes == -1) - break; - if (!strncmp (buf, s, strlen (s))) - break; - else - { - cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1); - i = strncmp (chk, s, strlen (s)); - if (strlen (buf) == 0 && i == 0) - continue; /* skip last '\n' */ - _cdk_trim_string (buf, i == 0 ? 0 : 1); - gcry_md_write (md, buf, strlen (buf)); - } - if (!strncmp (buf, "- ", 2)) /* FIXME: handle it recursive. */ - memmove (buf, buf + 2, nbytes - 2); - if (out) - { - if (strstr (buf, "\r\n")) - buf[strlen (buf) - 2] = '\0'; - cdk_stream_write (out, buf, strlen (buf)); - _cdk_stream_puts (out, _cdk_armor_get_lineend ()); - } - } - - /* We create a temporary stream object to store the - signature data in there. */ - rc = cdk_stream_tmp_new (&tmp); - if (rc) - goto leave; - - s = "-----BEGIN PGP SIGNATURE-----\n"; - _cdk_stream_puts (tmp, s); - while (!cdk_stream_eof (inp)) - { - nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); - if (!nbytes || nbytes == -1) - break; - if (nbytes < (DIM (buf) - 3)) - { - buf[nbytes - 1] = '\n'; - buf[nbytes] = '\0'; - } - cdk_stream_write (tmp, buf, nbytes); - } - - /* FIXME: This code is not very elegant. */ - cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ); - cdk_stream_seek (tmp, 0); - cdk_stream_set_armor_flag (tmp, 0); - cdk_stream_read (tmp, NULL, 0); - - /* the digest handle will be closed there. */ - rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, md); - -leave: - gcry_md_close (md); - cdk_stream_close (out); - cdk_stream_close (tmp); - cdk_stream_close (inp); - return rc; -} diff --git a/src/daemon/https/opencdk/write-packet.c b/src/daemon/https/opencdk/write-packet.c @@ -1,947 +0,0 @@ -/* write-packet.c - Write OpenPGP packets - * Copyright (C) 2001, 2002, 2003, 2007 Timo Schulz - * - * This file is part of OpenCDK. - * - * OpenCDK 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. - * - * OpenCDK 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. - */ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <string.h> -#include <stdio.h> -#include <assert.h> - -#include "opencdk.h" -#include "main.h" - - -static int -stream_write (cdk_stream_t s, const void *buf, size_t buflen) -{ - int nwritten; - - nwritten = cdk_stream_write (s, buf, buflen); - if (nwritten == EOF) - return _cdk_stream_get_errno (s); - return 0; -} - - -static int -stream_read (cdk_stream_t s, void *buf, size_t buflen, size_t * r_nread) -{ - int nread; - - assert (r_nread); - - nread = cdk_stream_read (s, buf, buflen); - if (nread == EOF) - return _cdk_stream_get_errno (s); - *r_nread = nread; - return 0; -} - - -static int -stream_putc (cdk_stream_t s, int c) -{ - int nwritten = cdk_stream_putc (s, c); - if (nwritten == EOF) - return _cdk_stream_get_errno (s); - return 0; -} - - -static int -write_32 (cdk_stream_t out, u32 u) -{ - byte buf[4]; - - buf[0] = u >> 24; - buf[1] = u >> 16; - buf[2] = u >> 8; - buf[3] = u; - return stream_write (out, buf, 4); -} - - -static int -write_16 (cdk_stream_t out, u16 u) -{ - byte buf[2]; - - buf[0] = u >> 8; - buf[1] = u; - return stream_write (out, buf, 2); -} - - -static size_t -calc_mpisize (gcry_mpi_t mpi[MAX_CDK_PK_PARTS], size_t ncount) -{ - size_t size, i; - - size = 0; - for (i = 0; i < ncount; i++) - size += (gcry_mpi_get_nbits (mpi[i]) + 7) / 8 + 2; - return size; -} - - -static int -write_mpi (cdk_stream_t out, gcry_mpi_t m) -{ - byte buf[MAX_MPI_BYTES + 2]; - size_t nbits, nread; - gcry_error_t err; - - if (!out || !m) - return CDK_Inv_Value; - nbits = gcry_mpi_get_nbits (m); - if (nbits > MAX_MPI_BITS || nbits < 1) - return CDK_MPI_Error; - err = gcry_mpi_print (GCRYMPI_FMT_PGP, buf, MAX_MPI_BYTES + 2, &nread, m); - if (err) - return map_gcry_error (err); - return stream_write (out, buf, nread); -} - - -static cdk_error_t -write_mpibuf (cdk_stream_t out, gcry_mpi_t mpi[MAX_CDK_PK_PARTS], - size_t count) -{ - size_t i; - cdk_error_t rc; - - for (i = 0; i < count; i++) - { - rc = write_mpi (out, mpi[i]); - if (rc) - return rc; - } - return 0; -} - - -static cdk_error_t -pkt_encode_len (cdk_stream_t out, size_t pktlen) -{ - cdk_error_t rc; - - assert (out); - - rc = 0; - if (!pktlen) - { - /* Block mode, partial bodies, with 'DEF_BLOCKSIZE' from main.h */ - rc = stream_putc (out, (0xE0 | DEF_BLOCKBITS)); - } - else if (pktlen < 192) - rc = stream_putc (out, pktlen); - else if (pktlen < 8384) - { - pktlen -= 192; - rc = stream_putc (out, (pktlen / 256) + 192); - if (!rc) - rc = stream_putc (out, (pktlen % 256)); - } - else - { - rc = stream_putc (out, 255); - if (!rc) - rc = write_32 (out, pktlen); - } - - return rc; -} - - -static cdk_error_t -write_head_new (cdk_stream_t out, size_t size, int type) -{ - cdk_error_t rc; - - assert (out); - - if (type < 0 || type > 63) - return CDK_Inv_Packet; - rc = stream_putc (out, (0xC0 | type)); - if (!rc) - rc = pkt_encode_len (out, size); - return rc; -} - - -static cdk_error_t -write_head_old (cdk_stream_t out, size_t size, int type) -{ - cdk_error_t rc; - int ctb; - - assert (out); - - if (type < 0 || type > 16) - return CDK_Inv_Packet; - ctb = 0x80 | (type << 2); - if (!size) - ctb |= 3; - else if (size < 256) - ; - else if (size < 65536) - ctb |= 1; - else - ctb |= 2; - rc = stream_putc (out, ctb); - if (!size) - return rc; - if (!rc) - { - if (size < 256) - rc = stream_putc (out, size); - else if (size < 65536) - rc = write_16 (out, size); - else - rc = write_32 (out, size); - } - - return rc; -} - - -/* Write special PGP2 packet header. PGP2 (wrongly) uses two byte header - length for signatures and keys even if the size is < 256. */ -static cdk_error_t -pkt_write_head2 (cdk_stream_t out, size_t size, int type) -{ - cdk_error_t rc; - - rc = cdk_stream_putc (out, 0x80 | (type << 2) | 1); - if (!rc) - rc = cdk_stream_putc (out, size >> 8); - if (!rc) - rc = cdk_stream_putc (out, size & 0xff); - return rc; -} - - -static int -pkt_write_head (cdk_stream_t out, int old_ctb, size_t size, int type) -{ - if (old_ctb) - return write_head_old (out, size, type); - return write_head_new (out, size, type); -} - - -static cdk_error_t -write_encrypted (cdk_stream_t out, cdk_pkt_encrypted_t enc, int old_ctb) -{ - size_t nbytes; - cdk_error_t rc; - - assert (out); - assert (enc); - - if (DEBUG_PKT) - _cdk_log_debug ("write_encrypted: %lu bytes\n", enc->len); - - nbytes = enc->len ? (enc->len + enc->extralen) : 0; - rc = pkt_write_head (out, old_ctb, nbytes, CDK_PKT_ENCRYPTED); - /* The rest of the packet is ciphertext */ - return rc; -} - - -static int -write_encrypted_mdc (cdk_stream_t out, cdk_pkt_encrypted_t enc) -{ - size_t nbytes; - cdk_error_t rc; - - assert (out); - assert (enc); - - if (!enc->mdc_method) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_encrypted_mdc: %lu bytes\n", enc->len); - - nbytes = enc->len ? (enc->len + enc->extralen + 1) : 0; - rc = pkt_write_head (out, 0, nbytes, CDK_PKT_ENCRYPTED_MDC); - if (!rc) - rc = stream_putc (out, 1); /* version */ - /* The rest of the packet is ciphertext */ - return rc; -} - - -static cdk_error_t -write_symkey_enc (cdk_stream_t out, cdk_pkt_symkey_enc_t ske) -{ - cdk_s2k_t s2k; - size_t size = 0, s2k_size = 0; - cdk_error_t rc; - - assert (out); - assert (ske); - - if (ske->version != 4) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_symkey_enc:\n"); - - s2k = ske->s2k; - if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) - s2k_size = 8; - if (s2k->mode == CDK_S2K_ITERSALTED) - s2k_size++; - size = 4 + s2k_size + ske->seskeylen; - rc = pkt_write_head (out, 0, size, CDK_PKT_SYMKEY_ENC); - if (!rc) - rc = stream_putc (out, ske->version); - if (!rc) - rc = stream_putc (out, ske->cipher_algo); - if (!rc) - rc = stream_putc (out, s2k->mode); - if (!rc) - rc = stream_putc (out, s2k->hash_algo); - if (s2k->mode == CDK_S2K_SALTED || s2k->mode == CDK_S2K_ITERSALTED) - { - rc = stream_write (out, s2k->salt, 8); - if (!rc) - { - if (s2k->mode == CDK_S2K_ITERSALTED) - rc = stream_putc (out, s2k->count); - } - } - return rc; -} - - -static int -write_pubkey_enc (cdk_stream_t out, cdk_pkt_pubkey_enc_t pke, int old_ctb) -{ - size_t size; - int rc, nenc; - - assert (out); - assert (pke); - - if (pke->version < 2 || pke->version > 3) - return CDK_Inv_Packet; - if (!KEY_CAN_ENCRYPT (pke->pubkey_algo)) - return CDK_Inv_Algo; - - if (DEBUG_PKT) - _cdk_log_debug ("write_pubkey_enc:\n"); - - nenc = cdk_pk_get_nenc (pke->pubkey_algo); - size = 10 + calc_mpisize (pke->mpi, nenc); - rc = pkt_write_head (out, old_ctb, size, CDK_PKT_PUBKEY_ENC); - if (rc) - return rc; - - rc = stream_putc (out, pke->version); - if (!rc) - rc = write_32 (out, pke->keyid[0]); - if (!rc) - rc = write_32 (out, pke->keyid[1]); - if (!rc) - rc = stream_putc (out, pke->pubkey_algo); - if (!rc) - rc = write_mpibuf (out, pke->mpi, nenc); - return rc; -} - - -static cdk_error_t -write_mdc (cdk_stream_t out, cdk_pkt_mdc_t mdc) -{ - cdk_error_t rc; - - assert (mdc); - assert (out); - - if (DEBUG_PKT) - _cdk_log_debug ("write_mdc:\n"); - - /* This packet requires a fixed header encoding */ - rc = stream_putc (out, 0xD3); /* packet ID and 1 byte length */ - if (!rc) - rc = stream_putc (out, 0x14); - if (!rc) - rc = stream_write (out, mdc->hash, DIM (mdc->hash)); - return rc; -} - - -static size_t -calc_subpktsize (cdk_subpkt_t s) -{ - size_t nbytes; - - /* In the count mode, no buffer is returned. */ - _cdk_subpkt_get_array (s, 1, &nbytes); - return nbytes; -} - - -static cdk_error_t -write_v3_sig (cdk_stream_t out, cdk_pkt_signature_t sig, int nsig) -{ - size_t size; - cdk_error_t rc; - - size = 19 + calc_mpisize (sig->mpi, nsig); - if (is_RSA (sig->pubkey_algo)) - rc = pkt_write_head2 (out, size, CDK_PKT_SIGNATURE); - else - rc = pkt_write_head (out, 1, size, CDK_PKT_SIGNATURE); - if (!rc) - rc = stream_putc (out, sig->version); - if (!rc) - rc = stream_putc (out, 5); - if (!rc) - rc = stream_putc (out, sig->sig_class); - if (!rc) - rc = write_32 (out, sig->timestamp); - if (!rc) - rc = write_32 (out, sig->keyid[0]); - if (!rc) - rc = write_32 (out, sig->keyid[1]); - if (!rc) - rc = stream_putc (out, sig->pubkey_algo); - if (!rc) - rc = stream_putc (out, sig->digest_algo); - if (!rc) - rc = stream_putc (out, sig->digest_start[0]); - if (!rc) - rc = stream_putc (out, sig->digest_start[1]); - if (!rc) - rc = write_mpibuf (out, sig->mpi, nsig); - return rc; -} - - -static cdk_error_t -write_signature (cdk_stream_t out, cdk_pkt_signature_t sig, int old_ctb) -{ - byte *buf; - size_t nbytes, size, nsig; - cdk_error_t rc; - - assert (out); - assert (sig); - - if (!KEY_CAN_SIGN (sig->pubkey_algo)) - return CDK_Inv_Algo; - if (sig->version < 2 || sig->version > 4) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_signature:\n"); - - nsig = cdk_pk_get_nsig (sig->pubkey_algo); - if (!nsig) - return CDK_Inv_Algo; - if (sig->version < 4) - return write_v3_sig (out, sig, nsig); - - size = 10 + calc_subpktsize (sig->hashed) - + calc_subpktsize (sig->unhashed) + calc_mpisize (sig->mpi, nsig); - rc = pkt_write_head (out, 0, size, CDK_PKT_SIGNATURE); - if (!rc) - rc = stream_putc (out, 4); - if (!rc) - rc = stream_putc (out, sig->sig_class); - if (!rc) - rc = stream_putc (out, sig->pubkey_algo); - if (!rc) - rc = stream_putc (out, sig->digest_algo); - if (!rc) - rc = write_16 (out, sig->hashed_size); - if (!rc) - { - buf = _cdk_subpkt_get_array (sig->hashed, 0, &nbytes); - if (!buf) - return CDK_Out_Of_Core; - rc = stream_write (out, buf, nbytes); - cdk_free (buf); - } - if (!rc) - rc = write_16 (out, sig->unhashed_size); - if (!rc) - { - buf = _cdk_subpkt_get_array (sig->unhashed, 0, &nbytes); - if (!buf) - return CDK_Out_Of_Core; - rc = stream_write (out, buf, nbytes); - cdk_free (buf); - } - if (!rc) - rc = stream_putc (out, sig->digest_start[0]); - if (!rc) - rc = stream_putc (out, sig->digest_start[1]); - if (!rc) - rc = write_mpibuf (out, sig->mpi, nsig); - return rc; -} - - -static cdk_error_t -write_public_key (cdk_stream_t out, cdk_pkt_pubkey_t pk, - int is_subkey, int old_ctb) -{ - int pkttype, ndays = 0; - size_t npkey = 0, size = 6; - cdk_error_t rc; - - assert (out); - assert (pk); - - if (pk->version < 2 || pk->version > 4) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_public_key: subkey=%d\n", is_subkey); - - pkttype = is_subkey ? CDK_PKT_PUBLIC_SUBKEY : CDK_PKT_PUBLIC_KEY; - npkey = cdk_pk_get_npkey (pk->pubkey_algo); - if (!npkey) - return CDK_Inv_Algo; - if (pk->version < 4) - size += 2; /* expire date */ - if (is_subkey) - old_ctb = 0; - size += calc_mpisize (pk->mpi, npkey); - if (old_ctb) - rc = pkt_write_head2 (out, size, pkttype); - else - rc = pkt_write_head (out, old_ctb, size, pkttype); - if (!rc) - rc = stream_putc (out, pk->version); - if (!rc) - rc = write_32 (out, pk->timestamp); - if (!rc && pk->version < 4) - { - if (pk->expiredate) - ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); - rc = write_16 (out, ndays); - } - if (!rc) - rc = stream_putc (out, pk->pubkey_algo); - if (!rc) - rc = write_mpibuf (out, pk->mpi, npkey); - return rc; -} - - -static int -calc_s2ksize (cdk_pkt_seckey_t sk) -{ - size_t nbytes = 0; - - if (!sk->is_protected) - return 0; - switch (sk->protect.s2k->mode) - { - case CDK_S2K_SIMPLE: - nbytes = 2; - break; - case CDK_S2K_SALTED: - nbytes = 10; - break; - case CDK_S2K_ITERSALTED: - nbytes = 11; - break; - } - nbytes += sk->protect.ivlen; - nbytes++; /* single cipher byte */ - return nbytes; -} - - -static cdk_error_t -write_secret_key (cdk_stream_t out, cdk_pkt_seckey_t sk, - int is_subkey, int old_ctb) -{ - cdk_pkt_pubkey_t pk = NULL; - size_t size = 6, npkey, nskey; - int pkttype, s2k_mode; - cdk_error_t rc; - - assert (out); - assert (sk); - - if (!sk->pk) - return CDK_Inv_Value; - pk = sk->pk; - if (pk->version < 2 || pk->version > 4) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_secret_key:\n"); - - npkey = cdk_pk_get_npkey (pk->pubkey_algo); - nskey = cdk_pk_get_nskey (pk->pubkey_algo); - if (!npkey || !nskey) - return CDK_Inv_Algo; - if (pk->version < 4) - size += 2; - /* If the key is unprotected, the 1 extra byte: - 1 octet - cipher algorithm byte (0x00) - the other bytes depend on the mode: - a) simple checksum - 2 octets - b) sha-1 checksum - 20 octets */ - size = !sk->is_protected ? size + 1 : size + 1 + calc_s2ksize (sk); - size += calc_mpisize (pk->mpi, npkey); - if (sk->version == 3 || !sk->is_protected) - { - if (sk->version == 3) - { - size += 2; /* force simple checksum */ - sk->protect.sha1chk = 0; - } - else - size += sk->protect.sha1chk ? 20 : 2; - size += calc_mpisize (sk->mpi, nskey); - } - else /* We do not know anything about the encrypted mpi's so we - treat the data as opaque. */ - size += sk->enclen; - - pkttype = is_subkey ? CDK_PKT_SECRET_SUBKEY : CDK_PKT_SECRET_KEY; - rc = pkt_write_head (out, old_ctb, size, pkttype); - if (!rc) - rc = stream_putc (out, pk->version); - if (!rc) - rc = write_32 (out, pk->timestamp); - if (!rc && pk->version < 4) - { - u16 ndays = 0; - if (pk->expiredate) - ndays = (u16) ((pk->expiredate - pk->timestamp) / 86400L); - rc = write_16 (out, ndays); - } - if (!rc) - rc = stream_putc (out, pk->pubkey_algo); - if (!rc) - rc = write_mpibuf (out, pk->mpi, npkey); - if (sk->is_protected == 0) - rc = stream_putc (out, 0x00); - else - { - if (is_RSA (pk->pubkey_algo) && pk->version < 4) - stream_putc (out, sk->protect.algo); - else if (sk->protect.s2k) - { - s2k_mode = sk->protect.s2k->mode; - rc = stream_putc (out, sk->protect.sha1chk ? 0xFE : 0xFF); - if (!rc) - rc = stream_putc (out, sk->protect.algo); - if (!rc) - rc = stream_putc (out, sk->protect.s2k->mode); - if (!rc) - rc = stream_putc (out, sk->protect.s2k->hash_algo); - if (!rc && (s2k_mode == 1 || s2k_mode == 3)) - { - rc = stream_write (out, sk->protect.s2k->salt, 8); - if (!rc && s2k_mode == 3) - rc = stream_putc (out, sk->protect.s2k->count); - } - } - else - return CDK_Inv_Value; - rc = stream_write (out, sk->protect.iv, sk->protect.ivlen); - } - if (!rc && sk->is_protected && pk->version == 4) - { - if (sk->encdata && sk->enclen) - rc = stream_write (out, sk->encdata, sk->enclen); - } - else - { - if (!rc) - rc = write_mpibuf (out, sk->mpi, nskey); - if (!rc) - { - if (!sk->csum) - sk->csum = _cdk_sk_get_csum (sk); - rc = write_16 (out, sk->csum); - } - } - - return rc; -} - - -static cdk_error_t -write_compressed (cdk_stream_t out, cdk_pkt_compressed_t cd) -{ - cdk_error_t rc; - - assert (out); - assert (cd); - - if (DEBUG_PKT) - _cdk_log_debug ("packet: write_compressed\n"); - - /* Use an old (RFC1991) header for this packet. */ - rc = pkt_write_head (out, 1, 0, CDK_PKT_COMPRESSED); - if (!rc) - rc = stream_putc (out, cd->algorithm); - return rc; -} - - -static cdk_error_t -write_literal (cdk_stream_t out, cdk_pkt_literal_t pt, int old_ctb) -{ - byte buf[BUFSIZE]; - size_t size; - cdk_error_t rc; - - assert (out); - assert (pt); - - /* We consider a packet without a body as an invalid packet. - At least one octet must be present. */ - if (!pt->len) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_literal:\n"); - - size = 6 + pt->namelen + pt->len; - rc = pkt_write_head (out, old_ctb, size, CDK_PKT_LITERAL); - if (rc) - return rc; - - rc = stream_putc (out, pt->mode); - if (rc) - return rc; - rc = stream_putc (out, pt->namelen); - if (rc) - return rc; - - if (pt->namelen > 0) - rc = stream_write (out, pt->name, pt->namelen); - if (!rc) - rc = write_32 (out, pt->timestamp); - if (rc) - return rc; - - while (!cdk_stream_eof (pt->buf) && !rc) - { - rc = stream_read (pt->buf, buf, DIM (buf), &size); - if (!rc) - rc = stream_write (out, buf, size); - } - - wipemem (buf, sizeof (buf)); - return rc; -} - - -static cdk_error_t -write_onepass_sig (cdk_stream_t out, cdk_pkt_onepass_sig_t sig) -{ - cdk_error_t rc; - - assert (out); - assert (sig); - - if (sig->version != 3) - return CDK_Inv_Packet; - - if (DEBUG_PKT) - _cdk_log_debug ("write_onepass_sig:\n"); - - rc = pkt_write_head (out, 0, 13, CDK_PKT_ONEPASS_SIG); - if (!rc) - rc = stream_putc (out, sig->version); - if (!rc) - rc = stream_putc (out, sig->sig_class); - if (!rc) - rc = stream_putc (out, sig->digest_algo); - if (!rc) - rc = stream_putc (out, sig->pubkey_algo); - if (!rc) - rc = write_32 (out, sig->keyid[0]); - if (!rc) - rc = write_32 (out, sig->keyid[1]); - if (!rc) - rc = stream_putc (out, sig->last); - return rc; -} - - -static cdk_error_t -write_user_id (cdk_stream_t out, cdk_pkt_userid_t id, int old_ctb, - int pkttype) -{ - cdk_error_t rc; - - if (!out || !id) - return CDK_Inv_Value; - - if (pkttype == CDK_PKT_ATTRIBUTE) - { - if (!id->attrib_img) - return CDK_Inv_Value; - rc = - pkt_write_head (out, old_ctb, id->attrib_len + 6, CDK_PKT_ATTRIBUTE); - if (rc) - return rc; - /* Write subpacket part. */ - stream_putc (out, 255); - write_32 (out, id->attrib_len + 1); - stream_putc (out, 1); - rc = stream_write (out, id->attrib_img, id->attrib_len); - } - else - { - if (!id->name) - return CDK_Inv_Value; - rc = pkt_write_head (out, old_ctb, id->len, CDK_PKT_USER_ID); - if (!rc) - rc = stream_write (out, id->name, id->len); - } - - return rc; -} - - -/** - * cdk_pkt_write: - * @out: the output stream handle - * @pkt: the packet itself - * - * Write the contents of @pkt into the @out stream. - * Return 0 on success. - **/ -cdk_error_t -cdk_pkt_write (cdk_stream_t out, cdk_packet_t pkt) -{ - cdk_error_t rc; - - if (!out || !pkt) - return CDK_Inv_Value; - - _cdk_log_debug ("write packet pkttype=%d\n", pkt->pkttype); - switch (pkt->pkttype) - { - case CDK_PKT_LITERAL: - rc = write_literal (out, pkt->pkt.literal, pkt->old_ctb); - break; - case CDK_PKT_ONEPASS_SIG: - rc = write_onepass_sig (out, pkt->pkt.onepass_sig); - break; - case CDK_PKT_MDC: - rc = write_mdc (out, pkt->pkt.mdc); - break; - case CDK_PKT_SYMKEY_ENC: - rc = write_symkey_enc (out, pkt->pkt.symkey_enc); - break; - case CDK_PKT_ENCRYPTED: - rc = write_encrypted (out, pkt->pkt.encrypted, pkt->old_ctb); - break; - case CDK_PKT_ENCRYPTED_MDC: - rc = write_encrypted_mdc (out, pkt->pkt.encrypted); - break; - case CDK_PKT_PUBKEY_ENC: - rc = write_pubkey_enc (out, pkt->pkt.pubkey_enc, pkt->old_ctb); - break; - case CDK_PKT_SIGNATURE: - rc = write_signature (out, pkt->pkt.signature, pkt->old_ctb); - break; - case CDK_PKT_PUBLIC_KEY: - rc = write_public_key (out, pkt->pkt.public_key, 0, pkt->old_ctb); - break; - case CDK_PKT_PUBLIC_SUBKEY: - rc = write_public_key (out, pkt->pkt.public_key, 1, pkt->old_ctb); - break; - case CDK_PKT_COMPRESSED: - rc = write_compressed (out, pkt->pkt.compressed); - break; - case CDK_PKT_SECRET_KEY: - rc = write_secret_key (out, pkt->pkt.secret_key, 0, pkt->old_ctb); - break; - case CDK_PKT_SECRET_SUBKEY: - rc = write_secret_key (out, pkt->pkt.secret_key, 1, pkt->old_ctb); - break; - case CDK_PKT_USER_ID: - case CDK_PKT_ATTRIBUTE: - rc = write_user_id (out, pkt->pkt.user_id, pkt->old_ctb, pkt->pkttype); - break; - default: - rc = CDK_Inv_Packet; - break; - } - - if (DEBUG_PKT) - _cdk_log_debug ("write_packet rc=%d pkttype=%d\n", rc, pkt->pkttype); - return rc; -} - - -cdk_error_t -_cdk_pkt_write2 (cdk_stream_t out, int pkttype, void *pktctx) -{ - cdk_packet_t pkt; - cdk_error_t rc; - - rc = cdk_pkt_new (&pkt); - if (rc) - return rc; - - switch (pkttype) - { - case CDK_PKT_PUBLIC_KEY: - case CDK_PKT_PUBLIC_SUBKEY: - pkt->pkt.public_key = pktctx; - break; - case CDK_PKT_SIGNATURE: - pkt->pkt.signature = pktctx; - break; - case CDK_PKT_SECRET_KEY: - case CDK_PKT_SECRET_SUBKEY: - pkt->pkt.secret_key = pktctx; - break; - - case CDK_PKT_USER_ID: - pkt->pkt.user_id = pktctx; - break; - } - pkt->pkttype = pkttype; - rc = cdk_pkt_write (out, pkt); - cdk_free (pkt); - return rc; -} - - -cdk_error_t -_cdk_pkt_write_fp (FILE * out, cdk_packet_t pkt) -{ - cdk_stream_t so; - cdk_error_t rc; - - rc = _cdk_stream_fpopen (out, 1, &so); - if (rc) - return rc; - rc = cdk_pkt_write (so, pkt); - cdk_stream_close (so); - return rc; -} diff --git a/src/daemon/https/openpgp/Makefile.am b/src/daemon/https/openpgp/Makefile.am @@ -1,28 +0,0 @@ -SUBDIRS = . - -AM_CPPFLAGS = \ --I$(top_srcdir)/src/include \ --I$(top_srcdir)/src/daemon/https \ --I$(top_srcdir)/src/daemon/https/lgl \ --I$(top_srcdir)/src/daemon/https/x509 \ --I$(top_srcdir)/src/daemon/https/tls \ --I$(top_srcdir)/src/daemon/https/openpgp \ --I$(top_srcdir)/src/daemon/https/opencdk \ --I$(top_srcdir)/src/daemon/https/minitasn1 - -noinst_LTLIBRARIES = libopenpgp.la - -# libopenpgp_la_LDFLAGS = -l$(top_srcdir)/src/daemon/https/libextra/.lib/libextra.la - -libopenpgp_la_SOURCES = \ -pgp_privkey.c \ -compat.c \ -pgp_verify.c \ -extras.c \ -pgp.c - -# x libextra source list -libopenpgp_la_SOURCES += \ -gnutls_openpgp.c \ -gnutls_ia.c \ -gnutls_extra.c diff --git a/src/daemon/https/openpgp/compat.c b/src/daemon/https/openpgp/compat.c @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation - * - * Author: Timo Schulz, Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -/* Compatibility functions on OpenPGP key parsing. - */ - -#include <gnutls_int.h> -#include <gnutls_errors.h> -#include <gnutls_openpgp.h> -#include "openpgp.h" - -/*- - * gnutls_openpgp_verify_key - Verify all signatures on the key - * @cert_list: the structure that holds the certificates. - * @cert_list_lenght: the items in the cert_list. - * @status: the output of the verification function - * - * Verify all signatures in the certificate list. When the key - * is not available, the signature is skipped. - * - * The return value is one of the CertificateStatus entries. - * - * NOTE: this function does not verify using any "web of trust". You - * may use GnuPG for that purpose, or any other external PGP application. - -*/ -int -_gnutls_openpgp_verify_key (const mhd_gtls_cert_credentials_t cred, - const gnutls_datum_t * cert_list, - int cert_list_length, unsigned int *status) -{ - int ret = 0; - gnutls_openpgp_crt_t key = NULL; - unsigned int verify = 0, verify_self = 0; - - if (!cert_list || cert_list_length != 1) - { - gnutls_assert (); - return GNUTLS_E_NO_CERTIFICATE_FOUND; - } - - ret = gnutls_openpgp_crt_init (&key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = - gnutls_openpgp_crt_import (key, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); - if (ret < 0) - { - gnutls_assert (); - goto leave; - } - -#ifndef KEYRING_HACK - if (cred->keyring != NULL) - { - ret = gnutls_openpgp_crt_verify_ring (key, cred->keyring, 0, &verify); - if (ret < 0) - { - gnutls_assert (); - goto leave; - } - } -#else - { - gnutls_openpgp_keyring_t kring; - - ret = gnutls_openpgp_keyring_init (&kring); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = - gnutls_openpgp_keyring_import (kring, &cred->keyring, - cred->keyring_format); - if (ret < 0) - { - gnutls_assert (); - gnutls_openpgp_keyring_deinit (kring); - return ret; - } - - ret = gnutls_openpgp_crt_verify_ring (key, kring, 0, &verify); - if (ret < 0) - { - gnutls_assert (); - gnutls_openpgp_keyring_deinit (kring); - return ret; - } - gnutls_openpgp_keyring_deinit (kring); - } -#endif - - /* Now try the self signature. */ - ret = gnutls_openpgp_crt_verify_self (key, 0, &verify_self); - if (ret < 0) - { - gnutls_assert (); - goto leave; - } - - *status = verify_self | verify; - -#ifndef KEYRING_HACK - /* If we only checked the self signature. */ - if (!cred->keyring) -#else - if (!cred->keyring.data || !cred->keyring.size) -#endif - *status |= GNUTLS_CERT_SIGNER_NOT_FOUND; - - - ret = 0; - -leave: - gnutls_openpgp_crt_deinit (key); - - return ret; -} - -/*- - * gnutls_openpgp_fingerprint - Gets the fingerprint - * @cert: the raw data that contains the OpenPGP public key. - * @fpr: the buffer to save the fingerprint. - * @fprlen: the integer to save the length of the fingerprint. - * - * Returns the fingerprint of the OpenPGP key. Depence on the algorithm, - * the fingerprint can be 16 or 20 bytes. - -*/ -int -_gnutls_openpgp_fingerprint (const gnutls_datum_t * cert, - unsigned char *fpr, size_t * fprlen) -{ - gnutls_openpgp_crt_t key; - int ret; - - ret = gnutls_openpgp_crt_init (&key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = gnutls_openpgp_crt_get_fingerprint (key, fpr, fprlen); - gnutls_openpgp_crt_deinit (key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - return 0; -} - -/*- - * gnutls_openpgp_get_raw_key_creation_time - Extract the timestamp - * @cert: the raw data that contains the OpenPGP public key. - * - * Returns the timestamp when the OpenPGP key was created. - -*/ -time_t -_gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * cert) -{ - gnutls_openpgp_crt_t key; - int ret; - time_t tim; - - ret = gnutls_openpgp_crt_init (&key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - tim = gnutls_openpgp_crt_get_creation_time (key); - - gnutls_openpgp_crt_deinit (key); - - return tim; -} - - -/*- - * gnutls_openpgp_get_raw_key_expiration_time - Extract the expire date - * @cert: the raw data that contains the OpenPGP public key. - * - * Returns the time when the OpenPGP key expires. A value of '0' means - * that the key doesn't expire at all. - -*/ -time_t -_gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * cert) -{ - gnutls_openpgp_crt_t key; - int ret; - time_t tim; - - ret = gnutls_openpgp_crt_init (&key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = gnutls_openpgp_crt_import (key, cert, GNUTLS_OPENPGP_FMT_RAW); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - tim = gnutls_openpgp_crt_get_expiration_time (key); - - gnutls_openpgp_crt_deinit (key); - - return tim; -} diff --git a/src/daemon/https/openpgp/extras.c b/src/daemon/https/openpgp/extras.c @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation - * - * Author: Nikos Mavrogiannopoulos, Timo Schulz - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -/* Functions on OpenPGP keyring parsing - */ - -#include <gnutls_int.h> -#include <gnutls_datum.h> -#include <gnutls_global.h> -#include <gnutls_errors.h> -#include <gnutls_openpgp.h> -#include <gnutls_num.h> -#include "openpgp.h" - -/* Keyring stuff. */ - -/** - * gnutls_openpgp_keyring_init - This function initializes a gnutls_openpgp_keyring_t structure - * @keyring: The structure to be initialized - *- - * This function will initialize an OpenPGP keyring structure. - * - * Returns 0 on success. - * - **/ -int -gnutls_openpgp_keyring_init (gnutls_openpgp_keyring_t * keyring) -{ - *keyring = gnutls_calloc (1, sizeof (gnutls_openpgp_keyring_int)); - - if (*keyring) - return 0; /* success */ - return GNUTLS_E_MEMORY_ERROR; -} - -/** - * gnutls_openpgp_keyring_deinit - This function deinitializes memory used by a gnutls_openpgp_keyring_t structure - * @keyring: The structure to be initialized - * - * This function will deinitialize a keyring structure. - * - **/ -void -gnutls_openpgp_keyring_deinit (gnutls_openpgp_keyring_t keyring) -{ - if (!keyring) - return; - - if (keyring->db) - { - cdk_keydb_free (keyring->db); - keyring->db = NULL; - } - - /* In some cases the stream is also stored outside the keydb context - and we need to close it here then. */ - if (keyring->db_stream) - { - cdk_stream_close (keyring->db_stream); - keyring->db_stream = NULL; - } - - gnutls_free (keyring); -} - -/** - * gnutls_openpgp_keyring_check_id - Check if a key id exists in the keyring - * @ring: holds the keyring to check against - * @keyid: will hold the keyid to check for. - * @flags: unused (should be 0) - * - * Check if a given key ID exists in the keyring. - * - * Returns 0 on success (if keyid exists) and a negative error code - * on failure. - **/ -int -gnutls_openpgp_keyring_check_id (gnutls_openpgp_keyring_t ring, - const unsigned char keyid[8], - unsigned int flags) -{ - cdk_pkt_pubkey_t pk; - uint32_t id[2]; - - id[0] = mhd_gtls_read_uint32 (keyid); - id[1] = mhd_gtls_read_uint32 (&keyid[4]); - - if (!cdk_keydb_get_pk (ring->db, id, &pk)) - { - cdk_pk_release (pk); - return 0; - } - - _gnutls_debug_log ("PGP: key not found %08lX\n", (unsigned long) id[1]); - return GNUTLS_E_NO_CERTIFICATE_FOUND; -} - -/** - * gnutls_openpgp_keyring_import - Import a raw- or Base64-encoded OpenPGP keyring - * @keyring: The structure to store the parsed key. - * @data: The RAW or BASE64 encoded keyring. - * @format: One of #gnutls_openpgp_keyring_fmt elements. - * - * This function will convert the given RAW or Base64 encoded keyring to the - * native #gnutls_openpgp_keyring_t format. The output will be stored in - * 'keyring'. - * - * Returns 0 on success. - * - **/ -int -gnutls_openpgp_keyring_import (gnutls_openpgp_keyring_t keyring, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format) -{ - cdk_error_t err; - cdk_stream_t input; - - _gnutls_debug_log ("PGP: keyring import format '%s'\n", - format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64"); - - if (format == GNUTLS_OPENPGP_FMT_RAW) - { - err - = - cdk_keydb_new (&keyring->db, CDK_DBTYPE_DATA, data->data, data->size); - if (err) - gnutls_assert (); - return _gnutls_map_cdk_rc (err); - } - - /* Create a new stream from the given data, which means to - allocate a new stream and to write the data in the stream. - Then push the armor filter to decode the data and to store - it in the raw format. */ - err = cdk_stream_tmp_from_mem (data->data, data->size, &input); - if (!err) - err = cdk_stream_set_armor_flag (input, 0); - if (!err) - err = cdk_keydb_new_from_stream (&keyring->db, 0, input); - if (err) - { - cdk_stream_close (input); - gnutls_assert (); - } - else - /* The keydb function will not close the stream itself, so we need to - store it separately to close it later. */ - keyring->db_stream = input; - - return _gnutls_map_cdk_rc (err); -} diff --git a/src/daemon/https/openpgp/gnutls_extra.c b/src/daemon/https/openpgp/gnutls_extra.c @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2001, 2004, 2005, 2007 Free Software Foundation - * - * Author: Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -#include <gnutls_int.h> -#include <gnutls_errors.h> -#include <gnutls_extensions.h> -#include <gnutls_openpgp.h> -#include <gnutls_extra.h> -#include <gnutls_extra_hooks.h> -#include <gnutls_algorithms.h> - -/* the number of the compression algorithms available in the compression - * structure. - */ -extern int _gnutls_comp_algorithms_size; - -/* Functions in gnutls that have not been initialized. - */ - -static int _gnutls_init_extra = 0; - -/** - * gnutls_global_init_extra - This function initializes the global state of gnutls-extra - * - * This function initializes the global state of gnutls-extra library - * to defaults. Returns zero on success. - * - * Note that MHD_gnutls_global_init() has to be called before this - * function. If this function is not called then the gnutls-extra - * library will not be usable. - * - **/ -int -gnutls_global_init_extra (void) -{ - /* If the version of libgnutls != version of - * libextra, then do not initialize the library. - * This is because it may break things. - */ - _gnutls_init_extra++; - - if (_gnutls_init_extra != 1) - { - return 0; - } - - /* Register the openpgp functions. This is because some - * of them are defined to be NULL in the main library. - */ - _gnutls_add_openpgp_functions (_gnutls_openpgp_verify_key, - _gnutls_openpgp_get_raw_key_creation_time, - _gnutls_openpgp_get_raw_key_expiration_time, - _gnutls_openpgp_fingerprint, - _gnutls_openpgp_request_key, - _gnutls_openpgp_raw_key_to_gcert, - _gnutls_openpgp_raw_privkey_to_gkey, - _gnutls_openpgp_crt_to_gcert, - _gnutls_openpgp_privkey_to_gkey, - gnutls_openpgp_crt_deinit, - gnutls_openpgp_keyring_deinit, - gnutls_openpgp_privkey_deinit); - - return 0; -} - -#include <strverscmp.h> - -/** - * gnutls_extra_check_version - This function checks the library's version - * @req_version: the version to check - * - * Check that the version of the gnutls-extra library is at minimum - * the requested one and return the version string; return NULL if the - * condition is not satisfied. If a NULL is passed to this function, - * no check is done, but the version string is simply returned. - * - **/ -const char * -gnutls_extra_check_version (const char *req_version) -{ - if (!req_version || strverscmp (req_version, VERSION) <= 0) - return VERSION; - - return NULL; -} diff --git a/src/daemon/https/openpgp/gnutls_extra.h b/src/daemon/https/openpgp/gnutls_extra.h @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation - * - * Author: Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the - * License, or (at your option) any later version. - * - * GNUTLS-EXTRA 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 GNUTLS-EXTRA; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include <auth_cert.h> - -typedef int (*OPENPGP_VERIFY_KEY_FUNC) (const - mhd_gtls_cert_credentials_t, - const gnutls_datum_t *, int, - unsigned int *); - -typedef time_t (*OPENPGP_KEY_CREATION_TIME_FUNC) (const gnutls_datum_t *); -typedef time_t (*OPENPGP_KEY_EXPIRATION_TIME_FUNC) (const gnutls_datum_t *); -typedef int (*OPENPGP_KEY_REQUEST) (mhd_gtls_session_t, gnutls_datum_t *, - const mhd_gtls_cert_credentials_t, - opaque *, int); - -typedef int (*OPENPGP_FINGERPRINT) (const gnutls_datum_t *, - unsigned char *, size_t *); - -typedef int (*OPENPGP_RAW_KEY_TO_GCERT) (gnutls_cert *, - const gnutls_datum_t *); -typedef int (*OPENPGP_RAW_PRIVKEY_TO_GKEY) (gnutls_privkey *, - const gnutls_datum_t *); - -typedef int (*OPENPGP_KEY_TO_GCERT) (gnutls_cert *, gnutls_openpgp_crt_t); -typedef int (*OPENPGP_PRIVKEY_TO_GKEY) (gnutls_privkey *, - gnutls_openpgp_privkey_t); -typedef void (*OPENPGP_KEY_DEINIT) (gnutls_openpgp_crt_t); -typedef void (*OPENPGP_PRIVKEY_DEINIT) (gnutls_openpgp_privkey_t); diff --git a/src/daemon/https/openpgp/gnutls_ia.c b/src/daemon/https/openpgp/gnutls_ia.c @@ -1,901 +0,0 @@ -/* - * Copyright (C) 2005, 2006 Free Software Foundation - * - * Author: Simon Josefsson - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -#include "gnutls_int.h" -#include "gnutls_record.h" -#include "gnutls_errors.h" -#include "gnutls_num.h" -#include "gnutls_state.h" - -#define CHECKSUM_SIZE 12 - -struct gnutls_ia_client_credentials_st -{ - gnutls_ia_avp_func avp_func; - void *avp_ptr; -}; - -struct gnutls_ia_server_credentials_st -{ - gnutls_ia_avp_func avp_func; - void *avp_ptr; -}; - -static const char server_finished_label[] = "server phase finished"; -static const char client_finished_label[] = "client phase finished"; -static const char inner_permutation_label[] = "inner secret permutation"; -static const char challenge_label[] = "inner application challenge"; - -/* - * The TLS/IA packet is the InnerApplication token, described as - * follows in draft-funk-tls-inner-application-extension-01.txt: - * - * enum { - * application_payload(0), intermediate_phase_finished(1), - * final_phase_finished(2), (255) - * } InnerApplicationType; - * - * struct { - * InnerApplicationType msg_type; - * uint24 length; - * select (InnerApplicationType) { - * case application_payload: ApplicationPayload; - * case intermediate_phase_finished: IntermediatePhaseFinished; - * case final_phase_finished: FinalPhaseFinished; - * } body; - * } InnerApplication; - * - */ - -/* Send TLS/IA data. If data==NULL && sizeofdata==NULL, then the last - send was interrupted for some reason, and then we try to send it - again. Returns the number of bytes sent, or an error code. If - this return E_AGAIN and E_INTERRUPTED, call this function again - with data==NULL&&sizeofdata=0NULL until it returns successfully. */ -static ssize_t -_gnutls_send_inner_application (mhd_gtls_session_t session, - gnutls_ia_apptype_t msg_type, - const char *data, size_t sizeofdata) -{ - opaque *p = NULL; - size_t plen = 0; - ssize_t len; - - if (data != NULL) - { - plen = sizeofdata + 4; - p = gnutls_malloc (plen); - if (!p) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - *(unsigned char *) p = (unsigned char) (msg_type & 0xFF); - mhd_gtls_write_uint24 (sizeofdata, p + 1); - memcpy (p + 4, data, sizeofdata); - } - - len = mhd_gtls_send_int (session, GNUTLS_INNER_APPLICATION, -1, p, plen); - - if (p) - gnutls_free (p); - - return len; -} - -/* Receive TLS/IA data. Store received TLS/IA message type in - *MSG_TYPE, and the data in DATA of max SIZEOFDATA size. Return the - number of bytes read, or an error code. */ -static ssize_t -_gnutls_recv_inner_application (mhd_gtls_session_t session, - gnutls_ia_apptype_t * msg_type, - opaque * data, size_t sizeofdata) -{ - ssize_t len; - opaque pkt[4]; - - len = mhd_gtls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, pkt, 4); - if (len != 4) - { - gnutls_assert (); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - *msg_type = pkt[0]; - len = mhd_gtls_read_uint24 (&pkt[1]); - - if (*msg_type != GNUTLS_IA_APPLICATION_PAYLOAD && len != CHECKSUM_SIZE) - { - gnutls_assert (); - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - - if (sizeofdata < len) - { - /* XXX push back pkt to IA buffer? */ - gnutls_assert (); - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - if (len > 0) - { - int tmplen = len; - - len = mhd_gtls_recv_int (session, GNUTLS_INNER_APPLICATION, -1, - data, tmplen); - if (len != tmplen) - { - gnutls_assert (); - /* XXX Correct? */ - return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - } - } - - return len; -} - -/* Apply the TLS PRF using the TLS/IA inner secret as keying material, - where the seed is the client random concatenated with the server - random concatenated EXTRA of EXTRA_SIZE length (which can be NULL/0 - respectively). LABEL and LABEL_SIZE is used as the label. The - result is placed in pre-allocated OUT of OUTSIZE length. */ -static int -_gnutls_ia_prf (mhd_gtls_session_t session, - size_t label_size, - const char *label, - size_t extra_size, - const char *extra, size_t outsize, opaque * out) -{ - int ret; - opaque *seed; - size_t seedsize = 2 * TLS_RANDOM_SIZE + extra_size; - - seed = gnutls_malloc (seedsize); - if (!seed) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - memcpy (seed, session->security_parameters.server_random, TLS_RANDOM_SIZE); - memcpy (seed + TLS_RANDOM_SIZE, session->security_parameters.client_random, - TLS_RANDOM_SIZE); - memcpy (seed + 2 * TLS_RANDOM_SIZE, extra, extra_size); - - ret = mhd_gtls_PRF (session, session->security_parameters.inner_secret, - TLS_MASTER_SIZE, - label, label_size, seed, seedsize, outsize, out); - - gnutls_free (seed); - - return ret; -} - -/** - * gnutls_ia_permute_inner_secret: - * @session: is a #mhd_gtls_session_t structure. - * @session_keys_size: Size of generated session keys (0 if none). - * @session_keys: Generated session keys, used to permute inner secret - * (NULL if none). - * - * Permute the inner secret using the generated session keys. - * - * This can be called in the TLS/IA AVP callback to mix any generated - * session keys with the TLS/IA inner secret. - * - * Return value: Return zero on success, or a negative error code. - **/ -int -gnutls_ia_permute_inner_secret (mhd_gtls_session_t session, - size_t session_keys_size, - const char *session_keys) -{ - return _gnutls_ia_prf (session, - sizeof (inner_permutation_label) - 1, - inner_permutation_label, - session_keys_size, - session_keys, - TLS_RANDOM_SIZE, - session->security_parameters.inner_secret); -} - -/** - * gnutls_ia_generate_challenge: - * @session: is a #mhd_gtls_session_t structure. - * @buffer_size: size of output buffer. - * @buffer: pre-allocated buffer to contain @buffer_size bytes of output. - * - * Generate an application challenge that the client cannot control or - * predict, based on the TLS/IA inner secret. - * - * Return value: Returns 0 on success, or an negative error code. - **/ -int -gnutls_ia_generate_challenge (mhd_gtls_session_t session, - size_t buffer_size, char *buffer) -{ - return _gnutls_ia_prf (session, - sizeof (challenge_label) - 1, - challenge_label, 0, NULL, buffer_size, buffer); -} - -/** - * gnutls_ia_extract_inner_secret: - * @session: is a #mhd_gtls_session_t structure. - * @buffer: pre-allocated buffer to hold 48 bytes of inner secret. - * - * Copy the 48 bytes large inner secret into the specified buffer - * - * This function is typically used after the TLS/IA handshake has - * concluded. The TLS/IA inner secret can be used as input to a PRF - * to derive session keys. Do not use the inner secret directly as a - * session key, because for a resumed session that does not include an - * application phase, the inner secret will be identical to the inner - * secret in the original session. It is important to include, for - * example, the client and server randomness when deriving a sesssion - * key from the inner secret. - **/ -void -gnutls_ia_extract_inner_secret (mhd_gtls_session_t session, char *buffer) -{ - memcpy (buffer, session->security_parameters.inner_secret, TLS_MASTER_SIZE); -} - -/** - * gnutls_ia_endphase_send: - * @session: is a #mhd_gtls_session_t structure. - * @final_p: Set iff this should signal the final phase. - * - * Send a TLS/IA end phase message. - * - * In the client, this should only be used to acknowledge an end phase - * message sent by the server. - * - * In the server, this can be called instead of gnutls_ia_send() if - * the server wishes to end an application phase. - * - * Return value: Return 0 on success, or an error code. - **/ -int -gnutls_ia_endphase_send (mhd_gtls_session_t session, int final_p) -{ - opaque local_checksum[CHECKSUM_SIZE]; - int client = session->security_parameters.entity == GNUTLS_CLIENT; - const char *label = client ? client_finished_label : server_finished_label; - int size_of_label = client ? sizeof (client_finished_label) : - sizeof (server_finished_label); - ssize_t len; - int ret; - - ret = mhd_gtls_PRF (session, session->security_parameters.inner_secret, - TLS_MASTER_SIZE, label, size_of_label - 1, - /* XXX specification unclear on seed. */ - "", 0, CHECKSUM_SIZE, local_checksum); - if (ret < 0) - return ret; - - len = _gnutls_send_inner_application - (session, - final_p ? GNUTLS_IA_FINAL_PHASE_FINISHED : - GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED, local_checksum, CHECKSUM_SIZE); - - /* XXX Instead of calling this function over and over...? - * while (len == GNUTLS_E_AGAIN || len == GNUTLS_E_INTERRUPTED) - * len = mhd_gtls_io_write_flush(session); - */ - - if (len < 0) - { - gnutls_assert (); - return len; - } - - return 0; -} - -/** - * gnutls_ia_verify_endphase: - * @session: is a #mhd_gtls_session_t structure. - * @checksum: 12-byte checksum data, received from gnutls_ia_recv(). - * - * Verify TLS/IA end phase checksum data. If verification fails, the - * %GNUTLS_A_INNER_APPLICATION_VERIFICATION alert is sent to the other - * sie. - * - * This function is called when gnutls_ia_recv() return - * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or - * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. - * - * Return value: Return 0 on successful verification, or an error - * code. If the checksum verification of the end phase message fails, - * %GNUTLS_E_IA_VERIFY_FAILED is returned. - **/ -int -gnutls_ia_verify_endphase (mhd_gtls_session_t session, const char *checksum) -{ - char local_checksum[CHECKSUM_SIZE]; - int client = session->security_parameters.entity == GNUTLS_CLIENT; - const char *label = client ? server_finished_label : client_finished_label; - int size_of_label = client ? sizeof (server_finished_label) : - sizeof (client_finished_label); - int ret; - - ret = mhd_gtls_PRF (session, session->security_parameters.inner_secret, - TLS_MASTER_SIZE, - label, size_of_label - 1, - "", 0, CHECKSUM_SIZE, local_checksum); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - if (memcmp (local_checksum, checksum, CHECKSUM_SIZE) != 0) - { - ret = MHD_gnutls_alert_send (session, GNUTLS_AL_FATAL, - GNUTLS_A_INNER_APPLICATION_VERIFICATION); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - return GNUTLS_E_IA_VERIFY_FAILED; - } - - return 0; -} - -/** - * gnutls_ia_send: Send peer the specified TLS/IA data. - * @session: is a #mhd_gtls_session_t structure. - * @data: contains the data to send - * @sizeofdata: is the length of the data - * - * Send TLS/IA application payload data. This function has the - * similar semantics with send(). The only difference is that is - * accepts a GNUTLS session, and uses different error codes. - * - * The TLS/IA protocol is synchronous, so you cannot send more than - * one packet at a time. The client always send the first packet. - * - * To finish an application phase in the server, use - * gnutls_ia_endphase_send(). The client cannot end an application - * phase unilaterally; rather, a client is required to respond with an - * endphase of its own if gnutls_ia_recv indicates that the server has - * sent one. - * - * If the EINTR is returned by the internal push function (the default - * is send()} then %GNUTLS_E_INTERRUPTED will be returned. If - * %GNUTLS_E_INTERRUPTED or %GNUTLS_E_AGAIN is returned, you must call - * this function again, with the same parameters; alternatively you - * could provide a %NULL pointer for data, and 0 for size. - * - * Returns the number of bytes sent, or a negative error code. - **/ -ssize_t -gnutls_ia_send (mhd_gtls_session_t session, const char *data, size_t sizeofdata) -{ - ssize_t len; - - len = _gnutls_send_inner_application (session, - GNUTLS_IA_APPLICATION_PAYLOAD, - data, sizeofdata); - - return len; -} - -/** - * gnutls_ia_recv - read data from the TLS/IA protocol - * @session: is a #mhd_gtls_session_t structure. - * @data: the buffer that the data will be read into, must hold >= 12 bytes. - * @sizeofdata: the number of requested bytes, must be >= 12. - * - * Receive TLS/IA data. This function has the similar semantics with - * recv(). The only difference is that is accepts a GNUTLS session, - * and uses different error codes. - * - * If the server attempt to finish an application phase, this function - * will return %GNUTLS_E_WARNING_IA_IPHF_RECEIVED or - * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED. The caller should then invoke - * gnutls_ia_verify_endphase(), and if it runs the client side, also - * send an endphase message of its own using gnutls_ia_endphase_send. - * - * If EINTR is returned by the internal push function (the default is - * @code{recv()}) then GNUTLS_E_INTERRUPTED will be returned. If - * GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN is returned, you must call - * this function again, with the same parameters; alternatively you - * could provide a NULL pointer for data, and 0 for size. - * - * Returns the number of bytes received. A negative error code is - * returned in case of an error. The - * %GNUTLS_E_WARNING_IA_IPHF_RECEIVED and - * %GNUTLS_E_WARNING_IA_FPHF_RECEIVED errors are returned when an - * application phase finished message has been sent by the server. - **/ -ssize_t -gnutls_ia_recv (mhd_gtls_session_t session, char *data, size_t sizeofdata) -{ - gnutls_ia_apptype_t msg_type; - ssize_t len; - - len = _gnutls_recv_inner_application (session, &msg_type, data, sizeofdata); - - if (msg_type == GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED) - return GNUTLS_E_WARNING_IA_IPHF_RECEIVED; - else if (msg_type == GNUTLS_IA_FINAL_PHASE_FINISHED) - return GNUTLS_E_WARNING_IA_FPHF_RECEIVED; - - return len; -} - -int -_gnutls_ia_client_handshake (mhd_gtls_session_t session) -{ - char *buf = NULL; - size_t buflen = 0; - char tmp[1024]; /* XXX */ - ssize_t len; - int ret; - const struct gnutls_ia_client_credentials_st *cred = - mhd_gtls_get_cred (session->key, MHD_GNUTLS_CRD_IA, NULL); - - if (cred == NULL) - return GNUTLS_E_INTERNAL_ERROR; - - while (1) - { - char *avp; - size_t avplen; - - ret = cred->avp_func (session, cred->avp_ptr, - buf, buflen, &avp, &avplen); - if (ret) - { - int tmpret; - tmpret = MHD_gnutls_alert_send (session, GNUTLS_AL_FATAL, - GNUTLS_A_INNER_APPLICATION_FAILURE); - if (tmpret < 0) - gnutls_assert (); - return ret; - } - - len = gnutls_ia_send (session, avp, avplen); - gnutls_free (avp); - if (len < 0) - return len; - - len = gnutls_ia_recv (session, tmp, sizeof (tmp)); - if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || - len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) - { - ret = gnutls_ia_verify_endphase (session, tmp); - if (ret < 0) - return ret; - - ret = gnutls_ia_endphase_send - (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED); - if (ret < 0) - return ret; - } - - if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED) - { - buf = NULL; - buflen = 0; - continue; - } - else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) - break; - - if (len < 0) - return len; - - buflen = len; - buf = tmp; - } - - return 0; -} - -int -_gnutls_ia_server_handshake (mhd_gtls_session_t session) -{ - gnutls_ia_apptype_t msg_type; - ssize_t len; - char buf[1024]; - int ret; - const struct gnutls_ia_server_credentials_st *cred = - mhd_gtls_get_cred (session->key, MHD_GNUTLS_CRD_IA, NULL); - - if (cred == NULL) - return GNUTLS_E_INTERNAL_ERROR; - - do - { - char *avp; - size_t avplen; - - len = gnutls_ia_recv (session, buf, sizeof (buf)); - if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || - len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) - { - ret = gnutls_ia_verify_endphase (session, buf); - if (ret < 0) - return ret; - } - - if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED) - continue; - else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) - break; - - if (len < 0) - return len; - - avp = NULL; - avplen = 0; - - ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen); - if (ret < 0) - { - int tmpret; - tmpret = MHD_gnutls_alert_send (session, GNUTLS_AL_FATAL, - GNUTLS_A_INNER_APPLICATION_FAILURE); - if (tmpret < 0) - gnutls_assert (); - return ret; - } - - msg_type = ret; - - if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD) - { - ret = gnutls_ia_endphase_send (session, msg_type == - GNUTLS_IA_FINAL_PHASE_FINISHED); - if (ret < 0) - return ret; - } - else - { - len = gnutls_ia_send (session, avp, avplen); - gnutls_free (avp); - if (len < 0) - return len; - } - } - while (1); - - return 0; -} - -/** - * gnutls_ia_handshake_p: - * @session: is a #mhd_gtls_session_t structure. - * - * Predicate to be used after MHD_gnutls_handshake() to decide whether to - * invoke gnutls_ia_handshake(). Usable by both clients and servers. - * - * Return value: non-zero if TLS/IA handshake is expected, zero - * otherwise. - **/ -int -gnutls_ia_handshake_p (mhd_gtls_session_t session) -{ - mhd_gtls_ext_st *ext = &session->security_parameters.extensions; - - /* Either local side or peer doesn't do TLS/IA: don't do IA */ - - if (!ext->gnutls_ia_enable || !ext->gnutls_ia_peer_enable) - return 0; - - /* Not resuming or we don't allow skipping on resumption locally: do IA */ - - if (!ext->gnutls_ia_allowskip || !MHD_gtls_session_is_resumed (session)) - return 1; - - /* If we're resuming and we and the peer both allow skipping on resumption: - * don't do IA */ - - return !ext->gnutls_ia_peer_allowskip; -} - - -/** - * gnutls_ia_handshake: - * @session: is a #mhd_gtls_session_t structure. - * - * Perform a TLS/IA handshake. This should be called after - * MHD_gnutls_handshake() iff gnutls_ia_handshake_p(). - * - * Return 0 on success, or an error code. - **/ -int -gnutls_ia_handshake (mhd_gtls_session_t session) -{ - int ret; - - if (session->security_parameters.entity == GNUTLS_CLIENT) - ret = _gnutls_ia_client_handshake (session); - else - ret = _gnutls_ia_server_handshake (session); - - return ret; -} - -/** - * gnutls_ia_allocate_client_credentials - Used to allocate an gnutls_ia_server_credentials_t structure - * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure. - * - * This structure is complex enough to manipulate directly thus this - * helper function is provided in order to allocate it. - * - * Adding this credential to a session will enable TLS/IA, and will - * require an Application Phase after the TLS handshake (if the server - * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the - * TLS/IA mode. - * - * Returns 0 on success. - **/ -int -gnutls_ia_allocate_client_credentials (gnutls_ia_client_credentials_t * sc) -{ - *sc = gnutls_calloc (1, sizeof (**sc)); - - if (*sc == NULL) - return GNUTLS_E_MEMORY_ERROR; - - return 0; -} - -/** - * gnutls_ia_free_client_credentials - Used to free an allocated #gnutls_ia_client_credentials_t structure - * @sc: is an #gnutls_ia_client_credentials_t structure. - * - * This structure is complex enough to manipulate directly thus this - * helper function is provided in order to free (deallocate) it. - * - **/ -void -gnutls_ia_free_client_credentials (gnutls_ia_client_credentials_t sc) -{ - gnutls_free (sc); -} - -/** - * gnutls_ia_set_client_avp_function - Used to set a AVP callback - * @cred: is a #gnutls_ia_client_credentials_t structure. - * @avp_func: is the callback function - * - * Set the TLS/IA AVP callback handler used for the session. - * - * The AVP callback is called to process AVPs received from the - * server, and to get a new AVP to send to the server. - * - * The callback's function form is: - * int (*avp_func) (mhd_gtls_session_t session, void *ptr, - * const char *last, size_t lastlen, - * char **next, size_t *nextlen); - * - * The @session parameter is the #mhd_gtls_session_t structure - * corresponding to the current session. The @ptr parameter is the - * application hook pointer, set through - * gnutls_ia_set_client_avp_ptr(). The AVP received from the server - * is present in @last of @lastlen size, which will be %NULL on the - * first invocation. The newly allocated output AVP to send to the - * server should be placed in *@next of *@nextlen size. - * - * The callback may invoke gnutls_ia_permute_inner_secret() to mix any - * generated session keys with the TLS/IA inner secret. - * - * Return 0 (%GNUTLS_IA_APPLICATION_PAYLOAD) on success, or a negative - * error code to abort the TLS/IA handshake. - * - * Note that the callback must use allocate the @next parameter using - * gnutls_malloc(), because it is released via gnutls_free() by the - * TLS/IA handshake function. - * - **/ -void -gnutls_ia_set_client_avp_function (gnutls_ia_client_credentials_t cred, - gnutls_ia_avp_func avp_func) -{ - cred->avp_func = avp_func; -} - -/** - * gnutls_ia_set_client_avp_ptr - Sets a pointer to be sent to TLS/IA callback - * @cred: is a #gnutls_ia_client_credentials_t structure. - * @ptr: is the pointer - * - * Sets the pointer that will be provided to the TLS/IA callback - * function as the first argument. - * - **/ -void -gnutls_ia_set_client_avp_ptr (gnutls_ia_client_credentials_t cred, void *ptr) -{ - cred->avp_ptr = ptr; -} - -/** - * gnutls_ia_get_client_avp_ptr - Returns the pointer which is sent to TLS/IA callback - * @cred: is a #gnutls_ia_client_credentials_t structure. - * - * Returns the pointer that will be provided to the TLS/IA callback - * function as the first argument. - * - **/ -void * -gnutls_ia_get_client_avp_ptr (gnutls_ia_client_credentials_t cred) -{ - return cred->avp_ptr; -} - -/** - * gnutls_ia_allocate_server_credentials - Used to allocate an gnutls_ia_server_credentials_t structure - * @sc: is a pointer to an #gnutls_ia_server_credentials_t structure. - * - * This structure is complex enough to manipulate directly thus this - * helper function is provided in order to allocate it. - * - * Adding this credential to a session will enable TLS/IA, and will - * require an Application Phase after the TLS handshake (if the client - * support TLS/IA). Use gnutls_ia_require_inner_phase() to toggle the - * TLS/IA mode. - * - * Returns 0 on success. - **/ -int -gnutls_ia_allocate_server_credentials (gnutls_ia_server_credentials_t * sc) -{ - *sc = gnutls_calloc (1, sizeof (**sc)); - - if (*sc == NULL) - return GNUTLS_E_MEMORY_ERROR; - - return 0; -} - -/** - * gnutls_ia_free_server_credentials - Used to free an allocated #gnutls_ia_server_credentials_t structure - * @sc: is an #gnutls_ia_server_credentials_t structure. - * - * This structure is complex enough to manipulate directly thus this - * helper function is provided in order to free (deallocate) it. - * - **/ -void -gnutls_ia_free_server_credentials (gnutls_ia_server_credentials_t sc) -{ - gnutls_free (sc); -} - -/** - * gnutls_ia_set_server_credentials_function - Used to set a AVP callback - * @cred: is a #gnutls_ia_server_credentials_t structure. - * @func: is the callback function - * - * Set the TLS/IA AVP callback handler used for the session. - * - * The callback's function form is: - * int (*avp_func) (mhd_gtls_session_t session, void *ptr, - * const char *last, size_t lastlen, - * char **next, size_t *nextlen); - * - * The @session parameter is the #mhd_gtls_session_t structure - * corresponding to the current session. The @ptr parameter is the - * application hook pointer, set through - * gnutls_ia_set_server_avp_ptr(). The AVP received from the client - * is present in @last of @lastlen size. The newly allocated output - * AVP to send to the client should be placed in *@next of *@nextlen - * size. - * - * The AVP callback is called to process incoming AVPs from the - * client, and to get a new AVP to send to the client. It can also be - * used to instruct the TLS/IA handshake to do go into the - * Intermediate or Final phases. It return a negative error code, or - * an #gnutls_ia_apptype_t message type. - * - * The callback may invoke gnutls_ia_permute_inner_secret() to mix any - * generated session keys with the TLS/IA inner secret. - * - * Specifically, return %GNUTLS_IA_APPLICATION_PAYLOAD (0) to send - * another AVP to the client, return - * %GNUTLS_IA_INTERMEDIATE_PHASE_FINISHED (1) to indicate that an - * IntermediatePhaseFinished message should be sent, and return - * %GNUTLS_IA_FINAL_PHASE_FINISHED (2) to indicate that an - * FinalPhaseFinished message should be sent. In the last two cases, - * the contents of the @next and @nextlen parameter is not used. - * - * Note that the callback must use allocate the @next parameter using - * gnutls_malloc(), because it is released via gnutls_free() by the - * TLS/IA handshake function. - **/ -void -gnutls_ia_set_server_avp_function (gnutls_ia_server_credentials_t cred, - gnutls_ia_avp_func avp_func) -{ - cred->avp_func = avp_func; -} - -/** - * gnutls_ia_set_server_avp_ptr - Sets a pointer to be sent to TLS/IA callback - * @cred: is a #gnutls_ia_client_credentials_t structure. - * @ptr: is the pointer - * - * Sets the pointer that will be provided to the TLS/IA callback - * function as the first argument. - * - **/ -void -gnutls_ia_set_server_avp_ptr (gnutls_ia_server_credentials_t cred, void *ptr) -{ - cred->avp_ptr = ptr; -} - -/** - * gnutls_ia_get_server_avp_ptr - Returns the pointer which is sent to TLS/IA callback - * @cred: is a #gnutls_ia_client_credentials_t structure. - * - * Returns the pointer that will be provided to the TLS/IA callback - * function as the first argument. - * - **/ -void * -gnutls_ia_get_server_avp_ptr (gnutls_ia_server_credentials_t cred) -{ - return cred->avp_ptr; -} - -/** - * gnutls_ia_enable - Indicate willingness for TLS/IA application phases - * @session: is a #mhd_gtls_session_t structure. - * @allow_skip_on_resume: non-zero if local party allows to skip the - * TLS/IA application phases for a resumed session. - * - * Specify whether we must advertise support for the TLS/IA extension - * during the handshake. - * - * At the client side, we always advertise TLS/IA if gnutls_ia_enable - * was called before the handshake; at the server side, we also - * require that the client has advertised that it wants to run TLS/IA - * before including the advertisement, as required by the protocol. - * - * Similarly, at the client side we always advertise that we allow - * TLS/IA to be skipped for resumed sessions if @allow_skip_on_resume - * is non-zero; at the server side, we also require that the session - * is indeed resumable and that the client has also advertised that it - * allows TLS/IA to be skipped for resumed sessions. - * - * After the TLS handshake, call gnutls_ia_handshake_p() to find out - * whether both parties agreed to do a TLS/IA handshake, before - * calling gnutls_ia_handshake() or one of the lower level gnutls_ia_* - * functions. - **/ -void -gnutls_ia_enable (mhd_gtls_session_t session, int allow_skip_on_resume) -{ - session->security_parameters.extensions.gnutls_ia_enable = 1; - session->security_parameters.extensions.gnutls_ia_allowskip = - allow_skip_on_resume; -} diff --git a/src/daemon/https/openpgp/gnutls_openpgp.c b/src/daemon/https/openpgp/gnutls_openpgp.c @@ -1,966 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation - * - * Author: Timo Schulz - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -#include "gnutls_int.h" -#include "gnutls_errors.h" -#include "gnutls_mpi.h" -#include "gnutls_cert.h" -#include "gnutls_datum.h" -#include "gnutls_global.h" -#include "gnutls_openpgp.h" -#include "read-file.h" -#include <gnutls_str.h> -#include <gnutls_sig.h> -#include <stdio.h> -#include <gcrypt.h> -#include <time.h> -#include <sys/stat.h> - -#define OPENPGP_NAME_SIZE 256 - -#define datum_append(x, y, z) mhd_gtls_datum_append_m (x, y, z, gnutls_realloc) - -static void -release_mpi_array (mpi_t * arr, size_t n) -{ - mpi_t x; - - while (arr && n--) - { - x = *arr; - mhd_gtls_mpi_release (&x); - *arr = NULL; - arr++; - } -} - - -/* Map an OpenCDK error type to a GnuTLS error type. */ -int -_gnutls_map_cdk_rc (int rc) -{ - switch (rc) - { - case CDK_Success: - return 0; - case CDK_Too_Short: - return GNUTLS_E_SHORT_MEMORY_BUFFER; - case CDK_General_Error: - return GNUTLS_E_INTERNAL_ERROR; - case CDK_File_Error: - return GNUTLS_E_FILE_ERROR; - case CDK_MPI_Error: - return GNUTLS_E_MPI_SCAN_FAILED; - case CDK_Error_No_Key: - return GNUTLS_E_OPENPGP_GETKEY_FAILED; - case CDK_Armor_Error: - return GNUTLS_E_BASE64_DECODING_ERROR; - case CDK_Inv_Value: - return GNUTLS_E_INVALID_REQUEST; - default: - return GNUTLS_E_INTERNAL_ERROR; - } -} - -static unsigned long -buftou32 (const uint8_t * buf) -{ - unsigned a; - a = buf[0] << 24; - a |= buf[1] << 16; - a |= buf[2] << 8; - a |= buf[3]; - return a; -} - -static int -openpgp_pk_to_gnutls_cert (gnutls_cert * cert, cdk_pkt_pubkey_t pk) -{ - uint8_t buf[512 + 2]; - size_t nbytes; - int algo, i; - int rc = 0; - - if (!cert || !pk) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - /* GnuTLS OpenPGP does not support ELG keys */ - if (is_ELG (pk->pubkey_algo)) - { - gnutls_assert (); - return GNUTLS_E_UNWANTED_ALGORITHM; - } - - algo = MHD_GNUTLS_PK_RSA; - cert->subject_pk_algorithm = algo; - cert->version = pk->version; - cert->cert_type = MHD_GNUTLS_CRT_OPENPGP; - - cert->key_usage = 0; - if (pk->pubkey_usage & CDK_KEY_USG_SIGN) - cert->key_usage = KEY_DIGITAL_SIGNATURE; - if (pk->pubkey_usage & CDK_KEY_USG_ENCR) - cert->key_usage = KEY_KEY_ENCIPHERMENT; - if (!cert->key_usage) /* Fallback code. */ - { - if (pk->pubkey_algo == GCRY_PK_DSA || pk->pubkey_algo == GCRY_PK_RSA_S) - cert->key_usage = KEY_DIGITAL_SIGNATURE; - else if (pk->pubkey_algo == GCRY_PK_RSA_E) - cert->key_usage = KEY_KEY_ENCIPHERMENT; - else if (pk->pubkey_algo == GCRY_PK_RSA) - cert->key_usage = KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT; - } - - cert->params_size = cdk_pk_get_npkey (pk->pubkey_algo); - for (i = 0; i < cert->params_size; i++) - { - nbytes = sizeof (buf) / sizeof (buf[0]); - cdk_pk_get_mpi (pk, i, buf, nbytes, &nbytes, NULL); - rc = mhd_gtls_mpi_scan_pgp (&cert->params[i], buf, &nbytes); - if (rc) - { - rc = GNUTLS_E_MPI_SCAN_FAILED; - break; - } - } - - if (rc) - release_mpi_array (cert->params, i - 1); - return rc; -} - -/*- - * _gnutls_openpgp_raw_privkey_to_gkey - Converts an OpenPGP secret key to GnuTLS - * @pkey: the GnuTLS private key context to store the key. - * @raw_key: the raw data which contains the whole key packets. - * @format: the format of the key packets. - * - * The RFC2440 (OpenPGP Message Format) data is converted into the - * GnuTLS specific data which is need to perform secret key operations. - * - * This function can read both BASE64 and RAW keys. - -*/ -int -_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey, - const gnutls_datum_t * raw_key, - gnutls_openpgp_crt_fmt_t format) -{ - cdk_kbnode_t snode = NULL; - cdk_packet_t pkt; - cdk_stream_t out; - cdk_pkt_seckey_t sk = NULL; - int pke_algo, i, j; - size_t nbytes = 0; - uint8_t buf[512]; - int rc = 0; - - if (!pkey || raw_key->size <= 0) - { - gnutls_assert (); - return GNUTLS_E_CERTIFICATE_ERROR; - } - - rc = cdk_stream_tmp_new (&out); - if (rc) - return GNUTLS_E_CERTIFICATE_ERROR; - - if (format == GNUTLS_OPENPGP_FMT_BASE64) - { - rc = cdk_stream_set_armor_flag (out, 0); - if (rc) - { - cdk_stream_close (out); - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - goto leave; - } - } - - cdk_stream_write (out, raw_key->data, raw_key->size); - cdk_stream_seek (out, 0); - - rc = cdk_keydb_get_keyblock (out, &snode); - cdk_stream_close (out); - if (rc) - { - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - goto leave; - } - - pkt = cdk_kbnode_find_packet (snode, CDK_PKT_SECRET_KEY); - if (!pkt) - { - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - goto leave; - } - sk = pkt->pkt.secret_key; - pke_algo = sk->pk->pubkey_algo; - pkey->params_size = cdk_pk_get_npkey (pke_algo); - for (i = 0; i < pkey->params_size; i++) - { - nbytes = sizeof (buf) / sizeof (buf[0]); - cdk_pk_get_mpi (sk->pk, i, buf, nbytes, &nbytes, NULL); - rc = mhd_gtls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes); - if (rc) - { - rc = GNUTLS_E_MPI_SCAN_FAILED; - release_mpi_array (pkey->params, i - 1); - goto leave; - } - } - - pkey->params_size += cdk_pk_get_nskey (pke_algo); - for (j = 0; j < cdk_pk_get_nskey (pke_algo); j++, i++) - { - nbytes = sizeof (buf) / sizeof (buf[0]); - cdk_sk_get_mpi (sk, j, buf, nbytes, &nbytes, NULL); - rc = mhd_gtls_mpi_scan_pgp (&pkey->params[i], buf, &nbytes); - if (rc) - { - rc = GNUTLS_E_MPI_SCAN_FAILED; - release_mpi_array (pkey->params, i - 1); - goto leave; - } - } - - if (is_ELG (pke_algo)) - return GNUTLS_E_UNWANTED_ALGORITHM; - else if (is_RSA (pke_algo)) - pkey->pk_algorithm = MHD_GNUTLS_PK_RSA; - -leave: - cdk_kbnode_release (snode); - return rc; -} - -/*- - * _gnutls_openpgp_raw_key_to_gcert - Converts raw OpenPGP data to GnuTLS certs - * @cert: the certificate to store the data. - * @raw: the buffer which contains the whole OpenPGP key packets. - * - * The RFC2440 (OpenPGP Message Format) data is converted to a GnuTLS - * specific certificate. - -*/ -int -_gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert, - const gnutls_datum_t * raw) -{ - cdk_kbnode_t knode = NULL; - cdk_packet_t pkt = NULL; - int rc; - - if (!cert) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - memset (cert, 0, sizeof *cert); - - rc = cdk_kbnode_read_from_mem (&knode, raw->data, raw->size); - if (!(rc = _gnutls_map_cdk_rc (rc))) - { - pkt = cdk_kbnode_find_packet (knode, CDK_PKT_PUBLIC_KEY); - } - if (!pkt) - { - gnutls_assert (); - rc = _gnutls_map_cdk_rc (rc); - } - if (!rc) - rc = _gnutls_set_datum (&cert->raw, raw->data, raw->size); - if (!rc) - rc = openpgp_pk_to_gnutls_cert (cert, pkt->pkt.public_key); - - cdk_kbnode_release (knode); - return rc; -} - -/** - * gnutls_certificate_set_openpgp_key - Used to set keys in a mhd_gtls_cert_credentials_t structure - * @res: is an #mhd_gtls_cert_credentials_t structure. - * @key: contains an openpgp public key - * @pkey: is an openpgp private key - * - * This function sets a certificate/private key pair in the - * mhd_gtls_cert_credentials_t structure. This function may be called - * more than once (in case multiple keys/certificates exist for the - * server). - * - **/ -int -gnutls_certificate_set_openpgp_key (mhd_gtls_cert_credentials_t - res, gnutls_openpgp_crt_t crt, - gnutls_openpgp_privkey_t pkey) -{ - int ret; - - /* this should be first */ - - res->pkey = mhd_gtls_realloc_fast (res->pkey, - (res->ncerts + 1) * - sizeof (gnutls_privkey)); - if (res->pkey == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - ret = _gnutls_openpgp_privkey_to_gkey (&res->pkey[res->ncerts], pkey); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - res->cert_list = mhd_gtls_realloc_fast (res->cert_list, - (1 + - res->ncerts) * - sizeof (gnutls_cert *)); - if (res->cert_list == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list_length = mhd_gtls_realloc_fast (res->cert_list_length, - (1 + - res->ncerts) * sizeof (int)); - if (res->cert_list_length == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list[res->ncerts] = gnutls_calloc (1, sizeof (gnutls_cert)); - if (res->cert_list[res->ncerts] == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - res->cert_list_length[res->ncerts] = 1; - - ret = _gnutls_openpgp_crt_to_gcert (res->cert_list[res->ncerts], crt); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - res->ncerts++; - - /* FIXME: Check if the keys match. */ - - return 0; -} - - -/*- - * gnutls_openpgp_get_key - Retrieve a key from the keyring. - * @key: the destination context to save the key. - * @keyring: the datum struct that contains all keyring information. - * @attr: The attribute (keyid, fingerprint, ...). - * @by: What attribute is used. - * - * This function can be used to retrieve keys by different pattern - * from a binary or a file keyring. - -*/ -int -gnutls_openpgp_get_key (gnutls_datum_t * key, - gnutls_openpgp_keyring_t keyring, key_attr_t by, - opaque * pattern) -{ - cdk_kbnode_t knode = NULL; - unsigned long keyid[2]; - unsigned char *buf; - void *desc; - size_t len; - int rc = 0; - - if (!key || !keyring || by == KEY_ATTR_NONE) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - memset (key, 0, sizeof *key); - - if (by == KEY_ATTR_SHORT_KEYID) - { - keyid[0] = buftou32 (pattern); - desc = keyid; - } - else if (by == KEY_ATTR_KEYID) - { - keyid[0] = buftou32 (pattern); - keyid[1] = buftou32 (pattern + 4); - desc = keyid; - } - else - desc = pattern; - rc = cdk_keydb_search_start (keyring->db, by, desc); - if (!rc) - rc = cdk_keydb_search (keyring->db, &knode); - if (rc) - { - rc = _gnutls_map_cdk_rc (rc); - goto leave; - } - - if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY)) - { - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - goto leave; - } - - /* We let the function allocate the buffer to avoid - to call the function twice. */ - rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len); - if (!rc) - datum_append (key, buf, len); - cdk_free (buf); - -leave: - cdk_kbnode_release (knode); - return rc; -} - - -/* Convert the stream to a datum. In this case we use the mmap - function to map the entire stream to a buffer. */ -static int -stream_to_datum (cdk_stream_t inp, gnutls_datum_t * raw) -{ - uint8_t *buf; - size_t buflen; - - if (!inp || !raw) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - cdk_stream_mmap (inp, &buf, &buflen); - datum_append (raw, buf, buflen); - cdk_free (buf); - - if (!buflen) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } - - return 0; -} - - - -/** - * gnutls_certificate_set_openpgp_key_mem - Used to set OpenPGP keys - * @res: the destination context to save the data. - * @cert: the datum that contains the public key. - * @key: the datum that contains the secret key. - * - * This funtion is used to load OpenPGP keys into the GnuTLS credential - * structure. - * It doesn't matter whether the keys are armored or not, but the files - * should only contain one key which should not be encrypted. - **/ -int -gnutls_certificate_set_openpgp_key_mem (mhd_gtls_cert_credentials_t - res, const gnutls_datum_t * icert, - const gnutls_datum_t * ikey, - gnutls_openpgp_crt_fmt_t format) -{ - gnutls_openpgp_privkey_t key; - gnutls_openpgp_crt_t cert; - int ret; - - ret = gnutls_openpgp_privkey_init (&key); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - - ret = gnutls_openpgp_privkey_import (key, ikey, format, NULL, 0); - if (ret < 0) - { - gnutls_assert (); - gnutls_openpgp_privkey_deinit (key); - return ret; - } - - ret = gnutls_openpgp_crt_init (&cert); - if (ret < 0) - { - gnutls_assert (); - gnutls_openpgp_privkey_deinit (key); - return ret; - } - - ret = gnutls_openpgp_crt_import (cert, icert, format); - if (ret < 0) - { - gnutls_assert (); - gnutls_openpgp_privkey_deinit (key); - gnutls_openpgp_crt_deinit (cert); - return ret; - } - - - ret = gnutls_certificate_set_openpgp_key (res, cert, key); - - gnutls_openpgp_privkey_deinit (key); - gnutls_openpgp_crt_deinit (cert); - - return ret; -} - - -/** - * gnutls_certificate_set_openpgp_key_file - Used to set OpenPGP keys - * @res: the destination context to save the data. - * @certfile: the file that contains the public key. - * @keyfile: the file that contains the secret key. - * - * This funtion is used to load OpenPGP keys into the GnuTLS credentials structure. - * It doesn't matter whether the keys are armored or not, but the files - * should only contain one key which should not be encrypted. - **/ -int -gnutls_certificate_set_openpgp_key_file (mhd_gtls_cert_credentials_t - res, const char *certfile, - const char *keyfile, - gnutls_openpgp_crt_fmt_t format) -{ - struct stat statbuf; - gnutls_datum_t key, cert; - int rc; - size_t size; - - if (!res || !keyfile || !certfile) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - if (stat (certfile, &statbuf) || stat (keyfile, &statbuf)) - { - gnutls_assert (); - return GNUTLS_E_FILE_ERROR; - } - - cert.data = read_binary_file (certfile, &size); - cert.size = (unsigned int) size; - if (cert.data == NULL) - { - gnutls_assert (); - return GNUTLS_E_FILE_ERROR; - } - - key.data = read_binary_file (keyfile, &size); - key.size = (unsigned int) size; - if (key.data == NULL) - { - gnutls_assert (); - free (cert.data); - return GNUTLS_E_FILE_ERROR; - } - - rc = gnutls_certificate_set_openpgp_key_mem (res, &cert, &key, format); - - free (cert.data); - free (key.data); - - if (rc < 0) - { - gnutls_assert (); - return rc; - } - - return 0; -} - - -int -gnutls_openpgp_count_key_names (const gnutls_datum_t * cert) -{ - cdk_kbnode_t knode, p, ctx; - cdk_packet_t pkt; - int nuids; - - if (cert == NULL) - { - gnutls_assert (); - return 0; - } - - if (cdk_kbnode_read_from_mem (&knode, cert->data, cert->size)) - { - gnutls_assert (); - return 0; - } - - ctx = NULL; - for (nuids = 0;;) - { - p = cdk_kbnode_walk (knode, &ctx, 0); - if (!p) - break; - pkt = cdk_kbnode_get_packet (p); - if (pkt->pkttype == CDK_PKT_USER_ID) - nuids++; - } - - cdk_kbnode_release (knode); - return nuids; -} - - -/** - * gnutls_certificate_set_openpgp_keyring_file - Sets a keyring file for OpenPGP - * @c: A certificate credentials structure - * @file: filename of the keyring. - * - * The function is used to set keyrings that will be used internally - * by various OpenPGP functions. For example to find a key when it - * is needed for an operations. The keyring will also be used at the - * verification functions. - * - **/ -int -gnutls_certificate_set_openpgp_keyring_file (mhd_gtls_cert_credentials_t - c, const char *file, - gnutls_openpgp_crt_fmt_t format) -{ - gnutls_datum_t ring; - size_t size; - int rc; - - if (!c || !file) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - ring.data = read_binary_file (file, &size); - ring.size = (unsigned int) size; - if (ring.data == NULL) - { - gnutls_assert (); - return GNUTLS_E_FILE_ERROR; - } - - rc = - gnutls_certificate_set_openpgp_keyring_mem (c, ring.data, ring.size, - format); - - free (ring.data); - - return rc; -} - -/** - * gnutls_certificate_set_openpgp_keyring_mem - Add keyring data for OpenPGP - * @c: A certificate credentials structure - * @data: buffer with keyring data. - * @dlen: length of data buffer. - * - * The function is used to set keyrings that will be used internally - * by various OpenPGP functions. For example to find a key when it - * is needed for an operations. The keyring will also be used at the - * verification functions. - * - **/ -int -gnutls_certificate_set_openpgp_keyring_mem (mhd_gtls_cert_credentials_t - c, const opaque * data, - size_t dlen, - gnutls_openpgp_crt_fmt_t format) -{ -#ifndef KEYRING_HACK - cdk_stream_t inp; - size_t count; - uint8_t *buf; - gnutls_datum ddata; - int rc; - - ddata.data = (void *) data; - ddata.size = dlen; - - if (!c || !data || !dlen) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - rc = gnutls_openpgp_keyring_init (&c->keyring); - if (rc < 0) - { - gnutls_assert (); - return rc; - } - - rc = gnutls_openpgp_keyring_import (c->keyring, &ddata, format); - if (rc < 0) - { - gnutls_assert (); - gnutls_openpgp_keyring_deinit (c->keyring); - return rc; - } -#else - c->keyring_format = format; - c->keyring.data = gnutls_malloc (dlen + 1); - if (c->keyring.data == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - memcpy (c->keyring.data, data, dlen); - c->keyring.data[dlen] = 0; - c->keyring.size = dlen; -#endif - return 0; -} - -/*- - * _gnutls_openpgp_request_key - Receives a key from a database, key server etc - * @ret - a pointer to gnutls_datum_t structure. - * @cred - a mhd_gtls_cert_credentials_t structure. - * @key_fingerprint - The keyFingerprint - * @key_fingerprint_size - the size of the fingerprint - * - * Retrieves a key from a local database, keyring, or a key server. The - * return value is locally allocated. - * - -*/ -int -_gnutls_openpgp_request_key (mhd_gtls_session_t session, gnutls_datum_t * ret, - const mhd_gtls_cert_credentials_t cred, - opaque * key_fpr, int key_fpr_size) -{ - int rc = 0; -#ifdef KEYRING_HACK - gnutls_openpgp_keyring_t kring; -#endif - - if (!ret || !cred || !key_fpr) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - if (key_fpr_size != 16 && key_fpr_size != 20) - return GNUTLS_E_HASH_FAILED; /* only MD5 and SHA1 are supported */ - -#ifndef KEYRING_HACK - rc = gnutls_openpgp_get_key (ret, cred->keyring, KEY_ATTR_FPR, key_fpr); -#else - rc = gnutls_openpgp_keyring_init (&kring); - if (rc < 0) - { - gnutls_assert (); - return rc; - } - - rc = - gnutls_openpgp_keyring_import (kring, &cred->keyring, - cred->keyring_format); - if (rc < 0) - { - gnutls_assert (); - gnutls_openpgp_keyring_deinit (kring); - return rc; - } -#endif - if (rc >= 0) /* key was found */ - { - rc = 0; - goto error; - } - else - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - - /* If the callback function was set, then try this one. */ - if (session->internals.openpgp_recv_key_func != NULL) - { - rc = session->internals.openpgp_recv_key_func (session, - key_fpr, - key_fpr_size, ret); - if (rc < 0) - { - gnutls_assert (); - rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; - goto error; - } - } - -error: -#ifdef KEYRING_HACK - gnutls_openpgp_keyring_deinit (kring); -#endif - return rc; -} - -/** - * gnutls_openpgp_set_recv_key_function - Used to set a key retrieval callback for PGP keys - * @session: a TLS session - * @func: the callback - * - * This funtion will set a key retrieval function for OpenPGP keys. This - * callback is only useful in server side, and will be used if the peer - * sent a key fingerprint instead of a full key. - * - **/ -void -gnutls_openpgp_set_recv_key_function (mhd_gtls_session_t session, - mhd_gtls_openpgp_recv_key_func func) -{ - session->internals.openpgp_recv_key_func = func; -} - - -/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */ -int -_gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest, - gnutls_openpgp_privkey_t src) -{ - int i, ret; - - memset (dest, 0, sizeof (gnutls_privkey)); - - for (i = 0; i < src->pkey.params_size; i++) - { - dest->params[i] = _gnutls_mpi_copy (src->pkey.params[i]); - if (dest->params[i] == NULL) - { - gnutls_assert (); - ret = GNUTLS_E_MEMORY_ERROR; - goto cleanup; - } - } - - dest->pk_algorithm = src->pkey.pk_algorithm; - dest->params_size = src->pkey.params_size; - - return 0; - -cleanup: - for (i = 0; i < src->pkey.params_size; i++) - mhd_gtls_mpi_release (&dest->params[i]); - return ret; -} - -/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure. - */ -int -_gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) -{ - opaque *der; - size_t der_size = 0; - gnutls_datum_t raw; - int ret; - - memset (gcert, 0, sizeof (gnutls_cert)); - gcert->cert_type = MHD_GNUTLS_CRT_OPENPGP; - - - ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, - NULL, &der_size); - if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) - { - gnutls_assert (); - return ret; - } - - der = gnutls_malloc (der_size); - if (der == NULL) - { - gnutls_assert (); - return GNUTLS_E_MEMORY_ERROR; - } - - ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, - der, &der_size); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (der); - return ret; - } - - raw.data = der; - raw.size = der_size; - - ret = _gnutls_openpgp_raw_key_to_gcert (gcert, &raw); - if (ret < 0) - { - gnutls_assert (); - gnutls_free (der); - return ret; - } - - gnutls_free (der); - - return 0; - -} - - -/** - * gnutls_openpgp_privkey_sign_hash - This function will sign the given data using the private key params - * @key: Holds the key - * @hash: holds the data to be signed - * @signature: will contain newly allocated signature - * - * This function will sign the given hash using the private key. - * - * Return value: In case of failure a negative value will be returned, - * and 0 on success. - **/ -int -gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, - const gnutls_datum_t * hash, - gnutls_datum_t * signature) -{ - int result; - - if (key == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - result = mhd_gtls_sign (key->pkey.pk_algorithm, key->pkey.params, - key->pkey.params_size, hash, signature); - if (result < 0) - { - gnutls_assert (); - return result; - } - - return 0; -} diff --git a/src/daemon/https/openpgp/gnutls_openpgp.h b/src/daemon/https/openpgp/gnutls_openpgp.h @@ -1,98 +0,0 @@ -#include <config.h> - -#if ENABLE_OPENPGP - -#ifndef GNUTLS_OPENPGP_H -#define GNUTLS_OPENPGP_H - -#include <auth_cert.h> -#include <opencdk.h> - -typedef struct - { - int type; - size_t size; - uint8_t *data; - }keybox_blob; - -typedef enum - { - KBX_BLOB_FILE = 0x00, - KBX_BLOB_DATA = 0x01 - }keyring_blob_types; - -/* OpenCDK compatible */ -typedef enum - { - KEY_ATTR_NONE = 0, - KEY_ATTR_SHORT_KEYID = 3, - KEY_ATTR_KEYID = 4, - KEY_ATTR_FPR = 5 - }key_attr_t; - -int -gnutls_certificate_set_openpgp_key_file (mhd_gtls_cert_credentials_t - res, const char *CERTFILE, - const char *KEYFILE, gnutls_openpgp_crt_fmt_t); - -int gnutls_openpgp_count_key_names (const gnutls_datum_t * cert); - -int gnutls_certificate_set_openpgp_keyring_file -(mhd_gtls_cert_credentials_t c, const char *file, gnutls_openpgp_crt_fmt_t); - -int -gnutls_certificate_set_openpgp_keyring_mem (mhd_gtls_cert_credentials_t - c, const opaque * data, - size_t dlen, gnutls_openpgp_crt_fmt_t); - -int gnutls_openpgp_get_key (gnutls_datum_t * key, - gnutls_openpgp_keyring_t keyring, - key_attr_t by, opaque * pattern); - -int gnutls_openpgp_recv_key (const char *host, - short port, uint32_t keyid, - gnutls_datum_t * key); - -/* internal */ -int _gnutls_openpgp_raw_key_to_gcert (gnutls_cert * cert, - const gnutls_datum_t * raw); - -extern int -_gnutls_openpgp_raw_privkey_to_gkey (gnutls_privkey * pkey, - const gnutls_datum_t * raw_key, - gnutls_openpgp_crt_fmt_t format); - -int -_gnutls_openpgp_request_key (mhd_gtls_session_t, - gnutls_datum_t * ret, - const mhd_gtls_cert_credentials_t cred, - opaque * key_fpr, int key_fpr_size); - -int _gnutls_openpgp_verify_key (const mhd_gtls_cert_credentials_t, - const gnutls_datum_t * cert_list, - int cert_list_length, unsigned int *status); -int _gnutls_openpgp_fingerprint (const gnutls_datum_t * cert, - unsigned char *fpr, size_t * fprlen); -time_t _gnutls_openpgp_get_raw_key_creation_time (const gnutls_datum_t * - cert); -time_t _gnutls_openpgp_get_raw_key_expiration_time (const gnutls_datum_t * - cert); - -int -gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); - -int -gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key); - -void -gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key); - -int -gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format, - const char *pass, unsigned int flags); - -#endif /*GNUTLS_OPENPGP_H */ - -#endif /*ENABLE_OPENPGP */ diff --git a/src/daemon/https/openpgp/openpgp.h b/src/daemon/https/openpgp/openpgp.h @@ -1,182 +0,0 @@ -#ifndef OPENPGP_H -#define OPENPGP_H - -#include "config.h" - -#if ENABLE_OPENPGP - -#ifdef __cplusplus -extern "C" - { -#endif - -#include <gnutls.h> -#include "opencdk.h" -#include <gnutls_cert.h> - -/* Internal context to store the OpenPGP key. */ -typedef struct gnutls_openpgp_crt_int - { - cdk_kbnode_t knode; - } gnutls_openpgp_crt_int; - -/* Internal context to store the private OpenPGP key. */ -typedef struct gnutls_openpgp_privkey_int - { - gnutls_privkey pkey; - } gnutls_openpgp_privkey_int; - -typedef struct gnutls_openpgp_keyring_int - { - cdk_keydb_hd_t db; - cdk_stream_t db_stream; - } gnutls_openpgp_keyring_int; - -typedef struct gnutls_openpgp_keyring_int * gnutls_openpgp_keyring_t; -/* gnutls_openpgp_cert_t should be defined in gnutls.h */ - -/* initializes the memory for gnutls_openpgp_crt_t struct */ -int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key); -/* frees all memory */ -void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key); - -int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format); -int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key, - gnutls_openpgp_crt_fmt_t format, - void *output_data, - size_t * output_data_size); - -/* The key_usage flags are defined in gnutls.h. They are - * the GNUTLS_KEY_* definitions. - */ -int gnutls_openpgp_crt_get_key_usage(gnutls_openpgp_crt_t cert, - unsigned int *key_usage); -int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key, - void *fpr, - size_t * fprlen); - -int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key, - int idx, - char *buf, - size_t * sizeof_buf); - -gnutls_pk_algorithm_t - gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key, - unsigned int *bits); - -int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key); - -time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key); -time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key); - -int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key, - unsigned char keyid[8]); - -int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key, - const char *hostname); - -/* privkey stuff. */ -int gnutls_openpgp_privkey_init(gnutls_openpgp_privkey_t * key); -void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey_t key); -gnutls_pk_algorithm_t - gnutls_openpgp_privkey_get_pk_algorithm(gnutls_openpgp_privkey_t key, - unsigned int *bits); -int gnutls_openpgp_privkey_import(gnutls_openpgp_privkey_t key, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format, - const char *pass, - unsigned int flags); -int gnutls_openpgp_privkey_sign_hash(gnutls_openpgp_privkey_t key, - const gnutls_datum_t * hash, - gnutls_datum_t * signature); - -/* Keyring stuff. */ - -int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring); -void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring); - -int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format); - -int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring, - const unsigned char keyid[8], - unsigned int flags); - -int gnutls_openpgp_crt_verify_ring(gnutls_openpgp_crt_t key, - gnutls_openpgp_keyring_t keyring, - unsigned int flags, - unsigned int *verify -/* the output of the verification */); - -int gnutls_openpgp_crt_verify_self(gnutls_openpgp_crt_t key, - unsigned int flags, - unsigned int *verify); - -/* certificate authentication stuff. - */ -int gnutls_certificate_set_openpgp_key(mhd_gtls_cert_credentials_t - res, - gnutls_openpgp_crt_t key, - gnutls_openpgp_privkey_t pkey); - -#ifdef __cplusplus -} -#endif - -int _gnutls_map_cdk_rc(int rc); -int gnutls_openpgp_crt_get_name(gnutls_openpgp_crt_t key, - int idx, - char *buf, - size_t * sizeof_buf); -int gnutls_openpgp_crt_get_fingerprint(gnutls_openpgp_crt_t key, - void *fpr, - size_t * fprlen); -gnutls_pk_algorithm_t - gnutls_openpgp_crt_get_pk_algorithm(gnutls_openpgp_crt_t key, - unsigned int *bits); -int gnutls_openpgp_crt_get_version(gnutls_openpgp_crt_t key); -time_t gnutls_openpgp_crt_get_creation_time(gnutls_openpgp_crt_t key); -time_t gnutls_openpgp_crt_get_expiration_time(gnutls_openpgp_crt_t key); -int gnutls_openpgp_crt_get_id(gnutls_openpgp_crt_t key, - unsigned char keyid[8]); - -int gnutls_openpgp_crt_init(gnutls_openpgp_crt_t * key); -void gnutls_openpgp_crt_deinit(gnutls_openpgp_crt_t key); -int gnutls_openpgp_crt_import(gnutls_openpgp_crt_t key, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format); -int gnutls_openpgp_crt_export(gnutls_openpgp_crt_t key, - gnutls_openpgp_crt_fmt_t format, - void *output_data, - size_t * output_data_size); - -void gnutls_openpgp_keyring_deinit(gnutls_openpgp_keyring_t keyring); -int gnutls_openpgp_keyring_init(gnutls_openpgp_keyring_t * keyring); -int gnutls_openpgp_keyring_import(gnutls_openpgp_keyring_t keyring, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format); -int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring, - const unsigned char keyid[8], - unsigned int flags); - -int gnutls_openpgp_crt_verify_ring(gnutls_openpgp_crt_t key, - gnutls_openpgp_keyring_t keyring, - unsigned int flags, - unsigned int *verify); - -int gnutls_openpgp_crt_verify_self(gnutls_openpgp_crt_t key, - unsigned int flags, - unsigned int *verify); - -int _gnutls_openpgp_crt_to_gcert(gnutls_cert * gcert, - gnutls_openpgp_crt_t cert); -int _gnutls_openpgp_privkey_to_gkey(gnutls_privkey * dest, - gnutls_openpgp_privkey_t src); - -void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey_t key); - -#endif /* ENABLE_OPENPGP */ -#endif /* OPENPGP_H */ diff --git a/src/daemon/https/openpgp/pgp.c b/src/daemon/https/openpgp/pgp.c @@ -1,543 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation - * - * Author: Timo Schulz, Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -/* Functions on OpenPGP key parsing - */ - -#include <gnutls_int.h> -#include <gnutls_datum.h> -#include <gnutls_global.h> -#include <gnutls_errors.h> -#include "openpgp.h" -/* x509 */ -#include <rfc2818.h> - -/** - * gnutls_openpgp_crt_init - This function initializes a gnutls_openpgp_crt_t structure - * @key: The structure to be initialized - * - * This function will initialize an OpenPGP key structure. - * - * Returns 0 on success. - * - **/ -int -gnutls_openpgp_crt_init (gnutls_openpgp_crt_t * key) -{ - *key = gnutls_calloc (1, sizeof (gnutls_openpgp_crt_int)); - - if (*key) - return 0; /* success */ - return GNUTLS_E_MEMORY_ERROR; -} - -/** - * gnutls_openpgp_crt_deinit - This function deinitializes memory used by a gnutls_openpgp_crt_t structure - * @key: The structure to be initialized - * - * This function will deinitialize a key structure. - **/ -void -gnutls_openpgp_crt_deinit (gnutls_openpgp_crt_t key) -{ - if (!key) - return; - - if (key->knode) - { - cdk_kbnode_release (key->knode); - key->knode = NULL; - } - - gnutls_free (key); -} - -/** - * gnutls_openpgp_crt_import - This function will import a RAW or BASE64 encoded key - * @key: The structure to store the parsed key. - * @data: The RAW or BASE64 encoded key. - * @format: One of gnutls_openpgp_crt_fmt_t elements. - * - * This function will convert the given RAW or Base64 encoded key - * to the native gnutls_openpgp_crt_t format. The output will be stored in 'key'. - * - * Returns 0 on success. - **/ -int -gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format) -{ - cdk_stream_t inp; - int rc; - - if (format == GNUTLS_OPENPGP_FMT_RAW) - rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size); - else - { - rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp); - if (rc) - { - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - return rc; - } - if (cdk_armor_filter_use (inp)) - rc = cdk_stream_set_armor_flag (inp, 0); - if (!rc) - rc = cdk_keydb_get_keyblock (inp, &key->knode); - cdk_stream_close (inp); - if (rc) - { - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - return rc; - } - } - - return 0; -} - -/** - * gnutls_openpgp_crt_export - This function will export a RAW or BASE64 encoded key - * @key: Holds the key. - * @format: One of gnutls_openpgp_crt_fmt_t elements. - * @output_data: will contain the key base64 encoded or raw - * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters) - * - * This function will convert the given key to RAW or Base64 format. - * If the buffer provided is not long enough to hold the output, then - * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. - * - * Returns 0 on success. - * - **/ -int -gnutls_openpgp_crt_export (gnutls_openpgp_crt_t key, - gnutls_openpgp_crt_fmt_t format, - void *output_data, size_t * output_data_size) -{ - size_t input_data_size = *output_data_size; - size_t calc_size; - int rc; - - rc = cdk_kbnode_write_to_mem (key->knode, output_data, output_data_size); - if (rc) - { - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - return rc; - } - - /* FIXME: The first call of this function is with output_data == NULL - to figure out the size and the caller expects this error here. */ - if (!output_data) - return GNUTLS_E_SHORT_MEMORY_BUFFER; - - if (format == GNUTLS_OPENPGP_FMT_BASE64) - { - unsigned char *in = cdk_calloc (1, *output_data_size); - memcpy (in, output_data, *output_data_size); - - /* Calculate the size of the encoded data and check if the provided - buffer is large enough. */ - rc = cdk_armor_encode_buffer (in, input_data_size, - NULL, 0, &calc_size, CDK_ARMOR_PUBKEY); - if (rc || calc_size > input_data_size) - { - cdk_free (in); - *output_data_size = calc_size; - rc = _gnutls_map_cdk_rc (CDK_Too_Short); - gnutls_assert (); - return rc; - } - - rc = cdk_armor_encode_buffer (in, input_data_size, output_data, - input_data_size, &calc_size, - CDK_ARMOR_PUBKEY); - cdk_free (in); - *output_data_size = calc_size; - } - - return 0; -} - -/** - * gnutls_openpgp_crt_get_fingerprint - Gets the fingerprint - * @key: the raw data that contains the OpenPGP public key. - * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes. - * @fprlen: the integer to save the length of the fingerprint. - * - * Returns the fingerprint of the OpenPGP key. Depends on the algorithm, - * the fingerprint can be 16 or 20 bytes. - **/ -int -gnutls_openpgp_crt_get_fingerprint (gnutls_openpgp_crt_t key, - void *fpr, size_t * fprlen) -{ - cdk_packet_t pkt; - cdk_pkt_pubkey_t pk = NULL; - - if (!fpr || !fprlen) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - *fprlen = 0; - - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (!pkt) - return GNUTLS_E_OPENPGP_GETKEY_FAILED; - - pk = pkt->pkt.public_key; - *fprlen = 20; - - /* FIXME: Check if the draft allows old PGP keys. */ - if (is_RSA (pk->pubkey_algo) && pk->version < 4) - *fprlen = 16; - cdk_pk_get_fingerprint (pk, fpr); - - return 0; -} - -int -_gnutls_openpgp_count_key_names (gnutls_openpgp_crt_t key) -{ - cdk_kbnode_t p, ctx; - cdk_packet_t pkt; - int nuids; - - if (key == NULL) - { - gnutls_assert (); - return 0; - } - - ctx = NULL; - nuids = 0; - while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) - { - pkt = cdk_kbnode_get_packet (p); - if (pkt->pkttype == CDK_PKT_USER_ID) - nuids++; - } - - return nuids; -} - -/** - * gnutls_openpgp_crt_get_name - Extracts the userID - * @key: the structure that contains the OpenPGP public key. - * @idx: the index of the ID to extract - * @buf: a pointer to a structure to hold the name - * @sizeof_buf: holds the maximum size of @buf, on return hold the - * actual/required size of @buf. - * - * Extracts the userID from the parsed OpenPGP key. - * - * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE - * if the index of the ID does not exist. - * - **/ -int -gnutls_openpgp_crt_get_name (gnutls_openpgp_crt_t key, - int idx, char *buf, size_t * sizeof_buf) -{ - cdk_kbnode_t ctx = NULL, p; - cdk_packet_t pkt = NULL; - cdk_pkt_userid_t uid = NULL; - int pos = 0; - - if (!key || !buf) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key)) - return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; - - if (!idx) - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID); - else - { - pos = 0; - while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) - { - pkt = cdk_kbnode_get_packet (p); - if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx) - break; - } - } - - if (!pkt) - { - gnutls_assert (); - return GNUTLS_E_INTERNAL_ERROR; - } - - uid = pkt->pkt.user_id; - if (uid->len >= *sizeof_buf) - { - gnutls_assert (); - *sizeof_buf = uid->len + 1; - return GNUTLS_E_SHORT_MEMORY_BUFFER; - } - - memcpy (buf, uid->name, uid->len); - buf[uid->len] = '\0'; /* make sure it's a string */ - *sizeof_buf = uid->len + 1; - - if (uid->is_revoked) - return GNUTLS_E_OPENPGP_UID_REVOKED; - - return 0; -} - -/** - * gnutls_openpgp_crt_get_pk_algorithm - This function returns the key's PublicKey algorithm - * @key: is an OpenPGP key - * @bits: if bits is non null it will hold the size of the parameters' in bits - * - * This function will return the public key algorithm of an OpenPGP - * certificate. - * - * If bits is non null, it should have enough size to hold the parameters - * size in bits. For RSA the bits returned is the modulus. - * For DSA the bits returned are of the public exponent. - * - * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, - * or a negative value on error. - * - **/ -gnutls_pk_algorithm_t -gnutls_openpgp_crt_get_pk_algorithm (gnutls_openpgp_crt_t key, - unsigned int *bits) -{ - cdk_packet_t pkt; - int algo; - - if (!key) - return MHD_GNUTLS_PK_UNKNOWN; - - algo = 0; - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY) - { - if (bits) - *bits = cdk_pk_get_nbits (pkt->pkt.public_key); - algo = pkt->pkt.public_key->pubkey_algo; - if (is_RSA (algo)) - algo = MHD_GNUTLS_PK_RSA; - else - algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; - } - - return algo; -} - -/** - * gnutls_openpgp_crt_get_version - Extracts the version of the key. - * @key: the structure that contains the OpenPGP public key. - * - * Extract the version of the OpenPGP key. - **/ -int -gnutls_openpgp_crt_get_version (gnutls_openpgp_crt_t key) -{ - cdk_packet_t pkt; - int version; - - if (!key) - return -1; - - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (pkt) - version = pkt->pkt.public_key->version; - else - version = 0; - - return version; -} - -/** - * gnutls_openpgp_crt_get_creation_time - Extract the timestamp - * @key: the structure that contains the OpenPGP public key. - * - * Returns the timestamp when the OpenPGP key was created. - **/ -time_t -gnutls_openpgp_crt_get_creation_time (gnutls_openpgp_crt_t key) -{ - cdk_packet_t pkt; - time_t timestamp; - - if (!key) - return (time_t) - 1; - - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (pkt) - timestamp = pkt->pkt.public_key->timestamp; - else - timestamp = 0; - - return timestamp; -} - -/** - * gnutls_openpgp_crt_get_expiration_time - Extract the expire date - * @key: the structure that contains the OpenPGP public key. - * - * Returns the time when the OpenPGP key expires. A value of '0' means - * that the key doesn't expire at all. - **/ -time_t -gnutls_openpgp_crt_get_expiration_time (gnutls_openpgp_crt_t key) -{ - cdk_packet_t pkt; - time_t expiredate; - - if (!key) - return (time_t) - 1; - - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (pkt) - expiredate = pkt->pkt.public_key->expiredate; - else - expiredate = 0; - - return expiredate; -} - -/** - * gnutls_openpgp_crt_get_id - Gets the keyID - * @key: the structure that contains the OpenPGP public key. - * @keyid: the buffer to save the keyid. - * - * Returns the 64-bit keyID of the OpenPGP key. - **/ -int -gnutls_openpgp_crt_get_id (gnutls_openpgp_crt_t key, unsigned char keyid[8]) -{ - cdk_packet_t pkt; - uint32_t kid[2]; - - if (!key || !keyid) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (!pkt) - return GNUTLS_E_OPENPGP_GETKEY_FAILED; - - cdk_pk_get_keyid (pkt->pkt.public_key, kid); - keyid[0] = kid[0] >> 24; - keyid[1] = kid[0] >> 16; - keyid[2] = kid[0] >> 8; - keyid[3] = kid[0]; - keyid[4] = kid[1] >> 24; - keyid[5] = kid[1] >> 16; - keyid[6] = kid[1] >> 8; - keyid[7] = kid[1]; - - return 0; -} - -/** - * gnutls_openpgp_crt_check_hostname - This function compares the given hostname with the hostname in the key - * @key: should contain an gnutls_openpgp_crt_t structure - * @hostname: A null terminated string that contains a DNS name - * - * This function will check if the given key's owner matches - * the given hostname. This is a basic implementation of the matching - * described in RFC2818 (HTTPS), which takes into account wildcards. - * - * Returns non zero on success, and zero on failure. - * - **/ -int -gnutls_openpgp_crt_check_hostname (gnutls_openpgp_crt_t key, - const char *hostname) -{ - char dnsname[MAX_CN]; - size_t dnsnamesize; - int ret; - int i; - - /* Check through all included names. */ - for (i = 0; !(ret < 0); i++) - { - dnsnamesize = sizeof (dnsname); - ret = gnutls_openpgp_crt_get_name (key, i, dnsname, &dnsnamesize); - /* FIXME: ret is not used */ - if (_gnutls_hostname_compare (dnsname, hostname)) - return 1; - } - - /* not found a matching name */ - return 0; -} - -/** - * gnutls_openpgp_crt_get_key_usage - This function returns the key's usage - * @key: should contain a gnutls_openpgp_crt_t structure - * @key_usage: where the key usage bits will be stored - * - * This function will return certificate's key usage, by checking the - * key algorithm. The key usage value will ORed values of the: - * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT. - * - * A negative value may be returned in case of parsing error. - * - */ -int -gnutls_openpgp_crt_get_key_usage (gnutls_openpgp_crt_t key, - unsigned int *key_usage) -{ - cdk_packet_t pkt; - int algo = 0; - - if (!key) - return GNUTLS_E_INVALID_REQUEST; - - *key_usage = 0; - - pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); - if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY) - { - algo = pkt->pkt.public_key->pubkey_algo; - - /* FIXME: We need to take a look at the key flags because - RSA-E and RSA-S are obsolete. Only RSA is used - and the flags are used to set the capabilities. */ - if (is_DSA (algo) || algo == GCRY_PK_RSA_S) - *key_usage |= KEY_DIGITAL_SIGNATURE; - else if (algo == GCRY_PK_RSA_E) - *key_usage |= KEY_KEY_ENCIPHERMENT; - else if (algo == GCRY_PK_RSA) - *key_usage |= KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT; - } - - return 0; -} diff --git a/src/daemon/https/openpgp/pgp_privkey.c b/src/daemon/https/openpgp/pgp_privkey.c @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation - * - * Author: Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -/* Functions on OpenPGP privkey parsing - */ - -#include <gnutls_int.h> -#include <gnutls_datum.h> -#include <gnutls_global.h> -#include <gnutls_errors.h> -#include "openpgp.h" -#include <gnutls_openpgp.h> -#include <gnutls_cert.h> -/* x509 */ -#include <rfc2818.h> - -/** - * gnutls_openpgp_privkey_init - This function initializes a gnutls_openpgp_privkey_t structure - * @key: The structure to be initialized - * - * This function will initialize an OpenPGP key structure. - * - * Returns 0 on success. - * - **/ -int -gnutls_openpgp_privkey_init (gnutls_openpgp_privkey_t * key) -{ - *key = gnutls_calloc (1, sizeof (gnutls_openpgp_privkey_int)); - - if (*key) - return 0; /* success */ - return GNUTLS_E_MEMORY_ERROR; -} - -/** - * gnutls_openpgp_privkey_deinit - This function deinitializes memory used by a gnutls_openpgp_privkey_t structure - * @key: The structure to be initialized - * - * This function will deinitialize a key structure. - * - **/ -void -gnutls_openpgp_privkey_deinit (gnutls_openpgp_privkey_t key) -{ - if (!key) - return; - - mhd_gtls_gkey_deinit (&key->pkey); - gnutls_free (key); -} - -/** - * gnutls_openpgp_privkey_import - This function will import a RAW or BASE64 encoded key - * @key: The structure to store the parsed key. - * @data: The RAW or BASE64 encoded key. - * @format: One of gnutls_openpgp_crt_fmt_t elements. - * @pass: Unused for now - * @flags: should be zero - * - * This function will convert the given RAW or Base64 encoded key - * to the native gnutls_openpgp_privkey_t format. The output will be stored in 'key'. - * - * Returns 0 on success. - * - **/ -int -gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key, - const gnutls_datum_t * data, - gnutls_openpgp_crt_fmt_t format, - const char *pass, unsigned int flags) -{ - int rc; - - rc = _gnutls_openpgp_raw_privkey_to_gkey (&key->pkey, data, format); - if (rc) - { - gnutls_assert (); - return rc; - } - - return 0; -} - - -/** - * gnutls_openpgp_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm - * @key: is an OpenPGP key - * @bits: if bits is non null it will hold the size of the parameters' in bits - * - * This function will return the public key algorithm of an OpenPGP - * certificate. - * - * If bits is non null, it should have enough size to hold the parameters - * size in bits. For RSA the bits returned is the modulus. - * For DSA the bits returned are of the public exponent. - * - * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, - * or a negative value on error. - * - **/ -gnutls_pk_algorithm_t -gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, - unsigned int *bits) -{ - int pk = key->pkey.pk_algorithm; - - if (bits) - { - *bits = 0; - if (pk == MHD_GNUTLS_PK_RSA) - *bits = _gnutls_mpi_get_nbits (key->pkey.params[0]); - } - - return pk; -} diff --git a/src/daemon/https/openpgp/pgp_verify.c b/src/daemon/https/openpgp/pgp_verify.c @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation - * - * Author: Timo Schulz, Nikos Mavrogiannopoulos - * - * This file is part of GNUTLS-EXTRA. - * - * GNUTLS-EXTRA 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 3 of the License, or - * (at your option) any later version. - * - * GNUTLS-EXTRA 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, see <http://www.gnu.org/licenses/>. - */ - -/* Functions on OpenPGP key parsing - */ - -#include <gnutls_int.h> -#include <gnutls_errors.h> -#include <gnutls_openpgp.h> -#include <gnutls_num.h> -#include "openpgp.h" -/* x509 */ -#include <verify.h> /* lib/x509/verify.h */ - - -/** - * gnutls_openpgp_crt_verify_ring - Verify all signatures in the key - * @key: the structure that holds the key. - * @keyring: holds the keyring to check against - * @flags: unused (should be 0) - * @verify: will hold the certificate verification output. - * - * Verify all signatures in the key, using the given set of keys (keyring). - * - * The key verification output will be put in @verify and will be - * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. - * - * GNUTLS_CERT_INVALID: A signature on the key is invalid. - * - * GNUTLS_CERT_REVOKED: The key has been revoked. - * - * Note that this function does not verify using any "web of - * trust". You may use GnuPG for that purpose, or any other external - * PGP application. - * - * Returns 0 on success. - **/ -int -gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key, - gnutls_openpgp_keyring_t keyring, - unsigned int flags, unsigned int *verify) -{ - opaque id[8]; - cdk_error_t rc; - int status; - - if (!key || !keyring) - { - gnutls_assert (); - return GNUTLS_E_NO_CERTIFICATE_FOUND; - } - - *verify = 0; - - rc = cdk_pk_check_sigs (key->knode, keyring->db, &status); - if (rc == CDK_Error_No_Key) - { - rc = GNUTLS_E_NO_CERTIFICATE_FOUND; - gnutls_assert (); - return rc; - } - else if (rc != CDK_Success) - { - _gnutls_x509_log ("cdk_pk_check_sigs: error %d\n", rc); - rc = _gnutls_map_cdk_rc (rc); - gnutls_assert (); - return rc; - } - _gnutls_x509_log ("status: %x\n", status); - - if (status & CDK_KEY_INVALID) - *verify |= GNUTLS_CERT_INVALID; - if (status & CDK_KEY_REVOKED) - *verify |= GNUTLS_CERT_REVOKED; - if (status & CDK_KEY_NOSIGNER) - *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND; - - /* Check if the key is included in the ring. */ - if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) - { - rc = gnutls_openpgp_crt_get_id (key, id); - if (rc < 0) - { - gnutls_assert (); - return rc; - } - - rc = gnutls_openpgp_keyring_check_id (keyring, id, 0); - /* If it exists in the keyring don't treat it as unknown. */ - if (rc == 0 && *verify & GNUTLS_CERT_SIGNER_NOT_FOUND) - *verify ^= GNUTLS_CERT_SIGNER_NOT_FOUND; - } - - return 0; -} - - -/** - * gnutls_openpgp_crt_verify_self - Verify the self signature on the key - * @key: the structure that holds the key. - * @flags: unused (should be 0) - * @verify: will hold the key verification output. - * - * Verifies the self signature in the key. - * The key verification output will be put in @verify and will be - * one or more of the gnutls_certificate_status_t enumerated elements bitwise or'd. - * - * GNUTLS_CERT_INVALID: The self signature on the key is invalid. - * - * Returns 0 on success. - **/ -int -gnutls_openpgp_crt_verify_self (gnutls_openpgp_crt_t key, - unsigned int flags, unsigned int *verify) -{ - int status; - cdk_error_t rc; - - rc = cdk_pk_check_self_sig (key->knode, &status); - if (rc || status != CDK_KEY_VALID) - *verify |= GNUTLS_CERT_INVALID; - else - *verify = 0; - - return 0; -}