static cdk_packet_t find_key_packet( cdk_kbnode_t knode, int * r_is_sk ) { cdk_packet_t pkt; pkt = cdk_kbnode_find_packet( knode, CDK_PKT_PUBLIC_KEY ); if( !pkt ) { pkt = cdk_kbnode_find_packet( knode, CDK_PKT_SECRET_KEY ); if( r_is_sk ) *r_is_sk = pkt? 1 : 0; } return pkt; }
/** * gnutls_openpgp_key_get_id - Gets the keyID * @key: the structure that contains the OpenPGP public key. * @keyid: the buffer to save the keyid. * * Returns the 64-bit keyID of the OpenPGP key. **/ int gnutls_openpgp_key_get_id (gnutls_openpgp_key_t key, unsigned char keyid[8]) { cdk_packet_t pkt; cdk_pkt_pubkey_t pk = NULL; uint32_t kid[2]; if (!key || !keyid) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; pk = pkt->pkt.public_key; cdk_pk_get_keyid (pk, kid); keyid[0] = kid[0] >> 24; keyid[1] = kid[0] >> 16; keyid[2] = kid[0] >> 8; keyid[3] = kid[0]; keyid[4] = kid[1] >> 24; keyid[5] = kid[1] >> 16; keyid[6] = kid[1] >> 8; keyid[7] = kid[1]; return 0; }
/** * gnutls_openpgp_key_get_pk_algorithm - This function returns the key's PublicKey algorithm * @key: is an OpenPGP key * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns a member of the GNUTLS_PKAlgorithm enumeration on success, * or a negative value on error. * **/ int gnutls_openpgp_key_get_pk_algorithm (gnutls_openpgp_key_t key, unsigned int *bits) { cdk_packet_t pkt; int algo = 0; if (!key) return GNUTLS_E_INVALID_REQUEST; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY) { if (bits) *bits = cdk_pk_get_nbits (pkt->pkt.public_key); algo = pkt->pkt.public_key->pubkey_algo; if (is_RSA (algo)) algo = GNUTLS_PK_RSA; else if (is_DSA (algo)) algo = GNUTLS_PK_DSA; else algo = GNUTLS_E_UNKNOWN_PK_ALGORITHM; } return algo; }
/** * 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; }
/** * gnutls_openpgp_key_get_key_usage - This function returns the key's usage * @key: should contain a gnutls_openpgp_key_t structure * @key_usage: where the key usage bits will be stored * * This function will return certificate's key usage, by checking the * key algorithm. The key usage value will ORed values of the: * GNUTLS_KEY_DIGITAL_SIGNATURE, GNUTLS_KEY_KEY_ENCIPHERMENT. * * A negative value may be returned in case of parsing error. * **/ int gnutls_openpgp_key_get_key_usage (gnutls_openpgp_key_t key, unsigned int *key_usage) { cdk_packet_t pkt; int algo = 0; if (!key) return GNUTLS_E_INVALID_REQUEST; *key_usage = 0; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt && pkt->pkttype == CDK_PKT_PUBLIC_KEY) { algo = pkt->pkt.public_key->pubkey_algo; if (is_DSA (algo) || algo == GCRY_PK_RSA_S) *key_usage |= KEY_DIGITAL_SIGNATURE; else if (algo == GCRY_PK_RSA_E) *key_usage |= KEY_KEY_ENCIPHERMENT; else if (algo == GCRY_PK_RSA) *key_usage |= KEY_DIGITAL_SIGNATURE | KEY_KEY_ENCIPHERMENT; } return 0; }
/** * gnutls_openpgp_crt_import: * @key: The structure to store the parsed key. * @data: The RAW or BASE64 encoded key. * @format: One of gnutls_openpgp_crt_fmt_t elements. * * This function will convert the given RAW or Base64 encoded key to * the native #gnutls_openpgp_crt_t format. The output will be stored * in 'key'. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_openpgp_crt_import (gnutls_openpgp_crt_t key, const gnutls_datum_t * data, gnutls_openpgp_crt_fmt_t format) { cdk_packet_t pkt; int rc, armor; if (data->data == NULL || data->size == 0) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } if (format == GNUTLS_OPENPGP_FMT_RAW) armor = 0; else armor = 1; rc = cdk_kbnode_read_from_mem (&key->knode, armor, data->data, data->size); if (rc) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } /* Test if the import was successful. */ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt == NULL) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } return 0; }
/** * gnutls_openpgp_key_get_expiration_time - Extract the expire date * @key: the structure that contains the OpenPGP public key. * * Returns the time when the OpenPGP key expires. A value of '0' means * that the key doesn't expire at all. **/ time_t gnutls_openpgp_key_get_expiration_time (gnutls_openpgp_key_t key) { cdk_packet_t pkt; time_t expiredate = 0; if (!key) return (time_t) - 1; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt) expiredate = pkt->pkt.public_key->expiredate; return expiredate; }
/** * gnutls_openpgp_key_get_creation_time - Extract the timestamp * @key: the structure that contains the OpenPGP public key. * * Returns the timestamp when the OpenPGP key was created. **/ time_t gnutls_openpgp_key_get_creation_time (gnutls_openpgp_key_t key) { cdk_packet_t pkt; time_t timestamp = 0; if (!key) return (time_t) - 1; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt) timestamp = pkt->pkt.public_key->timestamp; return timestamp; }
/** * gnutls_openpgp_key_get_version - Extracts the version of the key. * @key: the structure that contains the OpenPGP public key. * * Extract the version of the OpenPGP key. **/ int gnutls_openpgp_key_get_version (gnutls_openpgp_key_t key) { cdk_packet_t pkt; int version = 0; if (!key) return -1; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_PUBLIC_KEY); if (pkt) version = pkt->pkt.public_key->version; return version; }
/** * 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; }
/** * gnutls_openpgp_privkey_get_revoked_status: * @key: the structure that contains the OpenPGP private key. * * Get revocation status of key. * * Returns: true (1) if the key has been revoked, or false (0) if it * has not, or a negative error code indicates an error. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_revoked_status(gnutls_openpgp_privkey_t key) { cdk_packet_t pkt; if (!key) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_SECRET_KEY); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; if (pkt->pkt.secret_key->is_revoked != 0) return 1; return 0; }
/** * gnutls_openpgp_privkey_get_key_id: * @key: the structure that contains the OpenPGP secret key. * @keyid: the buffer to save the keyid. * * Get key-id. * * Returns: the 64-bit keyID of the OpenPGP key. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_key_id(gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid) { cdk_packet_t pkt; uint32_t kid[2]; if (!key || !keyid) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_SECRET_KEY); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; cdk_sk_get_keyid(pkt->pkt.secret_key, kid); _gnutls_write_uint32(kid[0], keyid); _gnutls_write_uint32(kid[1], keyid + 4); return 0; }
/** * gnutls_openpgp_privkey_get_subkey_expiration_time: * @key: the structure that contains the OpenPGP private key. * @idx: the subkey index * * Get subkey expiration time. A value of '0' means that the key * doesn't expire at all. * * Returns: the time when the OpenPGP key expires. * * Since: 2.4.0 **/ time_t gnutls_openpgp_privkey_get_subkey_expiration_time (gnutls_openpgp_privkey_t key, unsigned int idx) { cdk_packet_t pkt; time_t timestamp; if (!key) return (time_t) - 1; if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); else pkt = _get_secret_subkey (key, idx); if (pkt) timestamp = pkt->pkt.secret_key->pk->expiredate; else timestamp = 0; return timestamp; }
/** * gnutls_openpgp_privkey_get_pk_algorithm: * @key: is an OpenPGP key * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns: a member of the #gnutls_pk_algorithm_t enumeration on * success, or a negative error code on error. * * Since: 2.4.0 **/ gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, unsigned int *bits) { cdk_packet_t pkt; int algo = 0, ret; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; if (!key) { gnutls_assert (); return GNUTLS_PK_UNKNOWN; } ret = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); if (ret == 0) { int idx; idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); if (idx != GNUTLS_OPENPGP_MASTER_KEYID_IDX) { algo = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, bits); return algo; } } pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); if (pkt) { if (bits) *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); } return algo; }
/** * gnutls_openpgp_privkey_get_pk_algorithm: * @key: is an OpenPGP key * @bits: if bits is non null it will hold the size of the parameters' in bits * * This function will return the public key algorithm of an OpenPGP * certificate. * * If bits is non null, it should have enough size to hold the parameters * size in bits. For RSA the bits returned is the modulus. * For DSA the bits returned are of the public exponent. * * Returns: a member of the #gnutls_pk_algorithm_t enumeration on * success, or a negative value on error. * * Since: 2.4.0 **/ gnutls_pk_algorithm_t gnutls_openpgp_privkey_get_pk_algorithm (gnutls_openpgp_privkey_t key, unsigned int *bits) { cdk_packet_t pkt; int algo; if (!key) { gnutls_assert (); return GNUTLS_PK_UNKNOWN; } algo = 0; pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); if (pkt) { if (bits) *bits = cdk_pk_get_nbits (pkt->pkt.secret_key->pk); algo = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); } return algo; }
/* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_openpgp_privkey_get_mpis(gnutls_openpgp_privkey_t pkey, uint32_t * keyid /*[2] */ , gnutls_pk_params_st * params) { int result; unsigned int i, pk_algorithm; cdk_packet_t pkt; unsigned total; gnutls_pk_params_init(params); if (keyid == NULL) pkt = cdk_kbnode_find_packet(pkey->knode, CDK_PKT_SECRET_KEY); else pkt = _gnutls_openpgp_find_key(pkey->knode, keyid, 1); if (pkt == NULL) { gnutls_assert(); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } pk_algorithm = _gnutls_openpgp_get_algo(pkt->pkt.secret_key->pk->pubkey_algo); switch (pk_algorithm) { case GNUTLS_PK_RSA: /* openpgp does not hold all parameters as in PKCS #1 */ total = RSA_PRIVATE_PARAMS - 2; break; case GNUTLS_PK_DSA: total = DSA_PRIVATE_PARAMS; break; default: gnutls_assert(); return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; } for (i = 0; i < total; i++) { result = _gnutls_read_pgp_mpi(pkt, 1, i, ¶ms->params[i]); if (result < 0) { gnutls_assert(); goto error; } params->params_nr++; } /* fixup will generate exp1 and exp2 that are not * available here. */ result = _gnutls_pk_fixup(pk_algorithm, GNUTLS_IMPORT, params); if (result < 0) { gnutls_assert(); goto error; } return 0; error: gnutls_pk_params_clear(params); gnutls_pk_params_release(params); return result; }
/* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey, uint32_t * keyid /*[2] */ , bigint_t * params, int *params_size) { int result, i; int pk_algorithm; gnutls_pk_params_st pk_params; cdk_packet_t pkt; memset (&pk_params, 0, sizeof (pk_params)); if (keyid == NULL) pkt = cdk_kbnode_find_packet (pkey->knode, CDK_PKT_SECRET_KEY); else pkt = _gnutls_openpgp_find_key (pkey->knode, keyid, 1); if (pkt == NULL) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } pk_algorithm = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); switch (pk_algorithm) { case GNUTLS_PK_RSA: /* openpgp does not hold all parameters as in PKCS #1 */ pk_params.params_nr = RSA_PRIVATE_PARAMS - 2; break; case GNUTLS_PK_DSA: pk_params.params_nr = DSA_PRIVATE_PARAMS; break; default: gnutls_assert (); return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; } for (i = 0; i < pk_params.params_nr; i++) { result = _gnutls_read_pgp_mpi (pkt, 1, i, &pk_params.params[i]); if (result < 0) { gnutls_assert (); goto error; } } /* fixup will generate exp1 and exp2 that are not * available here. */ result = _gnutls_pk_fixup (pk_algorithm, GNUTLS_IMPORT, &pk_params); if (result < 0) { gnutls_assert (); goto error; } if (*params_size < pk_params.params_nr) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } *params_size = pk_params.params_nr; for (i = 0; i < pk_params.params_nr; i++) params[i] = pk_params.params[i]; return 0; error: { int j; for (j = 0; j < i; j++) _gnutls_mpi_release (&pk_params.params[j]); } return result; }
/** * gnutls_openpgp_privkey_import: * @key: The structure to store the parsed key. * @data: The RAW or BASE64 encoded key. * @format: One of #gnutls_openpgp_crt_fmt_t elements. * @password: not used for now * @flags: should be zero * * This function will convert the given RAW or Base64 encoded key to * the native gnutls_openpgp_privkey_t format. The output will be * stored in 'key'. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_openpgp_privkey_import (gnutls_openpgp_privkey_t key, const gnutls_datum_t * data, gnutls_openpgp_crt_fmt_t format, const char *password, unsigned int flags) { cdk_stream_t inp; cdk_packet_t pkt; int rc; if (data->data == NULL || data->size == 0) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } if (format == GNUTLS_OPENPGP_FMT_RAW) { rc = cdk_kbnode_read_from_mem (&key->knode, data->data, data->size); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } } else { rc = cdk_stream_tmp_from_mem (data->data, data->size, &inp); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } if (cdk_armor_filter_use (inp)) { rc = cdk_stream_set_armor_flag (inp, 0); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); cdk_stream_close (inp); gnutls_assert (); return rc; } } rc = cdk_keydb_get_keyblock (inp, &key->knode); cdk_stream_close (inp); if (rc != 0) { rc = _gnutls_map_cdk_rc (rc); gnutls_assert (); return rc; } } /* Test if the import was successful. */ pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_SECRET_KEY); if (pkt == NULL) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } return 0; }
/* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_openpgp_privkey_get_mpis (gnutls_openpgp_privkey_t pkey, uint32_t * keyid /*[2] */ , bigint_t * params, int *params_size) { int result, i; int pk_algorithm, local_params; cdk_packet_t pkt; if (keyid == NULL) pkt = cdk_kbnode_find_packet (pkey->knode, CDK_PKT_SECRET_KEY); else pkt = _gnutls_openpgp_find_key (pkey->knode, keyid, 1); if (pkt == NULL) { gnutls_assert (); return GNUTLS_E_OPENPGP_GETKEY_FAILED; } pk_algorithm = _gnutls_openpgp_get_algo (pkt->pkt.secret_key->pk->pubkey_algo); switch (pk_algorithm) { case GNUTLS_PK_RSA: local_params = RSA_PRIVATE_PARAMS; break; case GNUTLS_PK_DSA: local_params = DSA_PRIVATE_PARAMS; break; default: gnutls_assert (); return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; } if (*params_size < local_params) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } *params_size = local_params; for (i = 0; i < local_params; i++) { result = _gnutls_read_pgp_mpi (pkt, 1, i, ¶ms[i]); if (result < 0) { gnutls_assert (); goto error; } } return 0; error: { int j; for (j = 0; j < i; j++) _gnutls_mpi_release (¶ms[j]); } return result; }
/** * gnutls_openpgp_key_get_name - Extracts the userID * @key: the structure that contains the OpenPGP public key. * @idx: the index of the ID to extract * @buf: a pointer to a structure to hold the name * @sizeof_buf: holds the size of 'buf' * * Extracts the userID from the parsed OpenPGP key. * * Returns 0 on success, and GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE * if the index of the ID does not exist. * **/ int gnutls_openpgp_key_get_name (gnutls_openpgp_key_t key, int idx, char *buf, size_t * sizeof_buf) { cdk_kbnode_t ctx = NULL, p; cdk_packet_t pkt = NULL; cdk_pkt_userid_t uid = NULL; int pos = 0; size_t size = 0; int rc = 0; if (!key || !buf) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (idx < 0 || idx > _gnutls_openpgp_count_key_names (key)) { return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } if (!idx) pkt = cdk_kbnode_find_packet (key->knode, CDK_PKT_USER_ID); else { pos = 0; while ((p = cdk_kbnode_walk (key->knode, &ctx, 0))) { pkt = cdk_kbnode_get_packet (p); if (pkt->pkttype == CDK_PKT_USER_ID && ++pos == idx) break; } } if (!pkt) { rc = GNUTLS_E_INTERNAL_ERROR; goto leave; } uid = pkt->pkt.user_id; if (uid->len >= *sizeof_buf) { gnutls_assert (); *sizeof_buf = uid->len + 1; rc = GNUTLS_E_SHORT_MEMORY_BUFFER; goto leave; } size = uid->len < *sizeof_buf ? uid->len : *sizeof_buf - 1; memcpy (buf, uid->name, size); buf[size] = '\0'; /* make sure it's a string */ if (uid->is_revoked) { rc = GNUTLS_E_OPENPGP_UID_REVOKED; goto leave; } leave: return rc; }