/* This functions builds an index of the keyring into a separate file with the name keyring.ext.idx. It contains the offset of all public- and public subkeys. The format of the file is: -------- 4 octets offset of the packet 8 octets keyid 20 octets fingerprint -------- We store the keyid and the fingerprint due to the fact we can't get the keyid from a v3 fingerprint directly. */ static int keydb_idx_build( const char * file ) { cdk_packet_t pkt; cdk_stream_t inp, out = NULL; byte buf[8], fpr[20]; char * fname; u32 keyid[2]; int rc, pos; if( !file ) return CDK_Inv_Value; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; fname = keydb_idx_mkname( file ); if( !fname ) { rc = CDK_Out_Of_Core; goto leave; } rc = cdk_stream_open( file, &inp ); if( !rc ) rc = cdk_stream_create( fname, &out ); if( rc ) goto leave; while( !cdk_stream_eof( inp ) ) { pos = cdk_stream_tell( inp ); rc = cdk_pkt_read( inp, pkt ); if( rc ) break; if( pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) { _cdk_u32tobuf( pos, buf ); cdk_stream_write( out, buf, 4 ); cdk_pk_get_keyid( pkt->pkt.public_key, keyid ); _cdk_u32tobuf( keyid[0], buf ); _cdk_u32tobuf( keyid[1], buf + 4 ); cdk_stream_write( out, buf, 8 ); cdk_pk_get_fingerprint( pkt->pkt.public_key, fpr ); cdk_stream_write( out, fpr, 20 ); } cdk_pkt_free( pkt ); cdk_pkt_init( pkt ); } cdk_stream_close( out ); leave: cdk_stream_close( inp ); cdk_free( fname ); cdk_free( pkt ); return rc; }
int cdk_keydb_check_sk( cdk_keydb_hd_t hd, u32 * keyid ) { cdk_stream_t db; cdk_packet_t pkt; u32 kid[2]; int rc; if( !hd || !keyid ) return CDK_Inv_Value; if( !hd->secret ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; rc = cdk_keydb_open( hd, &db ); if( rc ) return rc; cdk_pkt_init( pkt ); while( !cdk_pkt_read( db, pkt ) ) { if( pkt->pkttype != CDK_PKT_SECRET_KEY && pkt->pkttype != CDK_PKT_SECRET_SUBKEY ) goto next; cdk_sk_get_keyid( pkt->pkt.secret_key, kid ); if( KEYID_CMP( kid, keyid ) ) { cdk_pkt_free( pkt ); cdk_free( pkt ); return 0; } next: cdk_pkt_free( pkt ); cdk_pkt_init( pkt ); } cdk_free( pkt ); return CDK_Error_No_Key; }
static cdk_error_t literal_decode (void *data, FILE * in, FILE * out) { literal_filter_t *pfx = data; cdk_stream_t si, so; cdk_packet_t pkt; cdk_pkt_literal_t pt; byte buf[BUFSIZE]; ssize_t nread; int bufsize; cdk_error_t rc; _cdk_log_debug ("literal filter: decode\n"); if (!pfx || !in || !out) return CDK_Inv_Value; rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si); if (rc) return rc; cdk_pkt_new (&pkt); rc = cdk_pkt_read (si, pkt); if (rc || pkt->pkttype != CDK_PKT_LITERAL) { cdk_pkt_release (pkt); cdk_stream_close (si); return !rc ? CDK_Inv_Packet : rc; } rc = _cdk_stream_fpopen (out, STREAMCTL_WRITE, &so); if (rc) { cdk_pkt_release (pkt); cdk_stream_close (si); return rc; } pt = pkt->pkt.literal; pfx->mode = pt->mode; if (pfx->filename && pt->namelen > 0) { /* The name in the literal packet is more authorative. */ cdk_free (pfx->filename); pfx->filename = dup_trim_filename (pt->name); } else if (!pfx->filename && pt->namelen > 0) pfx->filename = dup_trim_filename (pt->name); else if (!pt->namelen && !pfx->filename && pfx->orig_filename) { /* In this case, we need to derrive the output file name from the original name and cut off the OpenPGP extension. If this is not possible, we return an error. */ if (!stristr (pfx->orig_filename, ".gpg") && !stristr (pfx->orig_filename, ".pgp") && !stristr (pfx->orig_filename, ".asc")) { cdk_pkt_release (pkt); cdk_stream_close (si); cdk_stream_close (so); _cdk_log_debug ("literal filter: no file name and no PGP extension\n"); return CDK_Inv_Mode; } _cdk_log_debug ("literal filter: derrive file name from original\n"); pfx->filename = dup_trim_filename (pfx->orig_filename); pfx->filename[strlen (pfx->filename) - 4] = '\0'; } while (!feof (in)) { _cdk_log_debug ("literal_decode: part on %d size %lu\n", (int) pfx->blkmode.on, (unsigned long)pfx->blkmode.size); if (pfx->blkmode.on) bufsize = pfx->blkmode.size; else bufsize = pt->len < DIM (buf) ? pt->len : DIM (buf); nread = cdk_stream_read (pt->buf, buf, bufsize); if (nread == EOF) { rc = CDK_File_Error; break; } if (pfx->md_initialized) _gnutls_hash (&pfx->md, buf, nread); cdk_stream_write (so, buf, nread); pt->len -= nread; if (pfx->blkmode.on) { pfx->blkmode.size = _cdk_pkt_read_len (in, &pfx->blkmode.on); if ((ssize_t) pfx->blkmode.size == EOF) return CDK_Inv_Packet; } if (pt->len <= 0 && !pfx->blkmode.on) break; } cdk_stream_close (si); cdk_stream_close (so); cdk_pkt_release (pkt); return rc; }
static int literal_decode( void * opaque, FILE * in, FILE * out ) { literal_filter_t * pfx = opaque; cdk_stream_t si, so; CDK_PACKET pkt; cdk_pkt_literal_t pt; byte buf[8192]; size_t nread; int rc, bufsize; _cdk_log_debug( "literal filter: decode\n" ); if (!pfx || !in || !out) return CDK_Inv_Value; si = _cdk_stream_fpopen( in, STREAMCTL_READ ); if (!si) return CDK_Out_Of_Core; so = _cdk_stream_fpopen( out, STREAMCTL_WRITE ); if( !so ) { cdk_stream_close( si ); return CDK_Out_Of_Core; } cdk_pkt_init( &pkt ); rc = cdk_pkt_read( si, &pkt ); if( pkt.pkttype != CDK_PKT_LITERAL ) { if( pkt.pkttype ) cdk_pkt_free( &pkt ); return rc; } pt = pkt.pkt.literal; pfx->mode = pt->mode; pfx->filename = cdk_strdup( pt->name? pt->name : " " ); if( !pfx->filename ) { cdk_pkt_free( &pkt ); return CDK_Out_Of_Core; } while( !feof( in ) ) { _cdk_log_debug( "partial on=%d size=%lu\n", pfx->blkmode.on, pfx->blkmode.size ); if( pfx->blkmode.on ) bufsize = pfx->blkmode.size; else bufsize = pt->len < sizeof buf-1? pt->len : sizeof buf-1; nread = cdk_stream_read( pt->buf, buf, bufsize ); if( nread == EOF ) { rc = CDK_File_Error; break; } if( pfx->md ) cdk_md_write (pfx->md, buf, nread); cdk_stream_write( so, buf, nread ); pt->len -= nread; if( pfx->blkmode.on ) { pfx->blkmode.size = _cdk_pkt_read_len( in, &pfx->blkmode.on ); if( pfx->blkmode.size == (size_t)EOF ) return CDK_Inv_Packet; } if( pt->len <= 0 && !pfx->blkmode.on ) break; } cdk_stream_close( si ); cdk_stream_close( so ); cdk_pkt_free( &pkt ); return rc; }
cdk_error_t cdk_keydb_get_keyblock( cdk_stream_t inp, cdk_kbnode_t * r_knode ) { cdk_packet_t pkt = NULL; cdk_kbnode_t knode = NULL, node = NULL; cdk_desig_revoker_t revkeys = NULL; u32 keyid[2], main_keyid[2]; int rc = 0, old_off; int key_seen = 0, got_key = 0; if( !inp || !r_knode ) return CDK_Inv_Value; memset( keyid, 0, sizeof keyid ); memset( main_keyid, 0, sizeof main_keyid ); while( 1 ) { pkt = cdk_calloc( 1, sizeof *pkt ); if( !pkt ) return CDK_Out_Of_Core; old_off = cdk_stream_tell( inp ); rc = cdk_pkt_read( inp, pkt ); if( rc ) break; if( pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || pkt->pkttype == CDK_PKT_SECRET_KEY || pkt->pkttype == CDK_PKT_SECRET_SUBKEY) { if (key_seen && (pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_SECRET_KEY) ) { cdk_stream_seek( inp, old_off ); break; } if( pkt->pkttype == CDK_PKT_PUBLIC_KEY || pkt->pkttype == CDK_PKT_SECRET_KEY ) { _cdk_pkt_get_keyid( pkt, main_keyid ); key_seen = 1; } else if( pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY || pkt->pkttype == CDK_PKT_SECRET_SUBKEY ) { if( pkt->pkttype == CDK_PKT_PUBLIC_SUBKEY ) { pkt->pkt.public_key->main_keyid[0] = main_keyid[0]; pkt->pkt.public_key->main_keyid[1] = main_keyid[1]; } else { pkt->pkt.secret_key->main_keyid[0] = main_keyid[0]; pkt->pkt.secret_key->main_keyid[1] = main_keyid[1]; } } /* we save this for the signature */ _cdk_pkt_get_keyid( pkt, keyid ); got_key = 1; } else if( pkt->pkttype == CDK_PKT_USER_ID ) ; else if( pkt->pkttype == CDK_PKT_SIGNATURE ) { pkt->pkt.signature->key[0] = keyid[0]; pkt->pkt.signature->key[1] = keyid[1]; if( pkt->pkt.signature->sig_class == 0x1F && pkt->pkt.signature->revkeys ) revkeys = pkt->pkt.signature->revkeys; } node = cdk_kbnode_new( pkt ); if( !knode ) knode = node; else _cdk_kbnode_add( knode, node ); } if( got_key ) { keydb_merge_selfsig( knode, main_keyid ); rc = keydb_parse_allsigs( knode, NULL, 0 ); if( revkeys ) { node = cdk_kbnode_find( knode, CDK_PKT_PUBLIC_KEY ); if( node ) node->pkt->pkt.public_key->revkeys = revkeys; } } *r_knode = got_key ? knode : NULL; return rc; }