cdk_error_t cdk_stream_seek (cdk_stream_t s, off_t offset) { off_t len; if (!s) { gnutls_assert (); 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)) { gnutls_assert (); return CDK_File_Error; } return 0; }
/** * cdk_stream_mmap: * @s: the stream * @ret_buf: the buffer to store the content * @ret_count: 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( cdk_stream_t s, byte ** ret_buf, size_t * ret_count ) { const u32 max_filesize = 16777216; u32 len, oldpos; int n, rc; char * p; if( !s || !ret_buf || !ret_count ) return CDK_Inv_Value; *ret_count = 0; *ret_buf = NULL; oldpos = cdk_stream_tell( s ); rc = cdk_stream_flush( s ); if( !rc ) rc = cdk_stream_seek( s, 0 ); if( rc ) return rc; len = cdk_stream_get_length( s ); if( !len || len > max_filesize ) return 0; p = *ret_buf = cdk_calloc( 1, len+1 ); if( !p ) return 0; *ret_count = len; n = cdk_stream_read( s, p, len ); if( n != len ) *ret_count = 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_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 || !r_buf || !r_buflen) { gnutls_assert (); return CDK_Inv_Value; } *r_buf = NULL; *r_buflen = 0; rc = cdk_stream_tmp_new (&s); if (rc) { gnutls_assert (); 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); gnutls_assert (); 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; }
static cdk_error_t literal_encode (void *data, FILE * in, FILE * out) { literal_filter_t *pfx = data; 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); pt->name = (char *) pt + sizeof (*pt); 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; }
cdk_error_t cdk_stream_seek( cdk_stream_t s, long offset ) { int rc; if( !s ) return CDK_Inv_Value; if( offset < cdk_stream_get_length( s ) ) s->flags.eof = 0; rc = fseek( s->fp, offset, SEEK_SET ); if( rc ) rc = CDK_File_Error; return rc; }
static int literal_encode (void * opaque, FILE * in, FILE * out) { literal_filter_t * pfx = opaque; cdk_pkt_literal_t pt; cdk_stream_t si; CDK_PACKET pkt; size_t filelen; int 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; } si = _cdk_stream_fpopen (in, STREAMCTL_READ); if (!si) return CDK_Out_Of_Core; filelen = strlen (pfx->filename); pt = cdk_calloc (1, sizeof *pt + filelen - 1); if (!pt) return CDK_Out_Of_Core; memcpy (pt->name, pfx->filename, filelen); pt->namelen = filelen; pt->name[pt->namelen] = '\0'; pt->timestamp = _cdk_timestamp (); pt->mode = pfx->mode ? 't' : 'b'; pt->len = cdk_stream_get_length (si); pt->buf = si; cdk_pkt_init (&pkt); pkt.old_ctb = pfx->rfc1991? 1 : 0; pkt.pkttype = CDK_PKT_LITERAL; pkt.pkt.literal = pt; rc = _cdk_pkt_write_fp (out, &pkt); cdk_free (pt); cdk_stream_close (si); return rc; }
cdk_error_t cdk_stream_flush (cdk_stream_t s) { cdk_error_t rc; if (!s) { gnutls_assert (); 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; gnutls_assert (); return rc; } } return 0; }
cdk_error_t cdk_stream_flush( cdk_stream_t s ) { int rc = 0; if( !s ) return CDK_Inv_Value; 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 ); if( rc ) s->error = rc; } s->flags.filtrated = 1; } 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 * * Maps 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) { cdk_error_t rc; off_t oldpos; unsigned int n; if (!ret_buf || !ret_buflen) { gnutls_assert (); return CDK_Inv_Value; } *ret_buf = NULL; *ret_buflen = 0; if (!s) { gnutls_assert (); return CDK_Inv_Value; } /* Memory mapping is not supported on custom I/O objects. */ if (s->cbs_hd) { _cdk_log_debug ("cdk_stream_mmap_part: not supported on callbacks\n"); gnutls_assert (); return CDK_Inv_Mode; } oldpos = cdk_stream_tell (s); rc = cdk_stream_flush (s); if (rc) { gnutls_assert (); return rc; } rc = cdk_stream_seek (s, off); if (rc) { gnutls_assert (); return rc; } if (!len) len = cdk_stream_get_length (s); if (!len) { _cdk_log_debug ("cdk_stream_mmap_part: invalid file size %lu\n", len); gnutls_assert (); return s->error; } if (len > MAX_MAP_SIZE) { gnutls_assert (); return CDK_Too_Short; } *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); if (rc) gnutls_assert (); return rc; }
/** * gnutls_openpgp_keyring_import: * @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: %GNUTLS_E_SUCCESS on success, or an error code. **/ 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 = NULL; size_t raw_len = 0; uint8_t *raw_data = NULL; unsigned free_data = 0; if (data->data == NULL || data->size == 0) { gnutls_assert(); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } _gnutls_debug_log("PGP: keyring import format '%s'\n", format == GNUTLS_OPENPGP_FMT_RAW ? "raw" : "base64"); /* Create a new stream from the given data, decode it, and import * the raw database. This to avoid using opencdk streams which are * not thread safe. */ if (format == GNUTLS_OPENPGP_FMT_BASE64) { size_t seen = 0; err = cdk_stream_tmp_from_mem(data->data, data->size, &input); if (err == 0) err = cdk_stream_set_armor_flag(input, 0); if (err) { gnutls_assert(); err = _gnutls_map_cdk_rc(err); goto error; } raw_len = cdk_stream_get_length(input); if (raw_len == 0) { gnutls_assert(); err = GNUTLS_E_BASE64_DECODING_ERROR; goto error; } raw_data = gnutls_malloc(raw_len); if (raw_data == NULL) { gnutls_assert(); err = GNUTLS_E_MEMORY_ERROR; goto error; } do { err = cdk_stream_read(input, raw_data + seen, raw_len - seen); if (err > 0) seen += err; } while (seen < raw_len && err != EOF && err > 0); raw_len = seen; if (raw_len == 0) { gnutls_assert(); err = GNUTLS_E_BASE64_DECODING_ERROR; goto error; } free_data = 1; } else { /* RAW */ raw_len = data->size; raw_data = data->data; } err = cdk_keydb_new_from_mem(&keyring->db, 0, 0, raw_data, raw_len); if (err) gnutls_assert(); if (free_data) { err = _gnutls_map_cdk_rc(err); goto error; } return _gnutls_map_cdk_rc(err); error: gnutls_free(raw_data); cdk_stream_close(input); return err; }
/** * 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. * * Tries 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; cdk_error_t rc; size_t len; if (!node || !r_nbytes) { gnutls_assert (); return CDK_Inv_Value; } rc = cdk_stream_tmp_new (&s); if (rc) { gnutls_assert (); 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); gnutls_assert (); 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) { *r_nbytes = len; rc = CDK_Too_Short; } if (!rc) *r_nbytes = cdk_stream_read (s, buf, len); else gnutls_assert (); cdk_stream_close (s); return rc; }
/** * gnutls_openpgp_key_export - This function will export a RAW or BASE64 encoded key * @key: Holds the key. * @format: One of gnutls_openpgp_key_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_key_export (gnutls_openpgp_key_t key, gnutls_openpgp_key_fmt_t format, void *output_data, size_t * output_data_size) { int rc; size_t input_data_size = *output_data_size; 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; } if (format == GNUTLS_OPENPGP_FMT_BASE64) { cdk_stream_t s; s = cdk_stream_tmp_from_mem (output_data, *output_data_size); if (s == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } cdk_stream_tmp_set_mode (s, 1); rc = cdk_stream_set_armor_flag (s, CDK_ARMOR_PUBKEY); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); cdk_stream_close (s); return rc; } *output_data_size = input_data_size; rc = cdk_stream_read (s, output_data, *output_data_size); if (rc == EOF) { gnutls_assert (); cdk_stream_close (s); return GNUTLS_E_INTERNAL_ERROR; } *output_data_size = rc; if (*output_data_size != cdk_stream_get_length (s)) { *output_data_size = cdk_stream_get_length (s); cdk_stream_close (s); gnutls_assert (); return GNUTLS_E_SHORT_MEMORY_BUFFER; } cdk_stream_close (s); } return 0; }