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