1#include <vanetza/security/backend_openssl.hpp>
2#include <vanetza/security/key_type.hpp>
3#include <vanetza/security/openssl_wrapper.hpp>
4#include <vanetza/security/v2/public_key.hpp>
5#include <vanetza/security/v2/signature.hpp>
8#include <openssl/ecdsa.h>
9#include <openssl/obj_mac.h>
10#include <openssl/sha.h>
21int openssl_nid(KeyType key)
25 case KeyType::NistP256:
26 nid = NID_X9_62_prime256v1;
28 case KeyType::BrainpoolP256r1:
29 nid = NID_brainpoolP256r1;
31 case KeyType::BrainpoolP384r1:
32 nid = NID_brainpoolP384r1;
43BackendOpenSsl::BackendOpenSsl()
45#if OPENSSL_API_COMPAT < 0x10100000L
46 ERR_load_crypto_strings();
48 OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS,
nullptr);
58 openssl::Signature signature { ECDSA_do_sign(digest.data(), digest.size(), priv_key) };
59#if OPENSSL_API_COMPAT < 0x10100000L
60 const BIGNUM* sig_r = signature->r;
61 const BIGNUM* sig_s = signature->s;
63 const BIGNUM* sig_r =
nullptr;
64 const BIGNUM* sig_s =
nullptr;
65 ECDSA_SIG_get0(signature, &sig_r, &sig_s);
72 const size_t len = field_size(v2::PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256);
74 const auto num_bytes_s = BN_num_bytes(sig_s);
75 assert(len >=
static_cast<size_t>(num_bytes_s));
76 ecdsa_signature.s.resize(len, 0x00);
77 BN_bn2bin(sig_s, ecdsa_signature.s.data() + len - num_bytes_s);
79 const auto num_bytes_r = BN_num_bytes(sig_r);
80 assert(len >=
static_cast<size_t>(num_bytes_r));
81 coordinate.x.resize(len, 0x00);
82 BN_bn2bin(sig_r, coordinate.x.data() + len - num_bytes_r);
87 ecdsa_signature.R = std::move(coordinate);
88 return ecdsa_signature;
97 return (ECDSA_do_verify(digest.data(), digest.size(), signature, pub) == 1);
102 if (gpub.type != gsig.type) {
108 return ECDSA_do_verify(digest.data(), digest.size(), sig, pub) == 1;
113 struct DecompressionVisitor :
public boost::static_visitor<bool>
122 return decompress(p.x, 0);
127 return decompress(p.x, 1);
136 bool decompress(
const ByteBuffer& x,
int y_bit)
145 result.y.resize(result.x.size());
147#if OPENSSL_API_COMPAT < 0x10101000L
148 EC_POINT_set_compressed_coordinates_GFp(group, point, x_coordinate, y_bit, ctx);
149 EC_POINT_get_affine_coordinates_GFp(group, point,
nullptr, y_coordinate, ctx);
150 std::size_t y_coordinate_bytes = BN_num_bytes(y_coordinate);
151 if (y_coordinate_bytes <= result.y.size()) {
152 BN_bn2bin(y_coordinate, result.y.data() + (result.y.size() - y_coordinate_bytes));
158 EC_POINT_set_compressed_coordinates(group, point, x_coordinate, y_bit, ctx);
159 EC_POINT_get_affine_coordinates(group, point,
nullptr, y_coordinate, ctx);
160 return (BN_bn2binpad(y_coordinate, result.y.data(), result.y.size()) != -1);
167 DecompressionVisitor visitor;
168 if (boost::apply_visitor(visitor, ecc_point)) {
169 return visitor.result;
175ByteBuffer BackendOpenSsl::calculate_hash(KeyType key,
const ByteBuffer& data)
180 case KeyType::NistP256:
181 case KeyType::BrainpoolP256r1: {
183 result.assign(digest.begin(), digest.end());
186 case KeyType::BrainpoolP384r1: {
188 result.assign(digest.begin(), digest.end());
199 static_assert(SHA256_DIGEST_LENGTH == 32,
"Unexpected length of SHA256 digest");
201 std::array<uint8_t, 32> digest;
204 SHA256_Update(&ctx, data.data(), data.size());
205 SHA256_Final(digest.data(), &ctx);
211 static_assert(SHA384_DIGEST_LENGTH == 48,
"Unexpected length of SHA384 digest");
213 std::array<uint8_t, 48> digest;
214 SHA384(data.data(), data.size(), digest.data());
222 EC_KEY_set_private_key(key, prv);
226 const EC_GROUP* group = EC_KEY_get0_group(key);
228 openssl::check(EC_POINT_mul(group, pub, prv,
nullptr,
nullptr, ctx));
229 EC_KEY_set_public_key(key, pub);
231 openssl::check(EC_KEY_check_key(key));
240 EC_KEY_set_public_key_affine_coordinates(key, x, y);
242 openssl::check(EC_KEY_check_key(key));
250 EC_KEY_set_public_key(key, point);
252 openssl::check(EC_KEY_check_key(key));
262 switch (generic.compression)
264 case KeyCompression::NoCompression:
265 EC_POINT_set_affine_coordinates(group, point,
269 case KeyCompression::Y0:
270 EC_POINT_set_compressed_coordinates(group, point,
openssl::BigNumber {
generic.x }, 0, bn_ctx);
272 case KeyCompression::Y1:
273 EC_POINT_set_compressed_coordinates(group, point,
openssl::BigNumber {
generic.x }, 1, bn_ctx);
std::array< uint8_t, 32 > calculate_sha256_digest(const ByteBuffer &data) const
calculate SHA256 digest of data buffer
bool verify_data(const ecdsa256::PublicKey &public_key, const ByteBuffer &data, const EcdsaSignature &sig) override
bool verify_digest(const PublicKey &, const ByteBuffer &digest, const Signature &) override
std::array< uint8_t, 48 > calculate_sha384_digest(const ByteBuffer &data) const
calculate SHA384 digest of data buffer
openssl::Key internal_public_key(const ecdsa256::PublicKey &) const
convert to internal format of public key
openssl::Point internal_ec_point(const PublicKey &) const
convert to internal format of an EC point
EcdsaSignature sign_data(const ecdsa256::PrivateKey &private_key, const ByteBuffer &data_buffer) override
boost::optional< Uncompressed > decompress_point(const EccPoint &ecc_point) override
openssl::Key internal_private_key(const ecdsa256::PrivateKey &) const
convert to internal format of private key
Compressed_Lsb_Y_0 specified in TS 103 097 v1.2.1 in section 4.2.5.
Compressed_Lsb_Y_1 specified in TS 103 097 v1.2.1 in section 4.2.5.
EcdsaSignature specified in TS 103 097 v1.2.1, section 4.2.9.
Uncompressed specified in TS 103 097 v1.2.1 in section 4.2.5.
X_Coordinate_Only specified in TS 103 097 v1.2.1 in section 4.2.5.