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