/** * cdk_pk_get_fingerprint: * @pk: the public key * @fpr: the buffer to hold the fingerprint * * Return the fingerprint of the given public key. * The buffer must be at least 20 octets. * This function should be considered deprecated and * the new cdk_pk_to_fingerprint() should be used whenever * possible to avoid overflows. **/ cdk_error_t cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr) { digest_hd_st hd; int md_algo; int dlen = 0; int err; if (!pk || !fpr) return CDK_Inv_Value; if (pk->version < 4 && is_RSA (pk->pubkey_algo)) md_algo = GNUTLS_DIG_MD5; /* special */ else md_algo = GNUTLS_DIG_SHA1; dlen = _gnutls_hash_get_algo_len (md_algo); err = _gnutls_hash_init (&hd, md_algo); if (err < 0) { gnutls_assert (); return map_gnutls_error (err); } _cdk_hash_pubkey (pk, &hd, 1); _gnutls_hash_deinit (&hd, fpr); if (dlen == 16) memset (fpr + 16, 0, 4); return 0; }
/** * cdk_pk_get_fingerprint: * @pk: the public key * @fpr: the buffer to hold the fingerprint * * Return the fingerprint of the given public key. * The buffer must be at least 20 octets. * This function should be considered deprecated and * the new cdk_pk_to_fingerprint() should be used whenever * possible to avoid overflows. **/ cdk_error_t cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte *fpr) { gcry_md_hd_t hd; int md_algo; int dlen = 0; gcry_error_t err; if (!pk || !fpr) return CDK_Inv_Value; if (pk->version < 4 && is_RSA (pk->pubkey_algo)) md_algo = GCRY_MD_MD5; /* special */ else md_algo = GCRY_MD_SHA1; dlen = gcry_md_get_algo_dlen (md_algo); err = gcry_md_open (&hd, md_algo, 0); if (err) return map_gcry_error (err); _cdk_hash_pubkey (pk, hd, 1); gcry_md_final (hd); memcpy (fpr, gcry_md_read (hd, md_algo), dlen); gcry_md_close (hd); if (dlen == 16) memset (fpr + 16, 0, 4); return 0; }
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; }
/** * 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_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; }