Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2025 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : /**
19 : * @file
20 : * openSSL based implementation of CHIP crypto primitives
21 : */
22 :
23 : #include "CHIPCryptoPAL.h"
24 : #include "CHIPCryptoPALOpenSSL.h"
25 :
26 : #include <type_traits>
27 :
28 : #if CHIP_CRYPTO_BORINGSSL
29 : #include <openssl/aead.h>
30 : #endif // CHIP_CRYPTO_BORINGSSL
31 :
32 : #include <openssl/err.h>
33 : #include <openssl/evp.h>
34 :
35 : #include <lib/core/CHIPSafeCasts.h>
36 : #include <lib/support/BufferWriter.h>
37 : #include <lib/support/BytesToHex.h>
38 : #include <lib/support/CodeUtils.h>
39 : #include <lib/support/SafeInt.h>
40 :
41 : namespace chip {
42 : namespace Crypto {
43 :
44 2258 : static inline void from_EC_KEY(EC_KEY * key, P256KeypairContext * context)
45 : {
46 2258 : *SafePointerCast<EC_KEY **>(context) = key;
47 2258 : }
48 :
49 2819 : static inline EC_KEY * to_EC_KEY(P256KeypairContext * context)
50 : {
51 2819 : return *SafePointerCast<EC_KEY **>(context);
52 : }
53 :
54 914 : static inline const EC_KEY * to_const_EC_KEY(const P256KeypairContext * context)
55 : {
56 914 : return *SafePointerCast<const EC_KEY * const *>(context);
57 : }
58 :
59 : // helper function to populate octet key into EVP_PKEY out_evp_pkey. Caller must free out_evp_pkey
60 26 : static CHIP_ERROR _create_evp_key_from_binary_p256_key(const P256PublicKey & key, EVP_PKEY ** out_evp_pkey)
61 : {
62 :
63 26 : CHIP_ERROR error = CHIP_NO_ERROR;
64 26 : EC_KEY * ec_key = nullptr;
65 26 : int result = -1;
66 26 : EC_POINT * point = nullptr;
67 26 : EC_GROUP * group = nullptr;
68 26 : int nid = NID_undef;
69 :
70 26 : VerifyOrExit(*out_evp_pkey == nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
71 :
72 26 : nid = GetNidForCurve(MapECName(key.Type()));
73 26 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INTERNAL);
74 :
75 26 : ec_key = EC_KEY_new_by_curve_name(nid);
76 26 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
77 :
78 26 : group = EC_GROUP_new_by_curve_name(nid);
79 26 : VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
80 :
81 26 : point = EC_POINT_new(group);
82 26 : VerifyOrExit(point != nullptr, error = CHIP_ERROR_INTERNAL);
83 :
84 26 : result = EC_POINT_oct2point(group, point, Uint8::to_const_uchar(key), key.Length(), nullptr);
85 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
86 :
87 26 : result = EC_KEY_set_public_key(ec_key, point);
88 :
89 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
90 :
91 26 : *out_evp_pkey = EVP_PKEY_new();
92 26 : VerifyOrExit(*out_evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
93 :
94 26 : result = EVP_PKEY_set1_EC_KEY(*out_evp_pkey, ec_key);
95 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
96 :
97 26 : exit:
98 26 : if (ec_key != nullptr)
99 : {
100 26 : EC_KEY_free(ec_key);
101 26 : ec_key = nullptr;
102 : }
103 :
104 52 : if (error != CHIP_NO_ERROR && *out_evp_pkey)
105 : {
106 0 : EVP_PKEY_free(*out_evp_pkey);
107 0 : out_evp_pkey = nullptr;
108 : }
109 :
110 26 : if (point != nullptr)
111 : {
112 26 : EC_POINT_free(point);
113 26 : point = nullptr;
114 : }
115 :
116 26 : if (group != nullptr)
117 : {
118 26 : EC_GROUP_free(group);
119 26 : group = nullptr;
120 : }
121 :
122 26 : return error;
123 : }
124 :
125 523 : CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
126 : {
127 523 : CHIP_ERROR error = CHIP_NO_ERROR;
128 523 : int nid = NID_undef;
129 523 : EC_KEY * ec_key = nullptr;
130 523 : ECDSA_SIG * sig = nullptr;
131 523 : const BIGNUM * r = nullptr;
132 523 : const BIGNUM * s = nullptr;
133 :
134 523 : VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
135 :
136 : uint8_t digest[kSHA256_Hash_Length];
137 521 : memset(&digest[0], 0, sizeof(digest));
138 :
139 521 : ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
140 :
141 521 : ERR_clear_error();
142 :
143 : static_assert(P256ECDSASignature::Capacity() >= kP256_ECDSA_Signature_Length_Raw, "P256ECDSASignature must be large enough");
144 521 : VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
145 521 : nid = GetNidForCurve(MapECName(mPublicKey.Type()));
146 521 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
147 :
148 521 : ec_key = to_EC_KEY(&mKeypair);
149 521 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
150 :
151 521 : sig = ECDSA_do_sign(Uint8::to_const_uchar(&digest[0]), static_cast<boringssl_size_t_openssl_int>(sizeof(digest)), ec_key);
152 521 : VerifyOrExit(sig != nullptr, error = CHIP_ERROR_INTERNAL);
153 521 : ECDSA_SIG_get0(sig, &r, &s);
154 521 : VerifyOrExit((r != nullptr) && (s != nullptr), error = CHIP_ERROR_INTERNAL);
155 521 : VerifyOrExit(CanCastTo<size_t>(BN_num_bytes(r)) && CanCastTo<size_t>(BN_num_bytes(s)), error = CHIP_ERROR_INTERNAL);
156 521 : VerifyOrExit((static_cast<size_t>(BN_num_bytes(r)) <= kP256_FE_Length) &&
157 : (static_cast<size_t>(BN_num_bytes(s)) <= kP256_FE_Length),
158 : error = CHIP_ERROR_INTERNAL);
159 :
160 : // Concatenate r and s to output. Sizes were checked above.
161 1042 : VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
162 521 : VerifyOrExit(BN_bn2binpad(r, out_signature.Bytes() + 0u, kP256_FE_Length) == kP256_FE_Length, error = CHIP_ERROR_INTERNAL);
163 521 : VerifyOrExit(BN_bn2binpad(s, out_signature.Bytes() + kP256_FE_Length, kP256_FE_Length) == kP256_FE_Length,
164 : error = CHIP_ERROR_INTERNAL);
165 :
166 521 : exit:
167 521 : if (sig != nullptr)
168 : {
169 : // SIG owns the memory of r, s
170 521 : ECDSA_SIG_free(sig);
171 : }
172 :
173 1042 : if (error != CHIP_NO_ERROR)
174 : {
175 0 : SSLErrorLog();
176 : }
177 :
178 521 : return error;
179 : }
180 :
181 26 : CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
182 : {
183 26 : ERR_clear_error();
184 26 : CHIP_ERROR error = CHIP_NO_ERROR;
185 26 : int result = -1;
186 26 : EVP_PKEY * local_key = nullptr;
187 26 : EVP_PKEY * remote_key = nullptr;
188 :
189 26 : EVP_PKEY_CTX * context = nullptr;
190 26 : size_t out_buf_length = 0;
191 :
192 26 : EC_KEY * ec_key = EC_KEY_dup(to_const_EC_KEY(&mKeypair));
193 26 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
194 :
195 26 : VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
196 :
197 26 : local_key = EVP_PKEY_new();
198 26 : VerifyOrExit(local_key != nullptr, error = CHIP_ERROR_INTERNAL);
199 :
200 26 : result = EVP_PKEY_set1_EC_KEY(local_key, ec_key);
201 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
202 :
203 26 : error = _create_evp_key_from_binary_p256_key(remote_public_key, &remote_key);
204 26 : SuccessOrExit(error);
205 :
206 26 : context = EVP_PKEY_CTX_new(local_key, nullptr);
207 26 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
208 :
209 26 : result = EVP_PKEY_derive_init(context);
210 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
211 :
212 26 : result = EVP_PKEY_derive_set_peer(context, remote_key);
213 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
214 :
215 26 : out_buf_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
216 26 : result = EVP_PKEY_derive(context, out_secret.Bytes(), &out_buf_length);
217 26 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
218 26 : SuccessOrExit(error = out_secret.SetLength(out_buf_length));
219 :
220 26 : exit:
221 26 : if (ec_key != nullptr)
222 : {
223 26 : EC_KEY_free(ec_key);
224 26 : ec_key = nullptr;
225 : }
226 :
227 26 : if (local_key != nullptr)
228 : {
229 26 : EVP_PKEY_free(local_key);
230 26 : local_key = nullptr;
231 : }
232 :
233 26 : if (remote_key != nullptr)
234 : {
235 26 : EVP_PKEY_free(remote_key);
236 26 : remote_key = nullptr;
237 : }
238 :
239 26 : if (context != nullptr)
240 : {
241 26 : EVP_PKEY_CTX_free(context);
242 26 : context = nullptr;
243 : }
244 :
245 26 : SSLErrorLog();
246 26 : return error;
247 : }
248 :
249 191 : CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
250 : {
251 191 : ERR_clear_error();
252 :
253 191 : Clear();
254 :
255 191 : CHIP_ERROR error = CHIP_NO_ERROR;
256 191 : int result = 0;
257 191 : EC_KEY * ec_key = nullptr;
258 191 : ECName curve = MapECName(mPublicKey.Type());
259 :
260 191 : int nid = GetNidForCurve(curve);
261 191 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
262 :
263 191 : ec_key = EC_KEY_new_by_curve_name(nid);
264 191 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
265 :
266 191 : result = EC_KEY_generate_key(ec_key);
267 191 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
268 :
269 191 : error = P256PublicKeyFromECKey(ec_key, mPublicKey);
270 191 : SuccessOrExit(error);
271 :
272 191 : from_EC_KEY(ec_key, &mKeypair);
273 191 : mInitialized = true;
274 191 : ec_key = nullptr;
275 :
276 191 : exit:
277 191 : if (ec_key != nullptr)
278 : {
279 0 : EC_KEY_free(ec_key);
280 0 : ec_key = nullptr;
281 : }
282 :
283 191 : SSLErrorLog();
284 191 : return error;
285 : }
286 :
287 888 : CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
288 : {
289 888 : CHIP_ERROR error = CHIP_NO_ERROR;
290 :
291 888 : const EC_KEY * ec_key = to_const_EC_KEY(&mKeypair);
292 : uint8_t privkey[kP256_PrivateKey_Length];
293 :
294 888 : int privkey_size = 0;
295 888 : const BIGNUM * privkey_bn = EC_KEY_get0_private_key(ec_key);
296 888 : VerifyOrExit(privkey_bn != nullptr, error = CHIP_ERROR_INTERNAL);
297 :
298 888 : privkey_size = BN_bn2binpad(privkey_bn, privkey, sizeof(privkey));
299 888 : privkey_bn = nullptr;
300 :
301 888 : VerifyOrExit(privkey_size > 0, error = CHIP_ERROR_INTERNAL);
302 888 : VerifyOrExit((size_t) privkey_size == sizeof(privkey), error = CHIP_ERROR_INTERNAL);
303 :
304 : {
305 888 : size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
306 888 : Encoding::BufferWriter bbuf(output.Bytes(), len);
307 888 : bbuf.Put(mPublicKey, mPublicKey.Length());
308 888 : bbuf.Put(privkey, sizeof(privkey));
309 888 : VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
310 888 : TEMPORARY_RETURN_IGNORED output.SetLength(bbuf.Needed());
311 : }
312 :
313 888 : exit:
314 888 : ClearSecretData(privkey, sizeof(privkey));
315 888 : SSLErrorLog();
316 888 : return error;
317 : }
318 :
319 2068 : CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
320 : {
321 2068 : Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
322 :
323 2068 : Clear();
324 :
325 2068 : BIGNUM * pvt_key = nullptr;
326 2068 : EC_GROUP * group = nullptr;
327 2068 : EC_POINT * key_point = nullptr;
328 :
329 2068 : EC_KEY * ec_key = nullptr;
330 2068 : ECName curve = MapECName(mPublicKey.Type());
331 :
332 2068 : ERR_clear_error();
333 2068 : CHIP_ERROR error = CHIP_NO_ERROR;
334 2068 : int result = 0;
335 2068 : int nid = NID_undef;
336 :
337 2068 : const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length();
338 :
339 2068 : VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
340 2067 : bbuf.Put(input.ConstBytes(), mPublicKey.Length());
341 2067 : VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
342 :
343 2067 : nid = GetNidForCurve(curve);
344 2067 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
345 :
346 2067 : group = EC_GROUP_new_by_curve_name(nid);
347 2067 : VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
348 :
349 2067 : key_point = EC_POINT_new(group);
350 2067 : VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_INTERNAL);
351 :
352 2067 : result = EC_POINT_oct2point(group, key_point, Uint8::to_const_uchar(mPublicKey), mPublicKey.Length(), nullptr);
353 2067 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
354 :
355 2067 : ec_key = EC_KEY_new_by_curve_name(nid);
356 2067 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
357 :
358 2067 : result = EC_KEY_set_public_key(ec_key, key_point);
359 2067 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
360 :
361 2067 : pvt_key = BN_bin2bn(privkey, kP256_PrivateKey_Length, nullptr);
362 2067 : VerifyOrExit(pvt_key != nullptr, error = CHIP_ERROR_INTERNAL);
363 :
364 2067 : result = EC_KEY_set_private_key(ec_key, pvt_key);
365 2067 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
366 :
367 2067 : from_EC_KEY(ec_key, &mKeypair);
368 2067 : mInitialized = true;
369 2067 : ec_key = nullptr;
370 :
371 2068 : exit:
372 2068 : if (ec_key != nullptr)
373 : {
374 0 : EC_KEY_free(ec_key);
375 0 : ec_key = nullptr;
376 : }
377 :
378 2068 : if (group != nullptr)
379 : {
380 2067 : EC_GROUP_free(group);
381 2067 : group = nullptr;
382 : }
383 :
384 2068 : if (pvt_key != nullptr)
385 : {
386 2067 : BN_free(pvt_key);
387 2067 : pvt_key = nullptr;
388 : }
389 :
390 2068 : if (key_point != nullptr)
391 : {
392 2067 : EC_POINT_free(key_point);
393 2067 : key_point = nullptr;
394 : }
395 2068 : SSLErrorLog();
396 2068 : return error;
397 : }
398 :
399 4499 : void P256Keypair::Clear()
400 : {
401 4499 : if (mInitialized)
402 : {
403 2258 : EC_KEY * ec_key = to_EC_KEY(&mKeypair);
404 2258 : EC_KEY_free(ec_key);
405 2258 : mInitialized = false;
406 : }
407 4499 : }
408 :
409 2240 : P256Keypair::~P256Keypair()
410 : {
411 2240 : Clear();
412 2240 : }
413 :
414 40 : CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
415 : {
416 40 : ERR_clear_error();
417 40 : CHIP_ERROR error = CHIP_NO_ERROR;
418 40 : int result = 0;
419 40 : int csr_length_local = 0;
420 :
421 40 : X509_REQ * x509_req = X509_REQ_new();
422 40 : EVP_PKEY * evp_pkey = nullptr;
423 :
424 40 : EC_KEY * ec_key = to_EC_KEY(&mKeypair);
425 :
426 40 : X509_NAME * subject = X509_NAME_new();
427 40 : VerifyOrExit(subject != nullptr, error = CHIP_ERROR_INTERNAL);
428 :
429 40 : VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
430 :
431 40 : result = X509_REQ_set_version(x509_req, 0);
432 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
433 :
434 40 : result = EC_KEY_check_key(ec_key);
435 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
436 :
437 40 : evp_pkey = EVP_PKEY_new();
438 40 : VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
439 :
440 40 : result = EVP_PKEY_set1_EC_KEY(evp_pkey, ec_key);
441 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
442 :
443 40 : result = X509_REQ_set_pubkey(x509_req, evp_pkey);
444 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
445 :
446 : // TODO: mbedTLS CSR parser fails if the subject name is not set (or if empty).
447 : // CHIP Spec doesn't specify the subject name that can be used.
448 : // Figure out the correct value and update this code.
449 40 : result = X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC, Uint8::from_const_char("CSR"), -1, -1, 0);
450 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
451 :
452 40 : result = X509_REQ_set_subject_name(x509_req, subject);
453 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
454 :
455 40 : result = X509_REQ_sign(x509_req, evp_pkey, EVP_sha256());
456 40 : VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL);
457 :
458 40 : csr_length_local = i2d_X509_REQ(x509_req, nullptr);
459 40 : VerifyOrExit(csr_length_local >= 0, error = CHIP_ERROR_INTERNAL);
460 40 : VerifyOrExit(CanCastTo<size_t>(csr_length_local), error = CHIP_ERROR_BUFFER_TOO_SMALL);
461 40 : VerifyOrExit(static_cast<size_t>(csr_length_local) <= csr_length, error = CHIP_ERROR_BUFFER_TOO_SMALL);
462 40 : csr_length = static_cast<size_t>(i2d_X509_REQ(x509_req, &out_csr));
463 :
464 40 : exit:
465 40 : ec_key = nullptr;
466 :
467 40 : if (evp_pkey != nullptr)
468 : {
469 40 : EVP_PKEY_free(evp_pkey);
470 40 : evp_pkey = nullptr;
471 : }
472 :
473 40 : X509_NAME_free(subject);
474 40 : subject = nullptr;
475 :
476 40 : X509_REQ_free(x509_req);
477 :
478 40 : SSLErrorLog();
479 40 : return error;
480 : }
481 :
482 : } // namespace Crypto
483 : } // namespace chip
|