/** * cdk_pk_from_secret_key: * @sk: the secret key * @ret_pk: the new public key * * Create a new public key from a secret key. **/ cdk_error_t cdk_pk_from_secret_key (cdk_pkt_seckey_t sk, cdk_pubkey_t *ret_pk) { if (!sk) return CDK_Inv_Value; return _cdk_copy_pubkey (ret_pk, sk->pk); } #if 0 /* FIXME: Code is not finished yet. */ cdk_error_t cdk_pk_revoke_cert_create (cdk_pkt_seckey_t sk, int code, const char *inf, char **ret_revcert) { gcry_md_hd_t md; cdk_subpkt_t node; cdk_pkt_signature_t sig; char *p = NULL, *dat; gcry_error_t err; cdk_error_t rc = 0; size_t n; if (!sk || !ret_revcert) return CDK_Inv_Value; if(code < 0 || code > 3) return CDK_Inv_Value; sig = cdk_calloc (1, sizeof *sig); if (!sig) return CDK_Out_Of_Core; _cdk_sig_create (sk->pk, sig); n = 1; if (inf) { n += strlen (p); p = cdk_utf8_encode (inf); } dat = cdk_calloc (1, n+1); if (!dat) { _cdk_free_signature (sig); return CDK_Out_Of_Core; } dat[0] = code; if (inf) memcpy (dat+1, p, strlen (p)); cdk_free (p); node = cdk_subpkt_new (n); if (node) { cdk_subpkt_init (node, CDK_SIGSUBPKT_REVOC_REASON, dat, n); cdk_subpkt_add (sig->hashed, node); } cdk_free (dat); err = gcry_md_open (&md, GCRY_MD_SHA1, 0); if (err) rc = map_gcry_error (err); else _cdk_hash_pubkey (sk->pk, md, 0); _cdk_free_signature (sig); 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; }
static cdk_pkt_signature_t sig_subkey_create( cdk_keygen_ctx_t hd ) { cdk_md_hd_t md; cdk_subpkt_t node; cdk_pkt_signature_t sig; cdk_pkt_pubkey_t pk = hd->key[0].pk; cdk_pkt_pubkey_t sub_pk = hd->key[1].pk; cdk_pkt_seckey_t sk = hd->key[0].sk; byte buf[4]; int rc; sig = cdk_calloc( 1, sizeof * sig ); if( !sig ) return NULL; _cdk_sig_create( pk, sig ); sig->sig_class = 0x18; sig->digest_algo = CDK_MD_SHA1; if( sub_pk->expiredate ) { _cdk_u32tobuf( sub_pk->expiredate - sub_pk->timestamp, buf ); node = cdk_subpkt_new( 4 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_KEY_EXPIRE, buf, 4 ); cdk_subpkt_add( sig->hashed, node ); } } md = cdk_md_open( sig->digest_algo, 0 ); if( !md ) { _cdk_free_signature( sig ); return NULL; } _cdk_hash_pubkey( pk, md, 0 ); _cdk_hash_pubkey( sub_pk, md, 0 ); rc = _cdk_sig_complete( sig, sk, md ); cdk_md_close( md ); if( rc ) { _cdk_free_signature( sig ); return NULL; } return sig; }