Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 22 additions & 20 deletions contracts/AttestationAuther.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.0;

import "./interfaces/IAttestationVerifier.sol";
import {IAttestationVerifier} from "./interfaces/IAttestationVerifier.sol";

/// @notice Contract that allows children to check if a given address belongs to a verified enclave.
/// @dev The Oyster platform works on the basis of attestations to ensure security. These attestations contain a
Expand All @@ -25,14 +25,14 @@ contract AttestationAuther {
uint256 public immutable ATTESTATION_MAX_AGE;

struct EnclaveImage {
bytes PCR0;
bytes PCR1;
bytes PCR2;
bytes pcr0;
bytes pcr1;
bytes pcr2;
}

mapping(bytes32 => EnclaveImage) whitelistedImages;
mapping(address => bytes32) verifiedKeys;
mapping(bytes32 => mapping(bytes32 => bool)) imageFamilies;
mapping(bytes32 => EnclaveImage) public whitelistedImages;
mapping(address => bytes32) public verifiedKeys;
mapping(bytes32 => mapping(bytes32 => bool)) public imageFamilies;

/// @notice Expected a pubkey with length equal to 64.
error AttestationAutherPubkeyLengthInvalid();
Expand All @@ -49,8 +49,8 @@ contract AttestationAuther {
/// @notice Expected the arrays to have equal lengths.
error AttestationAutherMismatchedLengths();

/// @notice Emitted when enclave image `imageId` with PCRs `(PCR0,PCR1,PCR2)` is whitelisted.
event EnclaveImageWhitelisted(bytes32 indexed imageId, bytes PCR0, bytes PCR1, bytes PCR2);
/// @notice Emitted when enclave image `imageId` with PCRs `(pcr0,pcr1,pcr2)` is whitelisted.
event EnclaveImageWhitelisted(bytes32 indexed imageId, bytes pcr0, bytes pcr1, bytes pcr2);
/// @notice Emitted when enclave image `imageId` is revoked.
event EnclaveImageRevoked(bytes32 indexed imageId);
/// @notice Emitted when enclave image `imageId` is added to `family`.
Expand All @@ -76,6 +76,7 @@ contract AttestationAuther {

/// @notice Initializes the contract by whitelisting the provided enclave images.
/// @param images Enclave images to be whitelisted.
// solhint-disable-next-line func-name-mixedcase
function __AttestationAuther_constructor(EnclaveImage[] memory images) internal {
for (uint256 i = 0; i < images.length; i++) {
_whitelistEnclaveImage(images[i]);
Expand All @@ -86,6 +87,7 @@ contract AttestationAuther {
/// to the respective families.
/// @param images Enclave images to be whitelisted.
/// @param families Corresponding family for each enclave images.
// solhint-disable-next-line func-name-mixedcase
function __AttestationAuther_constructor(EnclaveImage[] memory images, bytes32[] memory families) internal {
if (!(images.length == families.length)) revert AttestationAutherMismatchedLengths();
for (uint256 i = 0; i < images.length; i++) {
Expand All @@ -109,14 +111,14 @@ contract AttestationAuther {
/// @param image Image to be whitelisted.
/// @return Computed image id and true if the image was freshly whitelisted, false otherwise.
function _whitelistEnclaveImage(EnclaveImage memory image) internal virtual returns (bytes32, bool) {
if (!(image.PCR0.length == 48 && image.PCR1.length == 48 && image.PCR2.length == 48))
if (!(image.pcr0.length == 48 && image.pcr1.length == 48 && image.pcr2.length == 48))
revert AttestationAutherPCRsInvalid();

bytes32 imageId = keccak256(abi.encodePacked(image.PCR0, image.PCR1, image.PCR2));
if (!(whitelistedImages[imageId].PCR0.length == 0)) return (imageId, false);
bytes32 imageId = keccak256(abi.encodePacked(image.pcr0, image.pcr1, image.pcr2));
if (!(whitelistedImages[imageId].pcr0.length == 0)) return (imageId, false);

whitelistedImages[imageId] = EnclaveImage(image.PCR0, image.PCR1, image.PCR2);
emit EnclaveImageWhitelisted(imageId, image.PCR0, image.PCR1, image.PCR2);
whitelistedImages[imageId] = EnclaveImage(image.pcr0, image.pcr1, image.pcr2);
emit EnclaveImageWhitelisted(imageId, image.pcr0, image.pcr1, image.pcr2);

return (imageId, true);
}
Expand All @@ -126,7 +128,7 @@ contract AttestationAuther {
/// @param imageId Image to be revoked.
/// @return true if the image was freshly revoked, false otherwise.
function _revokeEnclaveImage(bytes32 imageId) internal virtual returns (bool) {
if (!(whitelistedImages[imageId].PCR0.length != 0)) return false;
if (!(whitelistedImages[imageId].pcr0.length != 0)) return false;

delete whitelistedImages[imageId];
emit EnclaveImageRevoked(imageId);
Expand Down Expand Up @@ -168,7 +170,7 @@ contract AttestationAuther {
/// @param imageId Image to be whitelisted against.
/// @return true if the key was freshly whitelisted against the image, false otherwise.
function _whitelistEnclaveKey(bytes memory enclavePubKey, bytes32 imageId) internal virtual returns (bool) {
if (!(whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!(whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();

address enclaveAddress = _pubKeyToAddress(enclavePubKey);
if (!(verifiedKeys[enclaveAddress] == bytes32(0))) return false;
Expand Down Expand Up @@ -201,8 +203,8 @@ contract AttestationAuther {
bytes memory signature,
IAttestationVerifier.Attestation memory attestation
) internal virtual returns (bool) {
bytes32 imageId = keccak256(abi.encodePacked(attestation.PCR0, attestation.PCR1, attestation.PCR2));
if (!(whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
bytes32 imageId = keccak256(abi.encodePacked(attestation.pcr0, attestation.pcr1, attestation.pcr2));
if (!(whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!(attestation.timestampInMilliseconds / 1000 > block.timestamp - ATTESTATION_MAX_AGE))
revert AttestationAutherAttestationTooOld();

Expand Down Expand Up @@ -234,7 +236,7 @@ contract AttestationAuther {
function _allowOnlyVerified(address key) internal view virtual {
bytes32 imageId = verifiedKeys[key];
if (!(imageId != bytes32(0))) revert AttestationAutherKeyNotVerified();
if (!(whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!(whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();
}

/// @notice Returns only if the key is from a verified enclave of the given family, reverts otherwise.
Expand All @@ -243,7 +245,7 @@ contract AttestationAuther {
function _allowOnlyVerifiedFamily(address key, bytes32 family) internal view virtual {
bytes32 imageId = verifiedKeys[key];
if (!(imageId != bytes32(0))) revert AttestationAutherKeyNotVerified();
if (!(whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!(whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!(imageFamilies[family][imageId])) revert AttestationAutherImageNotInFamily();
}

Expand Down
20 changes: 10 additions & 10 deletions contracts/AttestationAutherSample.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
Comment thread
vg-27 marked this conversation as resolved.
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./AttestationAuther.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {AttestationAuther} from "./AttestationAuther.sol";
import {IAttestationVerifier} from "./interfaces/IAttestationVerifier.sol";

contract AttestationAutherSample is
Context, // _msgSender, _msgData
Expand Down Expand Up @@ -55,11 +55,11 @@ contract AttestationAutherSample is
//-------------------------------- Admin methods start --------------------------------//

function whitelistEnclaveImage(
bytes memory PCR0,
bytes memory PCR1,
bytes memory PCR2
bytes memory pcr0,
bytes memory pcr1,
bytes memory pcr2
) external onlyRole(DEFAULT_ADMIN_ROLE) returns (bytes32, bool) {
return _whitelistEnclaveImage(EnclaveImage(PCR0, PCR1, PCR2));
return _whitelistEnclaveImage(EnclaveImage(pcr0, pcr1, pcr2));
}

function revokeEnclaveImage(bytes32 imageId) external onlyRole(DEFAULT_ADMIN_ROLE) returns (bool) {
Expand Down
25 changes: 14 additions & 11 deletions contracts/AttestationAutherSampleUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "./AttestationAutherUpgradeable.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol";
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {AttestationAutherUpgradeable} from "./AttestationAutherUpgradeable.sol";
import {IAttestationVerifier} from "./interfaces/IAttestationVerifier.sol";

contract AttestationAutherSampleUpgradeable is
Initializable, // initializer
Expand All @@ -19,6 +20,7 @@ contract AttestationAutherSampleUpgradeable is
AttestationAutherUpgradeable // auther
{
// in case we add more contracts in the inheritance chain
// solhint-disable-next-line var-name-mixedcase
uint256[500] private __gap_0;

/// @custom:oz-upgrades-unsafe-allow constructor
Expand All @@ -39,6 +41,7 @@ contract AttestationAutherSampleUpgradeable is
return super.supportsInterface(interfaceId);
}

// solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address /*account*/) internal view override onlyRole(DEFAULT_ADMIN_ROLE) {}

//-------------------------------- Overrides end --------------------------------//
Expand Down Expand Up @@ -83,11 +86,11 @@ contract AttestationAutherSampleUpgradeable is
//-------------------------------- Admin methods start --------------------------------//

function whitelistEnclaveImage(
bytes memory PCR0,
bytes memory PCR1,
bytes memory PCR2
bytes memory pcr0,
bytes memory pcr1,
bytes memory pcr2
) external onlyRole(DEFAULT_ADMIN_ROLE) returns (bytes32, bool) {
return _whitelistEnclaveImage(EnclaveImage(PCR0, PCR1, PCR2));
return _whitelistEnclaveImage(EnclaveImage(pcr0, pcr1, pcr2));
}

function revokeEnclaveImage(bytes32 imageId) external onlyRole(DEFAULT_ADMIN_ROLE) returns (bool) {
Expand Down
43 changes: 23 additions & 20 deletions contracts/AttestationAutherUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

pragma solidity ^0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./interfaces/IAttestationVerifier.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {IAttestationVerifier} from "./interfaces/IAttestationVerifier.sol";

/// @notice Contract that allows children to check if a given address belongs to a verified enclave.
/// @dev The Oyster platform works on the basis of attestations to ensure security. These attestations contain a
Expand Down Expand Up @@ -40,9 +40,9 @@ contract AttestationAutherUpgradeable is
}

struct EnclaveImage {
bytes PCR0;
bytes PCR1;
bytes PCR2;
bytes pcr0;
bytes pcr1;
bytes pcr2;
}

/// @custom:storage-location erc7201:marlin.oyster.storage.AttestationAuther
Expand All @@ -53,12 +53,13 @@ contract AttestationAutherUpgradeable is
}

// keccak256(abi.encode(uint256(keccak256("marlin.oyster.storage.AttestationAuther")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AttestationAutherStorageLocation =
bytes32 private constant ATTESTATION_AUTHER_STORAGE_LOCATION =
0xc17b4b708b6f44255c20913a9d97a05300b670342c71fe5ae5b617bd4db55000;

function _getAttestationAutherStorage() private pure returns (AttestationAutherStorage storage $) {
// solhint-disable-next-line no-inline-assembly
assembly {
$.slot := AttestationAutherStorageLocation
$.slot := ATTESTATION_AUTHER_STORAGE_LOCATION
}
}

Expand All @@ -77,8 +78,8 @@ contract AttestationAutherUpgradeable is
/// @notice Expected the arrays to have equal lengths.
error AttestationAutherMismatchedLengths();

/// @notice Emitted when enclave image `imageId` with PCRs `(PCR0,PCR1,PCR2)` is whitelisted.
event EnclaveImageWhitelisted(bytes32 indexed imageId, bytes PCR0, bytes PCR1, bytes PCR2);
/// @notice Emitted when enclave image `imageId` with PCRs `(pcr0,pcr1,pcr2)` is whitelisted.
event EnclaveImageWhitelisted(bytes32 indexed imageId, bytes pcr0, bytes pcr1, bytes pcr2);
/// @notice Emitted when enclave image `imageId` is revoked.
event EnclaveImageRevoked(bytes32 indexed imageId);
/// @notice Emitted when enclave image `imageId` is added to `family`.
Expand All @@ -94,6 +95,7 @@ contract AttestationAutherUpgradeable is

/// @notice Initializes the contract by whitelisting the provided enclave images.
/// @param images Enclave images to be whitelisted.
// solhint-disable-next-line func-name-mixedcase
function __AttestationAuther_init_unchained(EnclaveImage[] memory images) internal onlyInitializing {
for (uint256 i = 0; i < images.length; i++) {
_whitelistEnclaveImage(images[i]);
Expand All @@ -104,6 +106,7 @@ contract AttestationAutherUpgradeable is
/// to the respective families.
/// @param images Enclave images to be whitelisted.
/// @param families Corresponding family for each enclave images.
// solhint-disable-next-line func-name-mixedcase
function __AttestationAuther_init_unchained(
EnclaveImage[] memory images,
bytes32[] memory families
Expand Down Expand Up @@ -132,14 +135,14 @@ contract AttestationAutherUpgradeable is
function _whitelistEnclaveImage(EnclaveImage memory image) internal virtual returns (bytes32, bool) {
AttestationAutherStorage storage $ = _getAttestationAutherStorage();

if (!(image.PCR0.length == 48 && image.PCR1.length == 48 && image.PCR2.length == 48))
if (!(image.pcr0.length == 48 && image.pcr1.length == 48 && image.pcr2.length == 48))
revert AttestationAutherPCRsInvalid();

bytes32 imageId = keccak256(abi.encodePacked(image.PCR0, image.PCR1, image.PCR2));
if (!($.whitelistedImages[imageId].PCR0.length == 0)) return (imageId, false);
bytes32 imageId = keccak256(abi.encodePacked(image.pcr0, image.pcr1, image.pcr2));
if (!($.whitelistedImages[imageId].pcr0.length == 0)) return (imageId, false);

$.whitelistedImages[imageId] = EnclaveImage(image.PCR0, image.PCR1, image.PCR2);
emit EnclaveImageWhitelisted(imageId, image.PCR0, image.PCR1, image.PCR2);
$.whitelistedImages[imageId] = EnclaveImage(image.pcr0, image.pcr1, image.pcr2);
emit EnclaveImageWhitelisted(imageId, image.pcr0, image.pcr1, image.pcr2);

return (imageId, true);
}
Expand All @@ -151,7 +154,7 @@ contract AttestationAutherUpgradeable is
function _revokeEnclaveImage(bytes32 imageId) internal virtual returns (bool) {
AttestationAutherStorage storage $ = _getAttestationAutherStorage();

if (!($.whitelistedImages[imageId].PCR0.length != 0)) return false;
if (!($.whitelistedImages[imageId].pcr0.length != 0)) return false;

delete $.whitelistedImages[imageId];
emit EnclaveImageRevoked(imageId);
Expand Down Expand Up @@ -199,7 +202,7 @@ contract AttestationAutherUpgradeable is
function _whitelistEnclaveKey(bytes memory enclavePubKey, bytes32 imageId) internal virtual returns (bool) {
AttestationAutherStorage storage $ = _getAttestationAutherStorage();

if (!($.whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!($.whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();

address enclaveAddress = _pubKeyToAddress(enclavePubKey);
if (!($.verifiedKeys[enclaveAddress] == bytes32(0))) return false;
Expand Down Expand Up @@ -236,8 +239,8 @@ contract AttestationAutherUpgradeable is
) internal virtual returns (bool) {
AttestationAutherStorage storage $ = _getAttestationAutherStorage();

bytes32 imageId = keccak256(abi.encodePacked(attestation.PCR0, attestation.PCR1, attestation.PCR2));
if (!($.whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
bytes32 imageId = keccak256(abi.encodePacked(attestation.pcr0, attestation.pcr1, attestation.pcr2));
if (!($.whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!(attestation.timestampInMilliseconds / 1000 > block.timestamp - ATTESTATION_MAX_AGE))
revert AttestationAutherAttestationTooOld();

Expand Down Expand Up @@ -271,7 +274,7 @@ contract AttestationAutherUpgradeable is

bytes32 imageId = $.verifiedKeys[key];
if (!(imageId != bytes32(0))) revert AttestationAutherKeyNotVerified();
if (!($.whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!($.whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();
}

/// @notice Returns only if the key is from a verified enclave of the given family, reverts otherwise.
Expand All @@ -282,7 +285,7 @@ contract AttestationAutherUpgradeable is

bytes32 imageId = $.verifiedKeys[key];
if (!(imageId != bytes32(0))) revert AttestationAutherKeyNotVerified();
if (!($.whitelistedImages[imageId].PCR0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!($.whitelistedImages[imageId].pcr0.length != 0)) revert AttestationAutherImageNotWhitelisted();
if (!($.imageFamilies[family][imageId])) revert AttestationAutherImageNotInFamily();
}

Expand Down
Loading