/** * gnutls_openpgp_keyring_get_crt_count: * @ring: is an OpenPGP key ring * * This function will return the number of OpenPGP certificates * present in the given keyring. * * Returns: the number of subkeys, or a negative error code on error. **/ int gnutls_openpgp_keyring_get_crt_count(gnutls_openpgp_keyring_t ring) { cdk_kbnode_t knode; cdk_error_t err; cdk_keydb_search_t st; int ret = 0; err = cdk_keydb_search_start(&st, ring->db, CDK_DBSEARCH_NEXT, NULL); if (err != CDK_Success) { gnutls_assert(); return _gnutls_map_cdk_rc(err); } do { err = cdk_keydb_search(st, ring->db, &knode); if (err != CDK_Error_No_Key && err != CDK_Success) { gnutls_assert(); cdk_keydb_search_release(st); return _gnutls_map_cdk_rc(err); } if (knode_is_pkey(knode)) ret++; cdk_kbnode_release(knode); } while (err != CDK_Error_No_Key); cdk_keydb_search_release(st); return ret; }
/** * gnutls_openpgp_crt_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. * * This function will convert the given RAW or Base64 encoded key to * the native #gnutls_openpgp_crt_t format. The output will be stored * in 'key'. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key, const gnutls_datum_t * data, gnutls_openpgp_crt_fmt_t format) { cdk_packet_t pkt; int rc, armor; if (data->data == NULL || data->size == 0) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } if (format == GNUTLS_OPENPGP_FMT_RAW) armor = 0; else armor = 1; rc = cdk_kbnode_read_from_mem (&key->knode, armor, data->data, data->size); if (rc) { 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_PUBLIC_KEY); if (pkt == NULL) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } return 0; }
/** * gnutls_openpgp_keyring_get_crt: * @ring: Holds the keyring. * @idx: the index of the certificate to export * @cert: An uninitialized #gnutls_openpgp_crt_t structure * * This function will extract an OpenPGP certificate from the given * keyring. If the index given is out of range * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. The * returned structure needs to be deinited. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_openpgp_keyring_get_crt (gnutls_openpgp_keyring_t ring, unsigned int idx, gnutls_openpgp_crt_t * cert) { cdk_kbnode_t knode; cdk_error_t err; int ret = 0; unsigned int count = 0; cdk_keydb_search_t st; err = cdk_keydb_search_start (&st, ring->db, CDK_DBSEARCH_NEXT, NULL); if (err != CDK_Success) { gnutls_assert (); return _gnutls_map_cdk_rc (err); } do { err = cdk_keydb_search (st, ring->db, &knode); if (err != CDK_EOF && err != CDK_Success) { gnutls_assert (); cdk_keydb_search_release (st); return _gnutls_map_cdk_rc (err); } if (idx == count && err == CDK_Success) { ret = gnutls_openpgp_crt_init (cert); if (ret == 0) (*cert)->knode = knode; cdk_keydb_search_release (st); return ret; } if (knode_is_pkey (knode)) count++; cdk_kbnode_release (knode); } while (err != CDK_EOF); cdk_keydb_search_release (st); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; }
/** * gnutls_openpgp_crt_verify_ring: * @key: the structure that holds the key. * @keyring: holds the keyring to check against * @flags: unused (should be 0) * @verify: will hold the certificate verification output. * * Verify all signatures in the key, using the given set of keys * (keyring). * * The key verification output will be put in @verify and will be one * or more of the #gnutls_certificate_status_t enumerated elements * bitwise or'd. * * %GNUTLS_CERT_INVALID: A signature on the key is invalid. * * %GNUTLS_CERT_REVOKED: The key has been revoked. * * Note that this function does not verify using any "web of trust". * You may use GnuPG for that purpose, or any other external PGP * application. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_openpgp_crt_verify_ring (gnutls_openpgp_crt_t key, gnutls_openpgp_keyring_t keyring, unsigned int flags, unsigned int *verify) { gnutls_openpgp_keyid_t id; cdk_error_t rc; int status; if (!key || !keyring) { gnutls_assert (); return GNUTLS_E_NO_CERTIFICATE_FOUND; } *verify = 0; rc = cdk_pk_check_sigs (key->knode, keyring->db, &status); if (rc == CDK_Error_No_Key) { rc = GNUTLS_E_NO_CERTIFICATE_FOUND; gnutls_assert (); return rc; } else if (rc != CDK_Success) { _gnutls_x509_log ("cdk_pk_check_sigs: error %d\n", rc); rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } _gnutls_x509_log ("status: %x\n", status); if (status & CDK_KEY_INVALID) *verify |= GNUTLS_CERT_INVALID; if (status & CDK_KEY_REVOKED) *verify |= GNUTLS_CERT_REVOKED; if (status & CDK_KEY_NOSIGNER) *verify |= GNUTLS_CERT_SIGNER_NOT_FOUND; /* Check if the key is included in the ring. */ if (!(flags & GNUTLS_VERIFY_DO_NOT_ALLOW_SAME)) { rc = gnutls_openpgp_crt_get_key_id (key, id); if (rc < 0) { gnutls_assert (); return rc; } rc = gnutls_openpgp_keyring_check_id (keyring, id, 0); /* If it exists in the keyring don't treat it as unknown. */ if (rc == 0 && *verify & GNUTLS_CERT_SIGNER_NOT_FOUND) *verify ^= GNUTLS_CERT_SIGNER_NOT_FOUND; } return 0; }
/** * 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; }
/** * 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; }
/*- * gnutls_openpgp_get_key - Retrieve a key from the keyring. * @key: the destination context to save the key. * @keyring: the datum struct that contains all keyring information. * @attr: The attribute (keyid, fingerprint, ...). * @by: What attribute is used. * * This function can be used to retrieve keys by different pattern * from a binary or a file keyring. -*/ int gnutls_openpgp_get_key (gnutls_datum_t * key, gnutls_openpgp_keyring_t keyring, key_attr_t by, opaque * pattern) { cdk_kbnode_t knode = NULL; unsigned long keyid[2]; unsigned char *buf; void *desc; size_t len; int rc = 0; cdk_keydb_search_t st; if (!key || !keyring || by == KEY_ATTR_NONE) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } memset (key, 0, sizeof *key); if (by == KEY_ATTR_SHORT_KEYID) { keyid[0] = _gnutls_read_uint32 (pattern); desc = keyid; } else if (by == KEY_ATTR_KEYID) { keyid[0] = _gnutls_read_uint32 (pattern); keyid[1] = _gnutls_read_uint32 (pattern + 4); desc = keyid; } else desc = pattern; rc = cdk_keydb_search_start (&st, keyring->db, by, desc); if (!rc) rc = cdk_keydb_search (st, keyring->db, &knode); cdk_keydb_search_release (st); if (rc) { rc = _gnutls_map_cdk_rc (rc); goto leave; } if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY)) { rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; goto leave; } /* We let the function allocate the buffer to avoid to call the function twice. */ rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len); if (!rc) datum_append (key, buf, len); gnutls_free (buf); leave: cdk_kbnode_release (knode); return rc; }