|
30 | 30 | #include <Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.h> |
31 | 31 | #include <BleLayer/WeaveBleServiceData.h> |
32 | 32 | #include <Weave/Support/Base64.h> |
| 33 | +#include <Weave/Profiles/security/WeavePrivateKey.h> |
33 | 34 |
|
34 | 35 | #if WEAVE_DEVICE_CONFIG_ENABLE_THREAD |
35 | 36 | #include <Weave/DeviceLayer/ThreadStackManager.h> |
@@ -532,6 +533,115 @@ void GenericConfigurationManagerImpl<ImplClass>::_UseManufacturerCredentialsAsOp |
532 | 533 | SetFlag(mFlags, kFlag_UseManufacturerCredentialsAsOperational, val); |
533 | 534 | } |
534 | 535 |
|
| 536 | +static WEAVE_ERROR GenerateOperationalECDSASignature(const uint8_t *hash, uint8_t hashLen, EncodedECDSASignature& ecdsaSig) |
| 537 | +{ |
| 538 | + WEAVE_ERROR err; |
| 539 | + uint8_t * weavePrivKey = NULL; |
| 540 | + size_t weavePrivKeyLen; |
| 541 | + uint32_t weaveCurveId; |
| 542 | + EncodedECPublicKey pubKey; |
| 543 | + EncodedECPrivateKey privKey; |
| 544 | + |
| 545 | + // Determine the length of the private key. |
| 546 | + err = ConfigurationMgr().GetDevicePrivateKey((uint8_t *)NULL, 0, weavePrivKeyLen); |
| 547 | + SuccessOrExit(err); |
| 548 | + |
| 549 | + // Fail if no private key has been configured. |
| 550 | + VerifyOrExit(weavePrivKeyLen != 0, err = WEAVE_ERROR_KEY_NOT_FOUND); |
| 551 | + |
| 552 | + // Create a temporary buffer to hold the private key. |
| 553 | + weavePrivKey = (uint8_t *)Platform::Security::MemoryAlloc(weavePrivKeyLen); |
| 554 | + VerifyOrExit(weavePrivKey != NULL, err = WEAVE_ERROR_NO_MEMORY); |
| 555 | + |
| 556 | + // Read the private key. |
| 557 | + err = ConfigurationMgr().GetDevicePrivateKey(weavePrivKey, weavePrivKeyLen, weavePrivKeyLen); |
| 558 | + SuccessOrExit(err); |
| 559 | + |
| 560 | + // Decode operational device private/public keys from private key TLV structure. |
| 561 | + err = Profiles::Security::DecodeWeaveECPrivateKey(weavePrivKey, weavePrivKeyLen, weaveCurveId, pubKey, privKey); |
| 562 | + SuccessOrExit(err); |
| 563 | + |
| 564 | + // Generate operational device signature. |
| 565 | + err = nl::Weave::Crypto::GenerateECDSASignature(Profiles::Security::WeaveCurveIdToOID(weaveCurveId), |
| 566 | + hash, hashLen, privKey, ecdsaSig); |
| 567 | + SuccessOrExit(err); |
| 568 | + |
| 569 | +exit: |
| 570 | + if (weavePrivKey != NULL) |
| 571 | + { |
| 572 | + Platform::Security::MemoryFree(weavePrivKey); |
| 573 | + } |
| 574 | + return err; |
| 575 | +} |
| 576 | + |
| 577 | +template<class ImplClass> |
| 578 | +WEAVE_ERROR GenericConfigurationManagerImpl<ImplClass>::_GenerateAndStoreOperationalDeviceCredentials(uint64_t deviceId) |
| 579 | +{ |
| 580 | + enum |
| 581 | + { |
| 582 | + kWeaveDeviceCertBufSize = 300, // Size of buffer needed to hold Weave device certificate. |
| 583 | + kWeaveDevicePrivateKeyBufSize = 128, // Size of buffer needed to hold Weave device private key. |
| 584 | + }; |
| 585 | + |
| 586 | + WEAVE_ERROR err; |
| 587 | + uint8_t weavePrivKey[kWeaveDevicePrivateKeyBufSize]; |
| 588 | + uint32_t weavePrivKeyLen; |
| 589 | + uint8_t weaveCert[kWeaveDeviceCertBufSize]; |
| 590 | + uint16_t weaveCertLen; |
| 591 | + uint8_t privKeyBuf[EncodedECPrivateKey::kMaxValueLength]; |
| 592 | + uint8_t pubKeyBuf[EncodedECPublicKey::kMaxValueLength]; |
| 593 | + EncodedECPublicKey pubKey; |
| 594 | + EncodedECPrivateKey privKey; |
| 595 | + |
| 596 | + // If not specified, generate random device Id. |
| 597 | + if (deviceId == kNodeIdNotSpecified) |
| 598 | + { |
| 599 | + err = GenerateWeaveNodeId(deviceId); |
| 600 | + SuccessOrExit(err); |
| 601 | + } |
| 602 | + |
| 603 | + // Store generated device Id. |
| 604 | + err = _StoreDeviceId(deviceId); |
| 605 | + SuccessOrExit(err); |
| 606 | + |
| 607 | + privKey.PrivKey = privKeyBuf; |
| 608 | + privKey.PrivKeyLen = sizeof(privKeyBuf); |
| 609 | + |
| 610 | + pubKey.ECPoint = pubKeyBuf; |
| 611 | + pubKey.ECPointLen = sizeof(pubKeyBuf); |
| 612 | + |
| 613 | + // Generate random EC private/public key pair. |
| 614 | + err = GenerateECDHKey(Profiles::Security::WeaveCurveIdToOID(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID), pubKey, privKey); |
| 615 | + SuccessOrExit(err); |
| 616 | + |
| 617 | + // Encode Weave device EC private/public key pair into EllipticCurvePrivateKey TLV structure. |
| 618 | + err = EncodeWeaveECPrivateKey(WEAVE_CONFIG_OPERATIONAL_DEVICE_CERT_CURVE_ID, &pubKey, privKey, |
| 619 | + weavePrivKey, sizeof(weavePrivKey), weavePrivKeyLen); |
| 620 | + SuccessOrExit(err); |
| 621 | + |
| 622 | + // Store generated operational device private key. |
| 623 | + err = _StoreDevicePrivateKey(weavePrivKey, weavePrivKeyLen); |
| 624 | + SuccessOrExit(err); |
| 625 | + |
| 626 | + // Generate self-signed operational device certificate. |
| 627 | + err = Profiles::Security::GenerateOperationalDeviceCert(deviceId, pubKey, weaveCert, sizeof(weaveCert), weaveCertLen, GenerateOperationalECDSASignature); |
| 628 | + SuccessOrExit(err); |
| 629 | + |
| 630 | + // Store generated operational device certificate. |
| 631 | + err = _StoreDeviceCertificate(weaveCert, weaveCertLen); |
| 632 | + SuccessOrExit(err); |
| 633 | + |
| 634 | + // Set flag indicating that the device has been provisioned with operational credentials. |
| 635 | + SetFlag(mFlags, kFlag_OperationalDeviceCredentialsProvisioned, Impl()->ConfigValueExists(ImplClass::kConfigKey_OperationalDeviceCert)); |
| 636 | + |
| 637 | +exit: |
| 638 | + if (err != WEAVE_NO_ERROR) |
| 639 | + { |
| 640 | + _ClearOperationalDeviceCredentials(); |
| 641 | + } |
| 642 | + return err; |
| 643 | +} |
| 644 | + |
535 | 645 | #endif // WEAVE_DEVICE_CONFIG_ENABLE_JUST_IN_TIME_PROVISIONING |
536 | 646 |
|
537 | 647 | template<class ImplClass> |
|
0 commit comments