/** * cdk_pkt_release: * @pkt: the packet * * Free the contents of the given package and * release the memory of the structure. **/ void cdk_pkt_release(cdk_packet_t pkt) { if (!pkt) return; cdk_pkt_free(pkt); cdk_free(pkt); }
/* 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; }
/** * cdk_sklist_write: * @skl: secret keylist * @outp: the stream to write in the data * @hash: opaque handle for the message digest operations * @sigclass: the class of the sig * @sigver: version of the sig * * Complete the sig based on @hash and write all signatures to @outp. **/ cdk_error_t cdk_sklist_write( cdk_keylist_t skl, cdk_stream_t outp, cdk_md_hd_t hash, int sigclass, int sigver ) { cdk_keylist_t r = NULL; cdk_pkt_signature_t sig = NULL; cdk_packet_t pkt; cdk_md_hd_t md = NULL; byte * mdbuf; int rc = 0, digest_algo; if( !skl || !outp || !hash ) return CDK_Inv_Value; if( skl->type != CDK_PKT_SECRET_KEY ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof *pkt ); if( !pkt ) return CDK_Out_Of_Core; digest_algo = cdk_md_get_algo( hash ); for( r = skl; r; r = r->next ) { sig = cdk_calloc( 1, sizeof *sig ); if( !sig ) return CDK_Out_Of_Core; sig->version = sigver; _cdk_sig_create( r->key.sk->pk, sig ); if( sig->digest_algo != digest_algo ) sig->digest_algo = digest_algo; sig->sig_class = sigclass; md = cdk_md_copy( hash ); _cdk_hash_sig_data( sig, md ); cdk_md_final( md ); mdbuf = cdk_md_read( md, sig->digest_algo ); rc = cdk_pk_sign( r->key.sk, sig, mdbuf ); if( rc ) break; cdk_pkt_init( pkt ); pkt->old_ctb = sig->version == 3? 1 : 0; pkt->pkttype = CDK_PKT_SIGNATURE; pkt->pkt.signature = sig; rc = cdk_pkt_write( outp, pkt ); cdk_pkt_free( pkt ); if( rc ) break; cdk_md_close( md ); md = NULL; } cdk_free( pkt ); cdk_md_close( md ); return rc; }
/** * cdk_sklist_write_onepass: * @skl: secret keylist * @outp: the stream to write in the data * @sigclass: the class of the sig to create * @mdalgo: the message digest algorithm * * Write a one-pass signature for each key in the list into @outp. **/ cdk_error_t cdk_sklist_write_onepass( cdk_keylist_t skl, cdk_stream_t outp, int sigclass, int mdalgo ) { cdk_pkt_onepass_sig_t ops; cdk_keylist_t r; cdk_packet_t pkt; int i, skcount = 0; int rc = 0; if( !skl || !outp ) return CDK_Inv_Value; if( skl->type != CDK_PKT_SECRET_KEY ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; for( skcount = 0, r = skl; r; r = r->next ) skcount++; for( ; skcount; skcount-- ) { for( i = 0, r = skl; r; r = r->next ) { if( ++i == skcount ) break; } ops = cdk_calloc( 1, sizeof *ops ); if( !ops ) return CDK_Out_Of_Core; ops->version = 3; cdk_sk_get_keyid( r->key.sk, ops->keyid ); ops->sig_class = sigclass; if( !mdalgo ) mdalgo = _cdk_sig_hash_for( r->key.sk->pubkey_algo, r->key.sk->version ); ops->digest_algo = mdalgo; ops->pubkey_algo = r->key.sk->pubkey_algo; ops->last = (skcount == 1); cdk_pkt_init( pkt ); pkt->pkttype = CDK_PKT_ONEPASS_SIG; pkt->pkt.onepass_sig = ops; rc = cdk_pkt_write( outp, pkt ); cdk_pkt_free( pkt ); if( rc ) break; } cdk_free( pkt ); return rc; }
/** * cdk_pklist_encrypt: * @pkl: the keylist * @dek: the data encryption key * @outp: the stream to write in the data * * Encrypt the session key with each key of the list and wrap it * into a PUBKEY_ENC packet and write it to @outp. */ cdk_error_t cdk_pklist_encrypt( cdk_keylist_t pk_list, cdk_dek_t dek, cdk_stream_t outp ) { cdk_pkt_pubkey_t pk = NULL; cdk_pkt_pubkey_enc_t enc = NULL; cdk_packet_t pkt; cdk_sesskey_t frame = NULL; int nbits = 0; int rc = 0; if( !pk_list || !dek || !outp ) return CDK_Inv_Value; if( pk_list->type != CDK_PKT_PUBLIC_KEY ) return CDK_Inv_Mode; pkt = cdk_calloc( 1, sizeof * pkt ); if( !pkt ) return CDK_Out_Of_Core; for( ; pk_list; pk_list = pk_list->next ) { pk = pk_list->key.pk; cdk_free( enc ); enc = cdk_calloc( 1, sizeof *enc ); if( !enc ) return CDK_Out_Of_Core; enc->version = 3; enc->pubkey_algo = pk->pubkey_algo; cdk_pk_get_keyid( pk, enc->keyid ); nbits = cdk_pk_get_nbits( pk ); rc = cdk_dek_encode_pkcs1( dek, nbits, &frame ); if( rc ) break; rc = cdk_pk_encrypt( pk, enc, frame ); cdk_sesskey_free( frame ); if( rc ) break; else { cdk_pkt_init( pkt ); pkt->old_ctb = dek->rfc1991? 1 : 0; pkt->pkttype = CDK_PKT_PUBKEY_ENC; pkt->pkt.pubkey_enc = enc; rc = cdk_pkt_write( outp, pkt ); cdk_pkt_free( pkt ); if( rc ) break; } } cdk_free( pkt ); cdk_free( enc ); 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; }
/** * cdk_keygen_save: save the generated keys to disk * @hd: the keygen object * @pub: name of the file to store the public key * @sec: name of the file to store the secret key * **/ cdk_error_t cdk_keygen_save( cdk_keygen_ctx_t hd, const char * pubf, const char * secf ) { cdk_stream_t out = NULL; CDK_PACKET pkt; int rc; hd->key[0].pk = pk_create( hd, 0 ); if( !hd->key[0].pk ) return CDK_Inv_Packet; hd->key[0].sk = sk_create( hd, 0 ); if( !hd->key[0].sk ) return CDK_Inv_Packet; hd->id = uid_create( hd ); if( !hd->id ) return CDK_Inv_Packet; hd->sig = sig_self_create( hd ); if( !hd->sig ) return CDK_Inv_Packet; rc = cdk_stream_create( pubf, &out ); if( rc ) return rc; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_PUBLIC_KEY; pkt.pkt.public_key = hd->key[0].pk; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_USER_ID; pkt.pkt.user_id = hd->id; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_SIGNATURE; pkt.pkt.signature = hd->sig; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; if( hd->key[1].algo ) { cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_PUBLIC_SUBKEY; pkt.pkt.public_key = hd->key[1].pk = pk_create( hd, 1 ); rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_SIGNATURE; pkt.pkt.signature = sig_subkey_create( hd ); rc = cdk_pkt_write( out, &pkt ); cdk_pkt_free( &pkt ); if( rc ) goto fail; } cdk_stream_close( out ); out = NULL; rc = cdk_stream_create( secf, &out ); if( rc ) goto fail; if( hd->protect ) { rc = cdk_sk_protect( hd->key[0].sk, hd->pass ); if( rc ) goto fail; } cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_SECRET_KEY; pkt.pkt.secret_key = hd->key[0].sk; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_USER_ID; pkt.pkt.user_id = hd->id; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_SIGNATURE; pkt.pkt.signature = hd->sig; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; if( hd->key[1].algo ) { hd->key[1].sk = sk_create( hd, 1 ); if( hd->protect && (rc = cdk_sk_protect( hd->key[1].sk, hd->pass )) ) goto fail; cdk_pkt_init( &pkt ); pkt.pkttype = CDK_PKT_SECRET_SUBKEY; pkt.pkt.secret_key = hd->key[1].sk; rc = cdk_pkt_write( out, &pkt ); if( rc ) goto fail; } fail: cdk_stream_close( out ); 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; }