static int set_dh_pk_params(gnutls_session_t session, bigint_t g, bigint_t p, unsigned q_bits) { /* just in case we are resuming a session */ gnutls_pk_params_release(&session->key.proto.tls12.dh.params); gnutls_pk_params_init(&session->key.proto.tls12.dh.params); session->key.proto.tls12.dh.params.params[DH_G] = _gnutls_mpi_copy(g); if (session->key.proto.tls12.dh.params.params[DH_G] == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); session->key.proto.tls12.dh.params.params[DH_P] = _gnutls_mpi_copy(p); if (session->key.proto.tls12.dh.params.params[DH_P] == NULL) { _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]); return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); } session->key.proto.tls12.dh.params.params_nr = 3; /* include empty q */ session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH; session->key.proto.tls12.dh.params.qbits = q_bits; return 0; }
/** * gnutls_privkey_export_dsa_raw: * @key: Holds the public key * @p: will hold the p * @q: will hold the q * @g: will hold the g * @y: will hold the y * @x: will hold the x * * This function will export the DSA private key's parameters found * in the given structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. * * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. * * Since: 3.3.0 **/ int gnutls_privkey_export_dsa_raw(gnutls_privkey_t key, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * g, gnutls_datum_t * y, gnutls_datum_t * x) { gnutls_pk_params_st params; int ret; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(¶ms); ret = _gnutls_privkey_get_mpis(key, ¶ms); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_params_get_dsa_raw(¶ms, p, q, g, y, x); gnutls_pk_params_release(¶ms); return ret; }
/** * gnutls_privkey_export_ecc_raw: * @key: Holds the public key * @curve: will hold the curve * @x: will hold the x coordinate * @y: will hold the y coordinate * @k: will hold the private key * * This function will export the ECC private key's parameters found * in the given structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. * * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. * * Since: 3.3.0 **/ int gnutls_privkey_export_ecc_raw(gnutls_privkey_t key, gnutls_ecc_curve_t * curve, gnutls_datum_t * x, gnutls_datum_t * y, gnutls_datum_t * k) { gnutls_pk_params_st params; int ret; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(¶ms); ret = _gnutls_privkey_get_mpis(key, ¶ms); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_params_get_ecc_raw(¶ms, curve, x, y, k); gnutls_pk_params_release(¶ms); return ret; }
/** * gnutls_privkey_export_rsa_raw: * @key: Holds the certificate * @m: will hold the modulus * @e: will hold the public exponent * @d: will hold the private exponent * @p: will hold the first prime (p) * @q: will hold the second prime (q) * @u: will hold the coefficient * @e1: will hold e1 = d mod (p-1) * @e2: will hold e2 = d mod (q-1) * * This function will export the RSA private key's parameters found * in the given structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. * * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. * * Since: 3.3.0 **/ int gnutls_privkey_export_rsa_raw(gnutls_privkey_t key, gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u, gnutls_datum_t * e1, gnutls_datum_t * e2) { gnutls_pk_params_st params; int ret; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(¶ms); ret = _gnutls_privkey_get_mpis(key, ¶ms); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_params_get_rsa_raw(¶ms, m, e, d, p, q, u, e1, e2); gnutls_pk_params_release(¶ms); return ret; }
int _gnutls_dh_compute_key(gnutls_dh_params_t dh_params, const gnutls_datum_t *priv_key, const gnutls_datum_t *pub_key, const gnutls_datum_t *peer_key, gnutls_datum_t *Z) { gnutls_pk_params_st pub, priv; int ret; gnutls_pk_params_init(&pub); gnutls_pk_params_init(&priv); pub.algo = GNUTLS_PK_DH; if (_gnutls_mpi_init_scan_nz (&pub.params[DH_Y], peer_key->data, peer_key->size) != 0) { ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); goto cleanup; } priv.params[DH_P] = _gnutls_mpi_copy(dh_params->params[0]); priv.params[DH_G] = _gnutls_mpi_copy(dh_params->params[1]); if (_gnutls_mpi_init_scan_nz (&priv.params[DH_X], priv_key->data, priv_key->size) != 0) { ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); goto cleanup; } priv.params_nr = 3; /* include empty q */ priv.algo = GNUTLS_PK_DH; Z->data = NULL; ret = _gnutls_pk_derive(GNUTLS_PK_DH, Z, &priv, &pub); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: gnutls_pk_params_clear(&pub); gnutls_pk_params_clear(&priv); return ret; }
/** * gnutls_x509_privkey_generate: * @key: should contain a #gnutls_x509_privkey_t structure * @algo: is one of the algorithms in #gnutls_pk_algorithm_t. * @bits: the size of the modulus * @flags: unused for now. Must be 0. * * This function will generate a random private key. Note that this * function must be called on an empty private key. * * Note that when generating an elliptic curve key, the curve * can be substituted in the place of the bits parameter using the * GNUTLS_CURVE_TO_BITS() macro. * * For DSA keys, if the subgroup size needs to be specified check * the GNUTLS_SUBGROUP_TO_BITS() macro. * * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags) { int ret; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(&key->params); if (algo == GNUTLS_PK_EC) { if (GNUTLS_BITS_ARE_CURVE(bits)) bits = GNUTLS_BITS_TO_CURVE(bits); else bits = _gnutls_ecc_bits_to_curve(bits); } ret = _gnutls_pk_generate_params(algo, bits, &key->params); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_pk_generate_keys(algo, bits, &key->params); if (ret < 0) { gnutls_assert(); return ret; } #ifndef ENABLE_FIPS140 ret = _gnutls_pk_verify_priv_params(algo, &key->params); #else ret = pct_test(algo, &key->params); #endif if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_asn1_encode_privkey(algo, &key->key, &key->params); if (ret < 0) { gnutls_assert(); goto cleanup; } key->pk_algorithm = algo; return 0; cleanup: key->pk_algorithm = GNUTLS_PK_UNKNOWN; gnutls_pk_params_clear(&key->params); gnutls_pk_params_release(&key->params); return ret; }
int _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session, gnutls_buffer_st * data, gnutls_datum_t * pskkey) { int ret; gnutls_pk_params_st peer_pub; gnutls_datum_t tmp_dh_key = {NULL, 0}; gnutls_pk_params_init(&peer_pub); ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, &session->key.dh_params, 1); if (ret < 0) return gnutls_assert_val(ret); _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X])); ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0); if (ret < 0) { gnutls_assert(); goto error; } peer_pub.params[DH_Y] = session->key.client_Y; /* calculate the key after calculating the message */ ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_DHE_PSK) { session->key.key.data = tmp_dh_key.data; session->key.key.size = tmp_dh_key.size; } else { /* In DHE_PSK the key is set differently */ ret = _gnutls_set_psk_session_key(session, pskkey, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { gnutls_assert(); goto error; } ret = data->length; error: gnutls_pk_params_clear(&session->key.dh_params); return ret; }
/* If the psk flag is set, then an empty psk_identity_hint will * be inserted */ int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session, gnutls_buffer_st * data, gnutls_ecc_curve_t curve) { uint8_t p; int ret; gnutls_datum_t out; if (curve == GNUTLS_ECC_CURVE_INVALID) return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); /* just in case we are resuming a session */ gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_init(&session->key.ecdh_params); /* curve type */ p = 3; ret = _gnutls_buffer_append_data(data, &p, 1); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_prefix(data, 16, _gnutls_ecc_curve_get_tls_id (curve)); if (ret < 0) return gnutls_assert_val(ret); /* generate temporal key */ ret = _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, &session->key.ecdh_params); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_ecc_ansi_x963_export(curve, session->key.ecdh_params. params[ECC_X] /* x */ , session->key.ecdh_params. params[ECC_Y] /* y */ , &out); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size); _gnutls_free_datum(&out); if (ret < 0) return gnutls_assert_val(ret); return data->length; }
/* This function reads the RSA parameters from peer's certificate; */ int _gnutls_get_public_rsa_params(gnutls_session_t session, gnutls_pk_params_st * params) { int ret; cert_auth_info_t info; unsigned key_usage; gnutls_pcert_st peer_cert; /* normal non export case */ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL || info->ncerts == 0) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_get_auth_info_pcert(&peer_cert, session->security_parameters. cert_type, info); if (ret < 0) { gnutls_assert(); return ret; } gnutls_pubkey_get_key_usage(peer_cert.pubkey, &key_usage); ret = check_key_usage_for_enc(session, key_usage); if (ret < 0) { gnutls_assert(); goto cleanup2; } gnutls_pk_params_init(params); ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); goto cleanup2; } gnutls_pcert_deinit(&peer_cert); return 0; cleanup2: gnutls_pcert_deinit(&peer_cert); return ret; }
int _gnutls_ecdh_generate_key(gnutls_ecc_curve_t curve, gnutls_datum_t *x, gnutls_datum_t *y, gnutls_datum_t *k) { gnutls_pk_params_st params; int ret; gnutls_pk_params_init(¶ms); params.flags = curve; params.algo = GNUTLS_PK_EC; x->data = NULL; y->data = NULL; k->data = NULL; ret = _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, ¶ms); if (ret < 0) { return gnutls_assert_val(ret); } ret = _gnutls_mpi_dprint_lz(params.params[ECC_X], x); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_mpi_dprint_lz(params.params[ECC_Y], y); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_mpi_dprint_lz(params.params[ECC_K], k); if (ret < 0) { gnutls_assert(); goto fail; } ret = 0; goto cleanup; fail: gnutls_free(y->data); gnutls_free(x->data); gnutls_free(k->data); cleanup: gnutls_pk_params_clear(¶ms); return ret; }
/** * 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); }
static int calc_ecdh_key(gnutls_session_t session, gnutls_datum_t * psk_key, gnutls_ecc_curve_t curve) { gnutls_pk_params_st pub; int ret; gnutls_pk_params_init(&pub); pub.params[ECC_X] = session->key.ecdh_x; pub.params[ECC_Y] = session->key.ecdh_y; pub.flags = curve; if (psk_key == NULL) { ret = _gnutls_pk_derive(GNUTLS_PK_EC, &session->key.key, &session->key.ecdh_params, &pub); } else { gnutls_datum_t tmp_dh_key; ret = _gnutls_pk_derive(GNUTLS_PK_EC, &tmp_dh_key, &session->key.ecdh_params, &pub); if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } ret = _gnutls_set_psk_session_key(session, psk_key, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } ret = 0; cleanup: /* no longer needed */ _gnutls_mpi_release(&session->key.ecdh_x); _gnutls_mpi_release(&session->key.ecdh_y); gnutls_pk_params_release(&session->key.ecdh_params); return ret; }
/* Reads and returns the PK algorithm of the given certificate-like * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo". */ int _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, unsigned int *bits) { int result; int algo; char oid[64]; int len; gnutls_pk_params_st params; char name[128]; gnutls_pk_params_init(¶ms); _asnstr_append_name (name, sizeof (name), src_name, ".algorithm.algorithm"); len = sizeof (oid); result = asn1_read_value (src, name, oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } algo = _gnutls_x509_oid2pk_algorithm (oid); if (algo == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log ("%s: unknown public key algorithm: %s\n", __func__, oid); } if (bits == NULL) { return algo; } /* Now read the parameters' bits */ result = _gnutls_get_asn_mpis(src, src_name, ¶ms); if (result < 0) return gnutls_assert_val(result); bits[0] = pubkey_to_bits(algo, ¶ms); gnutls_pk_params_release(¶ms); return algo; }
int _gnutls_proc_ecdh_common_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { int i, ret, point_size; gnutls_ecc_curve_t curve; ssize_t data_size = _data_size; /* just in case we are resuming a session */ gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_init(&session->key.ecdh_params); i = 0; DECR_LEN(data_size, 1); if (data[i++] != 3) return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); DECR_LEN(data_size, 2); curve = _gnutls_tls_id_to_ecc_curve(_gnutls_read_uint16(&data[i])); i += 2; ret = _gnutls_session_supports_ecc_curve(session, curve); if (ret < 0) return gnutls_assert_val(ret); _gnutls_session_ecc_curve_set(session, curve); DECR_LEN(data_size, 1); point_size = data[i]; i++; DECR_LEN(data_size, point_size); ret = _gnutls_ecc_ansi_x963_import(&data[i], point_size, &session->key.ecdh_x, &session->key.ecdh_y); if (ret < 0) return gnutls_assert_val(ret); i += point_size; return i; }
int _gnutls_dh_generate_key(gnutls_dh_params_t dh_params, gnutls_datum_t *priv_key, gnutls_datum_t *pub_key) { gnutls_pk_params_st params; int ret; gnutls_pk_params_init(¶ms); params.params[DH_P] = _gnutls_mpi_copy(dh_params->params[0]); params.params[DH_G] = _gnutls_mpi_copy(dh_params->params[1]); params.params_nr = 3; /* include empty q */ params.algo = GNUTLS_PK_DH; priv_key->data = NULL; pub_key->data = NULL; ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, ¶ms); if (ret < 0) { return gnutls_assert_val(ret); } ret = _gnutls_mpi_dprint_lz(params.params[DH_X], priv_key); if (ret < 0) { gnutls_assert(); goto fail; } ret = _gnutls_mpi_dprint_lz(params.params[DH_Y], pub_key); if (ret < 0) { gnutls_assert(); goto fail; } ret = 0; goto cleanup; fail: gnutls_free(pub_key->data); gnutls_free(priv_key->data); cleanup: gnutls_pk_params_clear(¶ms); return ret; }
/** * gnutls_dh_params_generate2: * @dparams: The parameters * @bits: is the prime's number of bits * * This function will generate a new pair of prime and generator for use in * the Diffie-Hellman key exchange. This may take long time. * * It is recommended not to set the number of bits directly, but * use gnutls_sec_param_to_pk_bits() instead. * Also note that the DH parameters are only useful to servers. * Since clients use the parameters sent by the server, it's of * no use to call this in client side. * * The parameters generated are of the DSA form. It also is possible * to generate provable parameters (following the Shawe-Taylor * algorithm), using gnutls_x509_privkey_generate2() with DSA option * and the %GNUTLS_PRIVKEY_FLAG_PROVABLE flag set. These can the * be imported with gnutls_dh_params_import_dsa(). * * It is no longer recommended for applications to generate parameters. * See the "Parameter generation" section in the manual. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_dh_params_generate2(gnutls_dh_params_t dparams, unsigned int bits) { int ret; gnutls_pk_params_st params; gnutls_pk_params_init(¶ms); ret = _gnutls_pk_generate_params(GNUTLS_PK_DH, bits, ¶ms); if (ret < 0) return gnutls_assert_val(ret); dparams->params[0] = params.params[DSA_P]; dparams->params[1] = params.params[DSA_G]; dparams->q_bits = _gnutls_mpi_get_nbits(params.params[DSA_Q]); _gnutls_mpi_release(¶ms.params[DSA_Q]); return 0; }
/** * gnutls_x509_privkey_generate: * @key: should contain a #gnutls_x509_privkey_t structure * @algo: is one of the algorithms in #gnutls_pk_algorithm_t. * @bits: the size of the modulus * @flags: unused for now. Must be 0. * * This function will generate a random private key. Note that this * function must be called on an empty private key. * * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_generate (gnutls_x509_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits, unsigned int flags) { int ret; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(&key->params); if (algo == GNUTLS_PK_EC) bits = _gnutls_ecc_bits_to_curve(bits); ret = _gnutls_pk_generate (algo, bits, &key->params); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_asn1_encode_privkey (algo, &key->key, &key->params); if (ret < 0) { gnutls_assert (); goto cleanup; } key->pk_algorithm = algo; return 0; cleanup: key->pk_algorithm = GNUTLS_PK_UNKNOWN; gnutls_pk_params_release(&key->params); return ret; }
static int _decode_pkcs8_eddsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, const char *oid) { int ret; gnutls_datum_t tmp; gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID; const gnutls_ecc_curve_entry_st *ce; gnutls_pk_params_init(&pkey->params); curve = gnutls_oid_to_ecc_curve(oid); if (curve == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid); return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); } ce = _gnutls_ecc_curve_get_params(curve); if (_curve_is_eddsa(ce)) { ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &tmp, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); return gnutls_assert_val(ret); } if (tmp.size != ce->size) { gnutls_free(tmp.data); return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); } gnutls_free(pkey->params.raw_priv.data); pkey->params.algo = GNUTLS_PK_EDDSA_ED25519; pkey->params.raw_priv.data = tmp.data; pkey->params.raw_priv.size = tmp.size; pkey->params.curve = curve; tmp.data = NULL; return 0; } else { return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); } }
/** * gnutls_privkey_verify_params: * @key: should contain a #gnutls_privkey_t type * * This function will verify the private key parameters. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.3.0 **/ int gnutls_privkey_verify_params(gnutls_privkey_t key) { gnutls_pk_params_st params; int ret; gnutls_pk_params_init(¶ms); ret = _gnutls_privkey_get_mpis(key, ¶ms); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_pk_verify_priv_params(key->pk_algorithm, ¶ms); gnutls_pk_params_release(¶ms); if (ret < 0) { gnutls_assert(); return ret; } return 0; }
int _gnutls_privkey_get_public_mpis(gnutls_privkey_t key, gnutls_pk_params_st * params) { int ret; gnutls_pk_params_st tmp1; gnutls_pk_params_init(&tmp1); ret = _gnutls_privkey_get_mpis(key, &tmp1); if (ret < 0) return gnutls_assert_val(ret); ret = privkey_to_pubkey(key->pk_algorithm, &tmp1, params); gnutls_pk_params_release(&tmp1); if (ret < 0) gnutls_assert(); return ret; }
/** * gnutls_x509_privkey_import_rsa_raw2: * @key: The structure to store the parsed key * @m: holds the modulus * @e: holds the public exponent * @d: holds the private exponent * @p: holds the first prime (p) * @q: holds the second prime (q) * @u: holds the coefficient * @e1: holds e1 = d mod (p-1) * @e2: holds e2 = d mod (q-1) * * This function will convert the given RSA raw parameters to the * native #gnutls_x509_privkey_t format. The output will be stored in * @key. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_privkey_import_rsa_raw2 (gnutls_x509_privkey_t key, const gnutls_datum_t * m, const gnutls_datum_t * e, const gnutls_datum_t * d, const gnutls_datum_t * p, const gnutls_datum_t * q, const gnutls_datum_t * u, const gnutls_datum_t * e1, const gnutls_datum_t * e2) { int ret; size_t siz = 0; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } gnutls_pk_params_init(&key->params); siz = m->size; if (_gnutls_mpi_scan_nz (&key->params.params[0], m->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = e->size; if (_gnutls_mpi_scan_nz (&key->params.params[1], e->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = d->size; if (_gnutls_mpi_scan_nz (&key->params.params[2], d->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = p->size; if (_gnutls_mpi_scan_nz (&key->params.params[3], p->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = q->size; if (_gnutls_mpi_scan_nz (&key->params.params[4], q->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = u->size; if (_gnutls_mpi_scan_nz (&key->params.params[5], u->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; if (e1 && e2) { siz = e1->size; if (_gnutls_mpi_scan_nz (&key->params.params[6], e1->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; siz = e2->size; if (_gnutls_mpi_scan_nz (&key->params.params[7], e2->data, siz)) { gnutls_assert (); ret = GNUTLS_E_MPI_SCAN_FAILED; goto cleanup; } key->params.params_nr++; } ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &key->params); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_asn1_encode_privkey (GNUTLS_PK_RSA, &key->key, &key->params); if (ret < 0) { gnutls_assert (); goto cleanup; } key->params.params_nr = RSA_PRIVATE_PARAMS; key->pk_algorithm = GNUTLS_PK_RSA; return 0; cleanup: gnutls_pk_params_release(&key->params); return ret; }
/* Encodes the RSA parameters into an ASN.1 RSA private key structure. */ static int _gnutls_asn1_encode_rsa(ASN1_TYPE * c2, gnutls_pk_params_st * params) { int result, ret; uint8_t null = '\0'; gnutls_pk_params_st pk_params; /* we do copy the parameters into a new structure to run _gnutls_pk_fixup, * i.e., regenerate some parameters in case they were broken */ gnutls_pk_params_init(&pk_params); ret = _gnutls_pk_params_copy(&pk_params, params); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_pk_fixup(GNUTLS_PK_RSA, GNUTLS_EXPORT, &pk_params); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Ok. Now we have the data. Create the asn1 structures */ /* first make sure that no previously allocated data are leaked */ if (*c2 != ASN1_TYPE_EMPTY) { asn1_delete_structure(c2); *c2 = ASN1_TYPE_EMPTY; } if ((result = asn1_create_element (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPrivateKey", c2)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } /* Write PRIME */ ret = _gnutls_x509_write_int(*c2, "modulus", params->params[RSA_MODULUS], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_int(*c2, "publicExponent", params->params[RSA_PUB], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_key_int(*c2, "privateExponent", params->params[RSA_PRIV], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_key_int(*c2, "prime1", params->params[RSA_PRIME1], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_key_int(*c2, "prime2", params->params[RSA_PRIME2], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_key_int(*c2, "coefficient", params->params[RSA_COEF], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_key_int(*c2, "exponent1", params->params[RSA_E1], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_x509_write_key_int(*c2, "exponent2", params->params[RSA_E2], 1); if (ret < 0) { gnutls_assert(); goto cleanup; } if ((result = asn1_write_value(*c2, "otherPrimeInfos", NULL, 0)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } if ((result = asn1_write_value(*c2, "version", &null, 1)) != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(result); goto cleanup; } ret = 0; cleanup: if (ret < 0) asn1_delete_structure2(c2, ASN1_DELETE_FLAG_ZEROIZE); gnutls_pk_params_clear(&pk_params); gnutls_pk_params_release(&pk_params); return ret; }
/* Converts an ECC key to * an internal structure (gnutls_private_key) */ ASN1_TYPE _gnutls_privkey_decode_ecc_key (const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) { int ret; ASN1_TYPE pkey_asn; unsigned int version; char oid[MAX_OID_SIZE]; int oid_size; gnutls_datum out; gnutls_pk_params_init(&pkey->params); if ((ret = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.ECPrivateKey", &pkey_asn)) != ASN1_SUCCESS) { gnutls_assert (); return NULL; } ret = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert (); goto error; } ret = _gnutls_x509_read_uint (pkey_asn, "Version", &version); if (ret < 0) { gnutls_assert(); goto error; } if (version != 1) { _gnutls_debug_log("ECC private key version %u is not supported\n", version); gnutls_assert(); goto error; } /* read the curve */ oid_size = sizeof(oid); ret = asn1_read_value(pkey_asn, "parameters.namedCurve", oid, &oid_size); if (ret != ASN1_SUCCESS) { gnutls_assert (); goto error; } pkey->params.flags = _gnutls_oid_to_ecc_curve(oid); if (pkey->params.flags == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("Curve %s is not supported\n", oid); gnutls_assert(); goto error; } ret = _gnutls_ecc_curve_fill_params(pkey->params.flags, &pkey->params); if (ret < 0) { gnutls_assert(); goto error; } /* read the public key */ ret = _gnutls_x509_read_value(pkey_asn, "publicKey", &out, 2); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_ecc_ansi_x963_import (out.data, out.size, &pkey->params.params[ECC_X], &pkey->params.params[ECC_Y]); _gnutls_free_datum(&out); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr += 2; /* read the private key */ ret = _gnutls_x509_read_int (pkey_asn, "privateKey", &pkey->params.params[ECC_K]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr ++; return pkey_asn; error: asn1_delete_structure (&pkey_asn); gnutls_pk_params_release (&pkey->params); return NULL; }
/** * gnutls_x509_privkey_export_rsa_raw2: * @key: a structure that holds the rsa parameters * @m: will hold the modulus * @e: will hold the public exponent * @d: will hold the private exponent * @p: will hold the first prime (p) * @q: will hold the second prime (q) * @u: will hold the coefficient * @e1: will hold e1 = d mod (p-1) * @e2: will hold e2 = d mod (q-1) * * This function will export the RSA private key's parameters found * in the given structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.12.0 **/ int gnutls_x509_privkey_export_rsa_raw2 (gnutls_x509_privkey_t key, gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * u, gnutls_datum_t * e1, gnutls_datum_t * e2) { int ret; gnutls_pk_params_st pk_params; gnutls_pk_params_init(&pk_params); if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } m->data = e->data = d->data = p->data = q->data = u->data = NULL; m->size = e->size = d->size = p->size = q->size = u->size = 0; ret = _gnutls_pk_params_copy (&pk_params, &key->params); if (ret < 0) { gnutls_assert (); return ret; } ret = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_EXPORT, &pk_params); if (ret < 0) { gnutls_assert (); goto error; } ret = _gnutls_mpi_dprint_lz (pk_params.params[0], m); if (ret < 0) { gnutls_assert (); goto error; } /* E */ ret = _gnutls_mpi_dprint_lz (pk_params.params[1], e); if (ret < 0) { gnutls_assert (); goto error; } /* D */ ret = _gnutls_mpi_dprint_lz (pk_params.params[2], d); if (ret < 0) { gnutls_assert (); goto error; } /* P */ ret = _gnutls_mpi_dprint_lz (pk_params.params[3], p); if (ret < 0) { gnutls_assert (); goto error; } /* Q */ ret = _gnutls_mpi_dprint_lz (pk_params.params[4], q); if (ret < 0) { gnutls_assert (); goto error; } /* U */ ret = _gnutls_mpi_dprint_lz (key->params.params[5], u); if (ret < 0) { gnutls_assert (); goto error; } /* E1 */ if (e1) { ret = _gnutls_mpi_dprint_lz (key->params.params[6], e1); if (ret < 0) { gnutls_assert (); goto error; } } /* E2 */ if (e2) { ret = _gnutls_mpi_dprint_lz (key->params.params[7], e2); if (ret < 0) { gnutls_assert (); goto error; } } gnutls_pk_params_release (&pk_params); return 0; error: _gnutls_free_datum (m); _gnutls_free_datum (d); _gnutls_free_datum (e); _gnutls_free_datum (p); _gnutls_free_datum (q); gnutls_pk_params_release (&pk_params); return ret; }
/* Converts an RSA PKCS#1 key to * an internal structure (gnutls_private_key) */ ASN1_TYPE _gnutls_privkey_decode_pkcs1_rsa_key (const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey) { int result; ASN1_TYPE pkey_asn; gnutls_pk_params_init(&pkey->params); if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", &pkey_asn)) != ASN1_SUCCESS) { gnutls_assert (); return NULL; } result = asn1_der_decoding (&pkey_asn, raw_key->data, raw_key->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_int (pkey_asn, "modulus", &pkey->params.params[0])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "publicExponent", &pkey->params.params[1])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "privateExponent", &pkey->params.params[2])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "prime1", &pkey->params.params[3])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "prime2", &pkey->params.params[4])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "coefficient", &pkey->params.params[5])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "exponent1", &pkey->params.params[6])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; if ((result = _gnutls_x509_read_int (pkey_asn, "exponent2", &pkey->params.params[7])) < 0) { gnutls_assert (); goto error; } pkey->params.params_nr++; result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_IMPORT, &pkey->params); if (result < 0) { gnutls_assert (); goto error; } pkey->params.params_nr = RSA_PRIVATE_PARAMS; return pkey_asn; error: asn1_delete_structure (&pkey_asn); gnutls_pk_params_release (&pkey->params); return NULL; }
/* Returns the bytes parsed */ int _gnutls_proc_dh_common_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { uint16_t n_Y, n_g, n_p; size_t _n_Y, _n_g, _n_p; uint8_t *data_p; uint8_t *data_g; uint8_t *data_Y; int i, bits, ret, p_bits; ssize_t data_size = _data_size; /* just in case we are resuming a session */ gnutls_pk_params_release(&session->key.dh_params); gnutls_pk_params_init(&session->key.dh_params); i = 0; DECR_LEN(data_size, 2); n_p = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_p); data_p = &data[i]; i += n_p; DECR_LEN(data_size, 2); n_g = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_g); data_g = &data[i]; i += n_g; DECR_LEN(data_size, 2); n_Y = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_Y); data_Y = &data[i]; _n_Y = n_Y; _n_g = n_g; _n_p = n_p; if (_gnutls_mpi_init_scan_nz(&session->key.client_Y, data_Y, _n_Y) != 0) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } if (_gnutls_mpi_init_scan_nz(&session->key.dh_params.params[DH_G], data_g, _n_g) != 0) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } if (_gnutls_mpi_init_scan_nz(&session->key.dh_params.params[DH_P], data_p, _n_p) != 0) { gnutls_assert(); /* we release now because session->key.dh_params.params_nr is not yet set */ _gnutls_mpi_release(&session->key.dh_params.params[DH_G]); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } session->key.dh_params.params_nr = 3; /* include empty q */ session->key.dh_params.algo = GNUTLS_PK_DH; bits = _gnutls_dh_get_min_prime_bits(session); if (bits < 0) { gnutls_assert(); return bits; } p_bits = _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_P]); if (p_bits < bits) { /* the prime used by the peer is not acceptable */ gnutls_assert(); _gnutls_debug_log ("Received a prime of %u bits, limit is %u\n", (unsigned) _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_P]), (unsigned) bits); return GNUTLS_E_DH_PRIME_UNACCEPTABLE; } if (p_bits >= DEFAULT_MAX_VERIFY_BITS) { gnutls_assert(); _gnutls_debug_log ("Received a prime of %u bits, limit is %u\n", (unsigned) p_bits, (unsigned) DEFAULT_MAX_VERIFY_BITS); return GNUTLS_E_DH_PRIME_UNACCEPTABLE; } _gnutls_dh_set_group(session, session->key.dh_params.params[DH_G], session->key.dh_params.params[DH_P]); _gnutls_dh_set_peer_public(session, session->key.client_Y); ret = n_Y + n_p + n_g + 6; return ret; }
int _gnutls_proc_dh_common_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size, bigint_t g, bigint_t p, gnutls_datum_t * psk_key) { uint16_t n_Y; size_t _n_Y; int ret; ssize_t data_size = _data_size; gnutls_datum_t tmp_dh_key = {NULL, 0}; gnutls_pk_params_st peer_pub; gnutls_pk_params_init(&peer_pub); DECR_LEN(data_size, 2); n_Y = _gnutls_read_uint16(&data[0]); _n_Y = n_Y; DECR_LEN(data_size, n_Y); if (data_size != 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); if (_gnutls_mpi_init_scan_nz(&session->key.client_Y, &data[2], _n_Y)) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* most likely zero or illegal size */ } _gnutls_dh_set_peer_public(session, session->key.client_Y); peer_pub.params[DH_Y] = session->key.client_Y; /* calculate the key after calculating the message */ ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub); if (ret < 0) { gnutls_assert(); goto error; } if (psk_key == NULL) { session->key.key.data = tmp_dh_key.data; session->key.key.size = tmp_dh_key.size; } else { /* In DHE_PSK the key is set differently */ ret = _gnutls_set_psk_session_key(session, psk_key, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { gnutls_assert(); goto error; } ret = 0; error: _gnutls_mpi_release(&session->key.client_Y); gnutls_pk_params_clear(&session->key.dh_params); return ret; }
/* 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; }
/* Decodes a GOST privateKey from a PKCS8 structure. */ static int _decode_pkcs8_gost_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, gnutls_pk_algorithm_t algo) { int ret; gnutls_datum_t tmp; unsigned char oid[3 * MAX_OID_SIZE]; /* GOST parameters can have 3 OIDs at most */ int len, result; gnutls_pk_params_init(&pkey->params); len = sizeof(oid); result = asn1_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto error; } else { ret = _gnutls_x509_read_gost_params(oid, len, &pkey->params, algo); if (ret < 0) { gnutls_assert(); goto error; } } /* Will be fixed later by pk_fixup */ ret = _gnutls_mpi_init(&pkey->params.params[GOST_X]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr++; ret = _gnutls_mpi_init(&pkey->params.params[GOST_Y]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr++; _gnutls_mpi_set_ui(pkey->params.params[GOST_X], 0); _gnutls_mpi_set_ui(pkey->params.params[GOST_Y], 0); ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _privkey_decode_gost_key(&tmp, pkey); _gnutls_free_key_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.algo = algo; return 0; error: gnutls_pk_params_clear(&pkey->params); gnutls_pk_params_release(&pkey->params); return ret; }
/* Decodes an DSA privateKey and params from a PKCS8 structure. */ static int _decode_pkcs8_dsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey) { int ret; gnutls_datum_t tmp = {NULL, 0}; gnutls_pk_params_init(&pkey->params); ret = _gnutls_x509_read_value(pkcs8_asn, "privateKey", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_read_der_int(tmp.data, tmp.size, &pkey->params.params[4]); _gnutls_free_key_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_read_value(pkcs8_asn, "privateKeyAlgorithm.parameters", &tmp); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_x509_read_pubkey_params(GNUTLS_PK_DSA, tmp.data, tmp.size, &pkey->params); _gnutls_free_datum(&tmp); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_mpi_cmp_ui(pkey->params.params[0], 0) == 0) { gnutls_assert(); ret = GNUTLS_E_ILLEGAL_PARAMETER; goto error; } /* the public key can be generated as g^x mod p */ ret = _gnutls_mpi_init(&pkey->params.params[3]); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_mpi_powm(pkey->params.params[3], pkey->params.params[2], pkey->params.params[4], pkey->params.params[0]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.algo = GNUTLS_PK_DSA; pkey->params.params_nr = DSA_PRIVATE_PARAMS; ret = _gnutls_asn1_encode_privkey(&pkey->key, &pkey->params); if (ret < 0) { gnutls_assert(); goto error; } return 0; error: if (pkey->params.params_nr != DSA_PRIVATE_PARAMS) _gnutls_mpi_release(&pkey->params.params[4]); return ret; }