int _gnutls_proc_ecdh_common_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size, gnutls_ecc_curve_t curve, gnutls_datum_t * psk_key) { ssize_t data_size = _data_size; int ret, i = 0; int point_size; if (curve == GNUTLS_ECC_CURVE_INVALID) return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); DECR_LEN(data_size, 1); point_size = data[i]; i += 1; 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); /* generate pre-shared key */ ret = calc_ecdh_key(session, psk_key, curve); if (ret < 0) return gnutls_assert_val(ret); return 0; }
/* * some x509 certificate parsing functions that relate to MPI parameter * extraction. This reads the BIT STRING subjectPublicKey. * Returns 2 parameters (m,e). It does not set params_nr. */ int _gnutls_x509_read_ecc_pubkey (opaque * der, int dersize, gnutls_pk_params_st * params) { /* Eventhough RFC5480 defines the public key to be an ECPoint (i.e. OCTET STRING), * it is actually copied in raw there. Why do they use ASN.1 anyway? */ return _gnutls_ecc_ansi_x963_import (der, dersize, ¶ms->params[ECC_X], ¶ms->params[ECC_Y]); }
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; }
/* 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; }
/* Converts an ECC key to * an internal structure (gnutls_private_key) */ int _gnutls_privkey_decode_ecc_key(ASN1_TYPE* pkey_asn, const gnutls_datum_t * raw_key, gnutls_x509_privkey_t pkey, gnutls_ecc_curve_t curve) { int ret; unsigned int version; char oid[MAX_OID_SIZE]; int oid_size; gnutls_datum out; gnutls_pk_params_init(&pkey->params); pkey->params.algo = GNUTLS_PK_EC; if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(), "GNUTLS.ECPrivateKey", pkey_asn)) != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(ret); } ret = asn1_der_decoding(pkey_asn, raw_key->data, raw_key->size, NULL); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); 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(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto error; } /* read the curve */ if (curve == GNUTLS_ECC_CURVE_INVALID) { oid_size = sizeof(oid); ret = asn1_read_value(*pkey_asn, "parameters.namedCurve", oid, &oid_size); if (ret != ASN1_SUCCESS) { gnutls_assert(); ret = _gnutls_asn2err(ret); 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(); ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE; goto error; } } else { pkey->params.flags = curve; } /* read the public key */ ret = _gnutls_x509_read_value(*pkey_asn, "publicKey", &out); 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_key_int(*pkey_asn, "privateKey", &pkey->params.params[ECC_K]); if (ret < 0) { gnutls_assert(); goto error; } pkey->params.params_nr++; return 0; error: asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE); gnutls_pk_params_clear(&pkey->params); gnutls_pk_params_release(&pkey->params); return ret; }