/** \ingroup Core_Keys \brief Decrypts secret key from given keydata with given passphrase \param key Key from which to get secret key \param passphrase Passphrase to use to decrypt secret key \return secret key */ pgp_seckey_t * pgp_decrypt_seckey(const pgp_key_t *key, void *passfp) { pgp_stream_t *stream; const int printerrors = 1; decrypt_t decrypt; (void) memset(&decrypt, 0x0, sizeof(decrypt)); decrypt.key = key; decrypt.passfp = passfp; stream = pgp_new(sizeof(*stream)); pgp_keydata_reader_set(stream, key); pgp_set_callback(stream, decrypt_cb, &decrypt); stream->readinfo.accumulate = 1; pgp_parse(stream, !printerrors); return decrypt.seckey; }
/* decrypt an area of memory */ pgp_memory_t * pgp_decrypt_buf(pgp_io_t *io, const void *input, const size_t insize, pgp_keyring_t *secring, pgp_keyring_t *pubring, const unsigned use_armour, const unsigned sshkeys, void *passfp, int numtries, pgp_cbfunc_t *getpassfunc) { pgp_stream_t *parse = NULL; pgp_memory_t *outmem; pgp_memory_t *inmem; const int printerrors = 1; if (input == NULL) { (void) fprintf(io->errs, "pgp_encrypt_buf: null memory\n"); return 0; } inmem = pgp_memory_new(); pgp_memory_add(inmem, input, insize); /* set up to read from memory */ pgp_setup_memory_read(io, &parse, inmem, NULL, write_parsed_cb, 0); /* setup for writing decrypted contents to given output file */ pgp_setup_memory_write(&parse->cbinfo.output, &outmem, insize); /* setup keyring and passphrase callback */ parse->cbinfo.cryptinfo.secring = secring; parse->cbinfo.cryptinfo.pubring = pubring; parse->cbinfo.passfp = passfp; parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; parse->cbinfo.numtries = numtries; /* Set up armour/passphrase options */ if (use_armour) { pgp_reader_push_dearmour(parse); } /* Do it */ pgp_parse(parse, printerrors); /* Unsetup */ if (use_armour) { pgp_reader_pop_dearmour(parse); } /* tidy up */ pgp_teardown_memory_read(parse, inmem); pgp_writer_close(parse->cbinfo.output); pgp_output_delete(parse->cbinfo.output); /* if we didn't get the passphrase, return NULL */ return (parse->cbinfo.gotpass) ? outmem : NULL; }
int pgp_decompress(pgp_region_t *region, pgp_stream_t *stream, pgp_compression_type_t type) { z_decompress_t z; #ifdef HAVE_BZLIB_H bz_decompress_t bz; #endif const int printerrors = 1; int ret; switch (type) { case PGP_C_ZIP: case PGP_C_ZLIB: (void) memset(&z, 0x0, sizeof(z)); z.region = region; z.offset = 0; z.type = type; z.zstream.next_in = Z_NULL; z.zstream.avail_in = 0; z.zstream.next_out = z.out; z.zstream.zalloc = Z_NULL; z.zstream.zfree = Z_NULL; z.zstream.opaque = Z_NULL; break; #ifdef HAVE_BZLIB_H case PGP_C_BZIP2: (void) memset(&bz, 0x0, sizeof(bz)); bz.region = region; bz.offset = 0; bz.type = type; bz.bzstream.next_in = NULL; bz.bzstream.avail_in = 0; bz.bzstream.next_out = bz.out; bz.bzstream.bzalloc = NULL; bz.bzstream.bzfree = NULL; bz.bzstream.opaque = NULL; #endif break; default: PGP_ERROR_1(&stream->errors, PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type); return 0; } switch (type) { case PGP_C_ZIP: /* LINTED */ /* this is a lint problem in zlib.h header */ ret = (int)inflateInit2(&z.zstream, -15); break; case PGP_C_ZLIB: /* LINTED */ /* this is a lint problem in zlib.h header */ ret = (int)inflateInit(&z.zstream); break; #ifdef HAVE_BZLIB_H case PGP_C_BZIP2: ret = BZ2_bzDecompressInit(&bz.bzstream, 1, 0); break; #endif default: PGP_ERROR_1(&stream->errors, PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type); return 0; } switch (type) { case PGP_C_ZIP: case PGP_C_ZLIB: if (ret != Z_OK) { PGP_ERROR_1(&stream->errors, PGP_E_P_DECOMPRESSION_ERROR, "Cannot initialise ZIP or ZLIB stream for decompression: error=%d", ret); return 0; } pgp_reader_push(stream, zlib_compressed_data_reader, NULL, &z); break; #ifdef HAVE_BZLIB_H case PGP_C_BZIP2: if (ret != BZ_OK) { PGP_ERROR_1(&stream->errors, PGP_E_P_DECOMPRESSION_ERROR, "Cannot initialise BZIP2 stream for decompression: error=%d", ret); return 0; } pgp_reader_push(stream, bzip2_compressed_data_reader, NULL, &bz); break; #endif default: PGP_ERROR_1(&stream->errors, PGP_E_ALG_UNSUPPORTED_COMPRESS_ALG, "Compression algorithm %d is not yet supported", type); return 0; } ret = pgp_parse(stream, !printerrors); pgp_reader_pop(stream); return ret; }
unsigned pgp_decrypt_file(pgp_io_t *io, const char *infile, const char *outfile, pgp_keyring_t *secring, pgp_keyring_t *pubring, const unsigned use_armour, const unsigned allow_overwrite, const unsigned sshkeys, void *passfp, int numtries, pgp_cbfunc_t *getpassfunc) { pgp_stream_t *parse = NULL; const int printerrors = 1; char *filename = NULL; int fd_in; int fd_out; /* setup for reading from given input file */ fd_in = pgp_setup_file_read(io, &parse, infile, NULL, write_parsed_cb, 0); if (fd_in < 0) { perror(infile); return 0; } /* setup output filename */ if (outfile) { fd_out = pgp_setup_file_write(&parse->cbinfo.output, outfile, allow_overwrite); if (fd_out < 0) { perror(outfile); pgp_teardown_file_read(parse, fd_in); return 0; } } else { const int suffixlen = 4; const char *suffix = infile + strlen(infile) - suffixlen; unsigned filenamelen; if (strcmp(suffix, ".gpg") == 0 || strcmp(suffix, ".asc") == 0) { filenamelen = (unsigned)(strlen(infile) - strlen(suffix)); if ((filename = calloc(1, filenamelen + 1)) == NULL) { (void) fprintf(stderr, "can't allocate %" PRIsize "d bytes\n", (size_t)(filenamelen + 1)); return 0; } (void) strncpy(filename, infile, filenamelen); filename[filenamelen] = 0x0; } fd_out = pgp_setup_file_write(&parse->cbinfo.output, filename, allow_overwrite); if (fd_out < 0) { perror(filename); free(filename); pgp_teardown_file_read(parse, fd_in); return 0; } } /* \todo check for suffix matching armour param */ /* setup for writing decrypted contents to given output file */ /* setup keyring and passphrase callback */ parse->cbinfo.cryptinfo.secring = secring; parse->cbinfo.passfp = passfp; parse->cbinfo.cryptinfo.getpassphrase = getpassfunc; parse->cbinfo.cryptinfo.pubring = pubring; parse->cbinfo.sshseckey = (sshkeys) ? &secring->keys[0].key.seckey : NULL; parse->cbinfo.numtries = numtries; /* Set up armour/passphrase options */ if (use_armour) { pgp_reader_push_dearmour(parse); } /* Do it */ pgp_parse(parse, printerrors); /* Unsetup */ if (use_armour) { pgp_reader_pop_dearmour(parse); } /* if we didn't get the passphrase, unlink output file */ if (!parse->cbinfo.gotpass) { (void) unlink((filename) ? filename : outfile); } if (filename) { pgp_teardown_file_write(parse->cbinfo.output, fd_out); free(filename); } pgp_teardown_file_read(parse, fd_in); /* \todo cleardown crypt */ return 1; }