/** * gnutls_openpgp_privkey_get_subkey_fingerprint: * @key: the raw data that contains the OpenPGP secret key. * @idx: the subkey index * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes. * @fprlen: the integer to save the length of the fingerprint. * * Get the fingerprint of an OpenPGP subkey. Depends on the * algorithm, the fingerprint can be 16 or 20 bytes. * * Returns: On success, 0 is returned, or an error code. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_subkey_fingerprint(gnutls_openpgp_privkey_t key, unsigned int idx, void *fpr, size_t * fprlen) { cdk_packet_t pkt; cdk_pkt_pubkey_t pk = NULL; if (!fpr || !fprlen) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) return gnutls_openpgp_privkey_get_fingerprint(key, fpr, fprlen); *fprlen = 0; pkt = _get_secret_subkey(key, idx); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; pk = pkt->pkt.secret_key->pk; *fprlen = 20; if (is_RSA(pk->pubkey_algo) && pk->version < 4) *fprlen = 16; cdk_pk_get_fingerprint(pk, fpr); return 0; }
/** * cdk_pk_to_fingerprint: * @pk: the public key * @fprbuf: buffer to save the fingerprint * @fprbuflen: buffer size * @r_nout: actual length of the fingerprint. * * Calculate a fingerprint of the given key and * return it in the given byte array. **/ cdk_error_t cdk_pk_to_fingerprint (cdk_pubkey_t pk, byte * fprbuf, size_t fprbuflen, size_t * r_nout) { size_t key_fprlen; cdk_error_t err; if (!pk) return CDK_Inv_Value; if (pk->version < 4) key_fprlen = 16; else key_fprlen = 20; /* Only return the required buffer size for the fingerprint. */ if (!fprbuf && !fprbuflen && r_nout) { *r_nout = key_fprlen; return 0; } if (!fprbuf || key_fprlen > fprbuflen) return CDK_Too_Short; err = cdk_pk_get_fingerprint (pk, fprbuf); if (r_nout) *r_nout = key_fprlen; return err; }
/** * gnutls_openpgp_privkey_get_fingerprint: * @key: the raw data that contains the OpenPGP secret key. * @fpr: the buffer to save the fingerprint, must hold at least 20 bytes. * @fprlen: the integer to save the length of the fingerprint. * * Get the fingerprint of the OpenPGP key. Depends on the * algorithm, the fingerprint can be 16 or 20 bytes. * * Returns: On success, 0 is returned, or an error code. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_fingerprint(gnutls_openpgp_privkey_t key, void *fpr, size_t * fprlen) { cdk_packet_t pkt; cdk_pkt_pubkey_t pk = NULL; if (!fpr || !fprlen) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } *fprlen = 0; pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_SECRET_KEY); if (!pkt) { gnutls_assert(); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } pk = pkt->pkt.secret_key->pk; *fprlen = 20; if (is_RSA(pk->pubkey_algo) && pk->version < 4) *fprlen = 16; cdk_pk_get_fingerprint(pk, fpr); return 0; }
/** * cdk_pk_get_keyid: * @pk: the public key * @keyid: buffer to store the key ID * * Calculate the key ID of the given public key. **/ u32 cdk_pk_get_keyid (cdk_pubkey_t pk, u32 *keyid) { u32 lowbits = 0; byte buf[24]; if (pk && (!pk->keyid[0] || !pk->keyid[1])) { if (pk->version < 4 && is_RSA (pk->pubkey_algo)) { byte p[MAX_MPI_BYTES]; size_t n; gcry_mpi_print (GCRYMPI_FMT_USG, p, MAX_MPI_BYTES, &n, pk->mpi[0]); pk->keyid[0] = p[n-8] << 24 | p[n-7] << 16 | p[n-6] << 8 | p[n-5]; pk->keyid[1] = p[n-4] << 24 | p[n-3] << 16 | p[n-2] << 8 | p[n-1]; } else if (pk->version == 4) { cdk_pk_get_fingerprint (pk, buf); pk->keyid[0] = _cdk_buftou32 (buf + 12); pk->keyid[1] = _cdk_buftou32 (buf + 16); } } lowbits = pk ? pk->keyid[1] : 0; if (keyid && pk) { keyid[0] = pk->keyid[0]; keyid[1] = pk->keyid[1]; } return lowbits; }
/* 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; }
/* Get the fingerprint of the packet if possible. */ cdk_error_t _cdk_pkt_get_fingerprint(cdk_packet_t pkt, byte * fpr) { if (!pkt || !fpr) return CDK_Inv_Value; switch (pkt->pkttype) { case CDK_PKT_PUBLIC_KEY: case CDK_PKT_PUBLIC_SUBKEY: return cdk_pk_get_fingerprint(pkt->pkt.public_key, fpr); case CDK_PKT_SECRET_KEY: case CDK_PKT_SECRET_SUBKEY: return cdk_pk_get_fingerprint(pkt->pkt.secret_key->pk, fpr); default: return CDK_Inv_Mode; } return 0; }
/** * cdk_pk_get_keyid: * @pk: the public key * @keyid: buffer to store the key ID * * Calculate the key ID of the given public key. **/ u32 cdk_pk_get_keyid(cdk_pubkey_t pk, u32 * keyid) { u32 lowbits = 0; byte buf[24]; int rc; if (pk && (!pk->keyid[0] || !pk->keyid[1])) { if (pk->version < 4 && is_RSA(pk->pubkey_algo)) { byte p[MAX_MPI_BYTES]; size_t n; n = MAX_MPI_BYTES; rc = _gnutls_mpi_print(pk->mpi[0], p, &n); if (rc < 0 || n < 8) { keyid[0] = keyid[1] = (u32)-1; return (u32)-1; } pk->keyid[0] = p[n - 8] << 24 | p[n - 7] << 16 | p[n - 6] << 8 | p[n - 5]; pk->keyid[1] = p[n - 4] << 24 | p[n - 3] << 16 | p[n - 2] << 8 | p[n - 1]; } else if (pk->version == 4) { cdk_pk_get_fingerprint(pk, buf); pk->keyid[0] = _cdk_buftou32(buf + 12); pk->keyid[1] = _cdk_buftou32(buf + 16); } } lowbits = pk ? pk->keyid[1] : 0; if (keyid && pk) { keyid[0] = pk->keyid[0]; keyid[1] = pk->keyid[1]; } return lowbits; }
static int xml_add_key (gnutls_string * xmlkey, int ext, cdk_pkt_pubkey_t pk, int sub) { const char *algo, *s; char keyid[16], fpr[41], tmp[32]; uint8_t fingerpr[20]; unsigned int kid[2]; int i = 0, rc = 0; if (!xmlkey || !pk) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } s = sub ? " <SUBKEY>\n" : " <MAINKEY>\n"; _gnutls_string_append_str (xmlkey, s); cdk_pk_get_keyid (pk, kid); snprintf (keyid, 16, "%08lX%08lX", kid[0], kid[1]); rc = xml_add_tag (xmlkey, "KEYID", keyid); if (rc) return rc; cdk_pk_get_fingerprint (pk, fingerpr); for (i = 0; i < 20; i++) sprintf (fpr + 2 * i, "%02X", fingerpr[i]); fpr[40] = '\0'; rc = xml_add_tag (xmlkey, "FINGERPRINT", fpr); if (rc) return rc; if (is_DSA (pk->pubkey_algo)) algo = "DSA"; else if (is_RSA (pk->pubkey_algo)) algo = "RSA"; else if (is_ELG (pk->pubkey_algo)) algo = "ELG"; else algo = "???"; rc = xml_add_tag (xmlkey, "PKALGO", algo); if (rc) return rc; sprintf (tmp, "%d", cdk_pk_get_nbits (pk)); rc = xml_add_tag (xmlkey, "KEYLEN", tmp); if (rc) return rc; sprintf (tmp, "%lu", pk->timestamp); rc = xml_add_tag (xmlkey, "CREATED", tmp); if (rc) return rc; if (pk->expiredate > 0) { sprintf (tmp, "%lu", (unsigned long) pk->expiredate); rc = xml_add_tag (xmlkey, "EXPIREDATE", tmp); if (rc) return rc; } sprintf (tmp, "%d", pk->is_revoked); rc = xml_add_tag (xmlkey, "REVOKED", tmp); if (rc) return rc; if (ext) { rc = xml_add_key_mpi (xmlkey, pk); if (rc) return rc; } s = sub ? " </SUBKEY>\n" : " </MAINKEY>\n"; _gnutls_string_append_str (xmlkey, s); return 0; }