/** * cdk_kbnode_hash: * @node: the key node * @hashctx: opaque pointer to the hash context * @is_v4: OpenPGP signature (yes=1, no=0) * @pkttype: packet type to hash (if zero use the packet type from the node) * @flags: flags which depend on the operation * * Hashes the key node contents. Two modes are supported. If the packet * type is used (!= 0) then the function searches the first node with * this type. Otherwise the node is seen as a single node and the type * is extracted from it. **/ cdk_error_t cdk_kbnode_hash (cdk_kbnode_t node, digest_hd_st * md, int is_v4, cdk_packet_type_t pkttype, int flags) { cdk_packet_t pkt; if (!node || !md) { gnutls_assert (); return CDK_Inv_Value; } if (!pkttype) { pkt = cdk_kbnode_get_packet (node); pkttype = pkt->pkttype; } else { pkt = cdk_kbnode_find_packet (node, pkttype); if (!pkt) { gnutls_assert (); return CDK_Inv_Packet; } } switch (pkttype) { case CDK_PKT_PUBLIC_KEY: case CDK_PKT_PUBLIC_SUBKEY: _cdk_hash_pubkey (pkt->pkt.public_key, md, flags & 1); break; case CDK_PKT_USER_ID: _cdk_hash_userid (pkt->pkt.user_id, is_v4, md); break; case CDK_PKT_SIGNATURE: _cdk_hash_sig_data (pkt->pkt.signature, md); break; default: gnutls_assert (); return CDK_Inv_Mode; } return 0; }
static cdk_pkt_signature_t sig_self_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_userid_t id = hd->id; cdk_pkt_seckey_t sk = hd->key[0].sk; u32 keyid[2]; byte buf[8], * p; int rc; sig = cdk_calloc( 1, sizeof * sig ); if( !sig ) return NULL; sig->version = 4; sig->timestamp = _cdk_timestamp( ); sig->sig_class = 0x13; sig->pubkey_algo = hd->key[0].algo; sig->digest_algo = CDK_MD_SHA1; _cdk_u32tobuf( sig->timestamp, buf ); sig->hashed = node = cdk_subpkt_new( 4 ); if( node ) cdk_subpkt_init( node, CDK_SIGSUBPKT_SIG_CREATED, buf, 4 ); p = hd->sym_prefs; node = cdk_subpkt_new( hd->sym_len + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_SYM, p, hd->sym_len ); cdk_subpkt_add( sig->hashed, node ); } p = hd->hash_prefs; node = cdk_subpkt_new( hd->hash_len + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_HASH, p, hd->hash_len ); cdk_subpkt_add( sig->hashed, node ); } p = hd->zip_prefs; node = cdk_subpkt_new( hd->zip_len + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREFS_ZIP, p, hd->zip_len ); cdk_subpkt_add( sig->hashed, node ); } if( hd->mdc_feature ) { buf[0] = 0x01; node = cdk_subpkt_new( 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_FEATURES, buf, 1 ); cdk_subpkt_add( sig->hashed, node ); } } if( hd->ks_no_modify ) { buf[0] = 0x80; node = cdk_subpkt_new( 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_KS_FLAGS, buf, 1 ); cdk_subpkt_add( sig->hashed, node ); } } if( hd->ks_pref_url ) { node = cdk_subpkt_new( strlen( hd->ks_pref_url ) + 1 ); if( node ) { cdk_subpkt_init( node, CDK_SIGSUBPKT_PREF_KS, hd->ks_pref_url, strlen( hd->ks_pref_url ) ); cdk_subpkt_add( sig->hashed, node ); } } if( pk->expiredate ) { node = cdk_subpkt_new( 4 ); if( node ) { _cdk_u32tobuf( pk->expiredate - pk->timestamp, buf ); cdk_subpkt_init( node, CDK_SIGSUBPKT_KEY_EXPIRE, buf, 4 ); cdk_subpkt_add( sig->hashed, node ); } } sig->unhashed = node = cdk_subpkt_new( 8 ); if( node ) { cdk_pk_get_keyid( pk, keyid ); _cdk_u32tobuf( keyid[0], buf ); _cdk_u32tobuf( keyid[1], buf + 4 ); cdk_subpkt_init( node, CDK_SIGSUBPKT_ISSUER, buf, 8 ); } md = cdk_md_open( sig->digest_algo, 0 ); if( !md ) { _cdk_free_signature( sig ); return NULL; } _cdk_hash_pubkey( pk, md, 0 ); _cdk_hash_userid( id, sig->version == 4, md ); rc = _cdk_sig_complete( sig, sk, md ); cdk_md_close( md ); if( rc ) { _cdk_free_signature( sig ); return NULL; } return sig; }