Add some EVP APIs for low-level EC point and scalar formats

I haven't yet done ECPrivateKey. That one is a bit hairy since it is two
formats in one.

Bug: 42290408
Change-Id: Ie579392f5df34c221f79879fa468b930a692e196
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/98730
Reviewed-by: Lily Chen <chlily@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
This commit is contained in:
David Benjamin
2026-07-10 00:13:17 -04:00
committed by boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 6fb1c4b18d
commit b08e6f859a
6 changed files with 290 additions and 10 deletions
+16 -5
View File
@@ -112,9 +112,7 @@ struct AlgorithmInfo {
};
const std::map<std::string, AlgorithmInfo> kAllAlgorithms = {
{"RSA",
{EVP_pkey_rsa(),
/*kem=*/nullptr, EVP_PKEY_RSA, true}},
{"RSA", {EVP_pkey_rsa(), /*kem=*/nullptr, EVP_PKEY_RSA, true}},
{"RSA-PSS-SHA-256",
{EVP_pkey_rsa_pss_sha256(), /*kem=*/nullptr, EVP_PKEY_RSA_PSS, false}},
@@ -307,7 +305,8 @@ bool ImportWithAlgCommon(FileTest *t, KeySet *key_set, KeyRole key_role,
EVP_PKEY *(*parse_func)(const EVP_PKEY_ALG *,
const uint8_t *, size_t)) {
SCOPED_TRACE(attr);
if (!t->HasAttribute(attr)) {
if (!t->HasAttribute(attr) ||
t->HasAttribute("SkipImport" + std::string(attr))) {
return true; // Nothing to import.
}
std::vector<uint8_t> input;
@@ -521,6 +520,12 @@ bool ImportKey(FileTest *t, KeyMap *key_map) {
alg_info, &EVP_PKEY_from_raw_private_key) ||
!ImportWithAlgCommon(t, &key_set, KeyRole::kPrivate, "PrivateSeed",
alg_info, &EVP_PKEY_from_private_seed) ||
!ImportWithAlgCommon(t, &key_set, KeyRole::kPublic, "ECUncompressedPoint",
alg_info, &EVP_PKEY_from_ec_uncompressed_point) ||
!ImportWithAlgCommon(t, &key_set, KeyRole::kPublic, "ECCompressedPoint",
alg_info, &EVP_PKEY_from_ec_compressed_point) ||
!ImportWithAlgCommon(t, &key_set, KeyRole::kPrivate, "ECPrivateScalar",
alg_info, &EVP_PKEY_from_ec_private_scalar) ||
!ImportRSAPublicParams(t, &key_set, alg_info) ||
!ImportRSAPrivateParams(t, &key_set, alg_info)) {
return false;
@@ -605,7 +610,13 @@ bool ImportKey(FileTest *t, KeyMap *key_map) {
!CheckRawKey(t, "RawPublic", KeyRoleSelect::kAny, key,
EVP_PKEY_get_raw_public_key) ||
!CheckRawKey(t, "PrivateSeed", KeyRoleSelect::kPrivate, key,
EVP_PKEY_get_private_seed)) {
EVP_PKEY_get_private_seed) ||
!CheckMarshalCBB(t, "ECUncompressedPoint", KeyRoleSelect::kAny, key,
EVP_PKEY_marshal_ec_uncompressed_point) ||
!CheckMarshalCBB(t, "ECCompressedPoint", KeyRoleSelect::kAny, key,
EVP_PKEY_marshal_ec_compressed_point) ||
!CheckMarshalCBB(t, "ECPrivateScalar", KeyRoleSelect::kPrivate, key,
EVP_PKEY_marshal_ec_private_scalar)) {
return false;
}
}
+121
View File
@@ -575,6 +575,127 @@ EC_KEY *EVP_PKEY_get1_EC_KEY(const EVP_PKEY *pkey) {
return ec_key;
}
static const EC_GROUP *alg_to_group(const EVP_PKEY_ALG *alg) {
if (alg->method->pkey_id != EVP_PKEY_EC) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return nullptr;
}
auto *alg_ec = static_cast<const EVP_PKEY_ALG_EC *>(alg);
if (alg_ec->ec_group == nullptr) {
OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
return nullptr;
}
return alg_ec->ec_group();
}
static EVP_PKEY *pkey_from_ec_point(const EC_GROUP *group, const uint8_t *in,
size_t len) {
UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
UniquePtr<EC_KEY> ec_key(EC_KEY_new());
if (pkey == nullptr || ec_key == nullptr ||
!EC_KEY_set_group(ec_key.get(), group) ||
!EC_KEY_oct2key(ec_key.get(), in, len, nullptr)) {
return nullptr;
}
EVP_PKEY_assign_EC_KEY(pkey.get(), ec_key.release());
return pkey.release();
}
EVP_PKEY *EVP_PKEY_from_ec_uncompressed_point(
const EVP_PKEY_ALG *alg, const uint8_t *in, size_t len) {
const EC_GROUP *group = alg_to_group(alg);
if (group == nullptr) {
return nullptr;
}
// The `EC_KEY` APIs are not separated by uncompressed and compressed.
if (len == 0 || in[0] != 0x04) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return nullptr;
}
return pkey_from_ec_point(group, in, len);
}
EVP_PKEY *EVP_PKEY_from_ec_compressed_point(const EVP_PKEY_ALG *alg,
const uint8_t *in, size_t len) {
const EC_GROUP *group = alg_to_group(alg);
if (group == nullptr) {
return nullptr;
}
// The `EC_KEY` APIs are not separated by uncompressed and compressed.
if (len == 0 || in[0] == 0x04) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
return nullptr;
}
return pkey_from_ec_point(group, in, len);
}
static int marshal_ec_point(CBB *cbb, const EVP_PKEY *key,
point_conversion_form_t form) {
const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(key);
if (ec_key == nullptr) {
return 0;
}
const EC_GROUP *group = EC_KEY_get0_group(ec_key);
const EC_POINT *pub = EC_KEY_get0_public_key(ec_key);
if (group == nullptr || pub == nullptr) {
OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PUBLIC_KEY);
return 0;
}
return EC_POINT_point2cbb(cbb, group, pub, form, nullptr);
}
int EVP_PKEY_marshal_ec_uncompressed_point(CBB *cbb, const EVP_PKEY *key) {
return marshal_ec_point(cbb, key, POINT_CONVERSION_UNCOMPRESSED);
}
int EVP_PKEY_marshal_ec_compressed_point(CBB *cbb, const EVP_PKEY *key) {
return marshal_ec_point(cbb, key, POINT_CONVERSION_COMPRESSED);
}
EVP_PKEY *EVP_PKEY_from_ec_private_scalar(const EVP_PKEY_ALG *alg,
const uint8_t *in, size_t len) {
const EC_GROUP *group = alg_to_group(alg);
if (group == nullptr) {
return nullptr;
}
UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
UniquePtr<EC_KEY> ec_key(EC_KEY_new());
if (pkey == nullptr || ec_key == nullptr ||
!EC_KEY_set_group(ec_key.get(), group) ||
!EC_KEY_oct2priv(ec_key.get(), in, len)) {
return nullptr;
}
// TODO(crbug.com/42290404): `EC_KEY_oct2priv` should fill in the public key
// internally.
UniquePtr<EC_POINT> pub(EC_POINT_new(group));
if (pub == nullptr ||
!EC_POINT_mul(group, pub.get(), EC_KEY_get0_private_key(ec_key.get()),
nullptr, nullptr, nullptr) ||
!EC_KEY_set_public_key(ec_key.get(), pub.get())) {
return 0;
}
EVP_PKEY_assign_EC_KEY(pkey.get(), ec_key.release());
return pkey.release();
}
int EVP_PKEY_marshal_ec_private_scalar(CBB *cbb, const EVP_PKEY *key) {
const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(key);
if (ec_key == nullptr) {
return 0;
}
size_t len = EC_KEY_priv2oct(ec_key, nullptr, 0);
if (len == 0) {
return 0;
}
uint8_t *out;
if (!CBB_reserve(cbb, &out, len)) {
return 0;
}
len = EC_KEY_priv2oct(ec_key, out, len);
return len != 0 && CBB_did_write(cbb, len);
}
int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey) {
const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
if (ec_key == nullptr) {
+94 -5
View File
@@ -5,6 +5,9 @@ Key = P-256
Algorithm = EC-P-256
Bits = 256
ECCurve = prime256v1
ECUncompressedPoint = 042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
ECCompressedPoint = 032c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b3
ECPrivateScalar = 8a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
PKCS8 = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
SPKI = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
# The same key as above with redundant parameters.
@@ -15,17 +18,22 @@ PKCS8NonCanonical = 308201610201003081ec06072a8648ce3d02013081e0020101302c06072a
PKCS8NonCanonical = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
# The same key as above with the optional public key omitted.
#
# TODO(crbug.com/503025567): Currently, we remember whether the public key was
# omitted and roundtrip it back out, so this is a seprate key set. Pick a
# canonical one instead?
Key = P-256-MissingPublic
Algorithm = EC-P-256
Bits = 256
ECCurve = prime256v1
ECUncompressedPoint = 042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
ECCompressedPoint = 032c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b3
ECPrivateScalar = 8a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
PKCS8 = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
# Even with the public key omitted, we compute the public key.
SPKI = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
# TODO(crbug.com/503025567): Currently, we remember whether the public key was
# omitted and roundtrip it back out, so this is a seprate key set. Pick a
# canonical one instead? Remembering it also means that importing
# ECPrivateScalar produces a slightly different object from importing PKCS8. To
# avoid breaking the cross-format tests, skip importing ECPrivateScalar.
SkipImportECPrivateScalar
# The same key, but with the redundant parameters in the ECPrivateKey mismatched.
Key = P-256-BadInnerParameters
@@ -68,6 +76,9 @@ PKCS8NonCanonical = 308201540201003081eb06072a8648ce3d02013081df020101302806072a
Algorithm = EC-P-224
Bits = 224
ECCurve = secp224r1
ECUncompressedPoint = 041a95d8c8d08635ad7fa0facd3a9fe56f8f42451b58ea8a29f7d28b0fb214690b1149a69f016f644cdb3320b78a381027835d6091903f0513
ECCompressedPoint = 031a95d8c8d08635ad7fa0facd3a9fe56f8f42451b58ea8a29f7d28b0f
ECPrivateScalar = aa17cf0a0c8064bf6b509c212e48293d61e0d97acc85f8dea5c99166
PKCS8 = 3078020100301006072a8648ce3d020106052b810400210461305f020101041caa17cf0a0c8064bf6b509c212e48293d61e0d97acc85f8dea5c99166a13c033a00041a95d8c8d08635ad7fa0facd3a9fe56f8f42451b58ea8a29f7d28b0fb214690b1149a69f016f644cdb3320b78a381027835d6091903f0513
SPKI = 304e301006072a8648ce3d020106052b81040021033a00041a95d8c8d08635ad7fa0facd3a9fe56f8f42451b58ea8a29f7d28b0fb214690b1149a69f016f644cdb3320b78a381027835d6091903f0513
@@ -77,6 +88,9 @@ PKCS8NonCanonical = 3082020c0201003082016406072a8648ce3d020130820157020101303c06
Algorithm = EC-P-384
Bits = 384
ECCurve = secp384r1
ECUncompressedPoint = 04826b3df548ad2e0b96436cb13508e88745a33b4b06cf485ad8350824b4dfe01ee66a5e1d1aaebfebcaa6337a1f33c338afc0d59b7ce7e389f73f66c9c4a44bbfcf570aec5cc52e7b6608c9061ab4d72de933448c39dd9238177917d398c22c5e
ECCompressedPoint = 02826b3df548ad2e0b96436cb13508e88745a33b4b06cf485ad8350824b4dfe01ee66a5e1d1aaebfebcaa6337a1f33c338
ECPrivateScalar = a29991b86091401328e62ec8caadd0482f887ff0936910e42a56c19f48cbe87331037a4e2b36f1091dd4a26ee2d2b01f
PKCS8 = 3081b6020100301006072a8648ce3d020106052b8104002204819e30819b0201010430a29991b86091401328e62ec8caadd0482f887ff0936910e42a56c19f48cbe87331037a4e2b36f1091dd4a26ee2d2b01fa16403620004826b3df548ad2e0b96436cb13508e88745a33b4b06cf485ad8350824b4dfe01ee66a5e1d1aaebfebcaa6337a1f33c338afc0d59b7ce7e389f73f66c9c4a44bbfcf570aec5cc52e7b6608c9061ab4d72de933448c39dd9238177917d398c22c5e
SPKI = 3076301006072a8648ce3d020106052b8104002203620004826b3df548ad2e0b96436cb13508e88745a33b4b06cf485ad8350824b4dfe01ee66a5e1d1aaebfebcaa6337a1f33c338afc0d59b7ce7e389f73f66c9c4a44bbfcf570aec5cc52e7b6608c9061ab4d72de933448c39dd9238177917d398c22c5e
@@ -86,9 +100,79 @@ PKCS8NonCanonical = 308202b0020100308201d006072a8648ce3d0201308201c3020101304d06
Algorithm = EC-P-521
Bits = 521
ECCurve = secp521r1
ECUncompressedPoint = 0400f58adcbe5c07f6b500fadd3209487e38f9567f97c2204435a4eb140739905c201407e2530a6667216aad01fb849bcbefa3862b2f187f13c9a87923d378a0a184df017b4bb93f4766531785878458da6aaa525724e10dfb1f35cfbe55c56fc705714295ea74b6c3e714152ad78e929f5415683aed9bc7c68f0329934177829d715f03f2
ECCompressedPoint = 0200f58adcbe5c07f6b500fadd3209487e38f9567f97c2204435a4eb140739905c201407e2530a6667216aad01fb849bcbefa3862b2f187f13c9a87923d378a0a184df
ECPrivateScalar = 002eeee9c16b9b4d2dee606f443cf3b41d2899a4734ff7555b54c735afb34a6912f81c68a89ea9b427c69a1026d98ef1d7f9c683aec5c5103d9a4c21e403c638412f
PKCS8 = 3081ee020100301006072a8648ce3d020106052b810400230481d63081d30201010442002eeee9c16b9b4d2dee606f443cf3b41d2899a4734ff7555b54c735afb34a6912f81c68a89ea9b427c69a1026d98ef1d7f9c683aec5c5103d9a4c21e403c638412fa18189038186000400f58adcbe5c07f6b500fadd3209487e38f9567f97c2204435a4eb140739905c201407e2530a6667216aad01fb849bcbefa3862b2f187f13c9a87923d378a0a184df017b4bb93f4766531785878458da6aaa525724e10dfb1f35cfbe55c56fc705714295ea74b6c3e714152ad78e929f5415683aed9bc7c68f0329934177829d715f03f2
SPKI = 30819b301006072a8648ce3d020106052b81040023038186000400f58adcbe5c07f6b500fadd3209487e38f9567f97c2204435a4eb140739905c201407e2530a6667216aad01fb849bcbefa3862b2f187f13c9a87923d378a0a184df017b4bb93f4766531785878458da6aaa525724e10dfb1f35cfbe55c56fc705714295ea74b6c3e714152ad78e929f5415683aed9bc7c68f0329934177829d715f03f2
# Compressed and uncompressed forms swapped
Key = P-256-WrongForm-1
Algorithm = EC-P-256
ECUncompressedPoint = 032c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b3
Error = DECODE_ERROR
Key = P-256-WrongForm-2
Algorithm = EC-P-256
ECCompressedPoint = 042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
Error = DECODE_ERROR
# Wrong length
Key = P-256-Scalar-Too-Short
Algorithm = EC-P-256
ECPrivateScalar = 8a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb57287
Error = DECODE_ERROR
Key = P-256-Scalar-Too-Long
Algorithm = EC-P-256
ECPrivateScalar = 008a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
Error = DECODE_ERROR
# Scalar not reduced.
Key = P-256-Scalar-NotReduced-1
Algorithm = EC-P-256
ECPrivateScalar = ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551
Error = INVALID_SCALAR
Key = P-256-Scalar-NotReduced-2
Algorithm = EC-P-256
ECPrivateScalar = ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552
Error = INVALID_SCALAR
# Truncated points
Key = P-256-Truncated-Uncompressed
Algorithm = EC-P-256
ECUncompressedPoint = 042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9f
Error = INVALID_ENCODING
Key = P-256-Truncated-Compressed
Algorithm = EC-P-256
ECCompressedPoint = 032c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78
Error = INVALID_ENCODING
# First byte is wrong
Key = P-256-Bad-First-Byte-Uncompressed
Algorithm = EC-P-256
ECUncompressedPoint = 052c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
Error = DECODE_ERROR
Key = P-256-Bad-First-Byte-Compressed
Algorithm = EC-P-256
ECCompressedPoint = 052c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b3
Error = INVALID_ENCODING
# Uncompressed point not on the curve
Key = P-256-Not-On-Curve
Algorithm = EC-P-256
ECUncompressedPoint = 042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c8
Error = POINT_IS_NOT_ON_CURVE
# Compressed point has no square root
Key = P-256-No-Square-Root-2
Algorithm = EC-P-256
ECCompressedPoint = 03ffffffff00000001000000000000000000000000fffffffffffffffffffffffe
Error = INVALID_COMPRESSED_POINT
# ECDSA tests
@@ -152,13 +236,18 @@ Key = ECDH-P256-Ours
Algorithm = EC-P-256
Bits = 256
ECCurve = prime256v1
PKCS8 = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104207d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534
ECUncompressedPoint = 04ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141
ECCompressedPoint = 03ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230
ECPrivateScalar = 7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534
PKCS8 = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104207d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534a14403420004ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141
SPKI = 3059301306072a8648ce3d020106082a8648ce3d03010703420004ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b23028af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141
Key = ECDH-P256-Peer
Algorithm = EC-P-256
Bits = 256
ECCurve = prime256v1
ECUncompressedPoint = 04700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac
ECCompressedPoint = 02700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287
SPKI = 3059301306072a8648ce3d020106082a8648ce3d03010703420004700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac
Derive = ECDH-P256-Ours/Private
+44
View File
@@ -1119,6 +1119,50 @@ OPENSSL_EXPORT int EVP_PKEY_CTX_get0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
// EC specific control functions.
// The following functions decode `len` bytes from `in` as an EC public key in
// compressed or uncompressed X9.62 format, respectively. The EC curve is
// determined by `alg`, which must be an EC algorithm (i.e. one of
// `EVP_pkey_ec_*`).
//
// The functions return a newly-allocated `EVP_PKEY` on success or NULL on
// error.
//
// To support both uncompressed and compressed forms, call
// `EVP_PKEY_from_ec_uncompressed_point` when the input begins with 0x04 and
// `EVP_PKEY_from_ec_compressed_point` otherwise. Uncompressed form is more
// common.
OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_ec_uncompressed_point(
const EVP_PKEY_ALG *alg, const uint8_t *in, size_t len);
OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_ec_compressed_point(
const EVP_PKEY_ALG *alg, const uint8_t *in, size_t len);
// The following functions marshal `key`'s EC public key in compressed or
// uncompressed X9.62 format, respectively, and write the result to `cbb`. They
// return one on success and zero on error. It is an error if `key` is not an EC
// key.
OPENSSL_EXPORT int EVP_PKEY_marshal_ec_uncompressed_point(CBB *cbb,
const EVP_PKEY *key);
OPENSSL_EXPORT int EVP_PKEY_marshal_ec_compressed_point(CBB *cbb,
const EVP_PKEY *key);
// EVP_PKEY_from_ec_private_scalar decodes `len` bytes from `in` as an EC
// private key, encoded as a big-endian, zero-padded integer. The EC curve is
// determined by `alg`, which must be an EC algorithm (i.e. one of
// `EVP_pkey_ec_*`). The input must be fully reduced and padded to the size of
// the group order (e.g. 32 bytes for P-256) or the import will fail.
//
// This function returns a newly-allocated `EVP_PKEY` on success or NULL on
// error.
OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_from_ec_private_scalar(
const EVP_PKEY_ALG *alg, const uint8_t *in, size_t len);
// EVP_PKEY_marshal_ec_private_scalar marshals `key`'s private key as a
// big-endian, zero-padded integer EC scalar and writes the result to `cbb`. It
// returns one on success or zero on error. It is an error if `key` is not an EC
// key.
OPENSSL_EXPORT int EVP_PKEY_marshal_ec_private_scalar(CBB *cbb,
const EVP_PKEY *key);
// EVP_PKEY_get_ec_curve_nid returns `pkey`'s curve as a NID constant, such as
// `NID_X9_62_prime256v1`, or `NID_undef` if `pkey` is not an EC key.
OPENSSL_EXPORT int EVP_PKEY_get_ec_curve_nid(const EVP_PKEY *pkey);
+12
View File
@@ -1168,6 +1168,9 @@
#pragma redefine_extname EVP_PKEY_encrypt_init BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_encrypt_init)
#pragma redefine_extname EVP_PKEY_eq BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_eq)
#pragma redefine_extname EVP_PKEY_free BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_free)
#pragma redefine_extname EVP_PKEY_from_ec_compressed_point BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_from_ec_compressed_point)
#pragma redefine_extname EVP_PKEY_from_ec_private_scalar BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_from_ec_private_scalar)
#pragma redefine_extname EVP_PKEY_from_ec_uncompressed_point BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_from_ec_uncompressed_point)
#pragma redefine_extname EVP_PKEY_from_private_key_info BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_from_private_key_info)
#pragma redefine_extname EVP_PKEY_from_private_seed BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_from_private_seed)
#pragma redefine_extname EVP_PKEY_from_raw_private_key BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_from_raw_private_key)
@@ -1195,6 +1198,9 @@
#pragma redefine_extname EVP_PKEY_is_opaque BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_is_opaque)
#pragma redefine_extname EVP_PKEY_keygen BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_keygen)
#pragma redefine_extname EVP_PKEY_keygen_init BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_keygen_init)
#pragma redefine_extname EVP_PKEY_marshal_ec_compressed_point BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_marshal_ec_compressed_point)
#pragma redefine_extname EVP_PKEY_marshal_ec_private_scalar BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_marshal_ec_private_scalar)
#pragma redefine_extname EVP_PKEY_marshal_ec_uncompressed_point BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_marshal_ec_uncompressed_point)
#pragma redefine_extname EVP_PKEY_missing_parameters BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_missing_parameters)
#pragma redefine_extname EVP_PKEY_new BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_new)
#pragma redefine_extname EVP_PKEY_new_raw_private_key BORINGSSL_ADD_USER_LABEL_AND_PREFIX(EVP_PKEY_new_raw_private_key)
@@ -4291,6 +4297,9 @@
#define EVP_PKEY_encrypt_init BORINGSSL_ADD_PREFIX(EVP_PKEY_encrypt_init)
#define EVP_PKEY_eq BORINGSSL_ADD_PREFIX(EVP_PKEY_eq)
#define EVP_PKEY_free BORINGSSL_ADD_PREFIX(EVP_PKEY_free)
#define EVP_PKEY_from_ec_compressed_point BORINGSSL_ADD_PREFIX(EVP_PKEY_from_ec_compressed_point)
#define EVP_PKEY_from_ec_private_scalar BORINGSSL_ADD_PREFIX(EVP_PKEY_from_ec_private_scalar)
#define EVP_PKEY_from_ec_uncompressed_point BORINGSSL_ADD_PREFIX(EVP_PKEY_from_ec_uncompressed_point)
#define EVP_PKEY_from_private_key_info BORINGSSL_ADD_PREFIX(EVP_PKEY_from_private_key_info)
#define EVP_PKEY_from_private_seed BORINGSSL_ADD_PREFIX(EVP_PKEY_from_private_seed)
#define EVP_PKEY_from_raw_private_key BORINGSSL_ADD_PREFIX(EVP_PKEY_from_raw_private_key)
@@ -4318,6 +4327,9 @@
#define EVP_PKEY_is_opaque BORINGSSL_ADD_PREFIX(EVP_PKEY_is_opaque)
#define EVP_PKEY_keygen BORINGSSL_ADD_PREFIX(EVP_PKEY_keygen)
#define EVP_PKEY_keygen_init BORINGSSL_ADD_PREFIX(EVP_PKEY_keygen_init)
#define EVP_PKEY_marshal_ec_compressed_point BORINGSSL_ADD_PREFIX(EVP_PKEY_marshal_ec_compressed_point)
#define EVP_PKEY_marshal_ec_private_scalar BORINGSSL_ADD_PREFIX(EVP_PKEY_marshal_ec_private_scalar)
#define EVP_PKEY_marshal_ec_uncompressed_point BORINGSSL_ADD_PREFIX(EVP_PKEY_marshal_ec_uncompressed_point)
#define EVP_PKEY_missing_parameters BORINGSSL_ADD_PREFIX(EVP_PKEY_missing_parameters)
#define EVP_PKEY_new BORINGSSL_ADD_PREFIX(EVP_PKEY_new)
#define EVP_PKEY_new_raw_private_key BORINGSSL_ADD_PREFIX(EVP_PKEY_new_raw_private_key)
+3
View File
@@ -357,6 +357,9 @@ impl Key {
// BoringSSL allows an `EC_KEY` to have a private scalar without a
// public point, but `Key` is never exposed in that state.
//
// TODO(crbug.com/42290404): `EC_KEY_oct2priv` should fill in the public
// key.
// Safety: `key.0` is valid by construction. The returned value is
// still owned the `EC_KEY`.