Blob PrivateKey::decrypt(const Blob& cipher) const { if (!key) throw CryptoException("Can't decrypt data without private key !"); unsigned key_len = 0; int err = gnutls_privkey_get_pk_algorithm(key, &key_len); if (err < 0) throw CryptoException("Can't read public key length !"); if (err != GNUTLS_PK_RSA) throw CryptoException("Must be an RSA key"); unsigned cypher_block_sz = key_len / 8; if (cipher.size() % cypher_block_sz) throw CryptoException("Unexpected cipher length"); Blob ret; for (auto cb = cipher.cbegin(), ce = cipher.cend(); cb < ce; cb += cypher_block_sz) { const gnutls_datum_t dat {(uint8_t*)(&(*cb)), cypher_block_sz}; gnutls_datum_t out; int err = gnutls_privkey_decrypt_data(key, 0, &dat, &out); if (err != GNUTLS_E_SUCCESS) throw DhtException(std::string("Can't decrypt data: ") + gnutls_strerror(err)); ret.insert(ret.end(), out.data, out.data+out.size); gnutls_free(out.data); } return ret; }
/* 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; }
static int dcrypt_gnutls_private_to_public_key(struct dcrypt_private_key *priv_key, struct dcrypt_public_key **pub_key_r, const char **error_r) { int ec; gnutls_privkey_t priv = (gnutls_privkey_t)priv_key; if (gnutls_privkey_get_pk_algorithm(priv, NULL) == GNUTLS_PK_RSA) { gnutls_datum_t m,e; /* do not extract anything we don't need */ ec = gnutls_privkey_export_rsa_raw(priv, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL); if (ec != GNUTLS_E_SUCCESS) return dcrypt_gnutls_error(ec, error_r); gnutls_pubkey_t pub; gnutls_pubkey_init(&pub); ec = gnutls_pubkey_import_rsa_raw(pub, &m, &e); gnutls_free(m.data); gnutls_free(e.data); if (ec < 0) { gnutls_pubkey_deinit(pub); return dcrypt_gnutls_error(ec, error_r); } *pub_key_r = (struct dcrypt_public_key*)pub; return 0; } else if (gnutls_privkey_get_pk_algorithm(priv, NULL) == GNUTLS_PK_EC) { gnutls_ecc_curve_t curve; gnutls_datum_t x,y,k; ec = gnutls_privkey_export_ecc_raw(priv, &curve, &x, &y, NULL); if (ec != GNUTLS_E_SUCCESS) return dcrypt_gnutls_error(ec, error_r); gnutls_pubkey_t pub; gnutls_pubkey_init(&pub); ec = gnutls_pubkey_import_ecc_raw(pub, curve, &x, &y); gnutls_free(x.data); gnutls_free(y.data); if (ec < 0) { gnutls_pubkey_deinit(pub); return dcrypt_gnutls_error(ec, error_r); } *pub_key_r = (struct dcrypt_public_key*)pub; return 0; } return -1; }
/** * gnutls_pubkey_import_privkey: * @key: The public key * @pkey: The private key * @usage: GNUTLS_KEY_* key usage flags. * @flags: should be zero * * Imports the public key from a private. This function will import * the given public key to the abstract #gnutls_pubkey_t type. * * Note that in certain keys this operation may not be possible, e.g., * in other than RSA PKCS#11 keys. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.12.0 **/ int gnutls_pubkey_import_privkey(gnutls_pubkey_t key, gnutls_privkey_t pkey, unsigned int usage, unsigned int flags) { gnutls_pk_params_release(&key->params); gnutls_pk_params_init(&key->params); key->pk_algorithm = gnutls_privkey_get_pk_algorithm(pkey, &key->bits); key->key_usage = usage; return _gnutls_privkey_get_public_mpis(pkey, &key->params); }
/* returns error if the certificate has different algorithm than * the given key parameters. */ int _gnutls_check_key_cert_match (gnutls_certificate_credentials_t res) { int pk = gnutls_pubkey_get_pk_algorithm(res->certs[res->ncerts-1].cert_list[0].pubkey, NULL); int pk2 = gnutls_privkey_get_pk_algorithm (res->pkey[res->ncerts - 1], NULL); if (pk2 != pk) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } return 0; }
/*- * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key * @src: should contain an ASN1_TYPE * @issuer: is the certificate of the certificate issuer * @issuer_key: holds the issuer's private key * * This function will sign a CRL or a certificate with the issuer's private key, and * will copy the issuer's information into the CRL or certificate. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ int _gnutls_x509_pkix_sign (ASN1_TYPE src, const char *src_name, gnutls_digest_algorithm_t dig, gnutls_x509_crt_t issuer, gnutls_privkey_t issuer_key) { int result; gnutls_datum_t signature; gnutls_datum_t tbs; char name[128]; /* Step 1. Copy the issuer's name into the certificate. */ _gnutls_str_cpy (name, sizeof (name), src_name); _gnutls_str_cat (name, sizeof (name), ".issuer"); result = asn1_copy_node (src, name, issuer->cert, "tbsCertificate.subject"); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Step 1.5. Write the signature stuff in the tbsCertificate. */ _gnutls_str_cpy (name, sizeof (name), src_name); _gnutls_str_cat (name, sizeof (name), ".signature"); result = _gnutls_x509_write_sig_params (src, name, gnutls_privkey_get_pk_algorithm (issuer_key, NULL), dig); if (result < 0) { gnutls_assert (); return result; } /* Step 2. Sign the certificate. */ result = _gnutls_x509_get_tbs (src, src_name, &tbs); if (result < 0) { gnutls_assert (); return result; } result = gnutls_privkey_sign_data (issuer_key, dig, 0, &tbs, &signature); gnutls_free (tbs.data); if (result < 0) { gnutls_assert (); return result; } /* write the signature (bits) */ result = asn1_write_value (src, "signature", signature.data, signature.size * 8); _gnutls_free_datum (&signature); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Step 3. Move up and write the AlgorithmIdentifier, which is also * the same. */ result = _gnutls_x509_write_sig_params (src, "signatureAlgorithm", gnutls_privkey_get_pk_algorithm (issuer_key, NULL), dig); if (result < 0) { gnutls_assert (); return result; } return 0; }
static int gen_rsa_export_server_kx (gnutls_session_t session, gnutls_buffer_st* data) { gnutls_rsa_params_t rsa_params; const bigint_t *rsa_mpis; int ret = 0; gnutls_pcert_st *apr_cert_list; gnutls_privkey_t apr_pkey; int apr_cert_list_length; gnutls_datum_t signature, ddata; gnutls_certificate_credentials_t cred; gnutls_sign_algorithm_t sign_algo; unsigned int bits = 0; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* find the appropriate certificate */ if ((ret = _gnutls_get_selected_cert (session, &apr_cert_list, &apr_cert_list_length, &apr_pkey)) < 0) { gnutls_assert (); return ret; } /* abort sending this message if we have a certificate * of 512 bits or less. */ gnutls_privkey_get_pk_algorithm (apr_pkey, &bits); if (apr_pkey && bits <= 512) { gnutls_assert (); return GNUTLS_E_INT_RET_0; } rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params); if (rsa_mpis == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, sizeof (cert_auth_info_st), 0)) < 0) { gnutls_assert (); return ret; } _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]); ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[0], 0); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[1], 0); if (ret < 0) return gnutls_assert_val(ret); /* Generate the signature. */ ddata.data = data->data; ddata.size = data->length; if (apr_cert_list_length > 0) { if ((ret = _gnutls_handshake_sign_data (session, &apr_cert_list[0], apr_pkey, &ddata, &signature, &sign_algo)) < 0) { gnutls_assert (); return ret; } } else { gnutls_assert (); return data->length; /* do not put a signature - ILLEGAL! */ } ret = _gnutls_buffer_append_data_prefix( data, 16, signature.data, signature.size); _gnutls_free_datum (&signature); if (ret < 0) return gnutls_assert_val(ret); return data->length; }
/* 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; }
/* Generates a signature of all the previous sent packets in the * handshake procedure. * 20040227: now it works for SSL 3.0 as well * 20091031: works for TLS 1.2 too! * * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success. * For TLS1.2 returns the signature algorithm used on success, or a negative error code; */ int _gnutls_handshake_sign_crt_vrfy(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_privkey_t pkey, gnutls_datum_t * signature) { gnutls_datum_t dconcat; int ret; uint8_t concat[MAX_SIG_SIZE]; digest_hd_st td_md5; digest_hd_st td_sha; const version_entry_st *ver = get_version(session); gnutls_pk_algorithm_t pk = gnutls_privkey_get_pk_algorithm(pkey, NULL); if (unlikely(ver == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); if (_gnutls_version_has_selectable_sighash(ver)) return _gnutls_handshake_sign_crt_vrfy12(session, cert, pkey, signature); ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1)); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td_sha, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer.length); if (ver->id == GNUTLS_SSL3) { ret = _gnutls_generate_master(session, 1); if (ret < 0) { gnutls_assert(); _gnutls_hash_deinit(&td_sha, NULL); return ret; } ret = _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16], session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); if (ret < 0) return gnutls_assert_val(ret); } else _gnutls_hash_deinit(&td_sha, &concat[16]); /* ensure 1024 bit DSA keys are used */ ret = _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver, GNUTLS_SIGN_UNKNOWN); if (ret < 0) return gnutls_assert_val(ret); switch (pk) { case GNUTLS_PK_RSA: ret = _gnutls_hash_init(&td_md5, hash_to_entry(GNUTLS_DIG_MD5)); if (ret < 0) return gnutls_assert_val(ret); _gnutls_hash(&td_md5, session->internals.handshake_hash_buffer.data, session->internals.handshake_hash_buffer. length); if (ver->id == GNUTLS_SSL3) { ret = _gnutls_mac_deinit_ssl3_handshake(&td_md5, concat, session->security_parameters. master_secret, GNUTLS_MASTER_SIZE); if (ret < 0) return gnutls_assert_val(ret); } else _gnutls_hash_deinit(&td_md5, concat); dconcat.data = concat; dconcat.size = 36; break; case GNUTLS_PK_DSA: case GNUTLS_PK_EC: dconcat.data = &concat[16]; dconcat.size = 20; break; default: return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); } ret = sign_tls_hash(session, NULL, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert(); } return ret; }
/* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ int _gnutls_handshake_sign_data(gnutls_session_t session, gnutls_pcert_st * cert, gnutls_privkey_t pkey, gnutls_datum_t * params, gnutls_datum_t * signature, gnutls_sign_algorithm_t * sign_algo) { gnutls_datum_t dconcat; int ret; digest_hd_st td_sha; uint8_t concat[MAX_SIG_SIZE]; const version_entry_st *ver = get_version(session); const mac_entry_st *hash_algo; *sign_algo = _gnutls_session_get_sign_algo(session, cert); if (*sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert(); return GNUTLS_E_UNKNOWN_PK_ALGORITHM; } gnutls_sign_algorithm_set_server(session, *sign_algo); hash_algo = hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo)); if (hash_algo == NULL) return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); _gnutls_handshake_log ("HSK[%p]: signing handshake data: using %s\n", session, gnutls_sign_algorithm_get_name(*sign_algo)); ret = _gnutls_hash_init(&td_sha, hash_algo); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td_sha, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_sha, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_sha, params->data, params->size); switch (gnutls_privkey_get_pk_algorithm(pkey, NULL)) { case GNUTLS_PK_RSA: if (!_gnutls_version_has_selectable_sighash(ver)) { digest_hd_st td_md5; ret = _gnutls_hash_init(&td_md5, hash_to_entry (GNUTLS_DIG_MD5)); if (ret < 0) { gnutls_assert(); return ret; } _gnutls_hash(&td_md5, session->security_parameters. client_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_md5, session->security_parameters. server_random, GNUTLS_RANDOM_SIZE); _gnutls_hash(&td_md5, params->data, params->size); _gnutls_hash_deinit(&td_md5, concat); _gnutls_hash_deinit(&td_sha, &concat[16]); dconcat.data = concat; dconcat.size = 36; } else { /* TLS 1.2 way */ _gnutls_hash_deinit(&td_sha, concat); dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(hash_algo); } break; case GNUTLS_PK_DSA: case GNUTLS_PK_EC: _gnutls_hash_deinit(&td_sha, concat); if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } dconcat.data = concat; dconcat.size = _gnutls_hash_get_algo_len(hash_algo); break; default: gnutls_assert(); _gnutls_hash_deinit(&td_sha, NULL); return GNUTLS_E_INTERNAL_ERROR; } ret = sign_tls_hash(session, hash_algo, cert, pkey, &dconcat, signature); if (ret < 0) { gnutls_assert(); } return ret; }