static int ec_security_bits(const EVP_PKEY *pkey)
{
- int ecbits = ec_bits(pkey);
-
- if (ecbits >= 512)
- return 256;
- if (ecbits >= 384)
- return 192;
- if (ecbits >= 256)
- return 128;
- if (ecbits >= 224)
- return 112;
- if (ecbits >= 160)
- return 80;
- return ecbits / 2;
+ return EC_GROUP_security_bits(EC_KEY_get0_group(pkey->pkey.ec));
}
static int ec_missing_parameters(const EVP_PKEY *pkey)
return group->meth->group_order_bits(group);
}
+int EC_GROUP_security_bits(const EC_GROUP *group)
+{
+ int ecbits = group->meth->group_order_bits(group);
+
+ /*
+ * The following estimates are based on the values published in Table 2 of
+ * "NIST Special Publication 800-57 Part 1 Revision 4" at
+ * http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
+ *
+ * Note that the above reference explicitly categorizes algorithms in a
+ * discrete set of values {80, 112, 128, 192, 256}, and that it is relevant
+ * only for NIST approved Elliptic Curves, while OpenSSL applies the same
+ * logic also to other curves.
+ */
+ if (ecbits >= 512)
+ return 256;
+ if (ecbits >= 384)
+ return 192;
+ if (ecbits >= 256)
+ return 128;
+ if (ecbits >= 224)
+ return 112;
+ if (ecbits >= 160)
+ return 80;
+ return ecbits / 2;
+}
+
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
BN_CTX *ctx)
{
-
if (group->cofactor == NULL)
return 0;
if (!BN_copy(cofactor, group->cofactor))
return get_payload_int(state, translation, ctx, val);
}
+static int get_ec_field_degree(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+#ifndef OPENSSL_NO_EC
+ const EC_KEY *key;
+ const EC_GROUP *group;
+#endif
+ EVP_PKEY *pkey = ctx->p2;
+ int val = 0;
+
+ switch (EVP_PKEY_base_id(pkey)) {
+#ifndef OPENSSL_NO_EC
+ case EVP_PKEY_EC:
+ if ((key = EVP_PKEY_get0_EC_KEY(pkey)) == NULL
+ || (group = EC_KEY_get0_group(key)) == NULL) {
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
+ return 0;
+ }
+ val = EC_GROUP_get_degree(group);
+ break;
+#endif
+ default:
+ ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
+ return 0;
+ }
+
+ return get_payload_int(state, translation, ctx, val);
+}
+
static int get_rsa_payload_n(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
{ OSSL_ACTION_GET, -1, -1, -1, 0, NULL, NULL,
OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS, OSSL_PARAM_INTEGER,
get_ec_decoded_from_explicit_params },
+ { OSSL_ACTION_GET, -1, -1, -1, 0, NULL, NULL,
+ OSSL_PKEY_PARAM_EC_FIELD_DEGREE, OSSL_PARAM_INTEGER,
+ get_ec_field_degree },
};
static const struct translation_st *
* on fixup_args to do the whole work. Also, we currently only
* support getting.
*/
- if (!ossl_assert(translation != NULL)
+ if (translation == NULL
|| !ossl_assert(translation->action_type == OSSL_ACTION_GET)
|| !ossl_assert(translation->fixup_args != NULL)) {
return -2;
=head1 NAME
-EC_GROUP_get0_order, EC_GROUP_order_bits, EC_GROUP_get0_cofactor,
-EC_GROUP_copy, EC_GROUP_dup, EC_GROUP_method_of, EC_GROUP_set_generator,
-EC_GROUP_get0_generator, EC_GROUP_get_order, EC_GROUP_get_cofactor,
-EC_GROUP_set_curve_name, EC_GROUP_get_curve_name, EC_GROUP_set_asn1_flag,
-EC_GROUP_get_asn1_flag, EC_GROUP_set_point_conversion_form,
-EC_GROUP_get_point_conversion_form, EC_GROUP_get0_seed,
-EC_GROUP_get_seed_len, EC_GROUP_set_seed, EC_GROUP_get_degree,
-EC_GROUP_check, EC_GROUP_check_named_curve,
-EC_GROUP_check_discriminant, EC_GROUP_cmp,
-EC_GROUP_get_basis_type, EC_GROUP_get_trinomial_basis,
-EC_GROUP_get_pentanomial_basis, EC_GROUP_get0_field,
-EC_GROUP_get_field_type
+EC_GROUP_get0_order, EC_GROUP_order_bits, EC_GROUP_security_bits,
+EC_GROUP_get0_cofactor, EC_GROUP_copy, EC_GROUP_dup, EC_GROUP_method_of,
+EC_GROUP_set_generator, EC_GROUP_get0_generator, EC_GROUP_get_order,
+EC_GROUP_get_cofactor, EC_GROUP_set_curve_name, EC_GROUP_get_curve_name,
+EC_GROUP_set_asn1_flag, EC_GROUP_get_asn1_flag,
+EC_GROUP_set_point_conversion_form, EC_GROUP_get_point_conversion_form,
+EC_GROUP_get0_seed, EC_GROUP_get_seed_len, EC_GROUP_set_seed,
+EC_GROUP_get_degree, EC_GROUP_check, EC_GROUP_check_named_curve,
+EC_GROUP_check_discriminant, EC_GROUP_cmp, EC_GROUP_get_basis_type,
+EC_GROUP_get_trinomial_basis, EC_GROUP_get_pentanomial_basis,
+EC_GROUP_get0_field, EC_GROUP_get_field_type
- Functions for manipulating EC_GROUP objects
=head1 SYNOPSIS
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx);
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group);
int EC_GROUP_order_bits(const EC_GROUP *group);
+ int EC_GROUP_security_bits(const EC_GROUP *group);
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx);
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group);
const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group);
EC_GROUP_get0_order() returns an internal pointer to the group order.
EC_GROUP_order_bits() returns the number of bits in the group order.
+EC_GROUP_security_bits() returns the symmetric-equivalent security bit count of the group,
+rounding down to the standard sizes (80, 112, 128, 192, 256) when the value is at least 80.
EC_GROUP_get0_cofactor() returns an internal pointer to the group cofactor.
EC_GROUP_get0_field() returns an internal pointer to the group field. For curves over GF(p), this is the modulus; for curves
over GF(2^m), this is the irreducible polynomial defining the field.
EC_GROUP_get0_field(), EC_GROUP_check_named_curve() and EC_GROUP_get_field_type() were added in OpenSSL 3.0.
EC_GROUP_get0_order(), EC_GROUP_order_bits() and EC_GROUP_get0_cofactor() were added in OpenSSL 1.1.0.
+EC_GROUP_security_bits() was added in OpenSSL 4.0.
+
=head1 COPYRIGHT
Copyright 2013-2023 The OpenSSL Project Authors. All Rights Reserved.
=over 4
+=item "field-degree" (B<OSSL_PKEY_PARAM_EC_FIELD_DEGREE>) <integer>
+
+This is the bit length of the curve's field coefficients.
+It coincides with the B<OSSL_PKEY_PARAM_EC_CHAR2_M> parameter for binary
+fields, and is otherwise (for prime fields) equal to the bit length of the
+field's characteristic.
+For most curves (e.g. C<secp160r1>) this number is embedded in the curve's
+name.
+
=item "basis-type" (B<OSSL_PKEY_PARAM_EC_CHAR2_TYPE>) <UTF8 string>
Supports the values "tpBasis" for a trinomial or "ppBasis" for a pentanomial.
=item "key-check" (B<OSSL_PKEY_PARAM_FIPS_KEY_CHECK>) <integer>
-See L<provider-keymgmt(7)/Common Information Parameters> for further information.
+See L<provider-keymgmt(7)/Common Information Parameters> for descriptions
+of additional parameters generally available across all algorithms.
=back
L<EVP_SIGNATURE-ECDSA(7)>,
L<EVP_KEYEXCH-ECDH(7)>
+=head1 HISTORY
+
+The B<OSSL_PKEY_PARAM_EC_FIELD_DEGREE> parameter was added in OpenSSL 4.0.
+
=head1 COPYRIGHT
Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
*/
int EC_GROUP_order_bits(const EC_GROUP *group);
+/** Gets the symmetric-equivalent security bit size an EC_GROUP.
+ * This is rounded down to one of the standard sizes, (80, 112,
+ * 128, 192, 256) or reported as-is when smaller than 80.
+ * \param group EC_GROUP object
+ * \return symmetric-equivalent security bits.
+ */
+int EC_GROUP_security_bits(const EC_GROUP *group);
+
/** Gets the cofactor of a EC_GROUP
* \param group EC_GROUP object
* \param cofactor BIGNUM to which the cofactor is copied
}
if (type_label != NULL
- && BIO_printf(out, "%s: (%d bit)\n", type_label,
- EC_GROUP_order_bits(group))
+ && BIO_printf(out, "%s: (%d bit field, %d bit security level)\n",
+ type_label, EC_GROUP_get_degree(group),
+ EC_GROUP_security_bits(group))
<= 0)
goto err;
if (priv != NULL
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
goto err;
- if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
- int ecbits, sec_bits;
-
- ecbits = EC_GROUP_order_bits(ecg);
-
- /*
- * The following estimates are based on the values published
- * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
- * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
- *
- * Note that the above reference explicitly categorizes algorithms in a
- * discrete set of values {80, 112, 128, 192, 256}, and that it is
- * relevant only for NIST approved Elliptic Curves, while OpenSSL
- * applies the same logic also to other curves.
- *
- * Classifications produced by other standardazing bodies might differ,
- * so the results provided for "bits of security" by this provider are
- * to be considered merely indicative, and it is the users'
- * responsibility to compare these values against the normative
- * references that may be relevant for their intent and purposes.
- */
- if (ecbits >= 512)
- sec_bits = 256;
- else if (ecbits >= 384)
- sec_bits = 192;
- else if (ecbits >= 256)
- sec_bits = 128;
- else if (ecbits >= 224)
- sec_bits = 112;
- else if (ecbits >= 160)
- sec_bits = 80;
- else
- sec_bits = ecbits / 2;
-
- if (!OSSL_PARAM_set_int(p, sec_bits))
- goto err;
- }
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_EC_FIELD_DEGREE)) != NULL
+ && !OSSL_PARAM_set_int(p, EC_GROUP_get_degree(ecg)))
+ goto err;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
+ && !OSSL_PARAM_set_int(p, EC_GROUP_security_bits(ecg)))
+ goto err;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_CATEGORY)) != NULL)
if (!OSSL_PARAM_set_int(p, 0))
goto err;
static const OSSL_PARAM ec_known_gettable_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_FIELD_DEGREE, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_CATEGORY, NULL),
static const OSSL_PARAM sm2_known_gettable_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
+ OSSL_PARAM_int(OSSL_PKEY_PARAM_EC_FIELD_DEGREE, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, NULL, 0),
"3168947d59dcc912042351377ac5fb32"))
|| !TEST_BN_eq(y, z)
|| !TEST_int_eq(EC_GROUP_get_degree(group), 160)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), 80)
|| !group_order_tests(group)
/* Curve P-192 (FIPS PUB 186-2, App. 6) */
|| !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
ctx))
|| !TEST_int_eq(EC_GROUP_get_degree(group), 192)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), 80)
|| !group_order_tests(group)
/* Curve P-224 (FIPS PUB 186-2, App. 6) */
|| !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
ctx))
|| !TEST_int_eq(EC_GROUP_get_degree(group), 224)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), 112)
|| !group_order_tests(group)
/* Curve P-256 (FIPS PUB 186-2, App. 6) */
|| !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
ctx))
|| !TEST_int_eq(EC_GROUP_get_degree(group), 256)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), 128)
|| !group_order_tests(group)
/* Curve P-384 (FIPS PUB 186-2, App. 6) */
|| !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
ctx))
|| !TEST_int_eq(EC_GROUP_get_degree(group), 384)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), 192)
|| !group_order_tests(group)
/* Curve P-521 (FIPS PUB 186-2, App. 6) */
|| !TEST_false(EC_POINT_set_affine_coordinates(group, P, x, yplusone,
ctx))
|| !TEST_int_eq(EC_GROUP_get_degree(group), 521)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), 256)
|| !group_order_tests(group)
/* more tests using the last curve */
const char *order;
const char *cof;
int degree;
+ int security;
} char2_curve_tests[] = {
/* Curve K-163 (FIPS PUB 186-2, App. 6) */
{
"1",
"02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8",
"0289070FB05D38FF58321F2E800536D538CCDAA3D9",
- 1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163 },
+ 1, "04000000000000000000020108A2E0CC0D99F8A5EF", "2", 163, 80 },
/* Curve B-163 (FIPS PUB 186-2, App. 6) */
{
"NIST curve B-163",
"020A601907B8C953CA1481EB10512F78744A3205FD",
"03F0EBA16286A2D57EA0991168D4994637E8343E36",
"00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1",
- 1, "040000000000000000000292FE77E70C12A4234C33", "2", 163 },
+ 1, "040000000000000000000292FE77E70C12A4234C33", "2", 163, 80 },
/* Curve K-233 (FIPS PUB 186-2, App. 6) */
{
"NIST curve K-233",
"01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3",
0,
"008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF",
- "4", 233 },
+ "4", 233, 112 },
/* Curve B-233 (FIPS PUB 186-2, App. 6) */
{
"NIST curve B-233",
"01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052",
1,
"01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7",
- "2", 233 },
+ "2", 233, 112 },
/* Curve K-283 (FIPS PUB 186-2, App. 6) */
{
"NIST curve K-283",
0,
"01FFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61",
- "4", 283 },
+ "4", 283, 128 },
/* Curve B-283 (FIPS PUB 186-2, App. 6) */
{
"NIST curve B-283",
1,
"03FFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
- "2", 283 },
+ "2", 283, 128 },
/* Curve K-409 (FIPS PUB 186-2, App. 6) */
{
"NIST curve K-409",
1,
"007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
"FFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF",
- "4", 409 },
+ "4", 409, 192 },
/* Curve B-409 (FIPS PUB 186-2, App. 6) */
{
"NIST curve B-409",
1,
"0100000000000000000000000000000000000000"
"00000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173",
- "2", 409 },
+ "2", 409, 192 },
/* Curve K-571 (FIPS PUB 186-2, App. 6) */
{
"NIST curve K-571",
"0200000000000000"
"00000000000000000000000000000000000000000000000000000000131850E1"
"F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001",
- "4", 571 },
+ "4", 571, 256 },
/* Curve B-571 (FIPS PUB 186-2, App. 6) */
{
"NIST curve B-571",
"03FFFFFFFFFFFFFF"
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18"
"FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47",
- "2", 571 }
+ "2", 571, 256 }
};
static int char2_curve_test(int n)
#endif
if (!TEST_int_eq(EC_GROUP_get_degree(group), test->degree)
+ || !TEST_int_eq(EC_GROUP_security_bits(group), test->security)
|| !group_order_tests(group))
goto err;
struct nistp_test_params {
const int nid;
int degree;
+ int security;
/*
* Qx, Qy and D are taken from
* http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/ECDSA_Prime.pdf
/* P-224 */
NID_secp224r1,
224,
+ 112,
/* p */
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
/* a */
/* P-256 */
NID_X9_62_prime256v1,
256,
+ 128,
/* p */
"ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
/* a */
/* P-521 */
NID_secp521r1,
521,
+ 256,
/* p */
"1ff"
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|| !TEST_true(EC_POINT_set_affine_coordinates(NISTP, G, x, y, ctx))
|| !TEST_true(BN_hex2bn(&order, test->order))
|| !TEST_true(EC_GROUP_set_generator(NISTP, G, order, BN_value_one()))
- || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree))
+ || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree)
+ || !TEST_int_eq(EC_GROUP_security_bits(NISTP), test->security))
goto err;
TEST_note("NIST test vectors ... ");
goto err;
}
+ if (!TEST_true(EVP_PKEY_get_int_param(pkeyparam,
+ OSSL_PKEY_PARAM_EC_FIELD_DEGREE, &i_out))
+ || !TEST_int_eq(EC_GROUP_get_degree(group), i_out))
+ goto err;
+
if (EC_GROUP_get_field_type(group) == NID_X9_62_prime_field) {
/* No extra fields should be set for a prime field */
if (!TEST_false(EVP_PKEY_get_int_param(pkeyparam,
const unsigned char *pk_enc = pubkey_enc;
EVP_PKEY *gen_key = NULL, *decoded_key = NULL;
EVP_PKEY_CTX *pctx = NULL;
- int pklen, ret = 0;
+ int pklen, i_out = 0, ret = 0;
OSSL_PARAM params[2];
if (!TEST_ptr(gen_key = EVP_EC_gen("P-256")))
&pk_enc, pklen)))
goto err;
- if (!TEST_true(EVP_PKEY_eq(gen_key, decoded_key)))
+ if (!TEST_true(EVP_PKEY_eq(gen_key, decoded_key))
+ || !TEST_true(EVP_PKEY_get_int_param(gen_key,
+ OSSL_PKEY_PARAM_EC_FIELD_DEGREE, &i_out))
+ || !TEST_int_eq(i_out, 256)
+ || !TEST_true(EVP_PKEY_get_int_param(decoded_key,
+ OSSL_PKEY_PARAM_EC_FIELD_DEGREE, &i_out))
+ || !TEST_int_eq(i_out, 256))
goto err;
+
ret = 1;
err:
-Private-Key: (256 bit)
+Private-Key: (256 bit field, 128 bit security level)
priv:
33:d0:43:83:a9:89:56:03:d2:d7:fe:6b:01:6f:e4:59:
cc:0d:9a:24:6c:86:1b:2e:dc:4b:4d:35:43:e1:1b:ad
-Public-Key: (256 bit)
+Public-Key: (256 bit field, 128 bit security level)
pub:
04:1b:93:67:55:1c:55:9f:63:d1:22:a4:d8:d1:0a:60:
6d:02:a5:77:57:c8:a3:47:73:3a:6a:08:28:39:bd:c9:
EC_GROUP_get_order ? 4_0_0 EXIST::FUNCTION:EC
EC_GROUP_get0_order ? 4_0_0 EXIST::FUNCTION:EC
EC_GROUP_order_bits ? 4_0_0 EXIST::FUNCTION:EC
+EC_GROUP_security_bits ? 4_0_0 EXIST::FUNCTION:EC
EC_GROUP_get_cofactor ? 4_0_0 EXIST::FUNCTION:EC
EC_GROUP_get0_cofactor ? 4_0_0 EXIST::FUNCTION:EC
EC_GROUP_set_curve_name ? 4_0_0 EXIST::FUNCTION:EC
# Elliptic Curve Explicit Domain Parameters
'OSSL_PKEY_PARAM_EC_FIELD_TYPE' => "field-type",
+ 'OSSL_PKEY_PARAM_EC_FIELD_DEGREE' => "field-degree",
'OSSL_PKEY_PARAM_EC_P' => "p",
'OSSL_PKEY_PARAM_EC_A' => "a",
'OSSL_PKEY_PARAM_EC_B' => "b",