/** \ingroup HighLevel_KeyringRead \brief Reads a keyring from memory \param keyring Pointer to existing pgp_keyring_t struct \param armour 1 if file is armoured; else 0 \param mem Pointer to a pgp_memory_t struct containing keyring to be read \return pgp 1 if OK; 0 on error \note Keyring struct must already exist. \note Can be used with either a public or secret keyring. \note You must call pgp_keyring_free() after usage to free alloc-ed memory. \note If you call this twice on the same keyring struct, without calling pgp_keyring_free() between these calls, you will introduce a memory leak. \sa pgp_keyring_fileread \sa pgp_keyring_free */ unsigned pgp_keyring_read_from_mem(pgp_io_t *io, pgp_keyring_t *keyring, const unsigned armour, pgp_memory_t *mem) { pgp_stream_t *stream; const unsigned noaccum = 0; keyringcb_t cb; unsigned res; (void) memset(&cb, 0x0, sizeof(cb)); cb.keyring = keyring; stream = pgp_new(sizeof(*stream)); pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); pgp_setup_memory_read(io, &stream, mem, &cb, cb_keyring_read, noaccum); if (armour) { pgp_reader_push_dearmour(stream); } res = (unsigned)pgp_parse_and_accumulate(keyring, stream); pgp_print_errors(pgp_stream_get_errors(stream)); if (armour) { pgp_reader_pop_dearmour(stream); } /* don't call teardown_memory_read because memory was passed in */ pgp_stream_delete(stream); return res; }
unsigned pgp_keyring_fileread(pgp_keyring_t *keyring, const unsigned armour, const char *filename) { pgp_stream_t *stream; keyringcb_t cb; unsigned res = 1; int fd; (void) memset(&cb, 0x0, sizeof(cb)); cb.keyring = keyring; stream = pgp_new(sizeof(*stream)); /* add this for the moment, */ /* * \todo need to fix the problems with reading signature subpackets * later */ /* pgp_parse_options(parse,PGP_PTAG_SS_ALL,PGP_PARSE_RAW); */ pgp_parse_options(stream, PGP_PTAG_SS_ALL, PGP_PARSE_PARSED); #ifdef O_BINARY fd = open(filename, O_RDONLY | O_BINARY); #else fd = open(filename, O_RDONLY); #endif if (fd < 0) { pgp_stream_delete(stream); perror(filename); return 0; } #ifdef USE_MMAP_FOR_FILES pgp_reader_set_mmap(stream, fd); #else pgp_reader_set_fd(stream, fd); #endif pgp_set_callback(stream, cb_keyring_read, &cb); if (armour) { pgp_reader_push_dearmour(stream); } res = pgp_parse_and_accumulate(keyring, stream); pgp_print_errors(pgp_stream_get_errors(stream)); if (armour) { pgp_reader_pop_dearmour(stream); } (void)close(fd); pgp_stream_delete(stream); return res; }
/* 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; }
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; }