Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update README.md #7

Merged
merged 1 commit into from
Sep 27, 2024
Merged

Update README.md #7

merged 1 commit into from
Sep 27, 2024

Conversation

Liao1
Copy link
Contributor

@Liao1 Liao1 commented Sep 27, 2024

No description provided.

Copy link

github-actions bot commented Sep 27, 2024

Slither report

Click me to view the full report Summary - [encode-packed-collision](#encode-packed-collision) (4 results) (High) - [incorrect-shift](#incorrect-shift) (1 results) (High) - [uninitialized-local](#uninitialized-local) (27 results) (Medium) - [unused-return](#unused-return) (3 results) (Medium) - [missing-zero-check](#missing-zero-check) (2 results) (Low) - [calls-loop](#calls-loop) (1 results) (Low) - [timestamp](#timestamp) (4 results) (Low) - [assembly](#assembly) (10 results) (Informational) - [cyclomatic-complexity](#cyclomatic-complexity) (4 results) (Informational) - [dead-code](#dead-code) (1 results) (Informational) - [solc-version](#solc-version) (2 results) (Informational) - [low-level-calls](#low-level-calls) (1 results) (Informational) - [missing-inheritance](#missing-inheritance) (1 results) (Informational) - [naming-convention](#naming-convention) (20 results) (Informational) - [too-many-digits](#too-many-digits) (2 results) (Informational) - [immutable-states](#immutable-states) (5 results) (Optimization) ## encode-packed-collision Impact: High Confidence: High - [ ] ID-0 [X509CRLHelper._getSignature(bytes,uint256)](https://github.com/automata-network/automata-on-chain-pccs/blob/b4800db3b81a166f867a2a2ff7917ff76347392a/src/helpers/X509CRLHelper.sol#L200-L210) calls abi.encodePacked() with multiple dynamic arguments: - [sig = abi.encodePacked(sigX,sigY)](https://github.com/automata-network/automata-on-chain-pccs/blob/b4800db3b81a166f867a2a2ff7917ff76347392a/src/helpers/X509CRLHelper.sol#L209)

function _getSignature(bytes calldata der, uint256 sigPtr) private pure returns (bytes memory sig) {
sigPtr = der.rootOfBitStringAt(sigPtr);
sigPtr = der.firstChildOf(sigPtr);
bytes memory sigX = _trimBytes(der.bytesAt(sigPtr), 32);
sigPtr = der.nextSiblingOf(sigPtr);
bytes memory sigY = _trimBytes(der.bytesAt(sigPtr), 32);
sig = abi.encodePacked(sigX, sigY);
}

function _validatePckTcb(bytes2 pceid, bytes18 tcbm, bytes memory der, uint256 pckExtensionPtr) private view {
(uint16 pcesvn, uint8[] memory cpusvns,, bytes memory pceidBytes) =
pckLib.parsePckExtension(der, pckExtensionPtr);
bool pceidMatched = bytes2(pceidBytes) == pceid;
bytes memory encodedPceSvn = _littleEndianEncode(abi.encodePacked(pcesvn));
bytes memory encodedCpuSvn;
for (uint256 i = 0; i < cpusvns.length; i++) {
encodedCpuSvn = abi.encodePacked(encodedCpuSvn, cpusvns[i]);
}
bytes memory encodedTcbmBytes = abi.encodePacked(encodedCpuSvn, encodedPceSvn);
bool tcbIsValid = tcbm == bytes18(encodedTcbmBytes);
if (!pceidMatched || !tcbIsValid) {
revert TCB_Mismatch();
}
}

function _getSignature(bytes calldata der, uint256 sigPtr) private pure returns (bytes memory sig) {
sigPtr = der.rootOfBitStringAt(sigPtr);
sigPtr = der.firstChildOf(sigPtr);
bytes memory sigX = _trimBytes(der.bytesAt(sigPtr), 32);
sigPtr = der.nextSiblingOf(sigPtr);
bytes memory sigY = _trimBytes(der.bytesAt(sigPtr), 32);
sig = abi.encodePacked(sigX, sigY);
}

function _getRevokedSerialNumbers(bytes calldata der, uint256 revokedParentPtr, bool breakIfFound, uint256 filter)
private
pure
returns (uint256[] memory serialNumbers)
{
uint256 revokedPtr = der.firstChildOf(revokedParentPtr);
if (der[revokedPtr.ixs()] == 0xA0) {
uint256 crlExtensionPtr = der.firstChildOf(revokedPtr);
require(BytesUtils.compareBytes(der.bytesAt(crlExtensionPtr), CRL_NUMBER_OID), "invalid CRL");
} else {
bytes memory serials;
while (revokedPtr.ixl() <= revokedParentPtr.ixl()) {
uint256 serialPtr = der.firstChildOf(revokedPtr);
bytes memory serialBytes = der.bytesAt(serialPtr);
uint256 serialNumber = _parseSerialNumber(serialBytes);
serials = abi.encodePacked(serials, serialNumber);
if (breakIfFound && filter == serialNumber) {
serialNumbers = new uint256[](1);
serialNumbers[0] = filter;
return serialNumbers;
}
revokedPtr = der.nextSiblingOf(revokedPtr);
}
uint256 count = serials.length / 32;
// ABI encoding format for a dynamic uint256[] value
serials = abi.encodePacked(abi.encode(0x20), abi.encode(count), serials);
serialNumbers = new uint256[](count);
serialNumbers = abi.decode(serials, (uint256[]));
}
}

incorrect-shift

Impact: High
Confidence: High

function _parseUintFromHex(string memory s) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(s)
// Skip two if starts with '0x' or '0X'.
let i := shl(1, and(eq(0x3078, or(shr(240, mload(add(s, 0x20))), 0x20)), gt(n, 1)))
for {} 1 {} {
i := add(i, 1)
let c :=
byte(
and(0x1f, shr(and(mload(add(s, i)), 0xff), 0x3e4088843e41bac000000000000)),
0x3010a071000000b0104040208000c05090d060e0f
)
n := mul(n, iszero(or(iszero(c), shr(252, result))))
result := add(shl(4, result), sub(c, 1))
if iszero(lt(i, n)) { break }
}
if iszero(n) {
mstore(0x00, 0x10182796) // `ParsingFailed()`.
revert(0x1c, 0x04)
}
}
}

uninitialized-local

Impact: Medium
Confidence: Medium

JSONParserLib.Item[] memory tcbLevelsObj;

TDXModuleIdentity[] memory moduleIdentities;

string memory expectedIssuer;

bool tdxModuleIdentitiesFound;

TDXModule memory module;

string memory expectedSubject;

unused-return

Impact: Medium
Confidence: Medium

function _validatePckTcb(bytes2 pceid, bytes18 tcbm, bytes memory der, uint256 pckExtensionPtr) private view {
(uint16 pcesvn, uint8[] memory cpusvns,, bytes memory pceidBytes) =
pckLib.parsePckExtension(der, pckExtensionPtr);
bool pceidMatched = bytes2(pceidBytes) == pceid;
bytes memory encodedPceSvn = _littleEndianEncode(abi.encodePacked(pcesvn));
bytes memory encodedCpuSvn;
for (uint256 i = 0; i < cpusvns.length; i++) {
encodedCpuSvn = abi.encodePacked(encodedCpuSvn, cpusvns[i]);
}
bytes memory encodedTcbmBytes = abi.encodePacked(encodedCpuSvn, encodedPceSvn);
bool tcbIsValid = tcbm == bytes18(encodedTcbmBytes);
if (!pceidMatched || !tcbIsValid) {
revert TCB_Mismatch();
}
}

function _upsertTcbm(bytes16 qeid, bytes2 pceid, bytes18 tcbm) private {
bytes32 k = keccak256(abi.encodePacked(qeid, pceid));
if (!_tcbmHSets[k].contains(bytes32(tcbm))) {
_tcbmHSets[k].add(bytes32(tcbm));
}
}

function _buildAttestationData(string memory tcbInfoStr, bytes memory signature)
private
view
returns (bytes memory attestationData, TcbInfoBasic memory tcbInfo)
{
(, TCBLevelsObj[] memory tcbLevels) = FmspcTcbLib.parseTcbLevels(tcbInfoStr);
tcbInfo = FmspcTcbLib.parseTcbString(tcbInfoStr);
if (tcbInfo.version < 3) {
attestationData = abi.encode(tcbInfo, tcbLevels, tcbInfoStr, signature);
} else {
TDXModule memory module;
TDXModuleIdentity[] memory moduleIdentities;
if (tcbInfo.id == TcbId.TDX) {
(module, moduleIdentities) = FmspcTcbLib.parseTcbTdxModules(tcbInfoStr);
}
attestationData = abi.encode(tcbInfo, module, moduleIdentities, tcbLevels, tcbInfoStr, signature);
}
}

missing-zero-check

Impact: Low
Confidence: Medium

function updateDeps(address _pcs, address _x509, address _crl) external onlyOwner {

function updateDeps(address _x509, address _crl) external onlyOwner {

calls-loop

Impact: Low
Confidence: Medium

function getAttestedData(bytes32 attestationId) public view override returns (bytes memory attestationData) {
attestationData = pccsStorage.readPccs(attestationId);
}

timestamp

Impact: Low
Confidence: Medium

function crlIsNotExpired(bytes calldata der) external view returns (bool isValid) {
uint256 root = der.root();
uint256 tbsParentPtr = der.firstChildOf(root);
uint256 tbsPtr = der.firstChildOf(tbsParentPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
(uint256 validityNotBefore, uint256 validityNotAfter) = _getValidity(der, tbsPtr);
isValid = block.timestamp > validityNotBefore && block.timestamp < validityNotAfter;
}

function certIsNotExpired(bytes calldata der) external view returns (bool isValid) {
uint256 root = der.root();
uint256 tbsParentPtr = der.firstChildOf(root);
uint256 tbsPtr = der.firstChildOf(tbsParentPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
tbsPtr = der.nextSiblingOf(tbsPtr);
(uint256 validityNotBefore, uint256 validityNotAfter) = _getValidity(der, tbsPtr);
isValid = block.timestamp > validityNotBefore && block.timestamp < validityNotAfter;
}

function _buildEnclaveIdentityAttestationRequest(
uint256 id,
uint256 version,
EnclaveIdentityJsonObj calldata enclaveIdentityObj
) private view returns (AttestationRequest memory req) {
bytes32 predecessorAttestationId = _getAttestationId(id, version);
IdentityObj memory identity = EnclaveIdentityLib.parseIdentityString(enclaveIdentityObj.identityStr);
if (id != uint256(identity.id)) {
revert Enclave_Id_Mismatch();
}
if (block.timestamp < identity.issueDateTimestamp || block.timestamp > identity.nextUpdateTimestamp) {
revert Enclave_Id_Expired();
}
bytes memory attestationData =
abi.encode(identity, enclaveIdentityObj.identityStr, enclaveIdentityObj.signature);
AttestationRequestData memory reqData = AttestationRequestData({
recipient: msg.sender,
expirationTime: uint64(identity.nextUpdateTimestamp),
revocable: true,
refUID: predecessorAttestationId,
data: attestationData,
value: 0
});
req = AttestationRequest({schema: enclaveIdentitySchemaID(), data: reqData});
}

function _buildTcbAttestationRequest(TcbInfoJsonObj calldata tcbInfoObj)
private
view
returns (AttestationRequest memory req, TcbInfoBasic memory tcbInfo)
{
bytes memory attestationData;
(attestationData, tcbInfo) = _buildAttestationData(tcbInfoObj.tcbInfoStr, tcbInfoObj.signature);
bytes32 predecessorAttestationId = _getAttestationId(uint8(tcbInfo.id), tcbInfo.fmspc, tcbInfo.version);
if (block.timestamp < tcbInfo.issueDate || block.timestamp > tcbInfo.nextUpdate) {
revert TCB_Expired();
}
AttestationRequestData memory reqData = AttestationRequestData({
recipient: msg.sender,
expirationTime: uint64(tcbInfo.nextUpdate),
revocable: true,
refUID: predecessorAttestationId,
data: attestationData,
value: 0
});
bytes32 schemaId = tcbInfo.version < 3 ? fmpscTcbV2SchemaID() : fmpscTcbV3SchemaID();
req = AttestationRequest({schema: schemaId, data: reqData});
}

assembly

Impact: Informational
Confidence: High

function readUint32(bytes memory self, uint256 idx) internal pure returns (uint32 ret) {
require(idx + 4 <= self.length);
assembly {
ret := and(mload(add(add(self, 4), idx)), 0xFFFFFFFF)
}
}

function readBytes20(bytes memory self, uint256 idx) internal pure returns (bytes20 ret) {
require(idx + 20 <= self.length);
assembly {
ret :=
and(mload(add(add(self, 32), idx)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000)
}
}

function _parseUintFromHex(string memory s) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(s)
// Skip two if starts with '0x' or '0X'.
let i := shl(1, and(eq(0x3078, or(shr(240, mload(add(s, 0x20))), 0x20)), gt(n, 1)))
for {} 1 {} {
i := add(i, 1)
let c :=
byte(
and(0x1f, shr(and(mload(add(s, i)), 0xff), 0x3e4088843e41bac000000000000)),
0x3010a071000000b0104040208000c05090d060e0f
)
n := mul(n, iszero(or(iszero(c), shr(252, result))))
result := add(shl(4, result), sub(c, 1))
if iszero(lt(i, n)) { break }
}
if iszero(n) {
mstore(0x00, 0x10182796) // `ParsingFailed()`.
revert(0x1c, 0x04)
}
}
}

function readUint16(bytes memory self, uint256 idx) internal pure returns (uint16 ret) {
require(idx + 2 <= self.length);
assembly {
ret := and(mload(add(add(self, 2), idx)), 0xFFFF)
}
}

function keccak(bytes memory self, uint256 offset, uint256 len) internal pure returns (bytes32 ret) {
require(offset + len <= self.length);
assembly {
ret := keccak256(add(add(self, 32), offset), len)
}
}

function substring(bytes memory self, uint256 offset, uint256 len) internal pure returns (bytes memory) {
require(offset + len <= self.length);
bytes memory ret = new bytes(len);
uint256 dest;
uint256 src;
assembly {
dest := add(ret, 32)
src := add(add(self, 32), offset)
}
memcpy(dest, src, len);
return ret;
}

function compare(
bytes memory self,
uint256 offset,
uint256 len,
bytes memory other,
uint256 otheroffset,
uint256 otherlen
) internal pure returns (int256) {
uint256 shortest = len;
if (otherlen < len) {
shortest = otherlen;
}
uint256 selfptr;
uint256 otherptr;
assembly {
selfptr := add(self, add(offset, 32))
otherptr := add(other, add(otheroffset, 32))
}
for (uint256 idx = 0; idx < shortest; idx += 32) {
uint256 a;
uint256 b;
assembly {
a := mload(selfptr)
b := mload(otherptr)
}
if (a != b) {
// Mask out irrelevant bytes and check again
uint256 mask;
if (shortest > 32) {
mask = type(uint256).max; // aka 0xffffff....
} else {
mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);
}
uint256 diff = (a & mask) - (b & mask);
if (diff != 0) {
return int256(diff);
}
}
selfptr += 32;
otherptr += 32;
}
return int256(len) - int256(otherlen);
}

function readBytes32(bytes memory self, uint256 idx) internal pure returns (bytes32 ret) {
require(idx + 32 <= self.length);
assembly {
ret := mload(add(add(self, 32), idx))
}
}

function readBytesN(bytes memory self, uint256 idx, uint256 len) internal pure returns (bytes32 ret) {
require(len <= 32);
require(idx + len <= self.length);
assembly {
let mask := not(sub(exp(256, sub(32, len)), 1))
ret := and(mload(add(add(self, 32), idx)), mask)
}
}

function memcpy(uint256 dest, uint256 src, uint256 len) private pure {
// Copy word-length chunks while possible
for (; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
uint256 mask;
if (len == 0) {
mask = type(uint256).max; // Set to maximum value of uint256
} else {
mask = 256 ** (32 - len) - 1;
}
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}

cyclomatic-complexity

Impact: Informational
Confidence: High

function parseTcbString(string calldata tcbInfoStr) external pure returns (TcbInfoBasic memory tcbInfo) {
JSONParserLib.Item memory root = JSONParserLib.parse(tcbInfoStr);
JSONParserLib.Item[] memory tcbInfoObj = root.children();
bool tcbTypeFound;
bool fmspcFound;
bool versionFound;
bool issueDateFound;
bool nextUpdateFound;
bool pceidFound;
bool evaluationFound;
bool idFound;
bool allFound;
for (uint256 y = 0; y < root.size(); y++) {
JSONParserLib.Item memory current = tcbInfoObj[y];
string memory decodedKey = JSONParserLib.decodeString(current.key());
string memory val = current.value();
if (decodedKey.eq("tcbType")) {
tcbInfo.tcbType = uint8(JSONParserLib.parseUint(val));
tcbTypeFound = true;
} else if (decodedKey.eq("id")) {
string memory idStr = JSONParserLib.decodeString(val);
if (idStr.eq("SGX")) {
tcbInfo.id = TcbId.SGX;
} else if (idStr.eq("TDX")) {
tcbInfo.id = TcbId.TDX;
} else {
revert TCBInfo_Invalid();
}
idFound = true;
} else if (decodedKey.eq("fmspc")) {
tcbInfo.fmspc = bytes6(uint48(JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(val))));
fmspcFound = true;
} else if (decodedKey.eq("version")) {
tcbInfo.version = uint32(JSONParserLib.parseUint(val));
versionFound = true;
} else if (decodedKey.eq("issueDate")) {
tcbInfo.issueDate = uint64(DateTimeUtils.fromISOToTimestamp(JSONParserLib.decodeString(val)));
issueDateFound = true;
} else if (decodedKey.eq("nextUpdate")) {
tcbInfo.nextUpdate = uint64(DateTimeUtils.fromISOToTimestamp(JSONParserLib.decodeString(val)));
nextUpdateFound = true;
} else if (decodedKey.eq("pceId")) {
tcbInfo.pceid = bytes2(uint16(JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(val))));
pceidFound = true;
} else if (decodedKey.eq("tcbEvaluationDataNumber")) {
tcbInfo.evaluationDataNumber = uint32(JSONParserLib.parseUint(val));
evaluationFound = true;
}
if (versionFound) {
allFound =
(tcbTypeFound && fmspcFound && issueDateFound && nextUpdateFound && pceidFound && evaluationFound);
if (tcbInfo.version >= 3) {
allFound = allFound && idFound;
}
if (allFound) {
break;
}
}
}
if (!allFound) {
revert TCBInfo_Invalid();
}
}

function _validatePcsCert(CA ca, bytes calldata cert) private view returns (bytes32 hash) {
X509Helper x509Lib = X509Helper(x509);
// Step 1: Check whether cert has expired
bool notExpired = x509Lib.certIsNotExpired(cert);
if (!notExpired) {
revert Certificate_Expired();
}
// Step 2: Check issuer and subject common names are valid
string memory issuerName = x509Lib.getIssuerCommonName(cert);
string memory subjectName = x509Lib.getSubjectCommonName(cert);
string memory expectedIssuer = ROOT_CA_COMMON_NAME;
string memory expectedSubject;
if (ca == CA.PLATFORM) {
expectedSubject = PCK_PLATFORM_CA_COMMON_NAME;
} else if (ca == CA.PROCESSOR) {
expectedSubject = PCK_PROCESSOR_CA_COMMON_NAME;
} else if (ca == CA.SIGNING) {
expectedSubject = SIGNING_COMMON_NAME;
} else if (ca == CA.ROOT) {
expectedSubject = ROOT_CA_COMMON_NAME;
}
if (!LibString.eq(issuerName, expectedIssuer)) {
revert Invalid_Issuer_Name();
}
if (!LibString.eq(subjectName, expectedSubject)) {
revert Invalid_Subject_Name();
}
// Step 3: Check Revocation Status
bytes memory rootCrlData = getAttestedData(pcsCrlAttestations[CA.ROOT]);
if (ca == CA.ROOT) {
bytes memory pubKey = x509Lib.getSubjectPublicKey(cert);
if (keccak256(pubKey) != ROOT_CA_PUBKEY_HASH) {
revert Root_Key_Mismatch();
}
} else if (rootCrlData.length > 0) {
uint256 serialNum = x509Lib.getSerialNumber(cert);
bool revoked = crlLib.serialNumberIsRevoked(serialNum, rootCrlData);
if (revoked) {
revert Certificate_Revoked(ca, serialNum);
}
}
// Step 4: Check signature
bytes memory rootCert = _getIssuer(CA.ROOT);
(bytes memory tbs, bytes memory signature) = x509Lib.getTbsAndSig(cert);
bytes32 digest = sha256(tbs);
bool sigVerified;
if (ca == CA.ROOT) {
// the root certificate is issued by its own key
sigVerified = verifySignature(digest, signature, cert);
} else if (rootCert.length > 0) {
sigVerified = verifySignature(digest, signature, rootCert);
} else {
// all other certificates should already have an iusuer configured
revert Missing_Issuer();
}
if (!sigVerified) {
revert Invalid_Signature();
}
hash = keccak256(tbs);
}

function _parseIdentity(string calldata identityStr) private pure returns (IdentityObj memory identity) {
JSONParserLib.Item memory root = JSONParserLib.parse(identityStr);
JSONParserLib.Item[] memory identityObj = root.children();
for (uint256 i = 0; i < root.size(); i++) {
JSONParserLib.Item memory current = identityObj[i];
string memory decodedKey = JSONParserLib.decodeString(current.key());
if (decodedKey.eq("issueDate")) {
identity.issueDateTimestamp =
uint64(DateTimeUtils.fromISOToTimestamp(JSONParserLib.decodeString(current.value())));
} else if (decodedKey.eq("nextUpdate")) {
identity.nextUpdateTimestamp =
uint64(DateTimeUtils.fromISOToTimestamp(JSONParserLib.decodeString(current.value())));
} else if (decodedKey.eq("id")) {
string memory idStr = JSONParserLib.decodeString(current.value());
if (LibString.eq(idStr, "QE")) {
identity.id = EnclaveId.QE;
} else if (LibString.eq(idStr, "QVE")) {
identity.id = EnclaveId.QVE;
} else if (LibString.eq(idStr, "TD_QE")) {
identity.id = EnclaveId.TD_QE;
} else {
revert Invalid_ID();
}
} else if (decodedKey.eq("version")) {
identity.version = uint32(JSONParserLib.parseUint(current.value()));
} else if (decodedKey.eq("tcbEvaluationDataNumber")) {
identity.tcbEvaluationDataNumber = uint32(JSONParserLib.parseUint(current.value()));
} else if (decodedKey.eq("miscselect")) {
uint256 val = JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(current.value()));
identity.miscselect = bytes4(uint32(val));
} else if (decodedKey.eq("miscselectMask")) {
uint256 val = JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(current.value()));
identity.miscselectMask = bytes4(uint32(val));
} else if (decodedKey.eq("attributes")) {
uint256 val = JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(current.value()));
identity.attributes = bytes16(uint128(val));
} else if (decodedKey.eq("attributesMask")) {
uint256 val = JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(current.value()));
identity.attributesMask = bytes16(uint128(val));
} else if (decodedKey.eq("mrsigner")) {
uint256 val = JSONParserLib.parseUintFromHex(JSONParserLib.decodeString(current.value()));
identity.mrsigner = bytes32(val);
} else if (decodedKey.eq("isvprodid")) {
identity.isvprodid = uint16(JSONParserLib.parseUint(current.value()));
} else if (decodedKey.eq("tcbLevels")) {
identity.tcb = _parseTcb(current.value());
}
}
}

function _parseTdxModuleIdentities(JSONParserLib.Item[] memory tdxModuleIdentitiesArr)
private
pure
returns (TDXModuleIdentity[] memory identities)
{
uint256 n = tdxModuleIdentitiesArr.length;
identities = new TDXModuleIdentity[](n);
for (uint256 i = 0; i < n; i++) {
JSONParserLib.Item[] memory currIdentity = tdxModuleIdentitiesArr[i].children();
for (uint256 j = 0; j < tdxModuleIdentitiesArr[i].size(); j++) {
string memory key = JSONParserLib.decodeString(currIdentity[j].key());
if (key.eq("id")) {
string memory val = JSONParserLib.decodeString(currIdentity[j].value());
identities[i].id = val;
}
if (key.eq("mrsigner")) {
string memory val = JSONParserLib.decodeString(currIdentity[j].value());
identities[i].mrsigner = _getMrSignerHex(val);
}
if (key.eq("attributes")) {
string memory val = JSONParserLib.decodeString(currIdentity[j].value());
identities[i].attributes = bytes8(uint64(JSONParserLib.parseUintFromHex(val)));
}
if (key.eq("attributesMask")) {
string memory val = JSONParserLib.decodeString(currIdentity[j].value());
identities[i].attributesMask = bytes8(uint64(JSONParserLib.parseUintFromHex(val)));
}
if (key.eq("tcbLevels")) {
JSONParserLib.Item[] memory tcbLevelsArr = currIdentity[j].children();
uint256 x = tcbLevelsArr.length;
identities[i].tcbLevels = new TDXModuleTCBLevelsObj[](x);
for (uint256 k = 0; k < x; k++) {
JSONParserLib.Item[] memory tcb = tcbLevelsArr[k].children();
for (uint256 l = 0; l < tcb.length; l++) {
key = JSONParserLib.decodeString(tcb[l].key());
if (key.eq("tcb")) {
JSONParserLib.Item[] memory isvsvnObj = tcb[l].children();
key = JSONParserLib.decodeString(isvsvnObj[0].key());
if (key.eq("isvsvn")) {
identities[i].tcbLevels[k].isvsvn =
uint8(JSONParserLib.parseUint(isvsvnObj[0].value()));
} else {
revert TCBInfo_Invalid();
}
}
if (key.eq("tcbDate")) {
identities[i].tcbLevels[k].tcbDateTimestamp =
uint64(DateTimeUtils.fromISOToTimestamp(JSONParserLib.decodeString(tcb[l].value())));
}
if (key.eq("tcbStatus")) {
identities[i].tcbLevels[k].status =
_getTcbStatus(JSONParserLib.decodeString(tcb[l].value()));
}
}
}
}
}
}
}

dead-code

Impact: Informational
Confidence: Medium

function _checkPckIsRevocable(CA ca, bytes memory pck) internal view pckCACheck(ca) returns (bool revocable) {
uint256 serialNumber = pckLib.getSerialNumber(pck);
bytes memory crlData = getAttestedData(Pcs.pcsCrlAttestations(ca));
revocable = crlLib.serialNumberIsRevoked(serialNumber, crlData);
}

solc-version

Impact: Informational
Confidence: High

  • ID-57
    Version constraint >=0.8.0 contains known severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)
    • FullInlinerNonExpressionSplitArgumentEvaluationOrder
    • MissingSideEffectsOnSelectorAccess
    • AbiReencodingHeadOverflowWithStaticArrayCleanup
    • DirtyBytesArrayToStorage
    • DataLocationChangeInInternalOverride
    • NestedCalldataArrayAbiReencodingSizeValidation
    • SignedImmutables
    • ABIDecodeTwoDimensionalArrayMemory
    • KeccakCaching.
      It is used by:
    • >=0.8.0

pragma solidity >=0.8.0;

pragma solidity ^0.8.0;

low-level-calls

Impact: Informational
Confidence: High

function ecdsaVerify(bytes32 messageHash, bytes memory signature, bytes memory key)
internal
view
returns (bool verified)
{
bytes memory args = abi.encode(
messageHash,
uint256(bytes32(signature.substring(0, 32))),
uint256(bytes32(signature.substring(32, 32))),
uint256(bytes32(key.substring(0, 32))),
uint256(bytes32(key.substring(32, 32)))
);
(bool success, bytes memory ret) = P256_VERIFIER.staticcall(args);
assert(success); // never reverts, always returns 0 or 1
verified = abi.decode(ret, (uint256)) == 1;
}

missing-inheritance

Impact: Informational
Confidence: High

contract AutomataDaoStorage is Ownable {
mapping(address => bool) _authorized;
mapping(bytes32 attId => bytes attData) _pccsData;
modifier onlyAuthorized(address dao) {
require(_authorized[dao], "Unauthorized caller");
_;
}
constructor() {
_initializeOwner(msg.sender);
}
function updateDao(address _pcsDao, address _pckDao, address _fmspcTcbDao, address _enclaveIdDao)
external
onlyOwner
{
_updateDao(_pcsDao, _pckDao, _fmspcTcbDao, _enclaveIdDao);
}
function revokeDao(address revoked) external onlyOwner {
_authorized[revoked] = false;
}
function writeToPccs(bytes32 attId, bytes memory attData) external onlyAuthorized(msg.sender) {
_pccsData[attId] = attData;
}
function deleteData(bytes32 attId) external onlyAuthorized(msg.sender) {
delete _pccsData[attId];
}
function readPccs(bytes32 attId) external view returns (bytes memory attData) {
attData = _pccsData[attId];
}
function _updateDao(address _pcsDao, address _pckDao, address _fmspcTcbDao, address _enclaveIdDao) private {
_authorized[_pcsDao] = true;
_authorized[_pckDao] = true;
_authorized[_fmspcTcbDao] = true;
_authorized[_enclaveIdDao] = true;
}
}

naming-convention

Impact: Informational
Confidence: High

function updateDao(address _pcsDao, address _pckDao, address _fmspcTcbDao, address _enclaveIdDao)

function setPcs(address _pcs) external onlyOwner {

function updateDao(address _pcsDao, address _pckDao, address _fmspcTcbDao, address _enclaveIdDao)

function updateDeps(address _x509, address _crl) external onlyOwner {

function getPtr(uint256 _ixs, uint256 _ixf, uint256 _ixl) internal pure returns (uint256) {

EnclaveIdentityHelper public EnclaveIdentityLib;

function getPtr(uint256 _ixs, uint256 _ixf, uint256 _ixl) internal pure returns (uint256) {

FmspcTcbHelper public FmspcTcbLib;

bytes constant base32HexTable =
hex"00010203040506070809FFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1FFFFFFFFFFFFFFFFFFFFF0A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";

function updateDeps(address _pcs, address _x509, address _crl) external onlyOwner {

function getPtr(uint256 _ixs, uint256 _ixf, uint256 _ixl) internal pure returns (uint256) {

function updateDeps(address _pcs, address _x509, address _crl) external onlyOwner {

function updateDeps(address _pcs, address _x509, address _crl) external onlyOwner {

function setPcs(address _pcs) external onlyOwner {

function updateDao(address _pcsDao, address _pckDao, address _fmspcTcbDao, address _enclaveIdDao)

function updateDeps(address _x509, address _crl) external onlyOwner {

function updateDao(address _pcsDao, address _pckDao, address _fmspcTcbDao, address _enclaveIdDao)

too-many-digits

Impact: Informational
Confidence: Medium

function _parseUintFromHex(string memory s) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(s)
// Skip two if starts with '0x' or '0X'.
let i := shl(1, and(eq(0x3078, or(shr(240, mload(add(s, 0x20))), 0x20)), gt(n, 1)))
for {} 1 {} {
i := add(i, 1)
let c :=
byte(
and(0x1f, shr(and(mload(add(s, i)), 0xff), 0x3e4088843e41bac000000000000)),
0x3010a071000000b0104040208000c05090d060e0f
)
n := mul(n, iszero(or(iszero(c), shr(252, result))))
result := add(shl(4, result), sub(c, 1))
if iszero(lt(i, n)) { break }
}
if iszero(n) {
mstore(0x00, 0x10182796) // `ParsingFailed()`.
revert(0x1c, 0x04)
}
}
}

function readBytes20(bytes memory self, uint256 idx) internal pure returns (bytes20 ret) {
require(idx + 20 <= self.length);
assembly {
ret :=
and(mload(add(add(self, 32), idx)), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000)
}
}

immutable-states

Impact: Optimization
Confidence: High

FmspcTcbHelper public FmspcTcbLib;

PCKHelper public pckLib;

EnclaveIdentityHelper public EnclaveIdentityLib;

@Liao1 Liao1 requested a review from smilenow September 27, 2024 08:29
@smilenow smilenow merged commit 408d2d3 into main Sep 27, 2024
2 checks passed
@preston4896 preston4896 deleted the Liao1-patch-1 branch November 6, 2024 04:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants