cdk_error_t cdk_keydb_get_sk( cdk_keydb_hd_t hd, u32 * keyid, cdk_pkt_seckey_t* ret_sk ) { cdk_kbnode_t snode, node; cdk_pkt_seckey_t sk = NULL; int rc = 0; if( !keyid || !ret_sk ) return CDK_Inv_Value; if( !hd ) return CDK_Error_No_Keyring; rc = cdk_keydb_get_bykeyid( hd, keyid, &snode ); if( rc ) goto leave; node = keydb_find_bykeyid( snode, keyid ); if( !node ) { rc = CDK_Error_No_Key; goto leave; } sk = node->pkt->pkt.secret_key; _cdk_kbnode_clone( node ); cdk_kbnode_release( snode ); leave: *ret_sk = sk; return rc; }
/** * 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; }
int _cdk_keydb_get_sk_byusage( cdk_keydb_hd_t hd, const char * name, cdk_pkt_seckey_t* ret_sk, int usage ) { cdk_kbnode_t knode = NULL, node = NULL; cdk_pkt_seckey_t sk = NULL; int rc = 0; if( !ret_sk || !usage ) return CDK_Inv_Value; if( !hd ) return CDK_Error_No_Keyring; rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_AUTO, (char *)name ); if( !rc ) rc = cdk_keydb_search( hd, &knode ); if( rc ) goto leave; node = keydb_find_byusage( knode, usage, 0 ); if( !node ) { rc = CDK_Unusable_Key; goto leave; } sk = node->pkt->pkt.secret_key; _cdk_kbnode_clone( node ); cdk_kbnode_release( knode ); leave: *ret_sk = sk; return rc; }
cdk_error_t cdk_keydb_get_pk( cdk_keydb_hd_t hd, u32 * keyid, cdk_pkt_pubkey_t* r_pk ) { cdk_kbnode_t knode = NULL, node = NULL; cdk_pkt_pubkey_t pk = NULL; int rc = 0; if( !keyid || !r_pk ) return CDK_Inv_Value; if( !hd ) return CDK_Error_No_Keyring; rc = cdk_keydb_search_start( hd, !keyid[0]? CDK_DBSEARCH_SHORT_KEYID : CDK_DBSEARCH_KEYID, keyid ); if( !rc ) rc = cdk_keydb_search( hd, &knode ); if( rc ) goto leave; node = keydb_find_bykeyid( knode, keyid ); if( !node ) { rc = CDK_Error_No_Key; goto leave; } _cdk_copy_pubkey( &pk, node->pkt->pkt.public_key ); cdk_kbnode_release( knode ); leave: *r_pk = pk; return rc; }
int gnutls_openpgp_count_key_names (const gnutls_datum_t * cert) { cdk_kbnode_t knode, p, ctx; cdk_packet_t pkt; int nuids; if (cert == NULL) { gnutls_assert (); return 0; } if (cdk_kbnode_read_from_mem (&knode, cert->data, cert->size)) { gnutls_assert (); return 0; } ctx = NULL; for (nuids = 0;;) { p = cdk_kbnode_walk (knode, &ctx, 0); if (!p) break; pkt = cdk_kbnode_get_packet (p); if (pkt->pkttype == CDK_PKT_USER_ID) nuids++; } cdk_kbnode_release (knode); return nuids; }
/** * gnutls_openpgp_privkey_deinit: * @key: The structure to be initialized * * This function will deinitialize a key structure. **/ void gnutls_openpgp_privkey_deinit(gnutls_openpgp_privkey_t key) { if (!key) return; if (key->knode) { cdk_kbnode_release(key->knode); key->knode = NULL; } gnutls_free(key); }
/** * gnutls_openpgp_key_deinit - This function deinitializes memory used by a gnutls_openpgp_key_t structure * @key: The structure to be initialized * * This function will deinitialize a key structure. * **/ void gnutls_openpgp_key_deinit (gnutls_openpgp_key_t key) { if (!key) return; if (key->knode) { cdk_kbnode_release (key->knode); key->knode = NULL; } if (key->inp) cdk_stream_close (key->inp); gnutls_free (key); }
/** * 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; }
cdk_error_t cdk_keydb_import( cdk_keydb_hd_t hd, cdk_kbnode_t knode, int *result ) { cdk_kbnode_t node, chk = NULL; cdk_packet_t pkt; cdk_stream_t out; u32 keyid[2]; int rc = 0, is_sk = 0; if( !hd || !knode ) return CDK_Inv_Value; memset( result, 0, 4 * sizeof (int) ); pkt = find_key_packet( knode, &is_sk ); if( !pkt ) return CDK_Inv_Packet; result[is_sk] = 1; _cdk_pkt_get_keyid( pkt, keyid ); cdk_keydb_get_bykeyid( hd, keyid, &chk ); if( chk ) { /* fixme: search for new signatures */ cdk_kbnode_release( chk ); return 0; } if( hd->buf ) { cdk_stream_close( hd->buf ); hd->buf = NULL; } rc = _cdk_stream_append( hd->name, &out ); if( rc ) return rc; for( node = knode; node; node = node->next ) { if( node->pkt->pkttype == CDK_PKT_RING_TRUST ) continue; /* No uniformed syntax for this packet */ rc = cdk_pkt_write( out, node->pkt ); if( rc ) break; } if( !rc ) result[is_sk? 3 : 2] = 1; cdk_stream_close( out ); if( !hd->no_cache ) cdk_keydb_idx_rebuild( hd ); return rc; }
int _cdk_keydb_get_pk_byusage( cdk_keydb_hd_t hd, const char * name, cdk_pkt_pubkey_t* ret_pk, int usage ) { cdk_kbnode_t knode, node = NULL; cdk_pkt_pubkey_t pk = NULL; const char * s; int rc = 0; if( !ret_pk || !usage ) return CDK_Inv_Value; if( !hd ) return CDK_Error_No_Keyring; rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_AUTO, (char *)name ); if( !rc ) rc = cdk_keydb_search( hd, &knode ); if( rc ) goto leave; node = keydb_find_byusage( knode, usage, 1 ); if( !node ) { rc = CDK_Unusable_Key; goto leave; } _cdk_copy_pubkey( &pk, node->pkt->pkt.public_key ); for( node = knode; node; node = node->next ) { if( node->pkt->pkttype == CDK_PKT_USER_ID ) { s = node->pkt->pkt.user_id->name; if( pk && !pk->uid && _cdk_memistr( s, strlen( s ), name ) ) { _cdk_copy_userid( &pk->uid, node->pkt->pkt.user_id ); break; } } } cdk_kbnode_release( knode ); leave: *ret_pk = pk; return rc; }
/** * cdk_listkey_next: * @ctx: list key context * @r_key: the pointer to the new key node object * * Retrieve the next key from the pattern of the key list context. **/ cdk_error_t cdk_listkey_next( cdk_listkey_t ctx, cdk_kbnode_t * ret_key ) { if( !ctx || !ret_key ) return CDK_Inv_Value; if( !ctx->init ) return CDK_Inv_Mode; if( ctx->type && ctx->u.patt[0] == '*' ) return cdk_keydb_get_keyblock( ctx->inp, ret_key ); else if( ctx->type ) { cdk_kbnode_t node; struct cdk_dbsearch_s ks; int rc; for( ;; ) { rc = cdk_keydb_get_keyblock( ctx->inp, &node ); if( rc ) return rc; memset( &ks, 0, sizeof ks ); ks.type = CDK_DBSEARCH_SUBSTR; ks.u.pattern = ctx->u.patt; if( find_by_pattern( node, &ks ) ) { *ret_key = node; return 0; } cdk_kbnode_release( node ); node = NULL; } } else { if( !ctx->t ) ctx->t = ctx->u.fpatt; else if( ctx->t->next ) ctx->t = ctx->t->next; else return CDK_EOF; return cdk_keydb_get_bypattern( ctx->db, ctx->t->d, ret_key ); } return CDK_General_Error; }
cdk_error_t cdk_keydb_export( cdk_keydb_hd_t hd, cdk_stream_t out, cdk_strlist_t remusr ) { cdk_kbnode_t knode, node; cdk_strlist_t r; int old_ctb = 0; int rc = 0; for( r = remusr; r; r = r->next ) { rc = cdk_keydb_search_start( hd, CDK_DBSEARCH_AUTO, r->d ); if( !rc ) rc = cdk_keydb_search( hd, &knode ); if( rc ) break; for( node = knode; node; node = node->next ) { /* those packets are not intended for the real wolrd */ if( node->pkt->pkttype == CDK_PKT_RING_TRUST ) continue; /* we never export local signed signatures */ if( node->pkt->pkttype == CDK_PKT_SIGNATURE && !node->pkt->pkt.signature->flags.exportable ) continue; /* filter out invalid signatures */ if( node->pkt->pkttype == CDK_PKT_SIGNATURE && !KEY_CAN_SIGN (node->pkt->pkt.signature->pubkey_algo) ) continue; if( node->pkt->pkttype == CDK_PKT_PUBLIC_KEY && node->pkt->pkt.public_key->version == 3 ) old_ctb = 1; node->pkt->old_ctb = old_ctb; rc = cdk_pkt_write( out, node->pkt ); if( rc ) break; } cdk_kbnode_release( knode ); knode = NULL; } return rc; }
/** * cdk_keydb_search: * @hd: the keydb object * @ks: the keydb search object * @ret_key: kbnode object to store the key * * Search for a key in the given keyring. The search mode is handled * via @ks. If the key was found, @ret_key contains the key data. **/ cdk_error_t cdk_keydb_search( cdk_keydb_hd_t hd, cdk_kbnode_t * ret_key ) { cdk_stream_t kr = NULL; cdk_kbnode_t knode = NULL; cdk_dbsearch_t ks; u32 off = 0; size_t pos = 0; int key_found = 0, cache_hit = 0; int rc = 0; if( !hd || !ret_key ) return CDK_Inv_Value; *ret_key = NULL; hd->search = 1; rc = cdk_keydb_open( hd, &kr ); if( rc ) return rc; rc = keydb_pos_from_cache( hd, hd->dbs, &cache_hit, &off ); if( rc ) return rc; ks = hd->dbs; while( !key_found && !rc ) { if( cache_hit && ks->type != CDK_DBSEARCH_NEXT ) cdk_stream_seek( kr, off ); pos = cdk_stream_tell( kr ); rc = cdk_keydb_get_keyblock( kr, &knode ); if( rc ) { if( rc == CDK_EOF && knode ) rc = 0; if( !knode && rc == CDK_EOF ) rc = CDK_Error_No_Key; if( rc ) break; } switch( ks->type ) { case CDK_DBSEARCH_SHORT_KEYID: case CDK_DBSEARCH_KEYID: key_found = find_by_keyid( knode, ks ); break; case CDK_DBSEARCH_FPR: key_found = find_by_fpr( knode, ks ); break; case CDK_DBSEARCH_EXACT: case CDK_DBSEARCH_SUBSTR: key_found = find_by_pattern( knode, ks ); break; case CDK_DBSEARCH_NEXT: key_found = knode? 1 : 0; break; } if( key_found ) { if( !keydb_cache_find( hd->cache, ks ) ) keydb_cache_add( hd, ks, pos ); break; } cdk_kbnode_release( knode ); knode = NULL; } hd->search = 0; *ret_key = key_found? knode : NULL; return rc; }
/*- * 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; }