12232f800Sagc /*- 22232f800Sagc * Copyright (c) 2009 The NetBSD Foundation, Inc. 32232f800Sagc * All rights reserved. 42232f800Sagc * 52232f800Sagc * This code is derived from software contributed to The NetBSD Foundation 62232f800Sagc * by Alistair Crooks (agc@NetBSD.org) 72232f800Sagc * 82232f800Sagc * Redistribution and use in source and binary forms, with or without 92232f800Sagc * modification, are permitted provided that the following conditions 102232f800Sagc * are met: 112232f800Sagc * 1. Redistributions of source code must retain the above copyright 122232f800Sagc * notice, this list of conditions and the following disclaimer. 132232f800Sagc * 2. Redistributions in binary form must reproduce the above copyright 142232f800Sagc * notice, this list of conditions and the following disclaimer in the 152232f800Sagc * documentation and/or other materials provided with the distribution. 162232f800Sagc * 172232f800Sagc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 182232f800Sagc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 192232f800Sagc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 202232f800Sagc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 212232f800Sagc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 222232f800Sagc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 232232f800Sagc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 242232f800Sagc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 252232f800Sagc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 262232f800Sagc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 272232f800Sagc * POSSIBILITY OF SUCH DAMAGE. 282232f800Sagc */ 2993bf6008Sagc /* 3093bf6008Sagc * Copyright (c) 2005-2008 Nominet UK (www.nic.uk) 3193bf6008Sagc * All rights reserved. 3293bf6008Sagc * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted 3393bf6008Sagc * their moral rights under the UK Copyright Design and Patents Act 1988 to 3493bf6008Sagc * be recorded as the authors of this copyright work. 3593bf6008Sagc * 3693bf6008Sagc * Licensed under the Apache License, Version 2.0 (the "License"); you may not 3793bf6008Sagc * use this file except in compliance with the License. 3893bf6008Sagc * 3993bf6008Sagc * You may obtain a copy of the License at 4093bf6008Sagc * http://www.apache.org/licenses/LICENSE-2.0 4193bf6008Sagc * 4293bf6008Sagc * Unless required by applicable law or agreed to in writing, software 4393bf6008Sagc * distributed under the License is distributed on an "AS IS" BASIS, 4493bf6008Sagc * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 4593bf6008Sagc * 4693bf6008Sagc * See the License for the specific language governing permissions and 4793bf6008Sagc * limitations under the License. 4893bf6008Sagc */ 4993bf6008Sagc #include "config.h" 5093bf6008Sagc 5157324b9fSagc #ifdef HAVE_SYS_CDEFS_H 5257324b9fSagc #include <sys/cdefs.h> 5357324b9fSagc #endif 5457324b9fSagc 5557324b9fSagc #if defined(__NetBSD__) 5657324b9fSagc __COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc. All rights reserved."); 57*c04135dcSagc __RCSID("$NetBSD: crypto.c,v 1.36 2014/02/17 07:39:19 agc Exp $"); 5857324b9fSagc #endif 5957324b9fSagc 6057324b9fSagc #include <sys/types.h> 6157324b9fSagc #include <sys/stat.h> 6257324b9fSagc 63efdd9dbaSagc #ifdef HAVE_UNISTD_H 64efdd9dbaSagc #include <unistd.h> 65efdd9dbaSagc #endif 66efdd9dbaSagc 6793bf6008Sagc #include <string.h> 68bcfd8565Sagc 69d21b929eSagc #include "types.h" 70bcfd8565Sagc #include "crypto.h" 71bcfd8565Sagc #include "readerwriter.h" 72bcfd8565Sagc #include "memory.h" 73bcfd8565Sagc #include "netpgpdefs.h" 74bcfd8565Sagc #include "signature.h" 7593bf6008Sagc 7693bf6008Sagc /** 7793bf6008Sagc \ingroup Core_MPI 7893bf6008Sagc \brief Decrypt and unencode MPI 7993bf6008Sagc \param buf Buffer in which to write decrypted unencoded MPI 8093bf6008Sagc \param buflen Length of buffer 8193bf6008Sagc \param encmpi 820c310959Sagc \param seckey 8393bf6008Sagc \return length of MPI 8493bf6008Sagc \note only RSA at present 8593bf6008Sagc */ 8693bf6008Sagc int 87fc1f8641Sagc pgp_decrypt_decode_mpi(uint8_t *buf, 88bcfd8565Sagc unsigned buflen, 89c2430ca2Sagc const BIGNUM *g_to_k, 90bcfd8565Sagc const BIGNUM *encmpi, 91fc1f8641Sagc const pgp_seckey_t *seckey) 9293bf6008Sagc { 93520c968fSagc unsigned mpisize; 94b15ec256Sagc uint8_t encmpibuf[NETPGP_BUFSIZ]; 95b15ec256Sagc uint8_t mpibuf[NETPGP_BUFSIZ]; 96c2430ca2Sagc uint8_t gkbuf[NETPGP_BUFSIZ]; 9793bf6008Sagc int i; 98520c968fSagc int n; 9993bf6008Sagc 1005a83dba0Sagc mpisize = (unsigned)BN_num_bytes(encmpi); 10193bf6008Sagc /* MPI can't be more than 65,536 */ 102bcfd8565Sagc if (mpisize > sizeof(encmpibuf)) { 103bcfd8565Sagc (void) fprintf(stderr, "mpisize too big %u\n", mpisize); 104bcfd8565Sagc return -1; 105bcfd8565Sagc } 106520c968fSagc switch (seckey->pubkey.alg) { 107fc1f8641Sagc case PGP_PKA_RSA: 108c2430ca2Sagc BN_bn2bin(encmpi, encmpibuf); 109fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 11047561e26Sagc hexdump(stderr, "encrypted", encmpibuf, 16); 111bcfd8565Sagc } 112fc1f8641Sagc n = pgp_rsa_private_decrypt(mpibuf, encmpibuf, 113bcfd8565Sagc (unsigned)(BN_num_bits(encmpi) + 7) / 8, 1140c310959Sagc &seckey->key.rsa, &seckey->pubkey.key.rsa); 115bcfd8565Sagc if (n == -1) { 116bcfd8565Sagc (void) fprintf(stderr, "ops_rsa_private_decrypt failure\n"); 117bcfd8565Sagc return -1; 118bcfd8565Sagc } 119fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 12047561e26Sagc hexdump(stderr, "decrypted", mpibuf, 16); 121bcfd8565Sagc } 122bcfd8565Sagc if (n <= 0) { 123bcfd8565Sagc return -1; 124bcfd8565Sagc } 12593bf6008Sagc /* Decode EME-PKCS1_V1_5 (RFC 2437). */ 126bcfd8565Sagc if (mpibuf[0] != 0 || mpibuf[1] != 2) { 127bcfd8565Sagc return -1; 128bcfd8565Sagc } 12993bf6008Sagc /* Skip the random bytes. */ 130bcfd8565Sagc for (i = 2; i < n && mpibuf[i]; ++i) { 131bcfd8565Sagc } 132bcfd8565Sagc if (i == n || i < 10) { 133bcfd8565Sagc return -1; 134bcfd8565Sagc } 13593bf6008Sagc /* Skip the zero */ 13657324b9fSagc i += 1; 13793bf6008Sagc /* this is the unencoded m buf */ 138bcfd8565Sagc if ((unsigned) (n - i) <= buflen) { 1395a83dba0Sagc (void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */ 140bcfd8565Sagc } 141fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 14247561e26Sagc hexdump(stderr, "decoded m", buf, (size_t)(n - i)); 14393bf6008Sagc } 14493bf6008Sagc return n - i; 145fc1f8641Sagc case PGP_PKA_DSA: 146fc1f8641Sagc case PGP_PKA_ELGAMAL: 147c2430ca2Sagc (void) BN_bn2bin(g_to_k, gkbuf); 148c2430ca2Sagc (void) BN_bn2bin(encmpi, encmpibuf); 149fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 15073f34b00Sagc hexdump(stderr, "encrypted", encmpibuf, 16); 15173f34b00Sagc } 152fc1f8641Sagc n = pgp_elgamal_private_decrypt(mpibuf, gkbuf, encmpibuf, 153c2430ca2Sagc (unsigned)BN_num_bytes(encmpi), 15473f34b00Sagc &seckey->key.elgamal, &seckey->pubkey.key.elgamal); 15573f34b00Sagc if (n == -1) { 15673f34b00Sagc (void) fprintf(stderr, "ops_elgamal_private_decrypt failure\n"); 15773f34b00Sagc return -1; 15873f34b00Sagc } 159fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 16073f34b00Sagc hexdump(stderr, "decrypted", mpibuf, 16); 16173f34b00Sagc } 16273f34b00Sagc if (n <= 0) { 16373f34b00Sagc return -1; 16473f34b00Sagc } 16573f34b00Sagc /* Decode EME-PKCS1_V1_5 (RFC 2437). */ 166c2430ca2Sagc if (mpibuf[0] != 2) { 167c2430ca2Sagc fprintf(stderr, "mpibuf mismatch\n"); 16873f34b00Sagc return -1; 16973f34b00Sagc } 17073f34b00Sagc /* Skip the random bytes. */ 171c2430ca2Sagc for (i = 1; i < n && mpibuf[i]; ++i) { 17273f34b00Sagc } 17373f34b00Sagc if (i == n || i < 10) { 174c2430ca2Sagc fprintf(stderr, "175 n %d\n", n); 17573f34b00Sagc return -1; 17673f34b00Sagc } 17773f34b00Sagc /* Skip the zero */ 17873f34b00Sagc i += 1; 17973f34b00Sagc /* this is the unencoded m buf */ 18073f34b00Sagc if ((unsigned) (n - i) <= buflen) { 18173f34b00Sagc (void) memcpy(buf, mpibuf + i, (unsigned)(n - i)); /* XXX - Flexelint */ 18273f34b00Sagc } 183fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 18473f34b00Sagc hexdump(stderr, "decoded m", buf, (size_t)(n - i)); 18573f34b00Sagc } 18673f34b00Sagc return n - i; 187520c968fSagc default: 188520c968fSagc (void) fprintf(stderr, "pubkey algorithm wrong\n"); 189520c968fSagc return -1; 190520c968fSagc } 19193bf6008Sagc } 19293bf6008Sagc 19393bf6008Sagc /** 19493bf6008Sagc \ingroup Core_MPI 19593bf6008Sagc \brief RSA-encrypt an MPI 19693bf6008Sagc */ 1974b3a3e18Sagc unsigned 198fc1f8641Sagc pgp_rsa_encrypt_mpi(const uint8_t *encoded_m_buf, 19993bf6008Sagc const size_t sz_encoded_m_buf, 200fc1f8641Sagc const pgp_pubkey_t * pubkey, 201fc1f8641Sagc pgp_pk_sesskey_params_t * skp) 20293bf6008Sagc { 20393bf6008Sagc 204b15ec256Sagc uint8_t encmpibuf[NETPGP_BUFSIZ]; 2055a83dba0Sagc int n; 20693bf6008Sagc 2070c310959Sagc if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.rsa.n)) { 208bcfd8565Sagc (void) fprintf(stderr, "sz_encoded_m_buf wrong\n"); 2094b3a3e18Sagc return 0; 210bcfd8565Sagc } 21193bf6008Sagc 212fc1f8641Sagc n = pgp_rsa_public_encrypt(encmpibuf, encoded_m_buf, 2130c310959Sagc sz_encoded_m_buf, &pubkey->key.rsa); 214bcfd8565Sagc if (n == -1) { 215fc1f8641Sagc (void) fprintf(stderr, "pgp_rsa_public_encrypt failure\n"); 2164b3a3e18Sagc return 0; 217bcfd8565Sagc } 21893bf6008Sagc 21993bf6008Sagc if (n <= 0) 2204b3a3e18Sagc return 0; 22193bf6008Sagc 22293bf6008Sagc skp->rsa.encrypted_m = BN_bin2bn(encmpibuf, n, NULL); 22393bf6008Sagc 224fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 22547561e26Sagc hexdump(stderr, "encrypted mpi", encmpibuf, 16); 22693bf6008Sagc } 2274b3a3e18Sagc return 1; 22893bf6008Sagc } 22993bf6008Sagc 23037d8b79bSagc /** 23137d8b79bSagc \ingroup Core_MPI 23237d8b79bSagc \brief Elgamal-encrypt an MPI 23337d8b79bSagc */ 23437d8b79bSagc unsigned 235fc1f8641Sagc pgp_elgamal_encrypt_mpi(const uint8_t *encoded_m_buf, 23637d8b79bSagc const size_t sz_encoded_m_buf, 237fc1f8641Sagc const pgp_pubkey_t * pubkey, 238fc1f8641Sagc pgp_pk_sesskey_params_t * skp) 23937d8b79bSagc { 24037d8b79bSagc 24137d8b79bSagc uint8_t encmpibuf[NETPGP_BUFSIZ]; 24237d8b79bSagc uint8_t g_to_k[NETPGP_BUFSIZ]; 24337d8b79bSagc int n; 24437d8b79bSagc 24537d8b79bSagc if (sz_encoded_m_buf != (size_t)BN_num_bytes(pubkey->key.elgamal.p)) { 24637d8b79bSagc (void) fprintf(stderr, "sz_encoded_m_buf wrong\n"); 24737d8b79bSagc return 0; 24837d8b79bSagc } 24937d8b79bSagc 250fc1f8641Sagc n = pgp_elgamal_public_encrypt(g_to_k, encmpibuf, encoded_m_buf, 25137d8b79bSagc sz_encoded_m_buf, &pubkey->key.elgamal); 25237d8b79bSagc if (n == -1) { 253fc1f8641Sagc (void) fprintf(stderr, "pgp_elgamal_public_encrypt failure\n"); 25437d8b79bSagc return 0; 25537d8b79bSagc } 25637d8b79bSagc 25737d8b79bSagc if (n <= 0) 25837d8b79bSagc return 0; 25937d8b79bSagc 26037d8b79bSagc skp->elgamal.g_to_k = BN_bin2bn(g_to_k, n / 2, NULL); 26137d8b79bSagc skp->elgamal.encrypted_m = BN_bin2bn(encmpibuf, n / 2, NULL); 26237d8b79bSagc 263fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 26437d8b79bSagc hexdump(stderr, "encrypted mpi", encmpibuf, 16); 26537d8b79bSagc } 26637d8b79bSagc return 1; 26737d8b79bSagc } 26837d8b79bSagc 269fc1f8641Sagc static pgp_cb_ret_t 270fc1f8641Sagc write_parsed_cb(const pgp_packet_t *pkt, pgp_cbdata_t *cbinfo) 271d369874eSagc { 272fc1f8641Sagc const pgp_contents_t *content = &pkt->u; 273d369874eSagc 274fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 275d369874eSagc printf("write_parsed_cb: "); 276fc1f8641Sagc pgp_print_packet(&cbinfo->printstate, pkt); 277d369874eSagc } 278fc1f8641Sagc if (pkt->tag != PGP_PTAG_CT_UNARMOURED_TEXT && cbinfo->printstate.skipping) { 279d369874eSagc puts("...end of skip"); 2802b48e3a6Sagc cbinfo->printstate.skipping = 0; 281d369874eSagc } 282d369874eSagc switch (pkt->tag) { 283fc1f8641Sagc case PGP_PTAG_CT_UNARMOURED_TEXT: 284fc1f8641Sagc printf("PGP_PTAG_CT_UNARMOURED_TEXT\n"); 2852b48e3a6Sagc if (!cbinfo->printstate.skipping) { 286d369874eSagc puts("Skipping..."); 2872b48e3a6Sagc cbinfo->printstate.skipping = 1; 288d369874eSagc } 289*c04135dcSagc if (fwrite(content->unarmoured_text.data, 1, 290*c04135dcSagc content->unarmoured_text.length, stdout) != content->unarmoured_text.length) { 291*c04135dcSagc fprintf(stderr, "unable to write unarmoured text data\n"); 292*c04135dcSagc cbinfo->printstate.skipping = 1; 293*c04135dcSagc } 294d369874eSagc break; 295d369874eSagc 296fc1f8641Sagc case PGP_PTAG_CT_PK_SESSION_KEY: 297fc1f8641Sagc return pgp_pk_sesskey_cb(pkt, cbinfo); 298d369874eSagc 299fc1f8641Sagc case PGP_GET_SECKEY: 30073f34b00Sagc if (cbinfo->sshseckey) { 30173f34b00Sagc *content->get_seckey.seckey = cbinfo->sshseckey; 302fc1f8641Sagc return PGP_KEEP_MEMORY; 30373f34b00Sagc } 304fc1f8641Sagc return pgp_get_seckey_cb(pkt, cbinfo); 305d369874eSagc 306fc1f8641Sagc case PGP_GET_PASSPHRASE: 307d369874eSagc return cbinfo->cryptinfo.getpassphrase(pkt, cbinfo); 308d369874eSagc 309fc1f8641Sagc case PGP_PTAG_CT_LITDATA_BODY: 310fc1f8641Sagc return pgp_litdata_cb(pkt, cbinfo); 311d369874eSagc 312fc1f8641Sagc case PGP_PTAG_CT_ARMOUR_HEADER: 313fc1f8641Sagc case PGP_PTAG_CT_ARMOUR_TRAILER: 314fc1f8641Sagc case PGP_PTAG_CT_ENCRYPTED_PK_SESSION_KEY: 315fc1f8641Sagc case PGP_PTAG_CT_COMPRESSED: 316fc1f8641Sagc case PGP_PTAG_CT_LITDATA_HEADER: 317fc1f8641Sagc case PGP_PTAG_CT_SE_IP_DATA_BODY: 318fc1f8641Sagc case PGP_PTAG_CT_SE_IP_DATA_HEADER: 319fc1f8641Sagc case PGP_PTAG_CT_SE_DATA_BODY: 320fc1f8641Sagc case PGP_PTAG_CT_SE_DATA_HEADER: 321d369874eSagc /* Ignore these packets */ 322e2c60ad1Sagc /* They're handled in parse_packet() */ 323d369874eSagc /* and nothing else needs to be done */ 324d369874eSagc break; 325d369874eSagc 326d369874eSagc default: 327fc1f8641Sagc if (pgp_get_debug_level(__FILE__)) { 328d369874eSagc fprintf(stderr, "Unexpected packet tag=%d (0x%x)\n", 329d369874eSagc pkt->tag, 330d369874eSagc pkt->tag); 331d369874eSagc } 332d369874eSagc break; 333d369874eSagc } 334d369874eSagc 335fc1f8641Sagc return PGP_RELEASE_MEMORY; 336d369874eSagc } 33793bf6008Sagc 33893bf6008Sagc /** 33993bf6008Sagc \ingroup HighLevel_Crypto 34093bf6008Sagc Encrypt a file 341b1b58706Sagc \param infile Name of file to be encrypted 342b1b58706Sagc \param outfile Name of file to write to. If NULL, name is constructed from infile 34357324b9fSagc \param pubkey Public Key to encrypt file for 34493bf6008Sagc \param use_armour Write armoured text, if set 34593bf6008Sagc \param allow_overwrite Allow output file to be overwrwritten if it exists 3464b3a3e18Sagc \return 1 if OK; else 0 34793bf6008Sagc */ 3484b3a3e18Sagc unsigned 349fc1f8641Sagc pgp_encrypt_file(pgp_io_t *io, 350d21b929eSagc const char *infile, 351b1b58706Sagc const char *outfile, 352fc1f8641Sagc const pgp_key_t *key, 3534b3a3e18Sagc const unsigned use_armour, 354f7745f84Sagc const unsigned allow_overwrite, 355f7745f84Sagc const char *cipher) 35693bf6008Sagc { 357fc1f8641Sagc pgp_output_t *output; 358fc1f8641Sagc pgp_memory_t *inmem; 3595a83dba0Sagc int fd_out; 36093bf6008Sagc 361fc1f8641Sagc __PGP_USED(io); 362fc1f8641Sagc inmem = pgp_memory_new(); 363fc1f8641Sagc if (!pgp_mem_readfile(inmem, infile)) { 3644b3a3e18Sagc return 0; 36593bf6008Sagc } 366fc1f8641Sagc fd_out = pgp_setup_file_write(&output, outfile, allow_overwrite); 367bcfd8565Sagc if (fd_out < 0) { 368fc1f8641Sagc pgp_memory_free(inmem); 3694b3a3e18Sagc return 0; 370bcfd8565Sagc } 37193bf6008Sagc 37293bf6008Sagc /* set armoured/not armoured here */ 373bcfd8565Sagc if (use_armour) { 374fc1f8641Sagc pgp_writer_push_armor_msg(output); 375bcfd8565Sagc } 37693bf6008Sagc 37793bf6008Sagc /* Push the encrypted writer */ 378fc1f8641Sagc if (!pgp_push_enc_se_ip(output, key, cipher)) { 379fc1f8641Sagc pgp_memory_free(inmem); 380520c968fSagc return 0; 381520c968fSagc } 38293bf6008Sagc 38393bf6008Sagc /* This does the writing */ 384fc1f8641Sagc pgp_write(output, pgp_mem_data(inmem), (unsigned)pgp_mem_len(inmem)); 38593bf6008Sagc 38693bf6008Sagc /* tidy up */ 387fc1f8641Sagc pgp_memory_free(inmem); 388fc1f8641Sagc pgp_teardown_file_write(output, fd_out); 38993bf6008Sagc 3904b3a3e18Sagc return 1; 39193bf6008Sagc } 39293bf6008Sagc 393d369874eSagc /* encrypt the contents of the input buffer, and return the mem structure */ 394fc1f8641Sagc pgp_memory_t * 395fc1f8641Sagc pgp_encrypt_buf(pgp_io_t *io, 396d369874eSagc const void *input, 397d369874eSagc const size_t insize, 398fc1f8641Sagc const pgp_key_t *pubkey, 399f7745f84Sagc const unsigned use_armour, 400f7745f84Sagc const char *cipher) 401d369874eSagc { 402fc1f8641Sagc pgp_output_t *output; 403fc1f8641Sagc pgp_memory_t *outmem; 404d369874eSagc 405fc1f8641Sagc __PGP_USED(io); 406d369874eSagc if (input == NULL) { 407d369874eSagc (void) fprintf(io->errs, 408fc1f8641Sagc "pgp_encrypt_buf: null memory\n"); 409d369874eSagc return 0; 410d369874eSagc } 411d369874eSagc 412fc1f8641Sagc pgp_setup_memory_write(&output, &outmem, insize); 413d369874eSagc 414d369874eSagc /* set armoured/not armoured here */ 415d369874eSagc if (use_armour) { 416fc1f8641Sagc pgp_writer_push_armor_msg(output); 417d369874eSagc } 418d369874eSagc 419d369874eSagc /* Push the encrypted writer */ 420fc1f8641Sagc pgp_push_enc_se_ip(output, pubkey, cipher); 421d369874eSagc 422d369874eSagc /* This does the writing */ 423fc1f8641Sagc pgp_write(output, input, (unsigned)insize); 424d369874eSagc 425d369874eSagc /* tidy up */ 426fc1f8641Sagc pgp_writer_close(output); 427fc1f8641Sagc pgp_output_delete(output); 428d369874eSagc 429d369874eSagc return outmem; 430d369874eSagc } 431d369874eSagc 43293bf6008Sagc /** 43393bf6008Sagc \ingroup HighLevel_Crypto 43493bf6008Sagc \brief Decrypt a file. 435b1b58706Sagc \param infile Name of file to be decrypted 436b1b58706Sagc \param outfile Name of file to write to. If NULL, the filename is constructed from the input filename, following GPG conventions. 43793bf6008Sagc \param keyring Keyring to use 43893bf6008Sagc \param use_armour Expect armoured text, if set 43993bf6008Sagc \param allow_overwrite Allow output file to overwritten, if set. 44041335e2dSagc \param getpassfunc Callback to use to get passphrase 44193bf6008Sagc */ 44293bf6008Sagc 4434b3a3e18Sagc unsigned 444fc1f8641Sagc pgp_decrypt_file(pgp_io_t *io, 445d21b929eSagc const char *infile, 446b1b58706Sagc const char *outfile, 447fc1f8641Sagc pgp_keyring_t *secring, 448fc1f8641Sagc pgp_keyring_t *pubring, 4494b3a3e18Sagc const unsigned use_armour, 4504b3a3e18Sagc const unsigned allow_overwrite, 45173f34b00Sagc const unsigned sshkeys, 45241335e2dSagc void *passfp, 453ea162599Sagc int numtries, 454fc1f8641Sagc pgp_cbfunc_t *getpassfunc) 45593bf6008Sagc { 456fc1f8641Sagc pgp_stream_t *parse = NULL; 457393ecd92Sagc const int printerrors = 1; 458b1b58706Sagc char *filename = NULL; 4595a83dba0Sagc int fd_in; 4605a83dba0Sagc int fd_out; 46193bf6008Sagc 46293bf6008Sagc /* setup for reading from given input file */ 463fc1f8641Sagc fd_in = pgp_setup_file_read(io, &parse, infile, 46493bf6008Sagc NULL, 465d369874eSagc write_parsed_cb, 4664b3a3e18Sagc 0); 46793bf6008Sagc if (fd_in < 0) { 468b1b58706Sagc perror(infile); 4694b3a3e18Sagc return 0; 47093bf6008Sagc } 4712232f800Sagc /* setup output filename */ 472b1b58706Sagc if (outfile) { 473fc1f8641Sagc fd_out = pgp_setup_file_write(&parse->cbinfo.output, outfile, 474b1b58706Sagc allow_overwrite); 47593bf6008Sagc if (fd_out < 0) { 476b1b58706Sagc perror(outfile); 477fc1f8641Sagc pgp_teardown_file_read(parse, fd_in); 4784b3a3e18Sagc return 0; 47993bf6008Sagc } 48093bf6008Sagc } else { 481d21b929eSagc const int suffixlen = 4; 482b1b58706Sagc const char *suffix = infile + strlen(infile) - suffixlen; 483d21b929eSagc unsigned filenamelen; 484b1b58706Sagc 48593bf6008Sagc if (strcmp(suffix, ".gpg") == 0 || 48693bf6008Sagc strcmp(suffix, ".asc") == 0) { 48769d4f30fSagc filenamelen = (unsigned)(strlen(infile) - strlen(suffix)); 4885a83dba0Sagc if ((filename = calloc(1, filenamelen + 1)) == NULL) { 4895a83dba0Sagc (void) fprintf(stderr, "can't allocate %" PRIsize "d bytes\n", 4905a83dba0Sagc (size_t)(filenamelen + 1)); 4915a83dba0Sagc return 0; 4925a83dba0Sagc } 493b1b58706Sagc (void) strncpy(filename, infile, filenamelen); 494b1b58706Sagc filename[filenamelen] = 0x0; 49593bf6008Sagc } 49693bf6008Sagc 497fc1f8641Sagc fd_out = pgp_setup_file_write(&parse->cbinfo.output, 498b1b58706Sagc filename, allow_overwrite); 49993bf6008Sagc if (fd_out < 0) { 500b1b58706Sagc perror(filename); 5015a83dba0Sagc free(filename); 502fc1f8641Sagc pgp_teardown_file_read(parse, fd_in); 5034b3a3e18Sagc return 0; 50493bf6008Sagc } 50593bf6008Sagc } 50693bf6008Sagc 50793bf6008Sagc /* \todo check for suffix matching armour param */ 50893bf6008Sagc 50993bf6008Sagc /* setup for writing decrypted contents to given output file */ 51093bf6008Sagc 51193bf6008Sagc /* setup keyring and passphrase callback */ 5120aa60872Sagc parse->cbinfo.cryptinfo.secring = secring; 51341335e2dSagc parse->cbinfo.passfp = passfp; 51441335e2dSagc parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 5150aa60872Sagc parse->cbinfo.cryptinfo.pubring = pubring; 51673f34b00Sagc parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; 517ea162599Sagc parse->cbinfo.numtries = numtries; 51893bf6008Sagc 51993bf6008Sagc /* Set up armour/passphrase options */ 520b1b58706Sagc if (use_armour) { 521fc1f8641Sagc pgp_reader_push_dearmour(parse); 522b1b58706Sagc } 52393bf6008Sagc 52493bf6008Sagc /* Do it */ 525fc1f8641Sagc pgp_parse(parse, printerrors); 52693bf6008Sagc 52793bf6008Sagc /* Unsetup */ 528b1b58706Sagc if (use_armour) { 529fc1f8641Sagc pgp_reader_pop_dearmour(parse); 530b1b58706Sagc } 53193bf6008Sagc 532ea162599Sagc /* if we didn't get the passphrase, unlink output file */ 533ea162599Sagc if (!parse->cbinfo.gotpass) { 534ea162599Sagc (void) unlink((filename) ? filename : outfile); 535ea162599Sagc } 536ea162599Sagc 537b1b58706Sagc if (filename) { 538fc1f8641Sagc pgp_teardown_file_write(parse->cbinfo.output, fd_out); 5395a83dba0Sagc free(filename); 540b1b58706Sagc } 541fc1f8641Sagc pgp_teardown_file_read(parse, fd_in); 54293bf6008Sagc /* \todo cleardown crypt */ 54393bf6008Sagc 5444b3a3e18Sagc return 1; 54593bf6008Sagc } 54693bf6008Sagc 547d369874eSagc /* decrypt an area of memory */ 548fc1f8641Sagc pgp_memory_t * 549fc1f8641Sagc pgp_decrypt_buf(pgp_io_t *io, 550d369874eSagc const void *input, 551d369874eSagc const size_t insize, 552fc1f8641Sagc pgp_keyring_t *secring, 553fc1f8641Sagc pgp_keyring_t *pubring, 554d369874eSagc const unsigned use_armour, 55573f34b00Sagc const unsigned sshkeys, 556d369874eSagc void *passfp, 557ea162599Sagc int numtries, 558fc1f8641Sagc pgp_cbfunc_t *getpassfunc) 55993bf6008Sagc { 560fc1f8641Sagc pgp_stream_t *parse = NULL; 561fc1f8641Sagc pgp_memory_t *outmem; 562fc1f8641Sagc pgp_memory_t *inmem; 563d369874eSagc const int printerrors = 1; 56493bf6008Sagc 565d369874eSagc if (input == NULL) { 566d369874eSagc (void) fprintf(io->errs, 567fc1f8641Sagc "pgp_encrypt_buf: null memory\n"); 568d369874eSagc return 0; 56993bf6008Sagc } 57093bf6008Sagc 571fc1f8641Sagc inmem = pgp_memory_new(); 572fc1f8641Sagc pgp_memory_add(inmem, input, insize); 573d369874eSagc 574d369874eSagc /* set up to read from memory */ 575fc1f8641Sagc pgp_setup_memory_read(io, &parse, inmem, 576d369874eSagc NULL, 577d369874eSagc write_parsed_cb, 578d369874eSagc 0); 579d369874eSagc 580d369874eSagc /* setup for writing decrypted contents to given output file */ 581fc1f8641Sagc pgp_setup_memory_write(&parse->cbinfo.output, &outmem, insize); 582d369874eSagc 583d369874eSagc /* setup keyring and passphrase callback */ 5840aa60872Sagc parse->cbinfo.cryptinfo.secring = secring; 5850aa60872Sagc parse->cbinfo.cryptinfo.pubring = pubring; 586d369874eSagc parse->cbinfo.passfp = passfp; 587d369874eSagc parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; 58873f34b00Sagc parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; 589ea162599Sagc parse->cbinfo.numtries = numtries; 590d369874eSagc 591d369874eSagc /* Set up armour/passphrase options */ 592d369874eSagc if (use_armour) { 593fc1f8641Sagc pgp_reader_push_dearmour(parse); 59493bf6008Sagc } 595d369874eSagc 596d369874eSagc /* Do it */ 597fc1f8641Sagc pgp_parse(parse, printerrors); 598d369874eSagc 599d369874eSagc /* Unsetup */ 600d369874eSagc if (use_armour) { 601fc1f8641Sagc pgp_reader_pop_dearmour(parse); 602d369874eSagc } 603d369874eSagc 604d369874eSagc /* tidy up */ 605fc1f8641Sagc pgp_teardown_memory_read(parse, inmem); 606d369874eSagc 607fc1f8641Sagc pgp_writer_close(parse->cbinfo.output); 608fc1f8641Sagc pgp_output_delete(parse->cbinfo.output); 609d369874eSagc 610ea162599Sagc /* if we didn't get the passphrase, return NULL */ 611ea162599Sagc return (parse->cbinfo.gotpass) ? outmem : NULL; 612d369874eSagc } 613