Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2023 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 :
25 : #include <type_traits>
26 :
27 : #if CHIP_CRYPTO_BORINGSSL
28 : #include <openssl/aead.h>
29 : #endif // CHIP_CRYPTO_BORINGSSL
30 :
31 : #include <openssl/bn.h>
32 : #include <openssl/conf.h>
33 : #include <openssl/ec.h>
34 : #include <openssl/ecdsa.h>
35 : #include <openssl/err.h>
36 : #include <openssl/evp.h>
37 : #include <openssl/hmac.h>
38 : #include <openssl/kdf.h>
39 : #include <openssl/ossl_typ.h>
40 : #include <openssl/pem.h>
41 : #include <openssl/rand.h>
42 : #include <openssl/sha.h>
43 : #include <openssl/x509.h>
44 : #include <openssl/x509v3.h>
45 :
46 : #include <lib/asn1/ASN1.h>
47 : #include <lib/core/CHIPSafeCasts.h>
48 : #include <lib/support/BufferWriter.h>
49 : #include <lib/support/BytesToHex.h>
50 : #include <lib/support/CHIPArgParser.hpp>
51 : #include <lib/support/CodeUtils.h>
52 : #include <lib/support/SafeInt.h>
53 : #include <lib/support/SafePointerCast.h>
54 : #include <lib/support/logging/CHIPLogging.h>
55 :
56 : #include <string.h>
57 :
58 : namespace chip {
59 : namespace Crypto {
60 :
61 : // BoringSSL is designed to implement the same interface as OpenSSL in most
62 : // cases. However, it removes some APIs that can allow very weak configuration.
63 : // (Example: CCM ciphers with low tag lengths.) In order to support Matter,
64 : // a more specific inteface is required.
65 : #if CHIP_CRYPTO_BORINGSSL
66 : #define RAND_priv_bytes RAND_bytes
67 : #define BN_CTX_secure_new BN_CTX_new
68 : #define EC_GROUP_clear_free EC_GROUP_free
69 : using boringssl_size_t_openssl_int = size_t;
70 : using boringssl_uint_openssl_int = unsigned int;
71 : using libssl_err_type = uint32_t;
72 : #else
73 : using boringssl_size_t_openssl_int = int;
74 : using boringssl_uint_openssl_int = int;
75 : using libssl_err_type = unsigned long;
76 : #endif // CHIP_CRYPTO_BORINGSSL
77 :
78 : #define kKeyLengthInBits 256
79 :
80 : typedef struct stack_st_X509 X509_LIST;
81 :
82 : enum class DigestType
83 : {
84 : SHA256
85 : };
86 :
87 : enum class ECName
88 : {
89 : None = 0,
90 : P256v1 = 1,
91 : };
92 :
93 3986 : static int _nidForCurve(ECName name)
94 : {
95 3986 : switch (name)
96 : {
97 3986 : case ECName::P256v1:
98 3986 : return EC_curve_nist2nid("P-256");
99 : break;
100 :
101 0 : default:
102 0 : return NID_undef;
103 : break;
104 : }
105 : }
106 :
107 4484 : static void _logSSLError()
108 : {
109 4484 : unsigned long ssl_err_code = ERR_get_error();
110 4487 : while (ssl_err_code != 0)
111 : {
112 : #if CHIP_ERROR_LOGGING
113 3 : const char * err_str_lib = ERR_lib_error_string(static_cast<libssl_err_type>(ssl_err_code));
114 3 : const char * err_str_routine = ERR_func_error_string(static_cast<libssl_err_type>(ssl_err_code));
115 3 : const char * err_str_reason = ERR_reason_error_string(static_cast<libssl_err_type>(ssl_err_code));
116 3 : if (err_str_lib)
117 : {
118 3 : ChipLogError(Crypto, " ssl err %s %s %s\n", StringOrNullMarker(err_str_lib), StringOrNullMarker(err_str_routine),
119 : StringOrNullMarker(err_str_reason));
120 : }
121 : #endif // CHIP_ERROR_LOGGING
122 3 : ssl_err_code = ERR_get_error();
123 : }
124 4484 : }
125 :
126 9555 : static const EVP_MD * _digestForType(DigestType digestType)
127 : {
128 9555 : switch (digestType)
129 : {
130 9555 : case DigestType::SHA256:
131 9555 : return EVP_sha256();
132 : break;
133 :
134 0 : default:
135 0 : return nullptr;
136 : break;
137 : }
138 : }
139 :
140 20 : static int _compareDaysAndSeconds(const int days, const int seconds)
141 : {
142 20 : if (days > 0 || seconds > 0)
143 3 : return 1;
144 17 : if (days < 0 || seconds < 0)
145 11 : return -1;
146 6 : return 0;
147 : }
148 :
149 10230 : CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
150 : const Aes128KeyHandle & key, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
151 : uint8_t * tag, size_t tag_length)
152 : {
153 : #if CHIP_CRYPTO_BORINGSSL
154 : EVP_AEAD_CTX * context = nullptr;
155 : size_t written_tag_len = 0;
156 : const EVP_AEAD * aead = nullptr;
157 : #else
158 10230 : EVP_CIPHER_CTX * context = nullptr;
159 10230 : int bytesWritten = 0;
160 10230 : size_t ciphertext_length = 0;
161 10230 : const EVP_CIPHER * type = nullptr;
162 : #endif
163 10230 : CHIP_ERROR error = CHIP_NO_ERROR;
164 10230 : int result = 1;
165 :
166 : // Placeholder location for avoiding null params for plaintexts when
167 : // size is zero.
168 10230 : uint8_t placeholder_empty_plaintext = 0;
169 :
170 : // Ciphertext block to hold a finalized ciphertext block if output
171 : // `ciphertext` buffer is nullptr or plaintext_length is zero (i.e.
172 : // we are only doing auth and don't care about output).
173 : uint8_t placeholder_ciphertext[kAES_CCM128_Block_Length];
174 10230 : bool ciphertext_was_null = (ciphertext == nullptr);
175 :
176 10230 : if (plaintext_length == 0)
177 : {
178 4 : if (plaintext == nullptr)
179 : {
180 4 : plaintext = &placeholder_empty_plaintext;
181 : }
182 : // Make sure we have at least 1 full block size buffer for the
183 : // extraction of final block (required by OpenSSL EVP_EncryptFinal_ex)
184 4 : if (ciphertext_was_null)
185 : {
186 4 : ciphertext = &placeholder_ciphertext[0];
187 : }
188 : }
189 :
190 10230 : VerifyOrExit((plaintext_length != 0) || ciphertext_was_null, error = CHIP_ERROR_INVALID_ARGUMENT);
191 10230 : VerifyOrExit(plaintext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
192 10230 : VerifyOrExit(ciphertext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
193 10230 : VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
194 10230 : VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
195 10229 : VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
196 10229 : VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
197 : #if CHIP_CRYPTO_BORINGSSL
198 : VerifyOrExit(tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, error = CHIP_ERROR_INVALID_ARGUMENT);
199 : #else
200 10229 : VerifyOrExit(tag_length == 8 || tag_length == 12 || tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES,
201 : error = CHIP_ERROR_INVALID_ARGUMENT);
202 : #endif // CHIP_CRYPTO_BORINGSSL
203 :
204 : #if CHIP_CRYPTO_BORINGSSL
205 : aead = EVP_aead_aes_128_ccm_matter();
206 :
207 : context = EVP_AEAD_CTX_new(aead, key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), tag_length);
208 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
209 :
210 : result = EVP_AEAD_CTX_seal_scatter(context, ciphertext, tag, &written_tag_len, tag_length, nonce, nonce_length, plaintext,
211 : plaintext_length, nullptr, 0, aad, aad_length);
212 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
213 : VerifyOrExit(written_tag_len == tag_length, error = CHIP_ERROR_INTERNAL);
214 : #else
215 :
216 10228 : type = EVP_aes_128_ccm();
217 :
218 10228 : context = EVP_CIPHER_CTX_new();
219 10228 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
220 :
221 : // Pass in cipher
222 10228 : result = EVP_EncryptInit_ex(context, type, nullptr, nullptr, nullptr);
223 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
224 :
225 : // Pass in nonce length. Cast is safe because we checked with CanCastTo.
226 10228 : result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_IVLEN, static_cast<int>(nonce_length), nullptr);
227 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
228 :
229 : // Pass in tag length. Cast is safe because we checked against CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES.
230 10228 : result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_TAG, static_cast<int>(tag_length), nullptr);
231 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
232 :
233 : // Pass in key + nonce
234 : static_assert(kAES_CCM128_Key_Length == sizeof(Symmetric128BitsKeyByteArray), "Unexpected key length");
235 10228 : result = EVP_EncryptInit_ex(context, nullptr, nullptr, key.As<Symmetric128BitsKeyByteArray>(), Uint8::to_const_uchar(nonce));
236 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
237 :
238 : // Pass in plain text length
239 10228 : VerifyOrExit(CanCastTo<int>(plaintext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
240 10228 : result = EVP_EncryptUpdate(context, nullptr, &bytesWritten, nullptr, static_cast<int>(plaintext_length));
241 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
242 :
243 : // Pass in AAD
244 10228 : if (aad_length > 0 && aad != nullptr)
245 : {
246 10103 : VerifyOrExit(CanCastTo<int>(aad_length), error = CHIP_ERROR_INVALID_ARGUMENT);
247 10103 : result = EVP_EncryptUpdate(context, nullptr, &bytesWritten, Uint8::to_const_uchar(aad), static_cast<int>(aad_length));
248 10103 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
249 : }
250 :
251 : // Encrypt
252 10228 : VerifyOrExit(CanCastTo<int>(plaintext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
253 10228 : result = EVP_EncryptUpdate(context, Uint8::to_uchar(ciphertext), &bytesWritten, Uint8::to_const_uchar(plaintext),
254 : static_cast<int>(plaintext_length));
255 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
256 10228 : VerifyOrExit((ciphertext_was_null && bytesWritten == 0) || (bytesWritten >= 0), error = CHIP_ERROR_INTERNAL);
257 10228 : ciphertext_length = static_cast<unsigned int>(bytesWritten);
258 :
259 : // Finalize encryption
260 10228 : result = EVP_EncryptFinal_ex(context, ciphertext + ciphertext_length, &bytesWritten);
261 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
262 10228 : VerifyOrExit(bytesWritten >= 0 && bytesWritten <= static_cast<int>(plaintext_length), error = CHIP_ERROR_INTERNAL);
263 :
264 : // Get tag
265 10228 : VerifyOrExit(CanCastTo<int>(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
266 10228 : result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_GET_TAG, static_cast<int>(tag_length), Uint8::to_uchar(tag));
267 10228 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
268 : #endif // CHIP_CRYPTO_BORINGSSL
269 :
270 10230 : exit:
271 10230 : if (context != nullptr)
272 : {
273 : #if CHIP_CRYPTO_BORINGSSL
274 : EVP_AEAD_CTX_free(context);
275 : #else
276 10228 : EVP_CIPHER_CTX_free(context);
277 : #endif // CHIP_CRYPTO_BORINGSSL
278 10228 : context = nullptr;
279 : }
280 :
281 10230 : return error;
282 : }
283 :
284 10088 : CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_length, const uint8_t * aad, size_t aad_length,
285 : const uint8_t * tag, size_t tag_length, const Aes128KeyHandle & key, const uint8_t * nonce,
286 : size_t nonce_length, uint8_t * plaintext)
287 : {
288 : #if CHIP_CRYPTO_BORINGSSL
289 : EVP_AEAD_CTX * context = nullptr;
290 : const EVP_AEAD * aead = nullptr;
291 : #else
292 :
293 10088 : EVP_CIPHER_CTX * context = nullptr;
294 10088 : int bytesOutput = 0;
295 10088 : const EVP_CIPHER * type = nullptr;
296 : #endif // CHIP_CRYPTO_BORINGSSL
297 10088 : CHIP_ERROR error = CHIP_NO_ERROR;
298 10088 : int result = 1;
299 :
300 : // Placeholder location for avoiding null params for ciphertext when
301 : // size is zero.
302 10088 : uint8_t placeholder_empty_ciphertext = 0;
303 :
304 : // Plaintext block to hold a finalized plaintext block if output
305 : // `plaintext` buffer is nullptr or ciphertext_length is zero (i.e.
306 : // we are only doing auth and don't care about output).
307 : uint8_t placeholder_plaintext[kAES_CCM128_Block_Length];
308 10088 : bool plaintext_was_null = (plaintext == nullptr);
309 :
310 10088 : if (ciphertext_length == 0)
311 : {
312 3 : if (ciphertext == nullptr)
313 : {
314 3 : ciphertext = &placeholder_empty_ciphertext;
315 : }
316 : // Make sure we have at least 1 full block size buffer for the
317 : // extraction of final block (required by OpenSSL EVP_DecryptFinal_ex)
318 3 : if (plaintext_was_null)
319 : {
320 3 : plaintext = &placeholder_plaintext[0];
321 : }
322 : }
323 :
324 10088 : VerifyOrExit(ciphertext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
325 10088 : VerifyOrExit(plaintext != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
326 10088 : VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
327 : #if CHIP_CRYPTO_BORINGSSL
328 : VerifyOrExit(tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES, error = CHIP_ERROR_INVALID_ARGUMENT);
329 : #else
330 10088 : VerifyOrExit(tag_length == 8 || tag_length == 12 || tag_length == CHIP_CRYPTO_AEAD_MIC_LENGTH_BYTES,
331 : error = CHIP_ERROR_INVALID_ARGUMENT);
332 : #endif // CHIP_CRYPTO_BORINGSSL
333 10088 : VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
334 10088 : VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
335 :
336 : #if CHIP_CRYPTO_BORINGSSL
337 : aead = EVP_aead_aes_128_ccm_matter();
338 :
339 : context = EVP_AEAD_CTX_new(aead, key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), tag_length);
340 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
341 :
342 : result = EVP_AEAD_CTX_open_gather(context, plaintext, nonce, nonce_length, ciphertext, ciphertext_length, tag, tag_length, aad,
343 : aad_length);
344 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
345 : #else
346 10087 : type = EVP_aes_128_ccm();
347 :
348 10087 : context = EVP_CIPHER_CTX_new();
349 10087 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_NO_MEMORY);
350 :
351 : // Pass in cipher
352 10087 : result = EVP_DecryptInit_ex(context, type, nullptr, nullptr, nullptr);
353 10087 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
354 :
355 : // Pass in nonce length
356 10087 : VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
357 10087 : result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_IVLEN, static_cast<int>(nonce_length), nullptr);
358 10087 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
359 :
360 : // Pass in expected tag
361 : // Removing "const" from |tag| here should hopefully be safe as
362 : // we're writing the tag, not reading.
363 10087 : VerifyOrExit(CanCastTo<int>(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
364 10087 : result = EVP_CIPHER_CTX_ctrl(context, EVP_CTRL_CCM_SET_TAG, static_cast<int>(tag_length),
365 : const_cast<void *>(static_cast<const void *>(tag)));
366 10087 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
367 :
368 : // Pass in key + nonce
369 : static_assert(kAES_CCM128_Key_Length == sizeof(Symmetric128BitsKeyByteArray), "Unexpected key length");
370 10087 : result = EVP_DecryptInit_ex(context, nullptr, nullptr, key.As<Symmetric128BitsKeyByteArray>(), Uint8::to_const_uchar(nonce));
371 10087 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
372 :
373 : // Pass in cipher text length
374 10087 : VerifyOrExit(CanCastTo<int>(ciphertext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
375 10087 : result = EVP_DecryptUpdate(context, nullptr, &bytesOutput, nullptr, static_cast<int>(ciphertext_length));
376 10087 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
377 10087 : VerifyOrExit(bytesOutput <= static_cast<int>(ciphertext_length), error = CHIP_ERROR_INTERNAL);
378 :
379 : // Pass in aad
380 10087 : if (aad_length > 0 && aad != nullptr)
381 : {
382 9995 : VerifyOrExit(CanCastTo<int>(aad_length), error = CHIP_ERROR_INVALID_ARGUMENT);
383 9995 : result = EVP_DecryptUpdate(context, nullptr, &bytesOutput, Uint8::to_const_uchar(aad), static_cast<int>(aad_length));
384 9995 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
385 9995 : VerifyOrExit(bytesOutput <= static_cast<int>(aad_length), error = CHIP_ERROR_INTERNAL);
386 : }
387 :
388 : // Pass in ciphertext. We wont get anything if validation fails.
389 10087 : VerifyOrExit(CanCastTo<int>(ciphertext_length), error = CHIP_ERROR_INVALID_ARGUMENT);
390 10087 : result = EVP_DecryptUpdate(context, Uint8::to_uchar(plaintext), &bytesOutput, Uint8::to_const_uchar(ciphertext),
391 : static_cast<int>(ciphertext_length));
392 10087 : if (plaintext_was_null)
393 : {
394 3 : VerifyOrExit(bytesOutput <= static_cast<int>(sizeof(placeholder_plaintext)), error = CHIP_ERROR_INTERNAL);
395 : }
396 10087 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
397 : #endif // CHIP_CRYPTO_BORINGSSL
398 :
399 10088 : exit:
400 10088 : if (context != nullptr)
401 : {
402 : #if CHIP_CRYPTO_BORINGSSL
403 : EVP_AEAD_CTX_free(context);
404 : #else
405 10087 : EVP_CIPHER_CTX_free(context);
406 : #endif // CHIP_CRYPTO_BORINGSSL
407 :
408 10087 : context = nullptr;
409 : }
410 :
411 10088 : return error;
412 : }
413 :
414 4077 : CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
415 : {
416 : // zero data length hash is supported.
417 4077 : VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
418 4077 : VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
419 :
420 4077 : SHA256(data, data_length, Uint8::to_uchar(out_buffer));
421 :
422 4077 : return CHIP_NO_ERROR;
423 : }
424 :
425 284 : CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
426 : {
427 : // zero data length hash is supported.
428 284 : VerifyOrReturnError(data != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
429 284 : VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
430 :
431 284 : SHA1(data, data_length, Uint8::to_uchar(out_buffer));
432 :
433 284 : return CHIP_NO_ERROR;
434 : }
435 :
436 : // For OpenSSL, we store a pointer to the digest context (EVP_MD_CTX) since EVP_MD_CTX is Opaque.
437 : static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(void *),
438 : "kMAX_Hash_SHA256_Context_Size needs to at least be able to store a pointer");
439 :
440 : // Storing a pointer to EVP_MD_CTX in HashSHA256OpaqueContext instead of the actual EVP_MD_CTX structure, as EVP_MD_CTX was made
441 : // opaque by OpenSSL and is dynamically allocated.
442 6327 : static inline void set_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * context, EVP_MD_CTX * evp_ctx)
443 : {
444 6327 : *SafePointerCast<EVP_MD_CTX **>(context) = evp_ctx;
445 6327 : }
446 :
447 18025 : static inline EVP_MD_CTX * to_inner_hash_evp_md_ctx(HashSHA256OpaqueContext * context)
448 : {
449 18025 : return *SafePointerCast<EVP_MD_CTX **>(context);
450 : }
451 :
452 1315 : Hash_SHA256_stream::Hash_SHA256_stream()
453 : {
454 1315 : set_inner_hash_evp_md_ctx(&mContext, nullptr);
455 1315 : }
456 :
457 1315 : Hash_SHA256_stream::~Hash_SHA256_stream()
458 : {
459 1315 : Clear();
460 1315 : }
461 :
462 1330 : CHIP_ERROR Hash_SHA256_stream::Begin()
463 : {
464 :
465 1330 : EVP_MD_CTX * mdctx = EVP_MD_CTX_new();
466 1330 : VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL);
467 :
468 1330 : set_inner_hash_evp_md_ctx(&mContext, mdctx);
469 :
470 1330 : const int result = EVP_DigestInit_ex(mdctx, _digestForType(DigestType::SHA256), nullptr);
471 :
472 1330 : VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
473 :
474 1330 : return CHIP_NO_ERROR;
475 : }
476 :
477 8211 : bool Hash_SHA256_stream::IsInitialized()
478 : {
479 8211 : EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
480 8211 : VerifyOrReturnValue(mdctx != nullptr, false);
481 :
482 : // Verify that the EVP_MD_CTX is initialized to SHA256 (ensures that EVP_DigestInit_ex was successfully called).
483 : // The legacy API EVP_MD_CTX_md() to check SHA256 initialization is deprecated in OpenSSL 3.0
484 : // and was replaced by EVP_MD_CTX_get0_md().
485 : // OpenSSL 1.1.1, which BoringSSL also uses at the time of this comment, does not support the newer replacement API.
486 : #if CHIP_CRYPTO_BORINGSSL || (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x30000000L)
487 : return EVP_MD_CTX_md(mdctx) == _digestForType(DigestType::SHA256);
488 : #else
489 8211 : return EVP_MD_CTX_get0_md(mdctx) == _digestForType(DigestType::SHA256);
490 : #endif
491 : }
492 :
493 2877 : CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
494 : {
495 2877 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear());
496 :
497 2877 : EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
498 2877 : VerifyOrReturnError(mdctx != nullptr, CHIP_ERROR_INTERNAL);
499 :
500 2877 : const int result = EVP_DigestUpdate(mdctx, data.data(), data.size());
501 :
502 2877 : VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
503 :
504 2877 : return CHIP_NO_ERROR;
505 : }
506 :
507 2079 : CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
508 : {
509 :
510 2079 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear());
511 :
512 2079 : EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
513 :
514 : // Back-up the context as we are about to finalize the hash to extract digest.
515 2079 : EVP_MD_CTX * previous_mdctx = EVP_MD_CTX_new();
516 2079 : VerifyOrReturnError(previous_mdctx != nullptr, CHIP_ERROR_INTERNAL);
517 2079 : const int copy_result = EVP_MD_CTX_copy_ex(previous_mdctx, mdctx);
518 2079 : VerifyOrReturnError(copy_result == 1, CHIP_ERROR_INTERNAL);
519 :
520 : // Pad + compute digest, then finalize context. It is restored next line to continue.
521 2079 : CHIP_ERROR result = Finish(out_buffer);
522 :
523 : // free the finalized context.
524 2079 : EVP_MD_CTX_free(mdctx);
525 :
526 : // Restore the backed up context, to be able to get intermediate digest again if needed
527 2079 : set_inner_hash_evp_md_ctx(&mContext, previous_mdctx);
528 :
529 2079 : return result;
530 : }
531 :
532 3257 : CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
533 : {
534 : unsigned int size;
535 :
536 3257 : VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
537 3255 : VerifyOrReturnError(IsInitialized(), CHIP_ERROR_UNINITIALIZED, Clear());
538 :
539 3255 : EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
540 :
541 3255 : const int result = EVP_DigestFinal_ex(mdctx, out_buffer.data(), &size);
542 :
543 3255 : VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
544 3255 : VerifyOrReturnError(size == kSHA256_Hash_Length, CHIP_ERROR_INTERNAL);
545 :
546 3255 : out_buffer = out_buffer.SubSpan(0, kSHA256_Hash_Length);
547 :
548 3255 : return CHIP_NO_ERROR;
549 : }
550 :
551 1603 : void Hash_SHA256_stream::Clear()
552 : {
553 1603 : EVP_MD_CTX * mdctx = to_inner_hash_evp_md_ctx(&mContext);
554 :
555 : // EVP_MD_CTX_free does nothing if a nullptr is passed to it
556 1603 : EVP_MD_CTX_free(mdctx);
557 1603 : set_inner_hash_evp_md_ctx(&mContext, nullptr);
558 :
559 1603 : OPENSSL_cleanse(this, sizeof(*this));
560 1603 : }
561 :
562 3778 : CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length,
563 : const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length)
564 : {
565 3778 : CHIP_ERROR error = CHIP_NO_ERROR;
566 3778 : int result = 1;
567 :
568 3778 : EVP_PKEY_CTX * const context = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, nullptr);
569 3778 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
570 :
571 3778 : VerifyOrExit(secret != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
572 3778 : VerifyOrExit(secret_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
573 :
574 : // Salt is optional
575 3778 : if (salt_length > 0)
576 : {
577 1041 : VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
578 : }
579 :
580 3778 : VerifyOrExit(info_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
581 3778 : VerifyOrExit(info != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
582 3778 : VerifyOrExit(out_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
583 3778 : VerifyOrExit(out_buffer != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
584 :
585 3778 : result = EVP_PKEY_derive_init(context);
586 3778 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
587 :
588 3778 : result = EVP_PKEY_CTX_set_hkdf_md(context, EVP_sha256());
589 3778 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
590 :
591 3778 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(secret_length), error = CHIP_ERROR_INVALID_ARGUMENT);
592 3778 : result = EVP_PKEY_CTX_set1_hkdf_key(context, Uint8::to_const_uchar(secret),
593 : static_cast<boringssl_size_t_openssl_int>(secret_length));
594 3778 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
595 :
596 3778 : if (salt_length > 0 && salt != nullptr)
597 : {
598 1041 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(salt_length), error = CHIP_ERROR_INVALID_ARGUMENT);
599 1041 : result = EVP_PKEY_CTX_set1_hkdf_salt(context, Uint8::to_const_uchar(salt),
600 : static_cast<boringssl_size_t_openssl_int>(salt_length));
601 1041 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
602 : }
603 :
604 3778 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(info_length), error = CHIP_ERROR_INVALID_ARGUMENT);
605 : result =
606 3778 : EVP_PKEY_CTX_add1_hkdf_info(context, Uint8::to_const_uchar(info), static_cast<boringssl_size_t_openssl_int>(info_length));
607 3778 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
608 :
609 3778 : result = EVP_PKEY_CTX_hkdf_mode(context, EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND);
610 3778 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
611 :
612 : // Get the OKM (Output Key Material)
613 3778 : result = EVP_PKEY_derive(context, Uint8::to_uchar(out_buffer), &out_length);
614 3778 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
615 :
616 3778 : exit:
617 3778 : if (context != nullptr)
618 : {
619 3778 : EVP_PKEY_CTX_free(context);
620 : }
621 3778 : return error;
622 : }
623 :
624 120 : CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
625 : uint8_t * out_buffer, size_t out_length)
626 : {
627 120 : VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
628 120 : VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
629 120 : VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
630 120 : VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
631 120 : VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
632 120 : VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
633 :
634 120 : CHIP_ERROR error = CHIP_ERROR_INTERNAL;
635 120 : int error_openssl = 0;
636 120 : unsigned int mac_out_len = 0;
637 :
638 120 : HMAC_CTX * mac_ctx = HMAC_CTX_new();
639 120 : VerifyOrExit(mac_ctx != nullptr, error = CHIP_ERROR_INTERNAL);
640 :
641 120 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(key_length), error = CHIP_ERROR_INVALID_ARGUMENT);
642 120 : error_openssl = HMAC_Init_ex(mac_ctx, Uint8::to_const_uchar(key), static_cast<boringssl_size_t_openssl_int>(key_length),
643 : EVP_sha256(), nullptr);
644 120 : VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
645 :
646 120 : error_openssl = HMAC_Update(mac_ctx, Uint8::to_const_uchar(message), message_length);
647 120 : VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
648 :
649 120 : mac_out_len = static_cast<unsigned int>(CHIP_CRYPTO_HASH_LEN_BYTES);
650 120 : error_openssl = HMAC_Final(mac_ctx, Uint8::to_uchar(out_buffer), &mac_out_len);
651 120 : VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
652 :
653 120 : error = CHIP_NO_ERROR;
654 120 : exit:
655 120 : HMAC_CTX_free(mac_ctx);
656 120 : return error;
657 : }
658 :
659 47 : CHIP_ERROR HMAC_sha::HMAC_SHA256(const Hmac128KeyHandle & key, const uint8_t * message, size_t message_length, uint8_t * out_buffer,
660 : size_t out_length)
661 : {
662 47 : return HMAC_SHA256(key.As<Symmetric128BitsKeyByteArray>(), sizeof(Symmetric128BitsKeyByteArray), message, message_length,
663 47 : out_buffer, out_length);
664 : }
665 :
666 19 : CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
667 : unsigned int iteration_count, uint32_t key_length, uint8_t * output)
668 : {
669 19 : CHIP_ERROR error = CHIP_NO_ERROR;
670 19 : int result = 1;
671 19 : const EVP_MD * md = nullptr;
672 :
673 19 : VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
674 18 : VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
675 18 : VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
676 16 : VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
677 15 : VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
678 14 : VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
679 14 : VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
680 :
681 14 : md = _digestForType(DigestType::SHA256);
682 14 : VerifyOrExit(md != nullptr, error = CHIP_ERROR_INTERNAL);
683 :
684 14 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(plen), error = CHIP_ERROR_INVALID_ARGUMENT);
685 14 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(slen), error = CHIP_ERROR_INVALID_ARGUMENT);
686 14 : VerifyOrExit(CanCastTo<boringssl_uint_openssl_int>(iteration_count), error = CHIP_ERROR_INVALID_ARGUMENT);
687 14 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(key_length), error = CHIP_ERROR_INVALID_ARGUMENT);
688 14 : result = PKCS5_PBKDF2_HMAC(Uint8::to_const_char(password), static_cast<boringssl_size_t_openssl_int>(plen),
689 : Uint8::to_const_uchar(salt), static_cast<boringssl_size_t_openssl_int>(slen),
690 : static_cast<boringssl_uint_openssl_int>(iteration_count), md,
691 : static_cast<boringssl_size_t_openssl_int>(key_length), Uint8::to_uchar(output));
692 :
693 14 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
694 :
695 19 : exit:
696 19 : if (error != CHIP_NO_ERROR)
697 : {
698 5 : _logSSLError();
699 : }
700 :
701 19 : return error;
702 : }
703 :
704 1 : CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold)
705 : {
706 1 : return CHIP_NO_ERROR;
707 : }
708 :
709 146793 : CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
710 : {
711 146793 : VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
712 146792 : VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
713 :
714 146791 : VerifyOrReturnError(CanCastTo<boringssl_size_t_openssl_int>(out_length), CHIP_ERROR_INVALID_ARGUMENT);
715 146791 : const int result = RAND_priv_bytes(Uint8::to_uchar(out_buffer), static_cast<boringssl_size_t_openssl_int>(out_length));
716 146791 : VerifyOrReturnError(result == 1, CHIP_ERROR_INTERNAL);
717 :
718 146791 : return CHIP_NO_ERROR;
719 : }
720 :
721 3986 : ECName MapECName(SupportedECPKeyTypes keyType)
722 : {
723 3986 : switch (keyType)
724 : {
725 3986 : case SupportedECPKeyTypes::ECP256R1:
726 3986 : return ECName::P256v1;
727 0 : default:
728 0 : return ECName::None;
729 : }
730 : }
731 :
732 1683 : static inline void from_EC_KEY(EC_KEY * key, P256KeypairContext * context)
733 : {
734 1683 : *SafePointerCast<EC_KEY **>(context) = key;
735 1683 : }
736 :
737 1982 : static inline EC_KEY * to_EC_KEY(P256KeypairContext * context)
738 : {
739 1982 : return *SafePointerCast<EC_KEY **>(context);
740 : }
741 :
742 722 : static inline const EC_KEY * to_const_EC_KEY(const P256KeypairContext * context)
743 : {
744 722 : return *SafePointerCast<const EC_KEY * const *>(context);
745 : }
746 :
747 276 : CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
748 : {
749 276 : CHIP_ERROR error = CHIP_NO_ERROR;
750 276 : int nid = NID_undef;
751 276 : EC_KEY * ec_key = nullptr;
752 276 : ECDSA_SIG * sig = nullptr;
753 276 : const BIGNUM * r = nullptr;
754 276 : const BIGNUM * s = nullptr;
755 :
756 276 : VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
757 :
758 : uint8_t digest[kSHA256_Hash_Length];
759 274 : memset(&digest[0], 0, sizeof(digest));
760 :
761 274 : ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
762 :
763 274 : ERR_clear_error();
764 :
765 : static_assert(P256ECDSASignature::Capacity() >= kP256_ECDSA_Signature_Length_Raw, "P256ECDSASignature must be large enough");
766 274 : VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
767 274 : nid = _nidForCurve(MapECName(mPublicKey.Type()));
768 274 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
769 :
770 274 : ec_key = to_EC_KEY(&mKeypair);
771 274 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
772 :
773 274 : sig = ECDSA_do_sign(Uint8::to_const_uchar(&digest[0]), static_cast<boringssl_size_t_openssl_int>(sizeof(digest)), ec_key);
774 274 : VerifyOrExit(sig != nullptr, error = CHIP_ERROR_INTERNAL);
775 274 : ECDSA_SIG_get0(sig, &r, &s);
776 274 : VerifyOrExit((r != nullptr) && (s != nullptr), error = CHIP_ERROR_INTERNAL);
777 274 : VerifyOrExit(CanCastTo<size_t>(BN_num_bytes(r)) && CanCastTo<size_t>(BN_num_bytes(s)), error = CHIP_ERROR_INTERNAL);
778 274 : VerifyOrExit((static_cast<size_t>(BN_num_bytes(r)) <= kP256_FE_Length) &&
779 : (static_cast<size_t>(BN_num_bytes(s)) <= kP256_FE_Length),
780 : error = CHIP_ERROR_INTERNAL);
781 :
782 : // Concatenate r and s to output. Sizes were checked above.
783 274 : VerifyOrExit(out_signature.SetLength(kP256_ECDSA_Signature_Length_Raw) == CHIP_NO_ERROR, error = CHIP_ERROR_INTERNAL);
784 274 : VerifyOrExit(BN_bn2binpad(r, out_signature.Bytes() + 0u, kP256_FE_Length) == kP256_FE_Length, error = CHIP_ERROR_INTERNAL);
785 274 : VerifyOrExit(BN_bn2binpad(s, out_signature.Bytes() + kP256_FE_Length, kP256_FE_Length) == kP256_FE_Length,
786 : error = CHIP_ERROR_INTERNAL);
787 :
788 274 : exit:
789 274 : if (sig != nullptr)
790 : {
791 : // SIG owns the memory of r, s
792 274 : ECDSA_SIG_free(sig);
793 : }
794 :
795 274 : if (error != CHIP_NO_ERROR)
796 : {
797 0 : _logSSLError();
798 : }
799 :
800 274 : return error;
801 : }
802 :
803 132 : CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
804 : const P256ECDSASignature & signature) const
805 : {
806 132 : VerifyOrReturnError((msg != nullptr) && (msg_length > 0), CHIP_ERROR_INVALID_ARGUMENT);
807 :
808 : uint8_t digest[kSHA256_Hash_Length];
809 130 : memset(&digest[0], 0, sizeof(digest));
810 :
811 130 : ReturnErrorOnFailure(Hash_SHA256(msg, msg_length, &digest[0]));
812 130 : return ECDSA_validate_hash_signature(&digest[0], sizeof(digest), signature);
813 : }
814 :
815 1846 : CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
816 : const P256ECDSASignature & signature) const
817 : {
818 1846 : ERR_clear_error();
819 1846 : CHIP_ERROR error = CHIP_ERROR_INTERNAL;
820 1846 : int nid = NID_undef;
821 1846 : EC_KEY * ec_key = nullptr;
822 1846 : EC_POINT * key_point = nullptr;
823 1846 : EC_GROUP * ec_group = nullptr;
824 1846 : ECDSA_SIG * ec_sig = nullptr;
825 1846 : BIGNUM * r = nullptr;
826 1846 : BIGNUM * s = nullptr;
827 1846 : int result = 0;
828 :
829 1846 : VerifyOrExit(hash != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
830 1845 : VerifyOrExit(hash_length == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
831 1844 : VerifyOrExit(signature.Length() == kP256_ECDSA_Signature_Length_Raw, error = CHIP_ERROR_INVALID_ARGUMENT);
832 :
833 1844 : nid = _nidForCurve(MapECName(Type()));
834 1844 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
835 :
836 1844 : ec_group = EC_GROUP_new_by_curve_name(nid);
837 1844 : VerifyOrExit(ec_group != nullptr, error = CHIP_ERROR_NO_MEMORY);
838 :
839 1844 : key_point = EC_POINT_new(ec_group);
840 1844 : VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_NO_MEMORY);
841 :
842 1844 : result = EC_POINT_oct2point(ec_group, key_point, Uint8::to_const_uchar(*this), Length(), nullptr);
843 1844 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
844 :
845 1844 : ec_key = EC_KEY_new_by_curve_name(nid);
846 1844 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_NO_MEMORY);
847 :
848 1844 : result = EC_KEY_set_public_key(ec_key, key_point);
849 1844 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
850 :
851 1844 : result = EC_KEY_check_key(ec_key);
852 1844 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
853 :
854 : // Build-up the signature object from raw <r,s> tuple
855 1844 : r = BN_bin2bn(Uint8::to_const_uchar(signature.ConstBytes()) + 0u, kP256_FE_Length, nullptr);
856 1844 : VerifyOrExit(r != nullptr, error = CHIP_ERROR_NO_MEMORY);
857 :
858 1844 : s = BN_bin2bn(Uint8::to_const_uchar(signature.ConstBytes()) + kP256_FE_Length, kP256_FE_Length, nullptr);
859 1844 : VerifyOrExit(s != nullptr, error = CHIP_ERROR_NO_MEMORY);
860 :
861 1844 : ec_sig = ECDSA_SIG_new();
862 1844 : VerifyOrExit(ec_sig != nullptr, error = CHIP_ERROR_NO_MEMORY);
863 :
864 1844 : result = ECDSA_SIG_set0(ec_sig, r, s);
865 1844 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
866 :
867 1844 : result = ECDSA_do_verify(Uint8::to_const_uchar(hash), static_cast<boringssl_size_t_openssl_int>(hash_length), ec_sig, ec_key);
868 1844 : VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_SIGNATURE);
869 1834 : error = CHIP_NO_ERROR;
870 :
871 1846 : exit:
872 1846 : _logSSLError();
873 1846 : if (ec_sig != nullptr)
874 : {
875 1844 : ECDSA_SIG_free(ec_sig);
876 :
877 : // After ECDSA_SIG_set0 succeeds, r and s memory is managed by ECDSA_SIG object.
878 : // We set to nullptr so that we don't try to double-free
879 1844 : r = nullptr;
880 1844 : s = nullptr;
881 : }
882 1846 : if (s != nullptr)
883 : {
884 0 : BN_clear_free(s);
885 : }
886 1846 : if (r != nullptr)
887 : {
888 0 : BN_clear_free(r);
889 : }
890 1846 : if (ec_key != nullptr)
891 : {
892 1844 : EC_KEY_free(ec_key);
893 : }
894 1846 : if (key_point != nullptr)
895 : {
896 1844 : EC_POINT_clear_free(key_point);
897 : }
898 1846 : if (ec_group != nullptr)
899 : {
900 1844 : EC_GROUP_free(ec_group);
901 : }
902 1846 : return error;
903 : }
904 :
905 : // helper function to populate octet key into EVP_PKEY out_evp_pkey. Caller must free out_evp_pkey
906 22 : static CHIP_ERROR _create_evp_key_from_binary_p256_key(const P256PublicKey & key, EVP_PKEY ** out_evp_pkey)
907 : {
908 :
909 22 : CHIP_ERROR error = CHIP_NO_ERROR;
910 22 : EC_KEY * ec_key = nullptr;
911 22 : int result = -1;
912 22 : EC_POINT * point = nullptr;
913 22 : EC_GROUP * group = nullptr;
914 22 : int nid = NID_undef;
915 :
916 22 : VerifyOrExit(*out_evp_pkey == nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
917 :
918 22 : nid = _nidForCurve(MapECName(key.Type()));
919 22 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INTERNAL);
920 :
921 22 : ec_key = EC_KEY_new_by_curve_name(nid);
922 22 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
923 :
924 22 : group = EC_GROUP_new_by_curve_name(nid);
925 22 : VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
926 :
927 22 : point = EC_POINT_new(group);
928 22 : VerifyOrExit(point != nullptr, error = CHIP_ERROR_INTERNAL);
929 :
930 22 : result = EC_POINT_oct2point(group, point, Uint8::to_const_uchar(key), key.Length(), nullptr);
931 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
932 :
933 22 : result = EC_KEY_set_public_key(ec_key, point);
934 :
935 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
936 :
937 22 : *out_evp_pkey = EVP_PKEY_new();
938 22 : VerifyOrExit(*out_evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
939 :
940 22 : result = EVP_PKEY_set1_EC_KEY(*out_evp_pkey, ec_key);
941 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
942 :
943 22 : exit:
944 22 : if (ec_key != nullptr)
945 : {
946 22 : EC_KEY_free(ec_key);
947 22 : ec_key = nullptr;
948 : }
949 :
950 22 : if (error != CHIP_NO_ERROR && *out_evp_pkey)
951 : {
952 0 : EVP_PKEY_free(*out_evp_pkey);
953 0 : out_evp_pkey = nullptr;
954 : }
955 :
956 22 : if (point != nullptr)
957 : {
958 22 : EC_POINT_free(point);
959 22 : point = nullptr;
960 : }
961 :
962 22 : if (group != nullptr)
963 : {
964 22 : EC_GROUP_free(group);
965 22 : group = nullptr;
966 : }
967 :
968 22 : return error;
969 : }
970 :
971 22 : CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
972 : {
973 22 : ERR_clear_error();
974 22 : CHIP_ERROR error = CHIP_NO_ERROR;
975 22 : int result = -1;
976 22 : EVP_PKEY * local_key = nullptr;
977 22 : EVP_PKEY * remote_key = nullptr;
978 :
979 22 : EVP_PKEY_CTX * context = nullptr;
980 22 : size_t out_buf_length = 0;
981 :
982 22 : EC_KEY * ec_key = EC_KEY_dup(to_const_EC_KEY(&mKeypair));
983 22 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
984 :
985 22 : VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
986 :
987 22 : local_key = EVP_PKEY_new();
988 22 : VerifyOrExit(local_key != nullptr, error = CHIP_ERROR_INTERNAL);
989 :
990 22 : result = EVP_PKEY_set1_EC_KEY(local_key, ec_key);
991 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
992 :
993 22 : error = _create_evp_key_from_binary_p256_key(remote_public_key, &remote_key);
994 22 : SuccessOrExit(error);
995 :
996 22 : context = EVP_PKEY_CTX_new(local_key, nullptr);
997 22 : VerifyOrExit(context != nullptr, error = CHIP_ERROR_INTERNAL);
998 :
999 22 : result = EVP_PKEY_derive_init(context);
1000 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1001 :
1002 22 : result = EVP_PKEY_derive_set_peer(context, remote_key);
1003 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1004 :
1005 22 : out_buf_length = (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length();
1006 22 : result = EVP_PKEY_derive(context, out_secret.Bytes(), &out_buf_length);
1007 22 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1008 22 : SuccessOrExit(error = out_secret.SetLength(out_buf_length));
1009 :
1010 22 : exit:
1011 22 : if (ec_key != nullptr)
1012 : {
1013 22 : EC_KEY_free(ec_key);
1014 22 : ec_key = nullptr;
1015 : }
1016 :
1017 22 : if (local_key != nullptr)
1018 : {
1019 22 : EVP_PKEY_free(local_key);
1020 22 : local_key = nullptr;
1021 : }
1022 :
1023 22 : if (remote_key != nullptr)
1024 : {
1025 22 : EVP_PKEY_free(remote_key);
1026 22 : remote_key = nullptr;
1027 : }
1028 :
1029 22 : if (context != nullptr)
1030 : {
1031 22 : EVP_PKEY_CTX_free(context);
1032 22 : context = nullptr;
1033 : }
1034 :
1035 22 : _logSSLError();
1036 22 : return error;
1037 : }
1038 :
1039 416551 : void ClearSecretData(uint8_t * buf, size_t len)
1040 : {
1041 416551 : OPENSSL_cleanse(buf, len);
1042 416551 : }
1043 :
1044 767 : bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n)
1045 : {
1046 767 : return CRYPTO_memcmp(a, b, n) == 0;
1047 : }
1048 :
1049 163 : static CHIP_ERROR P256PublicKeyFromECKey(EC_KEY * ec_key, P256PublicKey & pubkey)
1050 : {
1051 163 : ERR_clear_error();
1052 163 : CHIP_ERROR error = CHIP_NO_ERROR;
1053 :
1054 163 : int nid = NID_undef;
1055 163 : ECName curve = MapECName(pubkey.Type());
1056 163 : EC_GROUP * group = nullptr;
1057 163 : size_t pubkey_size = 0;
1058 :
1059 163 : const EC_POINT * pubkey_ecp = EC_KEY_get0_public_key(ec_key);
1060 163 : VerifyOrExit(pubkey_ecp != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
1061 :
1062 163 : nid = _nidForCurve(curve);
1063 163 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
1064 :
1065 163 : group = EC_GROUP_new_by_curve_name(nid);
1066 163 : VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
1067 :
1068 : pubkey_size =
1069 163 : EC_POINT_point2oct(group, pubkey_ecp, POINT_CONVERSION_UNCOMPRESSED, Uint8::to_uchar(pubkey), pubkey.Length(), nullptr);
1070 163 : pubkey_ecp = nullptr;
1071 :
1072 163 : VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INVALID_ARGUMENT);
1073 :
1074 163 : exit:
1075 163 : if (group != nullptr)
1076 : {
1077 163 : EC_GROUP_free(group);
1078 163 : group = nullptr;
1079 : }
1080 :
1081 163 : _logSSLError();
1082 163 : return error;
1083 : }
1084 :
1085 126 : CHIP_ERROR P256Keypair::Initialize(ECPKeyTarget key_target)
1086 : {
1087 126 : ERR_clear_error();
1088 :
1089 126 : Clear();
1090 :
1091 126 : CHIP_ERROR error = CHIP_NO_ERROR;
1092 126 : int result = 0;
1093 126 : EC_KEY * ec_key = nullptr;
1094 126 : ECName curve = MapECName(mPublicKey.Type());
1095 :
1096 126 : int nid = _nidForCurve(curve);
1097 126 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
1098 :
1099 126 : ec_key = EC_KEY_new_by_curve_name(nid);
1100 126 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
1101 :
1102 126 : result = EC_KEY_generate_key(ec_key);
1103 126 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1104 :
1105 126 : error = P256PublicKeyFromECKey(ec_key, mPublicKey);
1106 126 : SuccessOrExit(error);
1107 :
1108 126 : from_EC_KEY(ec_key, &mKeypair);
1109 126 : mInitialized = true;
1110 126 : ec_key = nullptr;
1111 :
1112 126 : exit:
1113 126 : if (ec_key != nullptr)
1114 : {
1115 0 : EC_KEY_free(ec_key);
1116 0 : ec_key = nullptr;
1117 : }
1118 :
1119 126 : _logSSLError();
1120 126 : return error;
1121 : }
1122 :
1123 700 : CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
1124 : {
1125 700 : CHIP_ERROR error = CHIP_NO_ERROR;
1126 :
1127 700 : const EC_KEY * ec_key = to_const_EC_KEY(&mKeypair);
1128 : uint8_t privkey[kP256_PrivateKey_Length];
1129 :
1130 700 : int privkey_size = 0;
1131 700 : const BIGNUM * privkey_bn = EC_KEY_get0_private_key(ec_key);
1132 700 : VerifyOrExit(privkey_bn != nullptr, error = CHIP_ERROR_INTERNAL);
1133 :
1134 700 : privkey_size = BN_bn2binpad(privkey_bn, privkey, sizeof(privkey));
1135 700 : privkey_bn = nullptr;
1136 :
1137 700 : VerifyOrExit(privkey_size > 0, error = CHIP_ERROR_INTERNAL);
1138 700 : VerifyOrExit((size_t) privkey_size == sizeof(privkey), error = CHIP_ERROR_INTERNAL);
1139 :
1140 : {
1141 700 : size_t len = output.Length() == 0 ? output.Capacity() : output.Length();
1142 700 : Encoding::BufferWriter bbuf(output.Bytes(), len);
1143 700 : bbuf.Put(mPublicKey, mPublicKey.Length());
1144 700 : bbuf.Put(privkey, sizeof(privkey));
1145 700 : VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
1146 700 : output.SetLength(bbuf.Needed());
1147 : }
1148 :
1149 700 : exit:
1150 700 : ClearSecretData(privkey, sizeof(privkey));
1151 700 : _logSSLError();
1152 700 : return error;
1153 : }
1154 :
1155 1557 : CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
1156 : {
1157 1557 : Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
1158 :
1159 1557 : Clear();
1160 :
1161 1557 : BIGNUM * pvt_key = nullptr;
1162 1557 : EC_GROUP * group = nullptr;
1163 1557 : EC_POINT * key_point = nullptr;
1164 :
1165 1557 : EC_KEY * ec_key = nullptr;
1166 1557 : ECName curve = MapECName(mPublicKey.Type());
1167 :
1168 1557 : ERR_clear_error();
1169 1557 : CHIP_ERROR error = CHIP_NO_ERROR;
1170 1557 : int result = 0;
1171 1557 : int nid = NID_undef;
1172 :
1173 1557 : const uint8_t * privkey = input.ConstBytes() + mPublicKey.Length();
1174 :
1175 1557 : VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
1176 1557 : bbuf.Put(input.ConstBytes(), mPublicKey.Length());
1177 1557 : VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
1178 :
1179 1557 : nid = _nidForCurve(curve);
1180 1557 : VerifyOrExit(nid != NID_undef, error = CHIP_ERROR_INVALID_ARGUMENT);
1181 :
1182 1557 : group = EC_GROUP_new_by_curve_name(nid);
1183 1557 : VerifyOrExit(group != nullptr, error = CHIP_ERROR_INTERNAL);
1184 :
1185 1557 : key_point = EC_POINT_new(group);
1186 1557 : VerifyOrExit(key_point != nullptr, error = CHIP_ERROR_INTERNAL);
1187 :
1188 1557 : result = EC_POINT_oct2point(group, key_point, Uint8::to_const_uchar(mPublicKey), mPublicKey.Length(), nullptr);
1189 1557 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1190 :
1191 1557 : ec_key = EC_KEY_new_by_curve_name(nid);
1192 1557 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INTERNAL);
1193 :
1194 1557 : result = EC_KEY_set_public_key(ec_key, key_point);
1195 1557 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1196 :
1197 1557 : pvt_key = BN_bin2bn(privkey, kP256_PrivateKey_Length, nullptr);
1198 1557 : VerifyOrExit(pvt_key != nullptr, error = CHIP_ERROR_INTERNAL);
1199 :
1200 1557 : result = EC_KEY_set_private_key(ec_key, pvt_key);
1201 1557 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1202 :
1203 1557 : from_EC_KEY(ec_key, &mKeypair);
1204 1557 : mInitialized = true;
1205 1557 : ec_key = nullptr;
1206 :
1207 1557 : exit:
1208 1557 : if (ec_key != nullptr)
1209 : {
1210 0 : EC_KEY_free(ec_key);
1211 0 : ec_key = nullptr;
1212 : }
1213 :
1214 1557 : if (group != nullptr)
1215 : {
1216 1557 : EC_GROUP_free(group);
1217 1557 : group = nullptr;
1218 : }
1219 :
1220 1557 : if (pvt_key != nullptr)
1221 : {
1222 1557 : BN_free(pvt_key);
1223 1557 : pvt_key = nullptr;
1224 : }
1225 :
1226 1557 : if (key_point != nullptr)
1227 : {
1228 1557 : EC_POINT_free(key_point);
1229 1557 : key_point = nullptr;
1230 : }
1231 1557 : _logSSLError();
1232 1557 : return error;
1233 : }
1234 :
1235 3346 : void P256Keypair::Clear()
1236 : {
1237 3346 : if (mInitialized)
1238 : {
1239 1683 : EC_KEY * ec_key = to_EC_KEY(&mKeypair);
1240 1683 : EC_KEY_free(ec_key);
1241 1683 : mInitialized = false;
1242 : }
1243 3346 : }
1244 :
1245 1663 : P256Keypair::~P256Keypair()
1246 : {
1247 1663 : Clear();
1248 1663 : }
1249 :
1250 25 : CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
1251 : {
1252 25 : ERR_clear_error();
1253 25 : CHIP_ERROR error = CHIP_NO_ERROR;
1254 25 : int result = 0;
1255 25 : int csr_length_local = 0;
1256 :
1257 25 : X509_REQ * x509_req = X509_REQ_new();
1258 25 : EVP_PKEY * evp_pkey = nullptr;
1259 :
1260 25 : EC_KEY * ec_key = to_EC_KEY(&mKeypair);
1261 :
1262 25 : X509_NAME * subject = X509_NAME_new();
1263 25 : VerifyOrExit(subject != nullptr, error = CHIP_ERROR_INTERNAL);
1264 :
1265 25 : VerifyOrExit(mInitialized, error = CHIP_ERROR_UNINITIALIZED);
1266 :
1267 25 : result = X509_REQ_set_version(x509_req, 0);
1268 25 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1269 :
1270 25 : result = EC_KEY_check_key(ec_key);
1271 25 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1272 :
1273 25 : evp_pkey = EVP_PKEY_new();
1274 25 : VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INTERNAL);
1275 :
1276 25 : result = EVP_PKEY_set1_EC_KEY(evp_pkey, ec_key);
1277 25 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1278 :
1279 25 : result = X509_REQ_set_pubkey(x509_req, evp_pkey);
1280 25 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1281 :
1282 : // TODO: mbedTLS CSR parser fails if the subject name is not set (or if empty).
1283 : // CHIP Spec doesn't specify the subject name that can be used.
1284 : // Figure out the correct value and update this code.
1285 25 : result = X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC, Uint8::from_const_char("CSR"), -1, -1, 0);
1286 25 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1287 :
1288 25 : result = X509_REQ_set_subject_name(x509_req, subject);
1289 25 : VerifyOrExit(result == 1, error = CHIP_ERROR_INTERNAL);
1290 :
1291 25 : result = X509_REQ_sign(x509_req, evp_pkey, EVP_sha256());
1292 25 : VerifyOrExit(result > 0, error = CHIP_ERROR_INTERNAL);
1293 :
1294 25 : csr_length_local = i2d_X509_REQ(x509_req, nullptr);
1295 25 : VerifyOrExit(csr_length_local >= 0, error = CHIP_ERROR_INTERNAL);
1296 25 : VerifyOrExit(CanCastTo<size_t>(csr_length_local), error = CHIP_ERROR_BUFFER_TOO_SMALL);
1297 25 : VerifyOrExit(static_cast<size_t>(csr_length_local) <= csr_length, error = CHIP_ERROR_BUFFER_TOO_SMALL);
1298 25 : csr_length = static_cast<size_t>(i2d_X509_REQ(x509_req, &out_csr));
1299 :
1300 25 : exit:
1301 25 : ec_key = nullptr;
1302 :
1303 25 : if (evp_pkey != nullptr)
1304 : {
1305 25 : EVP_PKEY_free(evp_pkey);
1306 25 : evp_pkey = nullptr;
1307 : }
1308 :
1309 25 : X509_NAME_free(subject);
1310 25 : subject = nullptr;
1311 :
1312 25 : X509_REQ_free(x509_req);
1313 :
1314 25 : _logSSLError();
1315 25 : return error;
1316 : }
1317 :
1318 44 : CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr, size_t csr_length, P256PublicKey & pubkey)
1319 : {
1320 44 : ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr, csr_length));
1321 :
1322 40 : ERR_clear_error();
1323 40 : CHIP_ERROR error = CHIP_NO_ERROR;
1324 40 : int result = 0;
1325 :
1326 40 : EVP_PKEY * evp_pkey = nullptr;
1327 40 : EC_KEY * ec_key = nullptr;
1328 :
1329 40 : const unsigned char * csr_buf = Uint8::to_const_uchar(csr);
1330 40 : X509_REQ * x509_req = d2i_X509_REQ(nullptr, &csr_buf, (int) csr_length);
1331 40 : VerifyOrExit(x509_req != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
1332 :
1333 40 : VerifyOrExit(X509_REQ_get_version(x509_req) == 0, error = CHIP_ERROR_INVALID_ARGUMENT);
1334 :
1335 40 : evp_pkey = X509_REQ_get_pubkey(x509_req);
1336 40 : VerifyOrExit(evp_pkey != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
1337 :
1338 40 : result = X509_REQ_verify(x509_req, evp_pkey);
1339 40 : VerifyOrExit(result == 1, error = CHIP_ERROR_INVALID_ARGUMENT);
1340 :
1341 37 : ec_key = EVP_PKEY_get1_EC_KEY(evp_pkey);
1342 37 : VerifyOrExit(ec_key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
1343 :
1344 37 : error = P256PublicKeyFromECKey(ec_key, pubkey);
1345 37 : SuccessOrExit(error);
1346 :
1347 40 : exit:
1348 :
1349 40 : if (x509_req != nullptr)
1350 : {
1351 40 : X509_REQ_free(x509_req);
1352 : }
1353 :
1354 40 : if (ec_key != nullptr)
1355 : {
1356 37 : EC_KEY_free(ec_key);
1357 : }
1358 :
1359 40 : if (evp_pkey != nullptr)
1360 : {
1361 40 : EVP_PKEY_free(evp_pkey);
1362 : }
1363 40 : _logSSLError();
1364 40 : return error;
1365 : }
1366 :
1367 : #define init_point(_point_) \
1368 : do \
1369 : { \
1370 : _point_ = EC_POINT_new(context->curve); \
1371 : VerifyOrReturnError(_point_ != nullptr, CHIP_ERROR_INTERNAL); \
1372 : } while (0)
1373 :
1374 : #define init_bn(_bn_) \
1375 : do \
1376 : { \
1377 : _bn_ = BN_new(); \
1378 : VerifyOrReturnError(_bn_ != nullptr, CHIP_ERROR_INTERNAL); \
1379 : } while (0)
1380 :
1381 : #define free_point(_point_) \
1382 : do \
1383 : { \
1384 : if (_point_ != nullptr) \
1385 : { \
1386 : EC_POINT_clear_free(static_cast<EC_POINT *>(_point_)); \
1387 : } \
1388 : } while (0)
1389 :
1390 : #define free_bn(_bn_) \
1391 : do \
1392 : { \
1393 : if (_bn_ != nullptr) \
1394 : { \
1395 : BN_clear_free(static_cast<BIGNUM *>(_bn_)); \
1396 : } \
1397 : } while (0)
1398 :
1399 : typedef struct Spake2p_Context
1400 : {
1401 : EC_GROUP * curve;
1402 : BN_CTX * bn_ctx;
1403 : const EVP_MD * md_info;
1404 : } Spake2p_Context;
1405 :
1406 1422 : static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context)
1407 : {
1408 1422 : return SafePointerCast<Spake2p_Context *>(context);
1409 : }
1410 :
1411 148 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal()
1412 : {
1413 148 : Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1414 :
1415 148 : context->curve = nullptr;
1416 148 : context->bn_ctx = nullptr;
1417 148 : context->md_info = nullptr;
1418 :
1419 148 : context->curve = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
1420 148 : VerifyOrReturnError(context->curve != nullptr, CHIP_ERROR_INTERNAL);
1421 :
1422 148 : G = EC_GROUP_get0_generator(context->curve);
1423 148 : VerifyOrReturnError(G != nullptr, CHIP_ERROR_INTERNAL);
1424 :
1425 148 : context->bn_ctx = BN_CTX_secure_new();
1426 148 : VerifyOrReturnError(context->bn_ctx != nullptr, CHIP_ERROR_INTERNAL);
1427 :
1428 148 : context->md_info = EVP_sha256();
1429 148 : VerifyOrReturnError(context->md_info != nullptr, CHIP_ERROR_INTERNAL);
1430 :
1431 148 : init_point(M);
1432 148 : init_point(N);
1433 148 : init_point(X);
1434 148 : init_point(Y);
1435 148 : init_point(L);
1436 148 : init_point(V);
1437 148 : init_point(Z);
1438 148 : init_bn(w0);
1439 148 : init_bn(w1);
1440 148 : init_bn(xy);
1441 148 : init_bn(tempbn);
1442 148 : init_bn(order);
1443 :
1444 148 : const int error_openssl = EC_GROUP_get_order(context->curve, static_cast<BIGNUM *>(order), context->bn_ctx);
1445 148 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1446 :
1447 148 : return CHIP_NO_ERROR;
1448 : }
1449 :
1450 216 : void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
1451 : {
1452 216 : VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT);
1453 :
1454 148 : Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1455 :
1456 148 : if (context->curve != nullptr)
1457 : {
1458 148 : EC_GROUP_clear_free(context->curve);
1459 : }
1460 :
1461 148 : if (context->bn_ctx != nullptr)
1462 : {
1463 148 : BN_CTX_free(context->bn_ctx);
1464 : }
1465 :
1466 148 : sha256_hash_ctx.Clear();
1467 :
1468 148 : free_point(M);
1469 148 : free_point(N);
1470 148 : free_point(X);
1471 148 : free_point(Y);
1472 148 : free_point(L);
1473 148 : free_point(V);
1474 148 : free_point(Z);
1475 148 : free_bn(w0);
1476 148 : free_bn(w1);
1477 148 : free_bn(xy);
1478 148 : free_bn(tempbn);
1479 148 : free_bn(order);
1480 :
1481 148 : state = CHIP_SPAKE2P_STATE::PREINIT;
1482 : }
1483 :
1484 49 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len,
1485 : MutableByteSpan & out_span)
1486 : {
1487 49 : HMAC_sha hmac;
1488 49 : VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
1489 49 : ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length));
1490 49 : out_span = out_span.SubSpan(0, kSHA256_Hash_Length);
1491 49 : return CHIP_NO_ERROR;
1492 49 : }
1493 :
1494 24 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len,
1495 : const uint8_t * in, size_t in_len)
1496 : {
1497 24 : VerifyOrReturnError(mac_len == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
1498 :
1499 : uint8_t computed_mac[kSHA256_Hash_Length];
1500 24 : MutableByteSpan computed_mac_span{ computed_mac };
1501 24 : ReturnErrorOnFailure(Mac(key, key_len, in, in_len, computed_mac_span));
1502 24 : VerifyOrReturnError(computed_mac_span.size() == mac_len, CHIP_ERROR_INTERNAL);
1503 :
1504 24 : VerifyOrReturnError(CRYPTO_memcmp(mac, computed_mac_span.data(), computed_mac_span.size()) == 0, CHIP_ERROR_INTERNAL);
1505 :
1506 23 : return CHIP_NO_ERROR;
1507 : }
1508 :
1509 148 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe)
1510 : {
1511 148 : BIGNUM * const bn_fe = static_cast<BIGNUM *>(fe);
1512 :
1513 148 : Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
1514 :
1515 148 : VerifyOrReturnError(CanCastTo<boringssl_size_t_openssl_int>(in_len), CHIP_ERROR_INTERNAL);
1516 148 : BN_bin2bn(Uint8::to_const_uchar(in), static_cast<boringssl_size_t_openssl_int>(in_len), bn_fe);
1517 148 : const int error_openssl = BN_mod(bn_fe, bn_fe, (BIGNUM *) order, context->bn_ctx);
1518 148 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1519 :
1520 148 : return CHIP_NO_ERROR;
1521 : }
1522 :
1523 50 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len)
1524 : {
1525 50 : VerifyOrReturnError(CanCastTo<int>(out_len), CHIP_ERROR_INTERNAL);
1526 50 : const int bn_out_len = BN_bn2binpad(static_cast<const BIGNUM *>(fe), Uint8::to_uchar(out), static_cast<int>(out_len));
1527 50 : VerifyOrReturnError(bn_out_len == static_cast<int>(out_len), CHIP_ERROR_INTERNAL);
1528 :
1529 50 : return CHIP_NO_ERROR;
1530 : }
1531 :
1532 12 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe)
1533 : {
1534 12 : const int error_openssl = BN_rand_range(static_cast<BIGNUM *>(fe), static_cast<BIGNUM *>(order));
1535 12 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1536 :
1537 12 : return CHIP_NO_ERROR;
1538 : }
1539 :
1540 50 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2)
1541 : {
1542 50 : const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1543 :
1544 50 : const int error_openssl = BN_mod_mul(static_cast<BIGNUM *>(fer), static_cast<const BIGNUM *>(fe1),
1545 50 : static_cast<const BIGNUM *>(fe2), static_cast<BIGNUM *>(order), context->bn_ctx);
1546 50 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1547 :
1548 50 : return CHIP_NO_ERROR;
1549 : }
1550 :
1551 436 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R)
1552 : {
1553 436 : const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1554 :
1555 : const int error_openssl =
1556 436 : EC_POINT_oct2point(context->curve, static_cast<EC_POINT *>(R), Uint8::to_const_uchar(in), in_len, context->bn_ctx);
1557 436 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1558 :
1559 416 : return CHIP_NO_ERROR;
1560 : }
1561 :
1562 165 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len)
1563 : {
1564 165 : const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1565 :
1566 165 : const size_t ec_out_len = EC_POINT_point2oct(context->curve, static_cast<const EC_POINT *>(R), POINT_CONVERSION_UNCOMPRESSED,
1567 165 : Uint8::to_uchar(out), out_len, context->bn_ctx);
1568 165 : VerifyOrReturnError(ec_out_len == out_len, CHIP_ERROR_INTERNAL);
1569 :
1570 165 : return CHIP_NO_ERROR;
1571 : }
1572 :
1573 170 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1)
1574 : {
1575 170 : const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1576 :
1577 170 : const int error_openssl = EC_POINT_mul(context->curve, static_cast<EC_POINT *>(R), nullptr, static_cast<const EC_POINT *>(P1),
1578 170 : static_cast<const BIGNUM *>(fe1), context->bn_ctx);
1579 170 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1580 :
1581 170 : return CHIP_NO_ERROR;
1582 : }
1583 :
1584 70 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2,
1585 : const void * fe2)
1586 : {
1587 70 : CHIP_ERROR error = CHIP_ERROR_INTERNAL;
1588 70 : int error_openssl = 0;
1589 70 : EC_POINT * scratch = nullptr;
1590 :
1591 70 : Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
1592 :
1593 70 : scratch = EC_POINT_new(context->curve);
1594 70 : VerifyOrExit(scratch != nullptr, error = CHIP_ERROR_INTERNAL);
1595 :
1596 70 : SuccessOrExit(error = PointMul(scratch, P1, fe1));
1597 70 : SuccessOrExit(error = PointMul(R, P2, fe2));
1598 :
1599 70 : error_openssl = EC_POINT_add(context->curve, static_cast<EC_POINT *>(R), static_cast<EC_POINT *>(R),
1600 : static_cast<const EC_POINT *>(scratch), context->bn_ctx);
1601 70 : VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
1602 :
1603 70 : error = CHIP_NO_ERROR;
1604 70 : exit:
1605 70 : EC_POINT_clear_free(scratch);
1606 70 : return error;
1607 : }
1608 :
1609 20 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R)
1610 : {
1611 20 : const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1612 :
1613 20 : const int error_openssl = EC_POINT_invert(context->curve, static_cast<EC_POINT *>(R), context->bn_ctx);
1614 20 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1615 :
1616 20 : return CHIP_NO_ERROR;
1617 : }
1618 :
1619 40 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R)
1620 : {
1621 : // Cofactor on P256 is 1 so this is a NOP
1622 40 : return CHIP_NO_ERROR;
1623 : }
1624 :
1625 7 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1sin, size_t w1sin_len)
1626 : {
1627 7 : CHIP_ERROR error = CHIP_ERROR_INTERNAL;
1628 7 : int error_openssl = 0;
1629 7 : BIGNUM * w1_bn = nullptr;
1630 7 : EC_POINT * Lout_point = nullptr;
1631 :
1632 7 : Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
1633 :
1634 7 : w1_bn = BN_new();
1635 7 : VerifyOrExit(w1_bn != nullptr, error = CHIP_ERROR_INTERNAL);
1636 :
1637 7 : Lout_point = EC_POINT_new(context->curve);
1638 7 : VerifyOrExit(Lout_point != nullptr, error = CHIP_ERROR_INTERNAL);
1639 :
1640 7 : VerifyOrExit(CanCastTo<boringssl_size_t_openssl_int>(w1sin_len), error = CHIP_ERROR_INTERNAL);
1641 7 : BN_bin2bn(Uint8::to_const_uchar(w1sin), static_cast<boringssl_size_t_openssl_int>(w1sin_len), w1_bn);
1642 7 : error_openssl = BN_mod(w1_bn, w1_bn, (BIGNUM *) order, context->bn_ctx);
1643 7 : VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
1644 :
1645 7 : error_openssl = EC_POINT_mul(context->curve, Lout_point, w1_bn, nullptr, nullptr, context->bn_ctx);
1646 7 : VerifyOrExit(error_openssl == 1, error = CHIP_ERROR_INTERNAL);
1647 :
1648 7 : *L_len = EC_POINT_point2oct(context->curve, Lout_point, POINT_CONVERSION_UNCOMPRESSED, Uint8::to_uchar(Lout), *L_len,
1649 : context->bn_ctx);
1650 7 : VerifyOrExit(*L_len != 0, error = CHIP_ERROR_INTERNAL);
1651 :
1652 7 : error = CHIP_NO_ERROR;
1653 7 : exit:
1654 7 : BN_clear_free(w1_bn);
1655 7 : EC_POINT_clear_free(Lout_point);
1656 :
1657 7 : return error;
1658 : }
1659 :
1660 60 : CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R)
1661 : {
1662 60 : const Spake2p_Context * const context = to_inner_spake2p_context(&mSpake2pContext);
1663 :
1664 60 : const int error_openssl = EC_POINT_is_on_curve(context->curve, static_cast<EC_POINT *>(R), context->bn_ctx);
1665 60 : VerifyOrReturnError(error_openssl == 1, CHIP_ERROR_INTERNAL);
1666 :
1667 40 : return CHIP_NO_ERROR;
1668 : }
1669 :
1670 299 : CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType)
1671 : {
1672 299 : CHIP_ERROR err = CHIP_NO_ERROR;
1673 299 : const uint8_t * certPtr = cert.data();
1674 299 : X509 * x509Cert = nullptr;
1675 299 : bool extBasicPresent = false;
1676 299 : bool extKeyUsagePresent = false;
1677 299 : bool extSKIDPresent = false;
1678 299 : bool extAKIDPresent = false;
1679 :
1680 299 : VerifyOrReturnError(!cert.empty() && CanCastTo<long>(cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
1681 :
1682 298 : x509Cert = d2i_X509(nullptr, &certPtr, static_cast<long>(cert.size()));
1683 298 : VerifyOrExit(x509Cert != nullptr, err = CHIP_ERROR_INTERNAL);
1684 :
1685 298 : VerifyOrExit(X509_get_version(x509Cert) == 2, err = CHIP_ERROR_INTERNAL);
1686 296 : VerifyOrExit(X509_get_serialNumber(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
1687 296 : VerifyOrExit(X509_get_signature_nid(x509Cert) == NID_ecdsa_with_SHA256, err = CHIP_ERROR_INTERNAL);
1688 294 : VerifyOrExit(X509_get_issuer_name(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
1689 294 : VerifyOrExit(X509_get_notBefore(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
1690 294 : VerifyOrExit(X509_get_notAfter(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
1691 294 : VerifyOrExit(X509_get_subject_name(x509Cert) != nullptr, err = CHIP_ERROR_INTERNAL);
1692 :
1693 : // Verify public key presence and format.
1694 : {
1695 294 : Crypto::P256PublicKey pubkey;
1696 294 : SuccessOrExit(err = ExtractPubkeyFromX509Cert(cert, pubkey));
1697 294 : }
1698 :
1699 1352 : for (int i = 0; i < X509_get_ext_count(x509Cert); i++)
1700 : {
1701 1089 : X509_EXTENSION * ex = X509_get_ext(x509Cert, i);
1702 1089 : ASN1_OBJECT * obj = X509_EXTENSION_get_object(ex);
1703 1089 : bool isCritical = X509_EXTENSION_get_critical(ex) == 1;
1704 :
1705 1089 : switch (OBJ_obj2nid(obj))
1706 : {
1707 291 : case NID_basic_constraints:
1708 291 : VerifyOrExit(isCritical && !extBasicPresent, err = CHIP_ERROR_INTERNAL);
1709 287 : extBasicPresent = true;
1710 : {
1711 287 : bool isCA = X509_get_extension_flags(x509Cert) & EXFLAG_CA;
1712 287 : long pathLen = X509_get_pathlen(x509Cert);
1713 287 : if (certType == AttestationCertType::kDAC)
1714 : {
1715 132 : VerifyOrExit(!isCA && pathLen == -1, err = CHIP_ERROR_INTERNAL);
1716 : }
1717 155 : else if (certType == AttestationCertType::kPAI)
1718 : {
1719 151 : VerifyOrExit(isCA && pathLen == 0, err = CHIP_ERROR_INTERNAL);
1720 : }
1721 : else
1722 : {
1723 : // For PAA, pathlen must be absent or equal to 1 (see Matter 1.1 spec 6.2.2.5)
1724 4 : VerifyOrExit(isCA && (pathLen == -1 || pathLen == 1), err = CHIP_ERROR_INTERNAL);
1725 : }
1726 : }
1727 270 : break;
1728 270 : case NID_key_usage:
1729 270 : VerifyOrExit(isCritical && !extKeyUsagePresent, err = CHIP_ERROR_INTERNAL);
1730 266 : extKeyUsagePresent = true;
1731 : {
1732 266 : uint32_t keyUsage = X509_get_key_usage(x509Cert);
1733 266 : if (certType == AttestationCertType::kDAC)
1734 : {
1735 : // SHALL only have the digitalSignature bit set.
1736 123 : VerifyOrExit(keyUsage == X509v3_KU_DIGITAL_SIGNATURE, err = CHIP_ERROR_INTERNAL);
1737 : }
1738 : else
1739 : {
1740 143 : bool keyCertSignFlag = keyUsage & X509v3_KU_KEY_CERT_SIGN;
1741 143 : bool crlSignFlag = keyUsage & X509v3_KU_CRL_SIGN;
1742 143 : bool otherFlags = keyUsage &
1743 : ~static_cast<uint32_t>(X509v3_KU_CRL_SIGN | X509v3_KU_KEY_CERT_SIGN | X509v3_KU_DIGITAL_SIGNATURE);
1744 143 : VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, err = CHIP_ERROR_INTERNAL);
1745 : }
1746 : }
1747 261 : break;
1748 261 : case NID_subject_key_identifier:
1749 261 : VerifyOrExit(!isCritical && !extSKIDPresent, err = CHIP_ERROR_INTERNAL);
1750 261 : VerifyOrExit(X509_get0_subject_key_id(x509Cert)->length == kSubjectKeyIdentifierLength, err = CHIP_ERROR_INTERNAL);
1751 261 : extSKIDPresent = true;
1752 261 : break;
1753 261 : case NID_authority_key_identifier:
1754 261 : VerifyOrExit(!isCritical && !extAKIDPresent, err = CHIP_ERROR_INTERNAL);
1755 261 : VerifyOrExit(X509_get0_authority_key_id(x509Cert)->length == kAuthorityKeyIdentifierLength, err = CHIP_ERROR_INTERNAL);
1756 261 : extAKIDPresent = true;
1757 261 : break;
1758 6 : default:
1759 6 : break;
1760 : }
1761 : }
1762 : // Mandatory extensions for all certs.
1763 263 : VerifyOrExit(extBasicPresent && extKeyUsagePresent && extSKIDPresent, err = CHIP_ERROR_INTERNAL);
1764 :
1765 257 : if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI)
1766 : {
1767 : // Mandatory extension for DAC and PAI certs.
1768 255 : VerifyOrExit(extAKIDPresent, err = CHIP_ERROR_INTERNAL);
1769 : }
1770 :
1771 2 : exit:
1772 298 : X509_free(x509Cert);
1773 :
1774 298 : return err;
1775 : }
1776 :
1777 112 : CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
1778 : size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
1779 : CertificateChainValidationResult & result)
1780 : {
1781 112 : CHIP_ERROR err = CHIP_NO_ERROR;
1782 112 : int status = 0;
1783 112 : X509_STORE_CTX * verifyCtx = nullptr;
1784 112 : X509_STORE * store = nullptr;
1785 112 : STACK_OF(X509) * chain = nullptr;
1786 112 : X509 * x509RootCertificate = nullptr;
1787 112 : X509 * x509CACertificate = nullptr;
1788 112 : X509 * x509LeafCertificate = nullptr;
1789 :
1790 112 : result = CertificateChainValidationResult::kInternalFrameworkError;
1791 :
1792 112 : VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0 && CanCastTo<long>(rootCertificateLen),
1793 : (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
1794 111 : VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0 && CanCastTo<long>(leafCertificateLen),
1795 : (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
1796 :
1797 110 : store = X509_STORE_new();
1798 110 : VerifyOrExit(store != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
1799 :
1800 110 : verifyCtx = X509_STORE_CTX_new();
1801 110 : VerifyOrExit(verifyCtx != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
1802 :
1803 110 : chain = sk_X509_new_null();
1804 110 : VerifyOrExit(chain != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
1805 :
1806 110 : VerifyOrExit(CanCastTo<long>(rootCertificateLen),
1807 : (result = CertificateChainValidationResult::kRootArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
1808 110 : x509RootCertificate = d2i_X509(nullptr, &rootCertificate, static_cast<long>(rootCertificateLen));
1809 110 : VerifyOrExit(x509RootCertificate != nullptr,
1810 : (result = CertificateChainValidationResult::kRootFormatInvalid, err = CHIP_ERROR_INTERNAL));
1811 :
1812 110 : status = X509_STORE_add_cert(store, x509RootCertificate);
1813 110 : VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
1814 :
1815 110 : if (caCertificate != nullptr && caCertificateLen > 0)
1816 : {
1817 106 : VerifyOrExit(CanCastTo<long>(caCertificateLen),
1818 : (result = CertificateChainValidationResult::kICAArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
1819 106 : x509CACertificate = d2i_X509(nullptr, &caCertificate, static_cast<long>(caCertificateLen));
1820 106 : VerifyOrExit(x509CACertificate != nullptr,
1821 : (result = CertificateChainValidationResult::kICAFormatInvalid, err = CHIP_ERROR_INTERNAL));
1822 :
1823 106 : status = static_cast<int>(sk_X509_push(chain, x509CACertificate));
1824 106 : VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
1825 : }
1826 :
1827 110 : VerifyOrExit(CanCastTo<long>(leafCertificateLen),
1828 : (result = CertificateChainValidationResult::kLeafArgumentInvalid, err = CHIP_ERROR_INVALID_ARGUMENT));
1829 110 : x509LeafCertificate = d2i_X509(nullptr, &leafCertificate, static_cast<long>(leafCertificateLen));
1830 110 : VerifyOrExit(x509LeafCertificate != nullptr,
1831 : (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
1832 :
1833 110 : status = X509_STORE_CTX_init(verifyCtx, store, x509LeafCertificate, chain);
1834 110 : VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kInternalFrameworkError, err = CHIP_ERROR_INTERNAL));
1835 :
1836 : // Set time used in the X509 certificate chain validation to the notBefore time of the leaf certificate.
1837 : // That way the X509_verify_cert() validates that intermediate and root certificates were
1838 : // valid at the time of the leaf certificate generation.
1839 : {
1840 110 : X509_VERIFY_PARAM * param = X509_STORE_CTX_get0_param(verifyCtx);
1841 : chip::ASN1::ASN1UniversalTime asn1Time;
1842 110 : char * asn1TimeStr = reinterpret_cast<char *>(X509_get_notBefore(x509LeafCertificate)->data);
1843 : uint32_t unixEpoch;
1844 :
1845 110 : VerifyOrExit(param != nullptr, (result = CertificateChainValidationResult::kNoMemory, err = CHIP_ERROR_NO_MEMORY));
1846 :
1847 110 : VerifyOrExit(CHIP_NO_ERROR == asn1Time.ImportFrom_ASN1_TIME_string(CharSpan(asn1TimeStr, strlen(asn1TimeStr))),
1848 : (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
1849 :
1850 110 : VerifyOrExit(asn1Time.ExportTo_UnixTime(unixEpoch),
1851 : (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
1852 :
1853 110 : VerifyOrExit(CanCastTo<time_t>(unixEpoch),
1854 : (result = CertificateChainValidationResult::kLeafFormatInvalid, err = CHIP_ERROR_INTERNAL));
1855 110 : X509_VERIFY_PARAM_set_time(param, static_cast<time_t>(unixEpoch));
1856 110 : X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_X509_STRICT);
1857 : }
1858 :
1859 110 : status = X509_verify_cert(verifyCtx);
1860 110 : VerifyOrExit(status == 1, (result = CertificateChainValidationResult::kChainInvalid, err = CHIP_ERROR_CERT_NOT_TRUSTED));
1861 :
1862 100 : err = CHIP_NO_ERROR;
1863 100 : result = CertificateChainValidationResult::kSuccess;
1864 :
1865 110 : exit:
1866 110 : X509_free(x509LeafCertificate);
1867 110 : X509_free(x509CACertificate);
1868 110 : X509_free(x509RootCertificate);
1869 110 : sk_X509_free(chain);
1870 110 : X509_STORE_CTX_free(verifyCtx);
1871 110 : X509_STORE_free(store);
1872 :
1873 110 : return err;
1874 : }
1875 :
1876 14 : CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & candidateCertificate, const ByteSpan & issuerCertificate)
1877 : {
1878 14 : CHIP_ERROR error = CHIP_NO_ERROR;
1879 14 : X509 * x509CandidateCertificate = nullptr;
1880 14 : X509 * x509issuerCertificate = nullptr;
1881 14 : const unsigned char * pCandidateCertificate = candidateCertificate.data();
1882 14 : const unsigned char * pIssuerCertificate = issuerCertificate.data();
1883 14 : ASN1_TIME * candidateNotBeforeTime = nullptr;
1884 14 : ASN1_TIME * issuerNotBeforeTime = nullptr;
1885 14 : ASN1_TIME * issuerNotAfterTime = nullptr;
1886 14 : int result = 0;
1887 14 : int days = 0;
1888 14 : int seconds = 0;
1889 :
1890 14 : VerifyOrReturnError(!candidateCertificate.empty() && CanCastTo<long>(candidateCertificate.size()) &&
1891 : !issuerCertificate.empty() && CanCastTo<long>(issuerCertificate.size()),
1892 : CHIP_ERROR_INVALID_ARGUMENT);
1893 :
1894 12 : x509CandidateCertificate = d2i_X509(nullptr, &pCandidateCertificate, static_cast<long>(candidateCertificate.size()));
1895 12 : VerifyOrExit(x509CandidateCertificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
1896 :
1897 12 : x509issuerCertificate = d2i_X509(nullptr, &pIssuerCertificate, static_cast<long>(issuerCertificate.size()));
1898 12 : VerifyOrExit(x509issuerCertificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
1899 :
1900 12 : candidateNotBeforeTime = X509_get_notBefore(x509CandidateCertificate);
1901 12 : issuerNotBeforeTime = X509_get_notBefore(x509issuerCertificate);
1902 12 : issuerNotAfterTime = X509_get_notAfter(x509issuerCertificate);
1903 12 : VerifyOrExit(candidateNotBeforeTime && issuerNotBeforeTime && issuerNotAfterTime, error = CHIP_ERROR_INTERNAL);
1904 :
1905 12 : result = ASN1_TIME_diff(&days, &seconds, issuerNotBeforeTime, candidateNotBeforeTime);
1906 12 : VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
1907 12 : result = _compareDaysAndSeconds(days, seconds);
1908 :
1909 : // check if candidateCertificate is issued at or after tbeCertificate's notBefore timestamp
1910 12 : VerifyOrExit(result >= 0, error = CHIP_ERROR_CERT_EXPIRED);
1911 :
1912 8 : result = ASN1_TIME_diff(&days, &seconds, issuerNotAfterTime, candidateNotBeforeTime);
1913 8 : VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
1914 8 : result = _compareDaysAndSeconds(days, seconds);
1915 :
1916 : // check if candidateCertificate is issued at or before tbeCertificate's notAfter timestamp
1917 8 : VerifyOrExit(result <= 0, error = CHIP_ERROR_CERT_EXPIRED);
1918 :
1919 12 : exit:
1920 12 : X509_free(x509CandidateCertificate);
1921 12 : X509_free(x509issuerCertificate);
1922 :
1923 12 : return error;
1924 : }
1925 :
1926 92 : CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate)
1927 : {
1928 92 : CHIP_ERROR error = CHIP_NO_ERROR;
1929 92 : X509 * x509Certificate = nullptr;
1930 92 : const unsigned char * pCertificate = certificate.data();
1931 92 : ASN1_TIME * time = nullptr;
1932 92 : int result = 0;
1933 :
1934 92 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
1935 :
1936 92 : x509Certificate = d2i_X509(nullptr, &pCertificate, static_cast<long>(certificate.size()));
1937 92 : VerifyOrExit(x509Certificate != nullptr, error = CHIP_ERROR_NO_MEMORY);
1938 :
1939 92 : time = X509_get_notBefore(x509Certificate);
1940 92 : VerifyOrExit(time, error = CHIP_ERROR_INTERNAL);
1941 :
1942 92 : result = X509_cmp_current_time(time);
1943 : // check if certificate's notBefore timestamp is earlier than or equal to current time.
1944 92 : VerifyOrExit(result == -1, error = CHIP_ERROR_CERT_EXPIRED);
1945 :
1946 91 : time = X509_get_notAfter(x509Certificate);
1947 91 : VerifyOrExit(time, error = CHIP_ERROR_INTERNAL);
1948 :
1949 91 : result = X509_cmp_current_time(time);
1950 : // check if certificate's notAfter timestamp is later than current time.
1951 91 : VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
1952 :
1953 92 : exit:
1954 92 : X509_free(x509Certificate);
1955 :
1956 92 : return error;
1957 : }
1958 :
1959 412 : CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey)
1960 : {
1961 412 : CHIP_ERROR err = CHIP_NO_ERROR;
1962 412 : EC_KEY * ec_key = nullptr;
1963 412 : EVP_PKEY * pkey = nullptr;
1964 412 : X509 * x509certificate = nullptr;
1965 412 : const unsigned char * pCertificate = certificate.data();
1966 412 : const unsigned char ** ppCertificate = &pCertificate;
1967 412 : unsigned char * pPubkey = pubkey;
1968 412 : unsigned char ** ppPubkey = &pPubkey;
1969 : int pkeyLen;
1970 :
1971 412 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
1972 :
1973 412 : x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
1974 412 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
1975 :
1976 412 : pkey = X509_get_pubkey(x509certificate);
1977 412 : VerifyOrExit(pkey != nullptr, err = CHIP_ERROR_INTERNAL);
1978 412 : VerifyOrExit(EVP_PKEY_base_id(pkey) == EVP_PKEY_EC, err = CHIP_ERROR_INTERNAL);
1979 412 : VerifyOrExit(EVP_PKEY_bits(pkey) == 256, err = CHIP_ERROR_INTERNAL);
1980 :
1981 412 : ec_key = EVP_PKEY_get1_EC_KEY(pkey);
1982 412 : VerifyOrExit(ec_key != nullptr, err = CHIP_ERROR_NO_MEMORY);
1983 412 : VerifyOrExit(EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) == NID_X9_62_prime256v1, err = CHIP_ERROR_INTERNAL);
1984 :
1985 411 : pkeyLen = i2d_PublicKey(pkey, nullptr);
1986 411 : VerifyOrExit(pkeyLen == static_cast<int>(pubkey.Length()), err = CHIP_ERROR_INTERNAL);
1987 :
1988 411 : VerifyOrExit(i2d_PublicKey(pkey, ppPubkey) == pkeyLen, err = CHIP_ERROR_INTERNAL);
1989 :
1990 412 : exit:
1991 412 : EC_KEY_free(ec_key);
1992 412 : EVP_PKEY_free(pkey);
1993 412 : X509_free(x509certificate);
1994 :
1995 412 : return err;
1996 : }
1997 :
1998 : namespace {
1999 :
2000 381 : CHIP_ERROR ExtractKIDFromX509Cert(bool isSKID, const ByteSpan & certificate, MutableByteSpan & kid)
2001 : {
2002 381 : CHIP_ERROR err = CHIP_NO_ERROR;
2003 381 : X509 * x509certificate = nullptr;
2004 381 : const unsigned char * pCertificate = certificate.data();
2005 381 : const unsigned char ** ppCertificate = &pCertificate;
2006 381 : const ASN1_OCTET_STRING * kidString = nullptr;
2007 :
2008 381 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
2009 :
2010 381 : x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
2011 381 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2012 :
2013 381 : kidString = isSKID ? X509_get0_subject_key_id(x509certificate) : X509_get0_authority_key_id(x509certificate);
2014 381 : VerifyOrExit(kidString != nullptr, err = CHIP_ERROR_NOT_FOUND);
2015 379 : VerifyOrExit(CanCastTo<size_t>(kidString->length), err = CHIP_ERROR_INVALID_ARGUMENT);
2016 379 : VerifyOrExit(kidString->length == kSubjectKeyIdentifierLength, err = CHIP_ERROR_WRONG_CERT_TYPE);
2017 379 : VerifyOrExit(static_cast<size_t>(kidString->length) <= kid.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
2018 :
2019 379 : memcpy(kid.data(), kidString->data, static_cast<size_t>(kidString->length));
2020 :
2021 379 : kid.reduce_size(static_cast<size_t>(kidString->length));
2022 :
2023 381 : exit:
2024 381 : X509_free(x509certificate);
2025 :
2026 381 : return err;
2027 : }
2028 :
2029 : } // namespace
2030 :
2031 248 : CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid)
2032 : {
2033 248 : return ExtractKIDFromX509Cert(true, certificate, skid);
2034 : }
2035 :
2036 133 : CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid)
2037 : {
2038 133 : return ExtractKIDFromX509Cert(false, certificate, akid);
2039 : }
2040 :
2041 19 : CHIP_ERROR ExtractCRLDistributionPointURIFromX509Cert(const ByteSpan & certificate, MutableCharSpan & cdpurl)
2042 : {
2043 19 : CHIP_ERROR err = CHIP_NO_ERROR;
2044 19 : X509 * x509certificate = nullptr;
2045 19 : const unsigned char * pCertificate = certificate.data();
2046 19 : const unsigned char ** ppCertificate = &pCertificate;
2047 19 : STACK_OF(DIST_POINT) * crldp = nullptr;
2048 19 : DIST_POINT * dp = nullptr;
2049 19 : GENERAL_NAMES * gens = nullptr;
2050 19 : GENERAL_NAME * gen = nullptr;
2051 19 : ASN1_STRING * uri = nullptr;
2052 19 : const char * urlptr = nullptr;
2053 19 : size_t len = 0;
2054 :
2055 19 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
2056 :
2057 18 : x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
2058 18 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2059 :
2060 : // CRL Distribution Point Extension is encoded as a sequence of DistributionPoint:
2061 : // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
2062 : //
2063 : // This implementation only supports a single DistributionPoint (sequence of size 1)
2064 : crldp =
2065 18 : reinterpret_cast<STACK_OF(DIST_POINT) *>(X509_get_ext_d2i(x509certificate, NID_crl_distribution_points, nullptr, nullptr));
2066 18 : VerifyOrExit(crldp != nullptr, err = CHIP_ERROR_NOT_FOUND);
2067 13 : VerifyOrExit(sk_DIST_POINT_num(crldp) == 1, err = CHIP_ERROR_NOT_FOUND);
2068 :
2069 10 : dp = sk_DIST_POINT_value(crldp, 0);
2070 10 : VerifyOrExit(dp != nullptr, err = CHIP_ERROR_NOT_FOUND);
2071 10 : VerifyOrExit(dp->distpoint != nullptr && dp->distpoint->type == 0, err = CHIP_ERROR_NOT_FOUND);
2072 :
2073 : // The DistributionPoint is a sequence of three optional elements:
2074 : // DistributionPoint ::= SEQUENCE {
2075 : // distributionPoint [0] DistributionPointName OPTIONAL,
2076 : // reasons [1] ReasonFlags OPTIONAL,
2077 : // cRLIssuer [2] GeneralNames OPTIONAL }
2078 : //
2079 : // where the DistributionPointName is a CHOICE of:
2080 : // DistributionPointName ::= CHOICE {
2081 : // fullName [0] GeneralNames,
2082 : // nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
2083 : //
2084 : // The URI should be encoded in the fullName element.
2085 : // This implementation only supports a single GeneralName in the fullName sequence:
2086 : // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
2087 10 : gens = dp->distpoint->name.fullname;
2088 10 : VerifyOrExit(sk_GENERAL_NAME_num(gens) == 1, err = CHIP_ERROR_NOT_FOUND);
2089 :
2090 : // The CDP URI is encoded as a uniformResourceIdentifier field of the GeneralName:
2091 : // GeneralName ::= CHOICE {
2092 : // otherName [0] OtherName,
2093 : // rfc822Name [1] IA5String,
2094 : // dNSName [2] IA5String,
2095 : // x400Address [3] ORAddress,
2096 : // directoryName [4] Name,
2097 : // ediPartyName [5] EDIPartyName,
2098 : // uniformResourceIdentifier [6] IA5String,
2099 : // iPAddress [7] OCTET STRING,
2100 : // registeredID [8] OBJECT IDENTIFIER }
2101 9 : gen = sk_GENERAL_NAME_value(gens, 0);
2102 9 : VerifyOrExit(gen->type == GEN_URI, err = CHIP_ERROR_NOT_FOUND);
2103 :
2104 9 : uri = reinterpret_cast<ASN1_STRING *>(GENERAL_NAME_get0_value(gen, nullptr));
2105 9 : urlptr = reinterpret_cast<const char *>(ASN1_STRING_get0_data(uri));
2106 9 : VerifyOrExit(CanCastTo<size_t>(ASN1_STRING_length(uri)), err = CHIP_ERROR_NOT_FOUND);
2107 9 : len = static_cast<size_t>(ASN1_STRING_length(uri));
2108 9 : VerifyOrExit(
2109 : (len > strlen(kValidCDPURIHttpPrefix) && strncmp(urlptr, kValidCDPURIHttpPrefix, strlen(kValidCDPURIHttpPrefix)) == 0) ||
2110 : (len > strlen(kValidCDPURIHttpsPrefix) &&
2111 : strncmp(urlptr, kValidCDPURIHttpsPrefix, strlen(kValidCDPURIHttpsPrefix)) == 0),
2112 : err = CHIP_ERROR_NOT_FOUND);
2113 8 : err = CopyCharSpanToMutableCharSpan(CharSpan(urlptr, len), cdpurl);
2114 :
2115 18 : exit:
2116 18 : sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
2117 18 : X509_free(x509certificate);
2118 :
2119 18 : return err;
2120 : }
2121 :
2122 19 : CHIP_ERROR ExtractCDPExtensionCRLIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & crlIssuer)
2123 : {
2124 19 : CHIP_ERROR err = CHIP_NO_ERROR;
2125 19 : int result = 1;
2126 19 : X509 * x509certificate = nullptr;
2127 19 : const unsigned char * pCertificate = certificate.data();
2128 19 : const unsigned char ** ppCertificate = &pCertificate;
2129 19 : STACK_OF(DIST_POINT) * crldp = nullptr;
2130 19 : DIST_POINT * dp = nullptr;
2131 19 : GENERAL_NAMES * gens = nullptr;
2132 19 : GENERAL_NAME * gen = nullptr;
2133 19 : X509_NAME * dirName = nullptr;
2134 19 : const uint8_t * pDirName = nullptr;
2135 19 : size_t dirNameLen = 0;
2136 :
2137 19 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
2138 :
2139 18 : x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
2140 18 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2141 :
2142 : // CRL Distribution Point Extension is encoded as a sequence of DistributionPoint:
2143 : // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
2144 : //
2145 : // This implementation only supports a single DistributionPoint (sequence of size 1)
2146 : crldp =
2147 18 : reinterpret_cast<STACK_OF(DIST_POINT) *>(X509_get_ext_d2i(x509certificate, NID_crl_distribution_points, nullptr, nullptr));
2148 18 : VerifyOrExit(crldp != nullptr, err = CHIP_ERROR_NOT_FOUND);
2149 13 : VerifyOrExit(sk_DIST_POINT_num(crldp) == 1, err = CHIP_ERROR_NOT_FOUND);
2150 :
2151 10 : dp = sk_DIST_POINT_value(crldp, 0);
2152 10 : VerifyOrExit(dp != nullptr, err = CHIP_ERROR_NOT_FOUND);
2153 :
2154 : // The DistributionPoint is a sequence of three optional elements:
2155 : // DistributionPoint ::= SEQUENCE {
2156 : // distributionPoint [0] DistributionPointName OPTIONAL,
2157 : // reasons [1] ReasonFlags OPTIONAL,
2158 : // cRLIssuer [2] GeneralNames OPTIONAL }
2159 : //
2160 : // the cRLIssuer is encoded as a GeneralNames, where:
2161 : // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
2162 : // This implementation only supports a single GeneralName element in the cRLIssuer sequence:
2163 10 : gens = dp->CRLissuer;
2164 10 : VerifyOrExit(sk_GENERAL_NAME_num(gens) == 1, err = CHIP_ERROR_NOT_FOUND);
2165 :
2166 : // In this implementation the cRLIssuer is expected to be encoded as a directoryName field of the GeneralName:
2167 : // GeneralName ::= CHOICE {
2168 : // otherName [0] OtherName,
2169 : // rfc822Name [1] IA5String,
2170 : // dNSName [2] IA5String,
2171 : // x400Address [3] ORAddress,
2172 : // directoryName [4] Name,
2173 : // ediPartyName [5] EDIPartyName,
2174 : // uniformResourceIdentifier [6] IA5String,
2175 : // iPAddress [7] OCTET STRING,
2176 : // registeredID [8] OBJECT IDENTIFIER }
2177 4 : gen = sk_GENERAL_NAME_value(gens, 0);
2178 4 : VerifyOrExit(gen->type == GEN_DIRNAME, err = CHIP_ERROR_NOT_FOUND);
2179 :
2180 4 : dirName = reinterpret_cast<X509_NAME *>(GENERAL_NAME_get0_value(gen, nullptr));
2181 4 : VerifyOrExit(dirName != nullptr, err = CHIP_ERROR_NOT_FOUND);
2182 :
2183 : // Extract directoryName as a raw DER Encoded data
2184 4 : result = X509_NAME_get0_der(dirName, &pDirName, &dirNameLen);
2185 4 : VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
2186 4 : err = CopySpanToMutableSpan(ByteSpan(pDirName, dirNameLen), crlIssuer);
2187 :
2188 18 : exit:
2189 18 : sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
2190 18 : X509_free(x509certificate);
2191 :
2192 18 : return err;
2193 : }
2194 :
2195 25 : CHIP_ERROR ExtractSerialNumberFromX509Cert(const ByteSpan & certificate, MutableByteSpan & serialNumber)
2196 : {
2197 25 : CHIP_ERROR err = CHIP_NO_ERROR;
2198 25 : X509 * x509certificate = nullptr;
2199 25 : auto * pCertificate = Uint8::to_const_uchar(certificate.data());
2200 25 : const unsigned char ** ppCertificate = &pCertificate;
2201 25 : const ASN1_INTEGER * serialNumberASN1 = nullptr;
2202 25 : size_t serialNumberLen = 0;
2203 :
2204 25 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
2205 :
2206 25 : x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
2207 25 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2208 :
2209 25 : serialNumberASN1 = X509_get_serialNumber(x509certificate);
2210 25 : VerifyOrExit(serialNumberASN1 != nullptr, err = CHIP_ERROR_INTERNAL);
2211 25 : VerifyOrExit(serialNumberASN1->data != nullptr, err = CHIP_ERROR_INTERNAL);
2212 25 : VerifyOrExit(CanCastTo<size_t>(serialNumberASN1->length), err = CHIP_ERROR_INTERNAL);
2213 :
2214 25 : serialNumberLen = static_cast<size_t>(serialNumberASN1->length);
2215 25 : VerifyOrExit(serialNumberLen <= serialNumber.size(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
2216 :
2217 25 : memcpy(serialNumber.data(), serialNumberASN1->data, serialNumberLen);
2218 25 : serialNumber.reduce_size(serialNumberLen);
2219 :
2220 25 : exit:
2221 25 : X509_free(x509certificate);
2222 :
2223 25 : return err;
2224 : }
2225 :
2226 : namespace {
2227 42 : CHIP_ERROR ExtractRawDNFromX509Cert(bool extractSubject, const ByteSpan & certificate, MutableByteSpan & dn)
2228 : {
2229 42 : CHIP_ERROR err = CHIP_NO_ERROR;
2230 42 : int result = 1;
2231 42 : X509 * x509certificate = nullptr;
2232 42 : auto * pCertificate = Uint8::to_const_uchar(certificate.data());
2233 42 : const unsigned char ** ppCertificate = &pCertificate;
2234 42 : X509_NAME * distinguishedName = nullptr;
2235 42 : const uint8_t * pDistinguishedName = nullptr;
2236 42 : size_t distinguishedNameLen = 0;
2237 :
2238 42 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
2239 :
2240 42 : x509certificate = d2i_X509(nullptr, ppCertificate, static_cast<long>(certificate.size()));
2241 42 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2242 :
2243 41 : if (extractSubject)
2244 : {
2245 16 : distinguishedName = X509_get_subject_name(x509certificate);
2246 : }
2247 : else
2248 : {
2249 25 : distinguishedName = X509_get_issuer_name(x509certificate);
2250 : }
2251 41 : VerifyOrExit(distinguishedName != nullptr, err = CHIP_ERROR_INTERNAL);
2252 :
2253 41 : result = X509_NAME_get0_der(distinguishedName, &pDistinguishedName, &distinguishedNameLen);
2254 41 : VerifyOrExit(result == 1, err = CHIP_ERROR_INTERNAL);
2255 41 : err = CopySpanToMutableSpan(ByteSpan(pDistinguishedName, distinguishedNameLen), dn);
2256 :
2257 42 : exit:
2258 42 : X509_free(x509certificate);
2259 :
2260 42 : return err;
2261 : }
2262 : } // namespace
2263 :
2264 17 : CHIP_ERROR ExtractSubjectFromX509Cert(const ByteSpan & certificate, MutableByteSpan & subject)
2265 : {
2266 17 : return ExtractRawDNFromX509Cert(true, certificate, subject);
2267 : }
2268 :
2269 25 : CHIP_ERROR ExtractIssuerFromX509Cert(const ByteSpan & certificate, MutableByteSpan & issuer)
2270 : {
2271 25 : return ExtractRawDNFromX509Cert(false, certificate, issuer);
2272 : }
2273 :
2274 330 : CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
2275 : {
2276 330 : ASN1_OBJECT * commonNameObj = OBJ_txt2obj("2.5.4.3", 1);
2277 330 : ASN1_OBJECT * matterVidObj = OBJ_txt2obj("1.3.6.1.4.1.37244.2.1", 1); // Matter VID OID - taken from Spec
2278 330 : ASN1_OBJECT * matterPidObj = OBJ_txt2obj("1.3.6.1.4.1.37244.2.2", 1); // Matter PID OID - taken from Spec
2279 :
2280 330 : CHIP_ERROR err = CHIP_NO_ERROR;
2281 330 : X509 * x509certificate = nullptr;
2282 330 : const unsigned char * pCertificate = certificate.data();
2283 330 : X509_NAME * subject = nullptr;
2284 330 : int x509EntryCountIdx = 0;
2285 330 : AttestationCertVidPid vidpidFromCN;
2286 :
2287 330 : VerifyOrReturnError(!certificate.empty() && CanCastTo<long>(certificate.size()), CHIP_ERROR_INVALID_ARGUMENT);
2288 :
2289 330 : x509certificate = d2i_X509(nullptr, &pCertificate, static_cast<long>(certificate.size()));
2290 330 : VerifyOrExit(x509certificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2291 :
2292 330 : subject = X509_get_subject_name(x509certificate);
2293 330 : VerifyOrExit(subject != nullptr, err = CHIP_ERROR_INTERNAL);
2294 :
2295 1111 : for (x509EntryCountIdx = 0; x509EntryCountIdx < X509_NAME_entry_count(subject); ++x509EntryCountIdx)
2296 : {
2297 795 : X509_NAME_ENTRY * name_entry = X509_NAME_get_entry(subject, x509EntryCountIdx);
2298 795 : VerifyOrExit(name_entry != nullptr, err = CHIP_ERROR_INTERNAL);
2299 795 : ASN1_OBJECT * object = X509_NAME_ENTRY_get_object(name_entry);
2300 795 : VerifyOrExit(object != nullptr, err = CHIP_ERROR_INTERNAL);
2301 :
2302 795 : DNAttrType attrType = DNAttrType::kUnspecified;
2303 795 : if (OBJ_cmp(object, commonNameObj) == 0)
2304 : {
2305 329 : attrType = DNAttrType::kCommonName;
2306 : }
2307 466 : else if (OBJ_cmp(object, matterVidObj) == 0)
2308 : {
2309 289 : attrType = DNAttrType::kMatterVID;
2310 : }
2311 177 : else if (OBJ_cmp(object, matterPidObj) == 0)
2312 : {
2313 175 : attrType = DNAttrType::kMatterPID;
2314 : }
2315 :
2316 795 : if (attrType != DNAttrType::kUnspecified)
2317 : {
2318 793 : ASN1_STRING * data_entry = X509_NAME_ENTRY_get_data(name_entry);
2319 793 : VerifyOrExit(data_entry != nullptr, err = CHIP_ERROR_INTERNAL);
2320 793 : unsigned char * str = ASN1_STRING_data(data_entry);
2321 793 : VerifyOrExit(str != nullptr, err = CHIP_ERROR_INTERNAL);
2322 793 : int len = ASN1_STRING_length(data_entry);
2323 793 : VerifyOrExit(CanCastTo<size_t>(len), err = CHIP_ERROR_INTERNAL);
2324 :
2325 793 : err = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(str, static_cast<size_t>(len)), vidpid, vidpidFromCN);
2326 793 : SuccessOrExit(err);
2327 : }
2328 : }
2329 :
2330 : // If Matter Attributes were not found use values extracted from the CN Attribute,
2331 : // which might be uninitialized as well.
2332 316 : if (!vidpid.Initialized())
2333 : {
2334 25 : vidpid = vidpidFromCN;
2335 : }
2336 :
2337 291 : exit:
2338 330 : ASN1_OBJECT_free(commonNameObj);
2339 330 : ASN1_OBJECT_free(matterVidObj);
2340 330 : ASN1_OBJECT_free(matterPidObj);
2341 330 : X509_free(x509certificate);
2342 :
2343 330 : return err;
2344 : }
2345 :
2346 12 : CHIP_ERROR ReplaceCertIfResignedCertFound(const ByteSpan & referenceCertificate, const ByteSpan * candidateCertificates,
2347 : size_t candidateCertificatesCount, ByteSpan & outCertificate)
2348 : {
2349 12 : CHIP_ERROR err = CHIP_NO_ERROR;
2350 12 : X509 * x509ReferenceCertificate = nullptr;
2351 12 : X509 * x509CandidateCertificate = nullptr;
2352 12 : const uint8_t * pReferenceCertificate = referenceCertificate.data();
2353 12 : X509_NAME * referenceSubject = nullptr;
2354 12 : X509_NAME * candidateSubject = nullptr;
2355 : uint8_t referenceSKIDBuf[kSubjectKeyIdentifierLength];
2356 : uint8_t candidateSKIDBuf[kSubjectKeyIdentifierLength];
2357 12 : MutableByteSpan referenceSKID(referenceSKIDBuf);
2358 12 : MutableByteSpan candidateSKID(candidateSKIDBuf);
2359 :
2360 12 : VerifyOrReturnError(!referenceCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
2361 :
2362 10 : outCertificate = referenceCertificate;
2363 :
2364 10 : VerifyOrReturnError(candidateCertificates != nullptr && candidateCertificatesCount != 0, CHIP_NO_ERROR);
2365 :
2366 8 : ReturnErrorOnFailure(ExtractSKIDFromX509Cert(referenceCertificate, referenceSKID));
2367 :
2368 8 : x509ReferenceCertificate = d2i_X509(nullptr, &pReferenceCertificate, static_cast<long>(referenceCertificate.size()));
2369 8 : VerifyOrExit(x509ReferenceCertificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2370 :
2371 8 : referenceSubject = X509_get_subject_name(x509ReferenceCertificate);
2372 8 : VerifyOrExit(referenceSubject != nullptr, err = CHIP_ERROR_INTERNAL);
2373 :
2374 25 : for (size_t i = 0; i < candidateCertificatesCount; i++)
2375 : {
2376 21 : const ByteSpan candidateCertificate = candidateCertificates[i];
2377 21 : const uint8_t * pCandidateCertificate = candidateCertificate.data();
2378 :
2379 25 : VerifyOrExit(!candidateCertificate.empty(), err = CHIP_ERROR_INVALID_ARGUMENT);
2380 :
2381 21 : SuccessOrExit(err = ExtractSKIDFromX509Cert(candidateCertificate, candidateSKID));
2382 :
2383 21 : x509CandidateCertificate = d2i_X509(nullptr, &pCandidateCertificate, static_cast<long>(candidateCertificate.size()));
2384 21 : VerifyOrExit(x509CandidateCertificate != nullptr, err = CHIP_ERROR_NO_MEMORY);
2385 :
2386 21 : candidateSubject = X509_get_subject_name(x509CandidateCertificate);
2387 21 : VerifyOrExit(candidateSubject != nullptr, err = CHIP_ERROR_INTERNAL);
2388 :
2389 21 : if (referenceSKID.data_equal(candidateSKID) && X509_NAME_cmp(referenceSubject, candidateSubject) == 0)
2390 : {
2391 4 : outCertificate = candidateCertificate;
2392 4 : ExitNow();
2393 : }
2394 :
2395 17 : X509_free(x509CandidateCertificate);
2396 17 : x509CandidateCertificate = nullptr;
2397 : }
2398 :
2399 4 : exit:
2400 8 : X509_free(x509ReferenceCertificate);
2401 8 : X509_free(x509CandidateCertificate);
2402 :
2403 8 : return err;
2404 : }
2405 :
2406 : } // namespace Crypto
2407 : } // namespace chip
|