1ebfedea0SLionel Sambuc /*- 2ebfedea0SLionel Sambuc * Copyright (c) 2009 The NetBSD Foundation, Inc. 3ebfedea0SLionel Sambuc * All rights reserved. 4ebfedea0SLionel Sambuc * 5ebfedea0SLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation 6ebfedea0SLionel Sambuc * by Alistair Crooks (agc@NetBSD.org) 7ebfedea0SLionel Sambuc * 8ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without 9ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions 10ebfedea0SLionel Sambuc * are met: 11ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright 12ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer. 13ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 14ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in the 15ebfedea0SLionel Sambuc * documentation and/or other materials provided with the distribution. 16ebfedea0SLionel Sambuc * 17ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18ebfedea0SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19ebfedea0SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20ebfedea0SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21ebfedea0SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22ebfedea0SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23ebfedea0SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24ebfedea0SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25ebfedea0SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26ebfedea0SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27ebfedea0SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE. 28ebfedea0SLionel Sambuc */ 29ebfedea0SLionel Sambuc /* 30ebfedea0SLionel Sambuc * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 31ebfedea0SLionel Sambuc * All rights reserved. 32ebfedea0SLionel Sambuc * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 33ebfedea0SLionel Sambuc * their moral rights under the UK Copyright Design and Patents Act 1988 to 34ebfedea0SLionel Sambuc * be recorded as the authors of this copyright work. 35ebfedea0SLionel Sambuc * 36ebfedea0SLionel Sambuc * Licensed under the Apache License, Version 2.0 (the "License"); you may not 37ebfedea0SLionel Sambuc * use this file except in compliance with the License. 38ebfedea0SLionel Sambuc * 39ebfedea0SLionel Sambuc * You may obtain a copy of the License at 40ebfedea0SLionel Sambuc * http://www.apache.org/licenses/LICENSE-2.0 41ebfedea0SLionel Sambuc * 42ebfedea0SLionel Sambuc * Unless required by applicable law or agreed to in writing, software 43ebfedea0SLionel Sambuc * distributed under the License is distributed on an "AS IS" BASIS, 44ebfedea0SLionel Sambuc * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 45ebfedea0SLionel Sambuc * 46ebfedea0SLionel Sambuc * See the License for the specific language governing permissions and 47ebfedea0SLionel Sambuc * limitations under the License. 48ebfedea0SLionel Sambuc */ 49ebfedea0SLionel Sambuc #include "config.h" 50ebfedea0SLionel Sambuc 51ebfedea0SLionel Sambuc #ifdef HAVE_SYS_CDEFS_H 52ebfedea0SLionel Sambuc #include <sys/cdefs.h> 53ebfedea0SLionel Sambuc #endif 54ebfedea0SLionel Sambuc 55ebfedea0SLionel Sambuc #if defined(__NetBSD__) 56ebfedea0SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 57*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: crypto.c,v 1.36 2014/02/17 07:39:19 agc Exp $"); 58ebfedea0SLionel Sambuc #endif 59ebfedea0SLionel Sambuc 60ebfedea0SLionel Sambuc #include <sys/types.h> 61ebfedea0SLionel Sambuc #include <sys/stat.h> 62ebfedea0SLionel Sambuc 63ebfedea0SLionel Sambuc #ifdef HAVE_UNISTD_H 64ebfedea0SLionel Sambuc #include <unistd.h> 65ebfedea0SLionel Sambuc #endif 66ebfedea0SLionel Sambuc 67ebfedea0SLionel Sambuc #include <string.h> 68ebfedea0SLionel Sambuc 69ebfedea0SLionel Sambuc #include "types.h" 70ebfedea0SLionel Sambuc #include "crypto.h" 71ebfedea0SLionel Sambuc #include "readerwriter.h" 72ebfedea0SLionel Sambuc #include "memory.h" 73ebfedea0SLionel Sambuc #include "netpgpdefs.h" 74ebfedea0SLionel Sambuc #include "signature.h" 75ebfedea0SLionel Sambuc 76ebfedea0SLionel Sambuc /** 77ebfedea0SLionel Sambuc \ingroup Core_MPI 78ebfedea0SLionel Sambuc \brief Decrypt and unencode MPI 79ebfedea0SLionel Sambuc \param buf Buffer in which to write decrypted unencoded MPI 80ebfedea0SLionel Sambuc \param buflen Length of buffer 81ebfedea0SLionel Sambuc \param encmpi 82ebfedea0SLionel Sambuc \param seckey 83ebfedea0SLionel Sambuc \return length of MPI 84ebfedea0SLionel Sambuc \note only RSA at present 85ebfedea0SLionel Sambuc */ 86ebfedea0SLionel Sambuc int 87ebfedea0SLionel Sambuc pgp_decrypt_decode_mpi(uint8_t *buf, 88ebfedea0SLionel Sambuc unsigned buflen, 89ebfedea0SLionel Sambuc const BIGNUM *g_to_k, 90ebfedea0SLionel Sambuc const BIGNUM *encmpi, 91ebfedea0SLionel Sambuc const pgp_seckey_t *seckey) 92ebfedea0SLionel Sambuc { 93ebfedea0SLionel Sambuc unsigned mpisize; 94ebfedea0SLionel Sambuc uint8_t encmpibuf[NETPGP_BUFSIZ]; 95ebfedea0SLionel Sambuc uint8_t mpibuf[NETPGP_BUFSIZ]; 96ebfedea0SLionel Sambuc uint8_t gkbuf[NETPGP_BUFSIZ]; 97ebfedea0SLionel Sambuc int i; 98ebfedea0SLionel Sambuc int n; 99ebfedea0SLionel Sambuc 100ebfedea0SLionel Sambuc mpisize = (unsigned)BN_num_bytes(encmpi); 101ebfedea0SLionel Sambuc /* MPI can't be more than 65,536 */ 102ebfedea0SLionel Sambuc if (mpisize > sizeof(encmpibuf)) { 103ebfedea0SLionel Sambuc (void) fprintf(stderr, "mpisize too big %u\n", mpisize); 104ebfedea0SLionel Sambuc return -1; 105ebfedea0SLionel Sambuc } 106ebfedea0SLionel Sambuc switch (seckey->pubkey.alg) { 107ebfedea0SLionel Sambuc case PGP_PKA_RSA: 108ebfedea0SLionel Sambuc BN_bn2bin(encmpi, encmpibuf); 109ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 110ebfedea0SLionel Sambuc hexdump(stderr, "encrypted", encmpibuf, 16); 111ebfedea0SLionel Sambuc } 112ebfedea0SLionel Sambuc n = pgp_rsa_private_decrypt(mpibuf, encmpibuf, 113ebfedea0SLionel Sambuc (unsigned)(BN_num_bits(encmpi) + 7) / 8, 114ebfedea0SLionel Sambuc &seckey->key.rsa, &seckey->pubkey.key.rsa); 115ebfedea0SLionel Sambuc if (n == -1) { 116ebfedea0SLionel Sambuc (void) fprintf(stderr, "ops_rsa_private_decrypt failure\n"); 117ebfedea0SLionel Sambuc return -1; 118ebfedea0SLionel Sambuc } 119ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 120ebfedea0SLionel Sambuc hexdump(stderr, "decrypted", mpibuf, 16); 121ebfedea0SLionel Sambuc } 122ebfedea0SLionel Sambuc if (n <= 0) { 123ebfedea0SLionel Sambuc return -1; 124ebfedea0SLionel Sambuc } 125ebfedea0SLionel Sambuc /* Decode EME-PKCS1_V1_5 (RFC 2437). */ 126ebfedea0SLionel Sambuc if (mpibuf[0] != 0 || mpibuf[1] != 2) { 127ebfedea0SLionel Sambuc return -1; 128ebfedea0SLionel Sambuc } 129ebfedea0SLionel Sambuc /* Skip the random bytes. */ 130ebfedea0SLionel Sambuc for (i = 2; i < n && mpibuf[i]; ++i) { 131ebfedea0SLionel Sambuc } 132ebfedea0SLionel Sambuc if (i == n || i < 10) { 133ebfedea0SLionel Sambuc return -1; 134ebfedea0SLionel Sambuc } 135ebfedea0SLionel Sambuc /* Skip the zero */ 136ebfedea0SLionel Sambuc i += 1; 137ebfedea0SLionel Sambuc /* this is the unencoded m buf */ 138ebfedea0SLionel Sambuc if ((unsigned) (n - i) <= buflen) { 139ebfedea0SLionel Sambuc (void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */ 140ebfedea0SLionel Sambuc } 141ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 142ebfedea0SLionel Sambuc hexdump(stderr, "decoded m", buf, (size_t)(n - i)); 143ebfedea0SLionel Sambuc } 144ebfedea0SLionel Sambuc return n - i; 145ebfedea0SLionel Sambuc case PGP_PKA_DSA: 146ebfedea0SLionel Sambuc case PGP_PKA_ELGAMAL: 147ebfedea0SLionel Sambuc (void) BN_bn2bin(g_to_k, gkbuf); 148ebfedea0SLionel Sambuc (void) BN_bn2bin(encmpi, encmpibuf); 149ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 150ebfedea0SLionel Sambuc hexdump(stderr, "encrypted", encmpibuf, 16); 151ebfedea0SLionel Sambuc } 152ebfedea0SLionel Sambuc n = pgp_elgamal_private_decrypt(mpibuf, gkbuf, encmpibuf, 153ebfedea0SLionel Sambuc (unsigned)BN_num_bytes(encmpi), 154ebfedea0SLionel Sambuc &seckey->key.elgamal, &seckey->pubkey.key.elgamal); 155ebfedea0SLionel Sambuc if (n == -1) { 156ebfedea0SLionel Sambuc (void) fprintf(stderr, "ops_elgamal_private_decrypt failure\n"); 157ebfedea0SLionel Sambuc return -1; 158ebfedea0SLionel Sambuc } 159ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 160ebfedea0SLionel Sambuc hexdump(stderr, "decrypted", mpibuf, 16); 161ebfedea0SLionel Sambuc } 162ebfedea0SLionel Sambuc if (n <= 0) { 163ebfedea0SLionel Sambuc return -1; 164ebfedea0SLionel Sambuc } 165ebfedea0SLionel Sambuc /* Decode EME-PKCS1_V1_5 (RFC 2437). */ 166ebfedea0SLionel Sambuc if (mpibuf[0] != 2) { 167ebfedea0SLionel Sambuc fprintf(stderr, "mpibuf mismatch\n"); 168ebfedea0SLionel Sambuc return -1; 169ebfedea0SLionel Sambuc } 170ebfedea0SLionel Sambuc /* Skip the random bytes. */ 171ebfedea0SLionel Sambuc for (i = 1; i < n && mpibuf[i]; ++i) { 172ebfedea0SLionel Sambuc } 173ebfedea0SLionel Sambuc if (i == n || i < 10) { 174ebfedea0SLionel Sambuc fprintf(stderr, "175 n %d\n", n); 175ebfedea0SLionel Sambuc return -1; 176ebfedea0SLionel Sambuc } 177ebfedea0SLionel Sambuc /* Skip the zero */ 178ebfedea0SLionel Sambuc i += 1; 179ebfedea0SLionel Sambuc /* this is the unencoded m buf */ 180ebfedea0SLionel Sambuc if ((unsigned) (n - i) <= buflen) { 181ebfedea0SLionel Sambuc (void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */ 182ebfedea0SLionel Sambuc } 183ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 184ebfedea0SLionel Sambuc hexdump(stderr, "decoded m", buf, (size_t)(n - i)); 185ebfedea0SLionel Sambuc } 186ebfedea0SLionel Sambuc return n - i; 187ebfedea0SLionel Sambuc default: 188ebfedea0SLionel Sambuc (void) fprintf(stderr, "pubkey algorithm wrong\n"); 189ebfedea0SLionel Sambuc return -1; 190ebfedea0SLionel Sambuc } 191ebfedea0SLionel Sambuc } 192ebfedea0SLionel Sambuc 193ebfedea0SLionel Sambuc /** 194ebfedea0SLionel Sambuc \ingroup Core_MPI 195ebfedea0SLionel Sambuc \brief RSA-encrypt an MPI 196ebfedea0SLionel Sambuc */ 197ebfedea0SLionel Sambuc unsigned 198ebfedea0SLionel Sambuc pgp_rsa_encrypt_mpi(const uint8_t *encoded_m_buf, 199ebfedea0SLionel Sambuc const size_t sz_encoded_m_buf, 200ebfedea0SLionel Sambuc const pgp_pubkey_t * pubkey, 201ebfedea0SLionel Sambuc pgp_pk_sesskey_params_t * skp) 202ebfedea0SLionel Sambuc { 203ebfedea0SLionel Sambuc 204ebfedea0SLionel Sambuc uint8_t encmpibuf[NETPGP_BUFSIZ]; 205ebfedea0SLionel Sambuc int n; 206ebfedea0SLionel Sambuc 207ebfedea0SLionel Sambuc if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.rsa.n)) { 208ebfedea0SLionel Sambuc (void) fprintf(stderr, "sz_encoded_m_buf wrong\n"); 209ebfedea0SLionel Sambuc return 0; 210ebfedea0SLionel Sambuc } 211ebfedea0SLionel Sambuc 212ebfedea0SLionel Sambuc n = pgp_rsa_public_encrypt(encmpibuf, encoded_m_buf, 213ebfedea0SLionel Sambuc sz_encoded_m_buf, &pubkey->key.rsa); 214ebfedea0SLionel Sambuc if (n == -1) { 215ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_rsa_public_encrypt failure\n"); 216ebfedea0SLionel Sambuc return 0; 217ebfedea0SLionel Sambuc } 218ebfedea0SLionel Sambuc 219ebfedea0SLionel Sambuc if (n <= 0) 220ebfedea0SLionel Sambuc return 0; 221ebfedea0SLionel Sambuc 222ebfedea0SLionel Sambuc skp->rsa.encrypted_m = BN_bin2bn(encmpibuf, n, NULL); 223ebfedea0SLionel Sambuc 224ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 225ebfedea0SLionel Sambuc hexdump(stderr, "encrypted mpi", encmpibuf, 16); 226ebfedea0SLionel Sambuc } 227ebfedea0SLionel Sambuc return 1; 228ebfedea0SLionel Sambuc } 229ebfedea0SLionel Sambuc 230ebfedea0SLionel Sambuc /** 231ebfedea0SLionel Sambuc \ingroup Core_MPI 232ebfedea0SLionel Sambuc \brief Elgamal-encrypt an MPI 233ebfedea0SLionel Sambuc */ 234ebfedea0SLionel Sambuc unsigned 235ebfedea0SLionel Sambuc pgp_elgamal_encrypt_mpi(const uint8_t *encoded_m_buf, 236ebfedea0SLionel Sambuc const size_t sz_encoded_m_buf, 237ebfedea0SLionel Sambuc const pgp_pubkey_t * pubkey, 238ebfedea0SLionel Sambuc pgp_pk_sesskey_params_t * skp) 239ebfedea0SLionel Sambuc { 240ebfedea0SLionel Sambuc 241ebfedea0SLionel Sambuc uint8_t encmpibuf[NETPGP_BUFSIZ]; 242ebfedea0SLionel Sambuc uint8_t g_to_k[NETPGP_BUFSIZ]; 243ebfedea0SLionel Sambuc int n; 244ebfedea0SLionel Sambuc 245ebfedea0SLionel Sambuc if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.elgamal.p)) { 246ebfedea0SLionel Sambuc (void) fprintf(stderr, "sz_encoded_m_buf wrong\n"); 247ebfedea0SLionel Sambuc return 0; 248ebfedea0SLionel Sambuc } 249ebfedea0SLionel Sambuc 250ebfedea0SLionel Sambuc n = pgp_elgamal_public_encrypt(g_to_k, encmpibuf, encoded_m_buf, 251ebfedea0SLionel Sambuc sz_encoded_m_buf, &pubkey->key.elgamal); 252ebfedea0SLionel Sambuc if (n == -1) { 253ebfedea0SLionel Sambuc (void) fprintf(stderr, "pgp_elgamal_public_encrypt failure\n"); 254ebfedea0SLionel Sambuc return 0; 255ebfedea0SLionel Sambuc } 256ebfedea0SLionel Sambuc 257ebfedea0SLionel Sambuc if (n <= 0) 258ebfedea0SLionel Sambuc return 0; 259ebfedea0SLionel Sambuc 260ebfedea0SLionel Sambuc skp->elgamal.g_to_k = BN_bin2bn(g_to_k, n / 2, NULL); 261ebfedea0SLionel Sambuc skp->elgamal.encrypted_m = BN_bin2bn(encmpibuf, n / 2, NULL); 262ebfedea0SLionel Sambuc 263ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 264ebfedea0SLionel Sambuc hexdump(stderr, "encrypted mpi", encmpibuf, 16); 265ebfedea0SLionel Sambuc } 266ebfedea0SLionel Sambuc return 1; 267ebfedea0SLionel Sambuc } 268ebfedea0SLionel Sambuc 269ebfedea0SLionel Sambuc static pgp_cb_ret_t 270ebfedea0SLionel Sambuc write_parsed_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) 271ebfedea0SLionel Sambuc { 272ebfedea0SLionel Sambuc const pgp_contents_t *content = &pkt->u; 273ebfedea0SLionel Sambuc 274ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 275ebfedea0SLionel Sambuc printf("write_parsed_cb: "); 276ebfedea0SLionel Sambuc pgp_print_packet(&cbinfo->printstate, pkt); 277ebfedea0SLionel Sambuc } 278ebfedea0SLionel Sambuc if (pkt->tag != PGP_PTAG_CT_UNARMOURED_TEXT && cbinfo->printstate.skipping) { 279ebfedea0SLionel Sambuc puts("...end of skip"); 280ebfedea0SLionel Sambuc cbinfo->printstate.skipping = 0; 281ebfedea0SLionel Sambuc } 282ebfedea0SLionel Sambuc switch (pkt->tag) { 283ebfedea0SLionel Sambuc case PGP_PTAG_CT_UNARMOURED_TEXT: 284ebfedea0SLionel Sambuc printf("PGP_PTAG_CT_UNARMOURED_TEXT\n"); 285ebfedea0SLionel Sambuc if (!cbinfo->printstate.skipping) { 286ebfedea0SLionel Sambuc puts("Skipping..."); 287ebfedea0SLionel Sambuc cbinfo->printstate.skipping = 1; 288ebfedea0SLionel Sambuc } 289*0a6a1f1dSLionel Sambuc if (fwrite(content->unarmoured_text.data, 1, 290*0a6a1f1dSLionel Sambuc content->unarmoured_text.length, stdout) != content->unarmoured_text.length) { 291*0a6a1f1dSLionel Sambuc fprintf(stderr, "unable to write unarmoured text data\n"); 292*0a6a1f1dSLionel Sambuc cbinfo->printstate.skipping = 1; 293*0a6a1f1dSLionel Sambuc } 294ebfedea0SLionel Sambuc break; 295ebfedea0SLionel Sambuc 296ebfedea0SLionel Sambuc case PGP_PTAG_CT_PK_SESSION_KEY: 297ebfedea0SLionel Sambuc return pgp_pk_sesskey_cb(pkt, cbinfo); 298ebfedea0SLionel Sambuc 299ebfedea0SLionel Sambuc case PGP_GET_SECKEY: 300ebfedea0SLionel Sambuc if (cbinfo->sshseckey) { 301ebfedea0SLionel Sambuc *content->get_seckey.seckey = cbinfo->sshseckey; 302ebfedea0SLionel Sambuc return PGP_KEEP_MEMORY; 303ebfedea0SLionel Sambuc } 304ebfedea0SLionel Sambuc return pgp_get_seckey_cb(pkt, cbinfo); 305ebfedea0SLionel Sambuc 306ebfedea0SLionel Sambuc case PGP_GET_PASSPHRASE: 307ebfedea0SLionel Sambuc return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); 308ebfedea0SLionel Sambuc 309ebfedea0SLionel Sambuc case PGP_PTAG_CT_LITDATA_BODY: 310ebfedea0SLionel Sambuc return pgp_litdata_cb(pkt, cbinfo); 311ebfedea0SLionel Sambuc 312ebfedea0SLionel Sambuc case PGP_PTAG_CT_ARMOUR_HEADER: 313ebfedea0SLionel Sambuc case PGP_PTAG_CT_ARMOUR_TRAILER: 314ebfedea0SLionel Sambuc case PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 315ebfedea0SLionel Sambuc case PGP_PTAG_CT_COMPRESSED: 316ebfedea0SLionel Sambuc case PGP_PTAG_CT_LITDATA_HEADER: 317ebfedea0SLionel Sambuc case PGP_PTAG_CT_SE_IP_DATA_BODY: 318ebfedea0SLionel Sambuc case PGP_PTAG_CT_SE_IP_DATA_HEADER: 319ebfedea0SLionel Sambuc case PGP_PTAG_CT_SE_DATA_BODY: 320ebfedea0SLionel Sambuc case PGP_PTAG_CT_SE_DATA_HEADER: 321ebfedea0SLionel Sambuc /* Ignore these packets */ 322ebfedea0SLionel Sambuc /* They're handled in parse_packet() */ 323ebfedea0SLionel Sambuc /* and nothing else needs to be done */ 324ebfedea0SLionel Sambuc break; 325ebfedea0SLionel Sambuc 326ebfedea0SLionel Sambuc default: 327ebfedea0SLionel Sambuc if (pgp_get_debug_level(__FILE__)) { 328ebfedea0SLionel Sambuc fprintf(stderr, "Unexpected packet tag=%d (0x%x)\n", 329ebfedea0SLionel Sambuc pkt->tag, 330ebfedea0SLionel Sambuc pkt->tag); 331ebfedea0SLionel Sambuc } 332ebfedea0SLionel Sambuc break; 333ebfedea0SLionel Sambuc } 334ebfedea0SLionel Sambuc 335ebfedea0SLionel Sambuc return PGP_RELEASE_MEMORY; 336ebfedea0SLionel Sambuc } 337ebfedea0SLionel Sambuc 338ebfedea0SLionel Sambuc /** 339ebfedea0SLionel Sambuc \ingroup HighLevel_Crypto 340ebfedea0SLionel Sambuc Encrypt a file 341ebfedea0SLionel Sambuc \param infile Name of file to be encrypted 342ebfedea0SLionel Sambuc \param outfile Name of file to write to. If NULL, name is constructed from infile 343ebfedea0SLionel Sambuc \param pubkey Public Key to encrypt file for 344ebfedea0SLionel Sambuc \param use_armour Write armoured text, if set 345ebfedea0SLionel Sambuc \param allow_overwrite Allow output file to be overwrwritten if it exists 346ebfedea0SLionel Sambuc \return 1 if OK; else 0 347ebfedea0SLionel Sambuc */ 348ebfedea0SLionel Sambuc unsigned 349ebfedea0SLionel Sambuc pgp_encrypt_file(pgp_io_t *io, 350ebfedea0SLionel Sambuc const char *infile, 351ebfedea0SLionel Sambuc const char *outfile, 352ebfedea0SLionel Sambuc const pgp_key_t *key, 353ebfedea0SLionel Sambuc const unsigned use_armour, 354ebfedea0SLionel Sambuc const unsigned allow_overwrite, 355ebfedea0SLionel Sambuc const char *cipher) 356ebfedea0SLionel Sambuc { 357ebfedea0SLionel Sambuc pgp_output_t *output; 358ebfedea0SLionel Sambuc pgp_memory_t *inmem; 359ebfedea0SLionel Sambuc int fd_out; 360ebfedea0SLionel Sambuc 361ebfedea0SLionel Sambuc __PGP_USED(io); 362ebfedea0SLionel Sambuc inmem = pgp_memory_new(); 363ebfedea0SLionel Sambuc if (!pgp_mem_readfile(inmem, infile)) { 364ebfedea0SLionel Sambuc return 0; 365ebfedea0SLionel Sambuc } 366ebfedea0SLionel Sambuc fd_out = pgp_setup_file_write(&output, outfile, allow_overwrite); 367ebfedea0SLionel Sambuc if (fd_out < 0) { 368ebfedea0SLionel Sambuc pgp_memory_free(inmem); 369ebfedea0SLionel Sambuc return 0; 370ebfedea0SLionel Sambuc } 371ebfedea0SLionel Sambuc 372ebfedea0SLionel Sambuc /* set armoured/not armoured here */ 373ebfedea0SLionel Sambuc if (use_armour) { 374ebfedea0SLionel Sambuc pgp_writer_push_armor_msg(output); 375ebfedea0SLionel Sambuc } 376ebfedea0SLionel Sambuc 377ebfedea0SLionel Sambuc /* Push the encrypted writer */ 378ebfedea0SLionel Sambuc if (!pgp_push_enc_se_ip(output, key, cipher)) { 379ebfedea0SLionel Sambuc pgp_memory_free(inmem); 380ebfedea0SLionel Sambuc return 0; 381ebfedea0SLionel Sambuc } 382ebfedea0SLionel Sambuc 383ebfedea0SLionel Sambuc /* This does the writing */ 384ebfedea0SLionel Sambuc pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem)); 385ebfedea0SLionel Sambuc 386ebfedea0SLionel Sambuc /* tidy up */ 387ebfedea0SLionel Sambuc pgp_memory_free(inmem); 388ebfedea0SLionel Sambuc pgp_teardown_file_write(output, fd_out); 389ebfedea0SLionel Sambuc 390ebfedea0SLionel Sambuc return 1; 391ebfedea0SLionel Sambuc } 392ebfedea0SLionel Sambuc 393ebfedea0SLionel Sambuc /* encrypt the contents of the input buffer, and return the mem structure */ 394ebfedea0SLionel Sambuc pgp_memory_t * 395ebfedea0SLionel Sambuc pgp_encrypt_buf(pgp_io_t *io, 396ebfedea0SLionel Sambuc const void *input, 397ebfedea0SLionel Sambuc const size_t insize, 398ebfedea0SLionel Sambuc const pgp_key_t *pubkey, 399ebfedea0SLionel Sambuc const unsigned use_armour, 400ebfedea0SLionel Sambuc const char *cipher) 401ebfedea0SLionel Sambuc { 402ebfedea0SLionel Sambuc pgp_output_t *output; 403ebfedea0SLionel Sambuc pgp_memory_t *outmem; 404ebfedea0SLionel Sambuc 405ebfedea0SLionel Sambuc __PGP_USED(io); 406ebfedea0SLionel Sambuc if (input == NULL) { 407ebfedea0SLionel Sambuc (void) fprintf(io->errs, 408ebfedea0SLionel Sambuc "pgp_encrypt_buf: null memory\n"); 409ebfedea0SLionel Sambuc return 0; 410ebfedea0SLionel Sambuc } 411ebfedea0SLionel Sambuc 412ebfedea0SLionel Sambuc pgp_setup_memory_write(&output, &outmem, insize); 413ebfedea0SLionel Sambuc 414ebfedea0SLionel Sambuc /* set armoured/not armoured here */ 415ebfedea0SLionel Sambuc if (use_armour) { 416ebfedea0SLionel Sambuc pgp_writer_push_armor_msg(output); 417ebfedea0SLionel Sambuc } 418ebfedea0SLionel Sambuc 419ebfedea0SLionel Sambuc /* Push the encrypted writer */ 420ebfedea0SLionel Sambuc pgp_push_enc_se_ip(output, pubkey, cipher); 421ebfedea0SLionel Sambuc 422ebfedea0SLionel Sambuc /* This does the writing */ 423ebfedea0SLionel Sambuc pgp_write(output, input, (unsigned)insize); 424ebfedea0SLionel Sambuc 425ebfedea0SLionel Sambuc /* tidy up */ 426ebfedea0SLionel Sambuc pgp_writer_close(output); 427ebfedea0SLionel Sambuc pgp_output_delete(output); 428ebfedea0SLionel Sambuc 429ebfedea0SLionel Sambuc return outmem; 430ebfedea0SLionel Sambuc } 431ebfedea0SLionel Sambuc 432ebfedea0SLionel Sambuc /** 433ebfedea0SLionel Sambuc \ingroup HighLevel_Crypto 434ebfedea0SLionel Sambuc \brief Decrypt a file. 435ebfedea0SLionel Sambuc \param infile Name of file to be decrypted 436ebfedea0SLionel Sambuc \param outfile Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. 437ebfedea0SLionel Sambuc \param keyring Keyring to use 438ebfedea0SLionel Sambuc \param use_armour Expect armoured text, if set 439ebfedea0SLionel Sambuc \param allow_overwrite Allow output file to overwritten, if set. 440ebfedea0SLionel Sambuc \param getpassfunc Callback to use to get passphrase 441ebfedea0SLionel Sambuc */ 442ebfedea0SLionel Sambuc 443ebfedea0SLionel Sambuc unsigned 444ebfedea0SLionel Sambuc pgp_decrypt_file(pgp_io_t *io, 445ebfedea0SLionel Sambuc const char *infile, 446ebfedea0SLionel Sambuc const char *outfile, 447ebfedea0SLionel Sambuc pgp_keyring_t *secring, 448ebfedea0SLionel Sambuc pgp_keyring_t *pubring, 449ebfedea0SLionel Sambuc const unsigned use_armour, 450ebfedea0SLionel Sambuc const unsigned allow_overwrite, 451ebfedea0SLionel Sambuc const unsigned sshkeys, 452ebfedea0SLionel Sambuc void *passfp, 453ebfedea0SLionel Sambuc int numtries, 454ebfedea0SLionel Sambuc pgp_cbfunc_t *getpassfunc) 455ebfedea0SLionel Sambuc { 456ebfedea0SLionel Sambuc pgp_stream_t *parse = NULL; 457ebfedea0SLionel Sambuc const int printerrors = 1; 458ebfedea0SLionel Sambuc char *filename = NULL; 459ebfedea0SLionel Sambuc int fd_in; 460ebfedea0SLionel Sambuc int fd_out; 461ebfedea0SLionel Sambuc 462ebfedea0SLionel Sambuc /* setup for reading from given input file */ 463ebfedea0SLionel Sambuc fd_in = pgp_setup_file_read(io, &parse, infile, 464ebfedea0SLionel Sambuc NULL, 465ebfedea0SLionel Sambuc write_parsed_cb, 466ebfedea0SLionel Sambuc 0); 467ebfedea0SLionel Sambuc if (fd_in < 0) { 468ebfedea0SLionel Sambuc perror(infile); 469ebfedea0SLionel Sambuc return 0; 470ebfedea0SLionel Sambuc } 471ebfedea0SLionel Sambuc /* setup output filename */ 472ebfedea0SLionel Sambuc if (outfile) { 473ebfedea0SLionel Sambuc fd_out = pgp_setup_file_write(&parse->cbinfo.output, outfile, 474ebfedea0SLionel Sambuc allow_overwrite); 475ebfedea0SLionel Sambuc if (fd_out < 0) { 476ebfedea0SLionel Sambuc perror(outfile); 477ebfedea0SLionel Sambuc pgp_teardown_file_read(parse, fd_in); 478ebfedea0SLionel Sambuc return 0; 479ebfedea0SLionel Sambuc } 480ebfedea0SLionel Sambuc } else { 481ebfedea0SLionel Sambuc const int suffixlen = 4; 482ebfedea0SLionel Sambuc const char *suffix = infile + strlen(infile) - suffixlen; 483ebfedea0SLionel Sambuc unsigned filenamelen; 484ebfedea0SLionel Sambuc 485ebfedea0SLionel Sambuc if (strcmp(suffix, ".gpg") == 0 || 486ebfedea0SLionel Sambuc strcmp(suffix, ".asc") == 0) { 487ebfedea0SLionel Sambuc filenamelen = (unsigned)(strlen(infile) - strlen(suffix)); 488ebfedea0SLionel Sambuc if ((filename = calloc(1, filenamelen + 1)) == NULL) { 489ebfedea0SLionel Sambuc (void) fprintf(stderr, "can't allocate %" PRIsize "d bytes\n", 490ebfedea0SLionel Sambuc (size_t)(filenamelen + 1)); 491ebfedea0SLionel Sambuc return 0; 492ebfedea0SLionel Sambuc } 493ebfedea0SLionel Sambuc (void) strncpy(filename, infile, filenamelen); 494ebfedea0SLionel Sambuc filename[filenamelen] = 0x0; 495ebfedea0SLionel Sambuc } 496ebfedea0SLionel Sambuc 497ebfedea0SLionel Sambuc fd_out = pgp_setup_file_write(&parse->cbinfo.output, 498ebfedea0SLionel Sambuc filename, allow_overwrite); 499ebfedea0SLionel Sambuc if (fd_out < 0) { 500ebfedea0SLionel Sambuc perror(filename); 501ebfedea0SLionel Sambuc free(filename); 502ebfedea0SLionel Sambuc pgp_teardown_file_read(parse, fd_in); 503ebfedea0SLionel Sambuc return 0; 504ebfedea0SLionel Sambuc } 505ebfedea0SLionel Sambuc } 506ebfedea0SLionel Sambuc 507ebfedea0SLionel Sambuc /* \todo check for suffix matching armour param */ 508ebfedea0SLionel Sambuc 509ebfedea0SLionel Sambuc /* setup for writing decrypted contents to given output file */ 510ebfedea0SLionel Sambuc 511ebfedea0SLionel Sambuc /* setup keyring and passphrase callback */ 512ebfedea0SLionel Sambuc parse->cbinfo.cryptinfo.secring = secring; 513ebfedea0SLionel Sambuc parse->cbinfo.passfp = passfp; 514ebfedea0SLionel Sambuc parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 515ebfedea0SLionel Sambuc parse->cbinfo.cryptinfo.pubring = pubring; 516ebfedea0SLionel Sambuc parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; 517ebfedea0SLionel Sambuc parse->cbinfo.numtries = numtries; 518ebfedea0SLionel Sambuc 519ebfedea0SLionel Sambuc /* Set up armour/passphrase options */ 520ebfedea0SLionel Sambuc if (use_armour) { 521ebfedea0SLionel Sambuc pgp_reader_push_dearmour(parse); 522ebfedea0SLionel Sambuc } 523ebfedea0SLionel Sambuc 524ebfedea0SLionel Sambuc /* Do it */ 525ebfedea0SLionel Sambuc pgp_parse(parse, printerrors); 526ebfedea0SLionel Sambuc 527ebfedea0SLionel Sambuc /* Unsetup */ 528ebfedea0SLionel Sambuc if (use_armour) { 529ebfedea0SLionel Sambuc pgp_reader_pop_dearmour(parse); 530ebfedea0SLionel Sambuc } 531ebfedea0SLionel Sambuc 532ebfedea0SLionel Sambuc /* if we didn't get the passphrase, unlink output file */ 533ebfedea0SLionel Sambuc if (!parse->cbinfo.gotpass) { 534ebfedea0SLionel Sambuc (void) unlink((filename) ? filename : outfile); 535ebfedea0SLionel Sambuc } 536ebfedea0SLionel Sambuc 537ebfedea0SLionel Sambuc if (filename) { 538ebfedea0SLionel Sambuc pgp_teardown_file_write(parse->cbinfo.output, fd_out); 539ebfedea0SLionel Sambuc free(filename); 540ebfedea0SLionel Sambuc } 541ebfedea0SLionel Sambuc pgp_teardown_file_read(parse, fd_in); 542ebfedea0SLionel Sambuc /* \todo cleardown crypt */ 543ebfedea0SLionel Sambuc 544ebfedea0SLionel Sambuc return 1; 545ebfedea0SLionel Sambuc } 546ebfedea0SLionel Sambuc 547ebfedea0SLionel Sambuc /* decrypt an area of memory */ 548ebfedea0SLionel Sambuc pgp_memory_t * 549ebfedea0SLionel Sambuc pgp_decrypt_buf(pgp_io_t *io, 550ebfedea0SLionel Sambuc const void *input, 551ebfedea0SLionel Sambuc const size_t insize, 552ebfedea0SLionel Sambuc pgp_keyring_t *secring, 553ebfedea0SLionel Sambuc pgp_keyring_t *pubring, 554ebfedea0SLionel Sambuc const unsigned use_armour, 555ebfedea0SLionel Sambuc const unsigned sshkeys, 556ebfedea0SLionel Sambuc void *passfp, 557ebfedea0SLionel Sambuc int numtries, 558ebfedea0SLionel Sambuc pgp_cbfunc_t *getpassfunc) 559ebfedea0SLionel Sambuc { 560ebfedea0SLionel Sambuc pgp_stream_t *parse = NULL; 561ebfedea0SLionel Sambuc pgp_memory_t *outmem; 562ebfedea0SLionel Sambuc pgp_memory_t *inmem; 563ebfedea0SLionel Sambuc const int printerrors = 1; 564ebfedea0SLionel Sambuc 565ebfedea0SLionel Sambuc if (input == NULL) { 566ebfedea0SLionel Sambuc (void) fprintf(io->errs, 567ebfedea0SLionel Sambuc "pgp_encrypt_buf: null memory\n"); 568ebfedea0SLionel Sambuc return 0; 569ebfedea0SLionel Sambuc } 570ebfedea0SLionel Sambuc 571ebfedea0SLionel Sambuc inmem = pgp_memory_new(); 572ebfedea0SLionel Sambuc pgp_memory_add(inmem, input, insize); 573ebfedea0SLionel Sambuc 574ebfedea0SLionel Sambuc /* set up to read from memory */ 575ebfedea0SLionel Sambuc pgp_setup_memory_read(io, &parse, inmem, 576ebfedea0SLionel Sambuc NULL, 577ebfedea0SLionel Sambuc write_parsed_cb, 578ebfedea0SLionel Sambuc 0); 579ebfedea0SLionel Sambuc 580ebfedea0SLionel Sambuc /* setup for writing decrypted contents to given output file */ 581ebfedea0SLionel Sambuc pgp_setup_memory_write(&parse->cbinfo.output, &outmem, insize); 582ebfedea0SLionel Sambuc 583ebfedea0SLionel Sambuc /* setup keyring and passphrase callback */ 584ebfedea0SLionel Sambuc parse->cbinfo.cryptinfo.secring = secring; 585ebfedea0SLionel Sambuc parse->cbinfo.cryptinfo.pubring = pubring; 586ebfedea0SLionel Sambuc parse->cbinfo.passfp = passfp; 587ebfedea0SLionel Sambuc parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 588ebfedea0SLionel Sambuc parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; 589ebfedea0SLionel Sambuc parse->cbinfo.numtries = numtries; 590ebfedea0SLionel Sambuc 591ebfedea0SLionel Sambuc /* Set up armour/passphrase options */ 592ebfedea0SLionel Sambuc if (use_armour) { 593ebfedea0SLionel Sambuc pgp_reader_push_dearmour(parse); 594ebfedea0SLionel Sambuc } 595ebfedea0SLionel Sambuc 596ebfedea0SLionel Sambuc /* Do it */ 597ebfedea0SLionel Sambuc pgp_parse(parse, printerrors); 598ebfedea0SLionel Sambuc 599ebfedea0SLionel Sambuc /* Unsetup */ 600ebfedea0SLionel Sambuc if (use_armour) { 601ebfedea0SLionel Sambuc pgp_reader_pop_dearmour(parse); 602ebfedea0SLionel Sambuc } 603ebfedea0SLionel Sambuc 604ebfedea0SLionel Sambuc /* tidy up */ 605ebfedea0SLionel Sambuc pgp_teardown_memory_read(parse, inmem); 606ebfedea0SLionel Sambuc 607ebfedea0SLionel Sambuc pgp_writer_close(parse->cbinfo.output); 608ebfedea0SLionel Sambuc pgp_output_delete(parse->cbinfo.output); 609ebfedea0SLionel Sambuc 610ebfedea0SLionel Sambuc /* if we didn't get the passphrase, return NULL */ 611ebfedea0SLionel Sambuc return (parse->cbinfo.gotpass) ? outmem : NULL; 612ebfedea0SLionel Sambuc } 613