| 174 | } |
| 175 | |
| 176 | Optional<PublicOrPrivateKey> parseEcP256Key(StringRef b64x, StringRef b64y, Optional<StringRef> b64d, int keyIndex) { |
| 177 | auto arena = Arena(); |
| 178 | EC_DECLARE_DECODED_REQUIRED_BN_MEMBER(x); |
| 179 | EC_DECLARE_DECODED_REQUIRED_BN_MEMBER(y); |
| 180 | EC_DECLARE_DECODED_OPTIONAL_BN_MEMBER(d); |
| 181 | #if USE_V3_API |
| 182 | // avoid deprecated API |
| 183 | auto bld = AutoCPointer(::OSSL_PARAM_BLD_new(), &::OSSL_PARAM_BLD_free); |
| 184 | if (!bld) { |
| 185 | JWK_PARSE_ERROR_OSSL("OSSL_PARAM_BLD_new() for EC"); |
| 186 | return {}; |
| 187 | } |
| 188 | // since OSSL_PKEY_PARAM_EC_PUB_{X|Y} are not settable params, we'll need to build a EC_GROUP and serialize it |
| 189 | auto group = AutoCPointer(::EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1), &::EC_GROUP_free); |
| 190 | if (!group) { |
| 191 | JWK_PARSE_ERROR_OSSL("EC_GROUP_new_by_curve_name()"); |
| 192 | return {}; |
| 193 | } |
| 194 | auto point = AutoCPointer(::EC_POINT_new(group), &::EC_POINT_free); |
| 195 | if (!point) { |
| 196 | JWK_PARSE_ERROR_OSSL("EC_POINT_new()"); |
| 197 | return {}; |
| 198 | } |
| 199 | if (1 != ::EC_POINT_set_affine_coordinates(group, point, x, y, nullptr)) { |
| 200 | JWK_PARSE_ERROR_OSSL("EC_POINT_set_affine_coordinates()"); |
| 201 | return {}; |
| 202 | } |
| 203 | auto pointBufLen = ::EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, nullptr); |
| 204 | if (!pointBufLen) { |
| 205 | JWK_PARSE_ERROR_OSSL("EC_POINT_point2oct() for length"); |
| 206 | return {}; |
| 207 | } |
| 208 | auto pointBuf = new (arena) uint8_t[pointBufLen]; |
| 209 | ::EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, pointBuf, pointBufLen, nullptr); |
| 210 | if (!::OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, "prime256v1", sizeof("prime256v1") - 1) || |
| 211 | !::OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pointBuf, pointBufLen)) { |
| 212 | JWK_PARSE_ERROR_OSSL("OSSL_PARAM_BLD_push_*() for EC (group, point)"); |
| 213 | return {}; |
| 214 | } |
| 215 | if (d && !::OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d)) { |
| 216 | JWK_PARSE_ERROR_OSSL("OSSL_PARAM_BLD_push_BN() for EC (d)"); |
| 217 | return {}; |
| 218 | } |
| 219 | auto params = AutoCPointer(::OSSL_PARAM_BLD_to_param(bld), &OSSL_PARAM_free); |
| 220 | if (!params) { |
| 221 | JWK_PARSE_ERROR_OSSL("OSSL_PARAM_BLD_to_param() for EC"); |
| 222 | return {}; |
| 223 | } |
| 224 | auto pctx = AutoCPointer(::EVP_PKEY_CTX_new_from_name(nullptr, "EC", nullptr), &::EVP_PKEY_CTX_free); |
| 225 | if (!pctx) { |
| 226 | JWK_PARSE_ERROR_OSSL("EVP_PKEY_CTX_new_from_name(EC)"); |
| 227 | return {}; |
| 228 | } |
| 229 | if (1 != ::EVP_PKEY_fromdata_init(pctx)) { |
| 230 | JWK_PARSE_ERROR_OSSL("EVP_PKEY_fromdata_init() for EC"); |
| 231 | return {}; |
| 232 | } |
| 233 | auto pkey = std::add_pointer_t<EVP_PKEY>(); |
no test coverage detected