/** * gnutls_openpgp_privkey_get_subkey_idx: * @key: the structure that contains the OpenPGP private key. * @keyid: the keyid. * * Get index of subkey. * * Returns: the index of the subkey or a negative error value. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_subkey_idx(gnutls_openpgp_privkey_t key, const gnutls_openpgp_keyid_t keyid) { int ret; uint32_t kid[2]; uint8_t master_id[GNUTLS_OPENPGP_KEYID_SIZE]; if (!key) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = gnutls_openpgp_privkey_get_key_id(key, master_id); if (ret < 0) return gnutls_assert_val(ret); if (memcmp(master_id, keyid, GNUTLS_OPENPGP_KEYID_SIZE) == 0) return GNUTLS_OPENPGP_MASTER_KEYID_IDX; KEYID_IMPORT(kid, keyid); ret = _gnutls_openpgp_find_subkey_idx(key->knode, kid, 1); if (ret < 0) { gnutls_assert(); } return ret; }
/** * gnutls_openpgp_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. * * Deprecated: Use gnutls_privkey_sign_hash() instead. */ int gnutls_openpgp_privkey_sign_hash (gnutls_openpgp_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { int result, i; bigint_t params[MAX_PRIV_PARAMS_SIZE]; int params_size = MAX_PRIV_PARAMS_SIZE; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); if (result == 0) { uint32_t kid[2]; int idx; KEYID_IMPORT (kid, keyid); idx = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, idx, NULL); result = _gnutls_openpgp_privkey_get_mpis (key, kid, params, ¶ms_size); } else { pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL); result = _gnutls_openpgp_privkey_get_mpis (key, NULL, params, ¶ms_size); } if (result < 0) { gnutls_assert (); return result; } result = _gnutls_soft_sign (pk_algorithm, params, params_size, hash, signature); for (i = 0; i < params_size; i++) _gnutls_mpi_release (¶ms[i]); if (result < 0) { gnutls_assert (); return result; } return 0; }
/*- * _gnutls_openpgp_privkey_decrypt_data: * @key: Holds the key * @flags: (0) for now * @ciphertext: holds the data to be decrypted * @plaintext: will contain newly allocated plaintext * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ int _gnutls_openpgp_privkey_decrypt_data (gnutls_openpgp_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext) { int result, i; gnutls_pk_params_st params; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; char buf[2*GNUTLS_OPENPGP_KEYID_SIZE+1]; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); if (result == 0) { uint32_t kid[2]; KEYID_IMPORT (kid, keyid); _gnutls_hard_log("Decrypting using PGP key ID %s\n", _gnutls_bin2hex(keyid, GNUTLS_OPENPGP_KEYID_SIZE, buf, sizeof(buf), NULL)); result = _gnutls_openpgp_privkey_get_mpis (key, kid, ¶ms); i = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL); } else { _gnutls_hard_log("Decrypting using master PGP key\n"); pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL); result = _gnutls_openpgp_privkey_get_mpis (key, NULL, ¶ms); } if (result < 0) { gnutls_assert (); return result; } result = _gnutls_pk_decrypt (pk_algorithm, plaintext, ciphertext, ¶ms); gnutls_pk_params_clear(¶ms); gnutls_pk_params_release(¶ms); if (result < 0) return gnutls_assert_val(result); return 0; }
/* Returns the public key of the private key (if possible) */ int _gnutls_privkey_get_public_mpis(gnutls_privkey_t key, gnutls_pk_params_st * params) { int ret; gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(key, NULL); switch (key->type) { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: { gnutls_pk_params_st tmp_params; uint32_t kid[2]; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; ret = gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp, keyid); if (ret == 0) { KEYID_IMPORT(kid, keyid); ret = _gnutls_openpgp_privkey_get_mpis(key-> key. openpgp, kid, &tmp_params); } else ret = _gnutls_openpgp_privkey_get_mpis(key-> key. openpgp, NULL, &tmp_params); if (ret < 0) { gnutls_assert(); return ret; } ret = privkey_to_pubkey(pk, &tmp_params, params); gnutls_pk_params_release(&tmp_params); } break; #endif case GNUTLS_PRIVKEY_X509: ret = privkey_to_pubkey(pk, &key->key.x509->params, params); break; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } return ret; }
/* Returns the public key of the private key (if possible) */ int _gnutls_privkey_get_mpis(gnutls_privkey_t key, gnutls_pk_params_st * params) { int ret; switch (key->type) { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: { uint32_t kid[2]; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; ret = gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp, keyid); if (ret == 0) { KEYID_IMPORT(kid, keyid); ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid, params); } else ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL, params); if (ret < 0) { gnutls_assert(); return ret; } } break; #endif case GNUTLS_PRIVKEY_X509: ret = _gnutls_pk_params_copy(params, &key->key.x509->params); break; #ifdef ENABLE_PKCS11 case GNUTLS_PRIVKEY_PKCS11: { gnutls_pubkey_t pubkey; ret = _pkcs11_privkey_get_pubkey(key->key.pkcs11, &pubkey, 0); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_pubkey_get_mpis(pubkey, params); gnutls_pubkey_deinit(pubkey); break; } #endif default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } return ret; }
/** * gnutls_openpgp_privkey_get_subkey_idx: * @key: the structure that contains the OpenPGP private key. * @keyid: the keyid. * * Get index of subkey. * * Returns: the index of the subkey or a negative error value. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_subkey_idx (gnutls_openpgp_privkey_t key, const gnutls_openpgp_keyid_t keyid) { int ret; uint32_t kid[2]; if (!key) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } KEYID_IMPORT (kid, keyid); ret = _gnutls_openpgp_find_subkey_idx (key->knode, kid, 1); if (ret < 0) { gnutls_assert (); } return ret; }
static int _get_sk_dsa_raw(gnutls_openpgp_privkey_t pkey, gnutls_openpgp_keyid_t keyid, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * g, gnutls_datum_t * y, gnutls_datum_t * x) { int pk_algorithm, ret; cdk_packet_t pkt; uint32_t kid32[2]; gnutls_pk_params_st params; if (pkey == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } KEYID_IMPORT(kid32, keyid); pkt = _gnutls_openpgp_find_key(pkey->knode, kid32, 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); if (pk_algorithm != GNUTLS_PK_DSA) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_openpgp_privkey_get_mpis(pkey, kid32, ¶ms); if (ret < 0) { gnutls_assert(); return ret; } /* P */ ret = _gnutls_mpi_dprint(params.params[0], p); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Q */ ret = _gnutls_mpi_dprint(params.params[1], q); if (ret < 0) { gnutls_assert(); _gnutls_free_datum(p); goto cleanup; } /* G */ ret = _gnutls_mpi_dprint(params.params[2], g); if (ret < 0) { gnutls_assert(); _gnutls_free_datum(p); _gnutls_free_datum(q); goto cleanup; } /* Y */ ret = _gnutls_mpi_dprint(params.params[3], y); if (ret < 0) { gnutls_assert(); _gnutls_free_datum(p); _gnutls_free_datum(g); _gnutls_free_datum(q); goto cleanup; } ret = _gnutls_mpi_dprint(params.params[4], x); if (ret < 0) { gnutls_assert(); _gnutls_free_datum(y); _gnutls_free_datum(p); _gnutls_free_datum(g); _gnutls_free_datum(q); goto cleanup; } ret = 0; cleanup: gnutls_pk_params_clear(¶ms); gnutls_pk_params_release(¶ms); return ret; }
/** * gnutls_openpgp_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Deprecated: Use gnutls_privkey_sign_hash() instead. */ int gnutls_openpgp_privkey_sign_hash(gnutls_openpgp_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { int result; gnutls_pk_params_st params; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; char buf[2 * GNUTLS_OPENPGP_KEYID_SIZE + 1]; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid); if (result == 0) { uint32_t kid[2]; int idx; KEYID_IMPORT(kid, keyid); _gnutls_hard_log("Signing using PGP key ID %s\n", _gnutls_bin2hex(keyid, GNUTLS_OPENPGP_KEYID_SIZE, buf, sizeof(buf), NULL)); idx = gnutls_openpgp_privkey_get_subkey_idx(key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm(key, idx, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, kid, ¶ms); } else { _gnutls_hard_log("Signing using master PGP key\n"); pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, NULL, ¶ms); } if (result < 0) { gnutls_assert(); return result; } result = _gnutls_pk_sign(pk_algorithm, signature, hash, ¶ms); gnutls_pk_params_clear(¶ms); gnutls_pk_params_release(¶ms); if (result < 0) { gnutls_assert(); return result; } return 0; }
/* The internal version of export */ static int _get_sk_rsa_raw (gnutls_openpgp_privkey_t pkey, gnutls_openpgp_keyid_t keyid, gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u) { int pk_algorithm, ret, i; cdk_packet_t pkt; uint32_t kid32[2]; bigint_t params[MAX_PRIV_PARAMS_SIZE]; int params_size = MAX_PRIV_PARAMS_SIZE; if (pkey == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } KEYID_IMPORT (kid32, keyid); pkt = _gnutls_openpgp_find_key (pkey->knode, kid32, 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); if (pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_openpgp_privkey_get_mpis (pkey, kid32, params, ¶ms_size); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_mpi_dprint (params[0], m); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_mpi_dprint (params[1], e); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (m); goto cleanup; } ret = _gnutls_mpi_dprint (params[2], d); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (m); _gnutls_free_datum (e); goto cleanup; } ret = _gnutls_mpi_dprint (params[3], p); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (m); _gnutls_free_datum (e); _gnutls_free_datum (d); goto cleanup; } ret = _gnutls_mpi_dprint (params[4], q); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (m); _gnutls_free_datum (e); _gnutls_free_datum (d); _gnutls_free_datum (p); goto cleanup; } ret = _gnutls_mpi_dprint (params[5], u); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (q); _gnutls_free_datum (m); _gnutls_free_datum (e); _gnutls_free_datum (d); _gnutls_free_datum (p); goto cleanup; } ret = 0; cleanup: for (i = 0; i < params_size; i++) { _gnutls_mpi_release (¶ms[i]); } return ret; }
/* Returns the public key of the private key (if possible) */ int _gnutls_privkey_get_public_mpis (gnutls_privkey_t key, bigint_t * params, int *params_size) { int ret; gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm (key, NULL); switch (key->type) { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: { bigint_t tmp_params[MAX_PRIV_PARAMS_SIZE]; int tmp_params_size = MAX_PRIV_PARAMS_SIZE; uint32_t kid[2], i; gnutls_openpgp_keyid_t keyid; ret = gnutls_openpgp_privkey_get_preferred_key_id (key->key.openpgp, keyid); if (ret == 0) { KEYID_IMPORT (kid, keyid); ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, kid, tmp_params, &tmp_params_size); } else ret = _gnutls_openpgp_privkey_get_mpis (key->key.openpgp, NULL, tmp_params, &tmp_params_size); if (ret < 0) { gnutls_assert (); return ret; } ret = privkey_to_pubkey (pk, tmp_params, tmp_params_size, params, params_size); for (i = 0; i < tmp_params_size; i++) _gnutls_mpi_release (&tmp_params[i]); } break; #endif case GNUTLS_PRIVKEY_X509: ret = privkey_to_pubkey (pk, key->key.x509->params, key->key.x509->params_size, params, params_size); break; default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } return ret; }
/*- * _gnutls_openpgp_privkey_decrypt_data: * @key: Holds the key * @flags: zero for now * @ciphertext: holds the data to be decrypted * @plaintext: will contain newly allocated plaintext * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. -*/ int _gnutls_openpgp_privkey_decrypt_data (gnutls_openpgp_privkey_t key, unsigned int flags, const gnutls_datum_t * ciphertext, gnutls_datum_t * plaintext) { int result, i; bigint_t params[MAX_PRIV_PARAMS_SIZE]; int params_size = MAX_PRIV_PARAMS_SIZE; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id (key, keyid); if (result == 0) { uint32_t kid[2]; KEYID_IMPORT (kid, keyid); result = _gnutls_openpgp_privkey_get_mpis (key, kid, params, ¶ms_size); i = gnutls_openpgp_privkey_get_subkey_idx (key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (key, i, NULL); } else { pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (key, NULL); result = _gnutls_openpgp_privkey_get_mpis (key, NULL, params, ¶ms_size); } if (result < 0) { gnutls_assert (); return result; } if (pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = _gnutls_pkcs1_rsa_decrypt (plaintext, ciphertext, params, params_size, 2); for (i = 0; i < params_size; i++) _gnutls_mpi_release (¶ms[i]); if (result < 0) { gnutls_assert (); return result; } return 0; }
/* Converts a parsed gnutls_openpgp_crt_t to a gnutls_cert structure. */ int _gnutls_openpgp_crt_to_gcert (gnutls_cert * gcert, gnutls_openpgp_crt_t cert) { int ret; gnutls_openpgp_keyid_t keyid; char err_buf[33]; memset (gcert, 0, sizeof (gnutls_cert)); gcert->cert_type = GNUTLS_CRT_OPENPGP; gcert->version = gnutls_openpgp_crt_get_version (cert); gcert->params_size = MAX_PUBLIC_PARAMS_SIZE; ret = gnutls_openpgp_crt_get_preferred_key_id (cert, keyid); if (ret == 0) { int idx; uint32_t kid32[2]; _gnutls_debug_log ("Importing Openpgp cert and using openpgp sub key: %s\n", _gnutls_bin2hex (keyid, sizeof (keyid), err_buf, sizeof (err_buf))); KEYID_IMPORT (kid32, keyid); idx = gnutls_openpgp_crt_get_subkey_idx (cert, keyid); if (idx < 0) { gnutls_assert (); return idx; } gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_subkey_pk_algorithm (cert, idx, NULL); gnutls_openpgp_crt_get_subkey_usage (cert, idx, &gcert->key_usage); gcert->use_subkey = 1; memcpy (gcert->subkey_id, keyid, sizeof (keyid)); ret = _gnutls_openpgp_crt_get_mpis (cert, kid32, gcert->params, &gcert->params_size); } else { _gnutls_debug_log ("Importing Openpgp cert and using main openpgp key\n"); gcert->subject_pk_algorithm = gnutls_openpgp_crt_get_pk_algorithm (cert, NULL); gnutls_openpgp_crt_get_key_usage (cert, &gcert->key_usage); ret = _gnutls_openpgp_crt_get_mpis (cert, NULL, gcert->params, &gcert->params_size); gcert->use_subkey = 0; } if (ret < 0) { gnutls_assert (); return ret; } { /* copy the raw certificate */ #define SMALL_RAW 512 opaque *raw; size_t raw_size = SMALL_RAW; /* initially allocate a bogus size, just in case the certificate * fits in it. That way we minimize the DER encodings performed. */ raw = gnutls_malloc (raw_size); if (raw == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert (); gnutls_free (raw); return ret; } if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { raw = gnutls_realloc (raw, raw_size); if (raw == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = gnutls_openpgp_crt_export (cert, GNUTLS_OPENPGP_FMT_RAW, raw, &raw_size); if (ret < 0) { gnutls_assert (); gnutls_free (raw); return ret; } } gcert->raw.data = raw; gcert->raw.size = raw_size; } return 0; }
/* Copies a gnutls_openpgp_privkey_t to a gnutls_privkey structure. */ int _gnutls_openpgp_privkey_to_gkey (gnutls_privkey * dest, gnutls_openpgp_privkey_t src) { int ret = 0; gnutls_openpgp_keyid_t keyid; char err_buf[33]; if (dest == NULL || src == NULL) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_ERROR; } dest->params_size = MAX_PRIV_PARAMS_SIZE; ret = gnutls_openpgp_privkey_get_preferred_key_id (src, keyid); if (ret == 0) { int idx; uint32_t kid32[2]; _gnutls_debug_log ("Importing Openpgp key and using openpgp sub key: %s\n", _gnutls_bin2hex (keyid, sizeof (keyid), err_buf, sizeof (err_buf))); KEYID_IMPORT (kid32, keyid); idx = gnutls_openpgp_privkey_get_subkey_idx (src, keyid); if (idx < 0) { gnutls_assert (); return idx; } dest->pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm (src, idx, NULL); ret = _gnutls_openpgp_privkey_get_mpis (src, kid32, dest->params, &dest->params_size); } else { _gnutls_debug_log ("Importing Openpgp key and using main openpgp key.\n"); dest->pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm (src, NULL); ret = _gnutls_openpgp_privkey_get_mpis (src, NULL, dest->params, &dest->params_size); } if (ret < 0) { gnutls_assert (); return ret; } return 0; }