/** * cdk_stream_verify: * @hd: session handle * @inp: the input stream * @data: for detached signatures, this is the data stream @inp is the sig * @out: where the output shall be written. * * Verify a signature in stream. */ cdk_error_t cdk_stream_verify (cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t data, cdk_stream_t out) { /* FIXME: out is not currently used. */ if (cdk_armor_filter_use (inp)) cdk_stream_set_armor_flag (inp, 0); return _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL); }
/** * cdk_file_verify: * @hd: the session handle * @file: the input file * @data_file: for detached signature this is the data file and @file is the sig. * @output: the output file * * Verify a signature. **/ cdk_error_t cdk_file_verify (cdk_ctx_t hd, const char *file, const char *data_file, const char *output) { struct stat stbuf; cdk_stream_t inp, data; char buf[4096]; int n; cdk_error_t rc; if (!hd || !file) return CDK_Inv_Value; if (output && !hd->opt.overwrite && !stat (output, &stbuf)) return CDK_Inv_Mode; rc = cdk_stream_open (file, &inp); if (rc) return rc; if (cdk_armor_filter_use (inp)) { n = cdk_stream_peek (inp, (byte *) buf, DIM (buf) - 1); if (!n || n == -1) return CDK_EOF; buf[n] = '\0'; if (strstr (buf, "BEGIN PGP SIGNED MESSAGE")) { cdk_stream_close (inp); return file_verify_clearsign (hd, file, output); } cdk_stream_set_armor_flag (inp, 0); } if (data_file) { rc = cdk_stream_open (data_file, &data); if (rc) { cdk_stream_close (inp); return rc; } } else data = NULL; rc = _cdk_proc_packets (hd, inp, data, NULL, NULL, NULL); if (data != NULL) cdk_stream_close (data); cdk_stream_close (inp); return rc; }
/** * gnutls_openpgp_key_import - This function will import a RAW or BASE64 encoded key * @key: The structure to store the parsed key. * @data: The RAW or BASE64 encoded key. * @format: One of gnutls_openpgp_key_fmt_t elements. * * This function will convert the given RAW or Base64 encoded key * to the native gnutls_openpgp_key_t format. The output will be stored in 'key'. * * Returns 0 on success. * **/ int gnutls_openpgp_key_import (gnutls_openpgp_key_t key, const gnutls_datum_t * data, gnutls_openpgp_key_fmt_t format) { int rc; if (format == GNUTLS_OPENPGP_FMT_RAW) { rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } } else { /* base64 */ key->inp = cdk_stream_tmp_from_mem (data->data, data->size); if (key->inp == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } rc = cdk_stream_set_armor_flag (key->inp, 0); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } rc = cdk_keydb_get_keyblock (key->inp, &key->knode); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } } return 0; }
/** * gnutls_openpgp_privkey_import: * @key: The structure to store the parsed key. * @data: The RAW or BASE64 encoded key. * @format: One of #gnutls_openpgp_crt_fmt_t elements. * @password: not used for now * @flags: should be zero * * This function will convert the given RAW or Base64 encoded key to * the native gnutls_openpgp_privkey_t format. The output will be * stored in 'key'. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key, const gnutls_datum_t * data, gnutls_openpgp_crt_fmt_t format, const char *password, unsigned int flags) { cdk_stream_t inp; cdk_packet_t pkt; int rc; if (data->data == NULL || data->size == 0) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } if (format == GNUTLS_OPENPGP_FMT_RAW) { rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } } else { rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } if (cdk_armor_filter_use (inp)) { rc = cdk_stream_set_armor_flag (inp, 0); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); cdk_stream_close (inp); gnutls_assert (); return rc; } } rc = cdk_keydb_get_keyblock (inp, &key->knode); cdk_stream_close (inp); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } } /* Test if the import was successful. */ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); if (pkt == NULL) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } return 0; }
/** * 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; }
static cdk_error_t file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output) { cdk_stream_t inp = NULL, out = NULL, tmp = NULL; digest_hd_st md; char buf[512], chk[512]; const char *s; int i, is_signed = 0, nbytes; int digest_algo = 0; int err; cdk_error_t rc; memset(&md, 0, sizeof(md)); if (output) { rc = cdk_stream_create (output, &out); if (rc) return rc; } rc = cdk_stream_open (file, &inp); if (rc) { if (output) cdk_stream_close (out); return rc; } s = "-----BEGIN PGP SIGNED MESSAGE-----"; while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (!strncmp (buf, s, strlen (s))) { is_signed = 1; break; } } if (cdk_stream_eof (inp) && !is_signed) { rc = CDK_Armor_Error; goto leave; } while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (nbytes == 1) /* Empty line */ break; else if (!strncmp (buf, "Hash: ", 6)) { for (i = 0; digest_table[i].name; i++) { if (!strcmp (buf + 6, digest_table[i].name)) { digest_algo = digest_table[i].algo; break; } } } } if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0) { rc = CDK_Inv_Algo; goto leave; } if (!digest_algo) digest_algo = GNUTLS_DIG_MD5; err = _gnutls_hash_init (&md, digest_algo); if (err < 0) { rc = map_gnutls_error (err); goto leave; } s = "-----BEGIN PGP SIGNATURE-----"; while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (!strncmp (buf, s, strlen (s))) break; else { cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1); i = strncmp (chk, s, strlen (s)); if (strlen (buf) == 0 && i == 0) continue; /* skip last '\n' */ _cdk_trim_string (buf, i == 0 ? 0 : 1); _gnutls_hash (&md, buf, strlen (buf)); } if (!strncmp (buf, "- ", 2)) /* FIXME: handle it recursive. */ memmove (buf, buf + 2, nbytes - 2); if (out) { if (strstr (buf, "\r\n")) buf[strlen (buf) - 2] = '\0'; cdk_stream_write (out, buf, strlen (buf)); _cdk_stream_puts (out, _cdk_armor_get_lineend ()); } } /* We create a temporary stream object to store the signature data in there. */ rc = cdk_stream_tmp_new (&tmp); if (rc) goto leave; s = "-----BEGIN PGP SIGNATURE-----\n"; _cdk_stream_puts (tmp, s); while (!cdk_stream_eof (inp)) { nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1); if (!nbytes || nbytes == -1) break; if (nbytes < (int) (DIM (buf) - 3)) { buf[nbytes - 1] = '\n'; buf[nbytes] = '\0'; } cdk_stream_write (tmp, buf, nbytes); } /* FIXME: This code is not very elegant. */ cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ); cdk_stream_seek (tmp, 0); cdk_stream_set_armor_flag (tmp, 0); cdk_stream_read (tmp, NULL, 0); /* the digest handle will be closed there. */ rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md); leave: _gnutls_hash_deinit (&md, NULL); cdk_stream_close (out); cdk_stream_close (tmp); cdk_stream_close (inp); 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; }
/** * cdk_keydb_open: * @hd: keydb object * @ret_kr: the STREAM object which contains the data of the keyring * * Open a STREAM with the contents of the keyring from @hd **/ cdk_error_t cdk_keydb_open( cdk_keydb_hd_t hd, cdk_stream_t * ret_kr ) { int rc = 0, ec; if( !hd || !ret_kr ) return CDK_Inv_Value; if( hd->type == CDK_DBTYPE_DATA && hd->buf ) cdk_stream_seek( hd->buf, 0 ); else if( hd->type == CDK_DBTYPE_PK_KEYRING || hd->type == CDK_DBTYPE_SK_KEYRING ) { if( !hd->isopen && hd->name ) { rc = cdk_stream_open( hd->name, &hd->buf ); if( rc ) goto leave; if( cdk_armor_filter_use( hd->buf ) ) cdk_stream_set_armor_flag( hd->buf, 0 ); hd->isopen = 1; cdk_free( hd->idx_name ); hd->idx_name = keydb_idx_mkname( hd->name ); if( !hd->idx_name ) { rc = CDK_Out_Of_Core; goto leave; } ec = cdk_stream_open( hd->idx_name, &hd->idx ); if( ec && !hd->secret ) { rc = keydb_idx_build( hd->name ); if( !rc ) rc = cdk_stream_open( hd->idx_name, &hd->idx ); if( !rc ) _cdk_log_debug( "create key index table\n" ); if( rc ) { /* this is no real error, it just means we can't create the index at the given directory. maybe we've no write access. in this case, we simply disable the index. */ _cdk_log_debug( "disable key index table\n" ); rc = 0; hd->no_cache = 1; } } } else { /* We use the cache to search keys, so we always rewind the STREAM. Except when the _NEXT search mode is used because this mode is an enumeration and no seeking is needed. */ if( !hd->search || (hd->search && hd->dbs->type != CDK_DBSEARCH_NEXT) ) cdk_stream_seek( hd->buf, 0 ); } } else return CDK_Inv_Mode; leave: if( rc ) { cdk_stream_close( hd->buf ); hd->buf = NULL; } *ret_kr = hd->buf; return rc; }