Skip to content

Commit 0a1741a

Browse files
committed
Rewrite generateP256Key for compatibility with openSSL 3.0
1 parent a1b4db4 commit 0a1741a

File tree

1 file changed

+59
-32
lines changed

1 file changed

+59
-32
lines changed

model/controller/dual_mode_controller.cc

Lines changed: 59 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
#include "model/controller/dual_mode_controller.h"
1818

1919
#include <openssl/ec.h>
20-
#include <openssl/ec_key.h>
21-
#include <openssl/mem.h>
22-
#include <openssl/nid.h>
20+
#include <openssl/obj_mac.h>
21+
#include <openssl/bn.h>
22+
#include <openssl/err.h>
23+
#include <openssl/evp.h>
2324
#include <packet_runtime.h>
2425

2526
#include <algorithm>
@@ -2242,40 +2243,66 @@ void DualModeController::LeWriteSuggestedDefaultDataLength(CommandView command)
22422243

22432244
static ErrorCode generateP256Key(std::array<uint8_t, 32>& key_x_coordinate,
22442245
std::array<uint8_t, 32>& key_y_coordinate) {
2245-
auto ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
2246-
if (!ec_key) {
2247-
WARNING("EC_KEY_new_by_curve_name(NID_X9_62_prime256v1) failed");
2248-
return ErrorCode::UNSPECIFIED_ERROR;
2249-
}
2246+
// Clear any previous OpenSSL errors.
2247+
ERR_clear_error();
2248+
2249+
// Use unique_ptr with custom deleters for automatic memory management
2250+
// This ensures resources are freed even if an early return occurs due
2251+
// to an error.
2252+
auto ec_key_deleter = [](EC_KEY* ptr) { EC_KEY_free(ptr); };
2253+
std::unique_ptr<EC_KEY, decltype(ec_key_deleter)> ec_key(
2254+
EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), ec_key_deleter);
2255+
2256+
if (!ec_key) {
2257+
WARNING("Failed to create EC_KEY for prime256v1 curve.");
2258+
return ErrorCode::UNSPECIFIED_ERROR;
2259+
}
22502260

2251-
if (!EC_KEY_generate_key(ec_key)) {
2252-
WARNING("EC_KEY_generate_key failed");
2253-
EC_KEY_free(ec_key);
2254-
return ErrorCode::UNSPECIFIED_ERROR;
2255-
}
2261+
// Generate the key pair.
2262+
if (!EC_KEY_generate_key(ec_key.get())) {
2263+
WARNING("Failed to generate EC key pair.");
2264+
return ErrorCode::UNSPECIFIED_ERROR;
2265+
}
22562266

2257-
uint8_t* out_buf = nullptr;
2258-
auto size = EC_KEY_key2buf(ec_key, POINT_CONVERSION_UNCOMPRESSED, &out_buf, nullptr);
2259-
if (!out_buf) {
2260-
WARNING("EC_KEY_key2buf failed");
2261-
EC_KEY_free(ec_key);
2262-
return ErrorCode::UNSPECIFIED_ERROR;
2263-
}
2267+
// Get the public key point and group.
2268+
const EC_POINT* pub_key_point = EC_KEY_get0_public_key(ec_key.get());
2269+
const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get());
22642270

2265-
const size_t expected_size = key_x_coordinate.size() + key_y_coordinate.size() + 1;
2266-
if (size != expected_size) {
2267-
WARNING("unexpected size {}", size);
2268-
OPENSSL_free(out_buf);
2269-
EC_KEY_free(ec_key);
2270-
return ErrorCode::UNSPECIFIED_ERROR;
2271-
}
2271+
if (!pub_key_point || !ec_group) {
2272+
WARNING("Failed to get public key point or EC group.");
2273+
return ErrorCode::UNSPECIFIED_ERROR;
2274+
}
2275+
2276+
// BIGNUM objects to hold the x and y coordinates
2277+
auto bn_deleter = [](BIGNUM* ptr) { BN_free(ptr); };
2278+
std::unique_ptr<BIGNUM, decltype(bn_deleter)> x_bn(BN_new(), bn_deleter);
2279+
std::unique_ptr<BIGNUM, decltype(bn_deleter)> y_bn(BN_new(), bn_deleter);
22722280

2273-
memcpy(key_x_coordinate.data(), out_buf + 1, key_x_coordinate.size());
2274-
memcpy(key_y_coordinate.data(), out_buf + 1 + key_x_coordinate.size(), key_y_coordinate.size());
2281+
if (!x_bn || !y_bn) {
2282+
WARNING("Failed to allocate BIGNUMs for coordinates.");
2283+
return ErrorCode::UNSPECIFIED_ERROR;
2284+
}
2285+
2286+
// Extract affine coordinates (x, y) from the public key point
2287+
if (!EC_POINT_get_affine_coordinates(ec_group, pub_key_point, x_bn.get(), y_bn.get(), NULL)) {
2288+
WARNING("Failed to get affine coordinates from public key.");
2289+
return ErrorCode::UNSPECIFIED_ERROR;
2290+
}
2291+
2292+
// Convert BIGNUMs to fixed-size byte arrays (32 bytes for P-256)
2293+
// BN_bn2binpad pads with zeros if the BIGNUM is smaller than 'len'.
2294+
// It returns the number of bytes written, or -1 on error.
2295+
if (BN_bn2binpad(x_bn.get(), key_x_coordinate.data(), key_x_coordinate.size()) == -1) {
2296+
WARNING("Failed to convert X coordinate BIGNUM to binary.");
2297+
return ErrorCode::UNSPECIFIED_ERROR;
2298+
}
2299+
2300+
if (BN_bn2binpad(y_bn.get(), key_y_coordinate.data(), key_y_coordinate.size()) == -1) {
2301+
WARNING("Failed to convert Y coordinate BIGNUM to binary.");
2302+
return ErrorCode::UNSPECIFIED_ERROR;
2303+
}
22752304

2276-
// OPENSSL_free(out_buf); // <-- this call fails with error invalid pointer
2277-
EC_KEY_free(ec_key);
2278-
return ErrorCode::SUCCESS;
2305+
return ErrorCode::SUCCESS;
22792306
}
22802307

22812308
void DualModeController::LeReadLocalP256PublicKey(CommandView command) {

0 commit comments

Comments
 (0)