@super-protocol/sdk-js 3.16.4 → 3.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/RIGenerator.d.ts +3 -2
- package/dist/cjs/RIGenerator.js +7 -6
- package/dist/cjs/TIIGenerator.d.ts +2 -2
- package/dist/cjs/TIIGenerator.js +32 -4
- package/dist/cjs/TeeInputGeneratorBase.d.ts +3 -3
- package/dist/cjs/TeeInputGeneratorBase.js +5 -5
- package/dist/cjs/certificates/serializer.d.ts +5 -3
- package/dist/cjs/certificates/serializer.js +26 -11
- package/dist/cjs/certificates/types.d.ts +1 -1
- package/dist/cjs/connectors/BaseConnector.d.ts +3 -3
- package/dist/cjs/connectors/BaseConnector.js +1 -1
- package/dist/cjs/connectors/BlockchainConnector.js +3 -3
- package/dist/cjs/connectors/BlockchainEventsListener.d.ts +2 -2
- package/dist/cjs/connectors/BlockchainEventsListener.js +3 -2
- package/dist/cjs/constants.d.ts +1 -3
- package/dist/cjs/constants.js +3 -7
- package/dist/cjs/contracts/abi.d.ts +1067 -1137
- package/dist/cjs/contracts/abi.js +1408 -1500
- package/dist/cjs/crypto/Crypto.d.ts +10 -13
- package/dist/cjs/crypto/Crypto.js +14 -17
- package/dist/cjs/crypto/nodejs/AES.d.ts +1 -1
- package/dist/cjs/crypto/nodejs/AES.js +2 -2
- package/dist/cjs/crypto/nodejs/ARIA.d.ts +1 -1
- package/dist/cjs/crypto/nodejs/ARIA.js +2 -2
- package/dist/cjs/errors/index.d.ts +1 -0
- package/dist/cjs/errors/index.js +4 -2
- package/dist/cjs/errors/insufficient-funds.error.d.ts +19 -0
- package/dist/cjs/errors/insufficient-funds.error.js +57 -0
- package/dist/cjs/index.d.ts +3 -6
- package/dist/cjs/index.js +6 -9
- package/dist/cjs/models/Offer.d.ts +16 -1
- package/dist/cjs/models/Offer.js +59 -9
- package/dist/cjs/models/Order.d.ts +1 -1
- package/dist/cjs/models/Order.js +11 -15
- package/dist/cjs/models/Provider.d.ts +0 -1
- package/dist/cjs/models/Provider.js +1 -7
- package/dist/cjs/models/TCB.d.ts +1 -28
- package/dist/cjs/models/TCB.js +1 -61
- package/dist/cjs/models/TeeOffer.d.ts +3 -18
- package/dist/cjs/models/TeeOffer.js +20 -106
- package/dist/cjs/providers/storage/S3StorageProvider.js +5 -5
- package/dist/cjs/providers/storage/StorageKeyValueAdapter.d.ts +1 -1
- package/dist/cjs/providers/storage/StorageKeyValueAdapter.js +7 -7
- package/dist/cjs/providers/storage/fs-storage-provider.js +35 -15
- package/dist/cjs/providers/storage/parseStorageCredentials.d.ts +1 -2
- package/dist/cjs/staticModels/Consensus.d.ts +5 -16
- package/dist/cjs/staticModels/Consensus.js +17 -86
- package/dist/cjs/staticModels/Offers.d.ts +4 -1
- package/dist/cjs/staticModels/Offers.js +9 -8
- package/dist/cjs/staticModels/OffersCommon.d.ts +3 -1
- package/dist/cjs/staticModels/OffersCommon.js +6 -2
- package/dist/cjs/staticModels/Orders.js +12 -11
- package/dist/cjs/staticModels/ProviderRewards.js +2 -2
- package/dist/cjs/staticModels/StaticModel.js +5 -5
- package/dist/cjs/staticModels/SuperproToken.d.ts +7 -7
- package/dist/cjs/staticModels/SuperproToken.js +3 -3
- package/dist/cjs/staticModels/TeeOffers.d.ts +1 -7
- package/dist/cjs/staticModels/TeeOffers.js +11 -20
- package/dist/cjs/store.d.ts +0 -1
- package/dist/cjs/store.js +1 -2
- package/dist/cjs/tee/TeeBlockVerifier.d.ts +1 -2
- package/dist/cjs/tee/TeeBlockVerifier.js +17 -24
- package/dist/cjs/tee/TeeCertificateService.d.ts +1 -1
- package/dist/cjs/tee/TeeCertificateService.js +6 -10
- package/dist/cjs/tee/statuses.d.ts +0 -7
- package/dist/cjs/tee/statuses.js +2 -10
- package/dist/cjs/types/Consensus.d.ts +10 -31
- package/dist/cjs/types/Consensus.js +2 -10
- package/dist/cjs/types/Offer.d.ts +5 -0
- package/dist/cjs/types/Order.d.ts +26 -21
- package/dist/cjs/types/Order.js +24 -17
- package/dist/cjs/types/index.d.ts +0 -1
- package/dist/cjs/types/index.js +1 -2
- package/dist/cjs/utils/CryptoKeysTransformer.js +5 -5
- package/dist/cjs/utils/TxManager.js +21 -5
- package/dist/cjs/utils/helper.d.ts +2 -8
- package/dist/cjs/utils/helper.js +6 -75
- package/dist/cjs/utils/helpers/OrderArgsHelper.d.ts +2 -2
- package/dist/cjs/utils/helpers/OrderArgsHelper.js +5 -5
- package/dist/cjs/utils/helpers/index.d.ts +1 -0
- package/dist/cjs/utils/helpers/index.js +2 -1
- package/dist/cjs/utils/helpers/streamToBuffer.d.ts +4 -0
- package/dist/cjs/utils/helpers/streamToBuffer.js +13 -0
- package/dist/cjs/utils/order/versify.js +1 -7
- package/dist/cjs/utils/rent-calculator/rent-calculator.js +2 -3
- package/dist/cjs/utils/rent-calculator/types.d.ts +0 -1
- package/dist/cjs/utils/tcb.d.ts +2 -0
- package/dist/cjs/utils/tcb.js +13 -0
- package/dist/cjs/utils/types.d.ts +0 -5
- package/dist/mjs/RIGenerator.d.ts +3 -2
- package/dist/mjs/RIGenerator.js +8 -7
- package/dist/mjs/TIIGenerator.d.ts +2 -2
- package/dist/mjs/TIIGenerator.js +32 -4
- package/dist/mjs/TeeInputGeneratorBase.d.ts +3 -3
- package/dist/mjs/TeeInputGeneratorBase.js +5 -5
- package/dist/mjs/certificates/serializer.d.ts +5 -3
- package/dist/mjs/certificates/serializer.js +26 -11
- package/dist/mjs/certificates/types.d.ts +1 -1
- package/dist/mjs/connectors/BaseConnector.d.ts +3 -3
- package/dist/mjs/connectors/BaseConnector.js +1 -1
- package/dist/mjs/connectors/BlockchainConnector.js +3 -3
- package/dist/mjs/connectors/BlockchainEventsListener.d.ts +2 -2
- package/dist/mjs/connectors/BlockchainEventsListener.js +3 -2
- package/dist/mjs/constants.d.ts +1 -3
- package/dist/mjs/constants.js +2 -6
- package/dist/mjs/contracts/abi.d.ts +1067 -1137
- package/dist/mjs/contracts/abi.js +1406 -1498
- package/dist/mjs/crypto/Crypto.d.ts +10 -13
- package/dist/mjs/crypto/Crypto.js +14 -17
- package/dist/mjs/crypto/nodejs/AES.d.ts +1 -1
- package/dist/mjs/crypto/nodejs/AES.js +2 -2
- package/dist/mjs/crypto/nodejs/ARIA.d.ts +1 -1
- package/dist/mjs/crypto/nodejs/ARIA.js +2 -2
- package/dist/mjs/errors/index.d.ts +1 -0
- package/dist/mjs/errors/index.js +2 -1
- package/dist/mjs/errors/insufficient-funds.error.d.ts +19 -0
- package/dist/mjs/errors/insufficient-funds.error.js +53 -0
- package/dist/mjs/index.d.ts +3 -6
- package/dist/mjs/index.js +4 -7
- package/dist/mjs/models/Offer.d.ts +16 -1
- package/dist/mjs/models/Offer.js +53 -3
- package/dist/mjs/models/Order.d.ts +1 -1
- package/dist/mjs/models/Order.js +11 -15
- package/dist/mjs/models/Provider.d.ts +0 -1
- package/dist/mjs/models/Provider.js +1 -7
- package/dist/mjs/models/TCB.d.ts +1 -28
- package/dist/mjs/models/TCB.js +2 -62
- package/dist/mjs/models/TeeOffer.d.ts +3 -18
- package/dist/mjs/models/TeeOffer.js +13 -99
- package/dist/mjs/providers/storage/S3StorageProvider.js +5 -5
- package/dist/mjs/providers/storage/StorageKeyValueAdapter.d.ts +1 -1
- package/dist/mjs/providers/storage/StorageKeyValueAdapter.js +7 -7
- package/dist/mjs/providers/storage/fs-storage-provider.js +35 -15
- package/dist/mjs/providers/storage/parseStorageCredentials.d.ts +1 -2
- package/dist/mjs/staticModels/Consensus.d.ts +5 -16
- package/dist/mjs/staticModels/Consensus.js +18 -87
- package/dist/mjs/staticModels/Offers.d.ts +4 -1
- package/dist/mjs/staticModels/Offers.js +9 -8
- package/dist/mjs/staticModels/OffersCommon.d.ts +3 -1
- package/dist/mjs/staticModels/OffersCommon.js +6 -2
- package/dist/mjs/staticModels/Orders.js +12 -11
- package/dist/mjs/staticModels/ProviderRewards.js +3 -3
- package/dist/mjs/staticModels/StaticModel.js +5 -5
- package/dist/mjs/staticModels/SuperproToken.d.ts +7 -7
- package/dist/mjs/staticModels/SuperproToken.js +3 -3
- package/dist/mjs/staticModels/TeeOffers.d.ts +1 -7
- package/dist/mjs/staticModels/TeeOffers.js +12 -21
- package/dist/mjs/store.d.ts +0 -1
- package/dist/mjs/store.js +2 -3
- package/dist/mjs/tee/TeeBlockVerifier.d.ts +1 -2
- package/dist/mjs/tee/TeeBlockVerifier.js +17 -24
- package/dist/mjs/tee/TeeCertificateService.d.ts +1 -1
- package/dist/mjs/tee/TeeCertificateService.js +7 -11
- package/dist/mjs/tee/statuses.d.ts +0 -7
- package/dist/mjs/tee/statuses.js +1 -9
- package/dist/mjs/types/Consensus.d.ts +10 -31
- package/dist/mjs/types/Consensus.js +1 -9
- package/dist/mjs/types/Offer.d.ts +5 -0
- package/dist/mjs/types/Order.d.ts +26 -21
- package/dist/mjs/types/Order.js +21 -17
- package/dist/mjs/types/index.d.ts +0 -1
- package/dist/mjs/types/index.js +1 -2
- package/dist/mjs/utils/CryptoKeysTransformer.js +5 -5
- package/dist/mjs/utils/TxManager.js +21 -5
- package/dist/mjs/utils/helper.d.ts +2 -8
- package/dist/mjs/utils/helper.js +5 -68
- package/dist/mjs/utils/helpers/OrderArgsHelper.d.ts +2 -2
- package/dist/mjs/utils/helpers/OrderArgsHelper.js +5 -5
- package/dist/mjs/utils/helpers/index.d.ts +1 -0
- package/dist/mjs/utils/helpers/index.js +2 -1
- package/dist/mjs/utils/helpers/streamToBuffer.d.ts +4 -0
- package/dist/mjs/utils/helpers/streamToBuffer.js +9 -0
- package/dist/mjs/utils/order/versify.js +1 -7
- package/dist/mjs/utils/rent-calculator/rent-calculator.js +2 -3
- package/dist/mjs/utils/rent-calculator/types.d.ts +0 -1
- package/dist/mjs/utils/tcb.d.ts +2 -0
- package/dist/mjs/utils/tcb.js +9 -0
- package/dist/mjs/utils/types.d.ts +0 -5
- package/package.json +8 -9
- package/dist/cjs/contracts/Campaign.d.ts +0 -1198
- package/dist/cjs/contracts/Campaign.js +0 -1554
- package/dist/cjs/contracts/adminCertificateHelperAbi.d.ts +0 -316
- package/dist/cjs/contracts/adminCertificateHelperAbi.js +0 -410
- package/dist/cjs/proto/TeeDeviceInfo.d.ts +0 -292
- package/dist/cjs/proto/TeeDeviceInfo.js +0 -491
- package/dist/cjs/staticModels/AdminCertificateHelper.d.ts +0 -24
- package/dist/cjs/staticModels/AdminCertificateHelper.js +0 -99
- package/dist/cjs/staticModels/Campaign.d.ts +0 -62
- package/dist/cjs/staticModels/Campaign.js +0 -318
- package/dist/cjs/tee/QuoteValidator.d.ts +0 -46
- package/dist/cjs/tee/QuoteValidator.js +0 -456
- package/dist/cjs/tee/TcbSerializer.d.ts +0 -20
- package/dist/cjs/tee/TcbSerializer.js +0 -27
- package/dist/cjs/types/Campaign.d.ts +0 -55
- package/dist/cjs/types/Campaign.js +0 -17
- package/dist/cjs/utils/admin-service.d.ts +0 -13
- package/dist/cjs/utils/admin-service.js +0 -73
- package/dist/mjs/contracts/Campaign.d.ts +0 -1198
- package/dist/mjs/contracts/Campaign.js +0 -1551
- package/dist/mjs/contracts/adminCertificateHelperAbi.d.ts +0 -316
- package/dist/mjs/contracts/adminCertificateHelperAbi.js +0 -407
- package/dist/mjs/proto/TeeDeviceInfo.d.ts +0 -292
- package/dist/mjs/proto/TeeDeviceInfo.js +0 -485
- package/dist/mjs/staticModels/AdminCertificateHelper.d.ts +0 -24
- package/dist/mjs/staticModels/AdminCertificateHelper.js +0 -92
- package/dist/mjs/staticModels/Campaign.d.ts +0 -62
- package/dist/mjs/staticModels/Campaign.js +0 -313
- package/dist/mjs/tee/QuoteValidator.d.ts +0 -46
- package/dist/mjs/tee/QuoteValidator.js +0 -449
- package/dist/mjs/tee/TcbSerializer.d.ts +0 -20
- package/dist/mjs/tee/TcbSerializer.js +0 -23
- package/dist/mjs/types/Campaign.d.ts +0 -55
- package/dist/mjs/types/Campaign.js +0 -14
- package/dist/mjs/utils/admin-service.d.ts +0 -13
- package/dist/mjs/utils/admin-service.js +0 -66
|
@@ -1,449 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
import elliptic from 'elliptic';
|
|
3
|
-
import forge from 'node-forge';
|
|
4
|
-
import { Certificate } from '@fidm/x509';
|
|
5
|
-
import { formatter } from 'js-encoding-utils';
|
|
6
|
-
import { CertificateRevocationList } from 'pkijs';
|
|
7
|
-
import { fromBER } from 'asn1js';
|
|
8
|
-
import _ from 'lodash';
|
|
9
|
-
import { TeeSgxParser, TeeTdxParser, TeeParser } from './QuoteParser.js';
|
|
10
|
-
import { QuoteType, } from './types.js';
|
|
11
|
-
import rootLogger from '../logger.js';
|
|
12
|
-
import { TeeQuoteValidatorError } from './errors.js';
|
|
13
|
-
import { QEIdentityStatuses, TCBStatuses, QuoteValidationStatuses } from './statuses.js';
|
|
14
|
-
import { Encoding, HashAlgorithm } from '@super-protocol/dto-js';
|
|
15
|
-
import Crypto from '../crypto/index.js';
|
|
16
|
-
import { TeeSignatureVerifier } from './TeeSignatureVerifier.js';
|
|
17
|
-
import { ChallengeType } from '@super-protocol/pki-common';
|
|
18
|
-
const { ec } = elliptic;
|
|
19
|
-
const { util, asn1 } = forge;
|
|
20
|
-
const INTEL_BASE_SGX_URL = 'https://api.trustedservices.intel.com';
|
|
21
|
-
const INTEL_SGX_ROOT_CA_URL = 'https://certificates.trustedservices.intel.com/IntelSGXRootCA.der';
|
|
22
|
-
const SGX_OID = '1.2.840.113741.1.13.1';
|
|
23
|
-
const FMSPC_OID = `${SGX_OID}.4`;
|
|
24
|
-
const PCEID_OID = `${SGX_OID}.3`;
|
|
25
|
-
const TCB_OID = `${SGX_OID}.2`;
|
|
26
|
-
const PCESVN_OID = `${TCB_OID}.17`;
|
|
27
|
-
const INTEL_ROOT_PUB_KEY = new Uint8Array([
|
|
28
|
-
4, 11, 169, 196, 192, 192, 200, 97, 147, 163, 254, 35, 214, 176, 44, 218, 16, 168, 187, 212, 232,
|
|
29
|
-
142, 72, 180, 69, 133, 97, 163, 110, 112, 85, 37, 245, 103, 145, 142, 46, 220, 136, 228, 13, 134,
|
|
30
|
-
11, 208, 204, 78, 226, 106, 172, 201, 136, 229, 5, 169, 83, 85, 140, 69, 63, 107, 9, 4, 174, 115,
|
|
31
|
-
148,
|
|
32
|
-
]);
|
|
33
|
-
export class QuoteValidator {
|
|
34
|
-
isDefault;
|
|
35
|
-
baseUrl;
|
|
36
|
-
teeSgxParser;
|
|
37
|
-
teeTdxParser;
|
|
38
|
-
logger;
|
|
39
|
-
constructor(baseUrl) {
|
|
40
|
-
this.isDefault = baseUrl === INTEL_BASE_SGX_URL;
|
|
41
|
-
this.baseUrl = `${baseUrl}/sgx/certification/v4`;
|
|
42
|
-
this.teeSgxParser = new TeeSgxParser();
|
|
43
|
-
this.teeTdxParser = new TeeTdxParser();
|
|
44
|
-
this.logger = rootLogger.child({ className: QuoteValidator.name });
|
|
45
|
-
}
|
|
46
|
-
static getSignature(mrEnclave, challengeType, options) {
|
|
47
|
-
return TeeSignatureVerifier.getSignature(mrEnclave, challengeType, options);
|
|
48
|
-
}
|
|
49
|
-
static async checkSignature(quote, options = { getMrEnclaveSignature: TeeSignatureVerifier.getSignature }) {
|
|
50
|
-
const { type: quoteType } = TeeSgxParser.determineQuoteType(quote);
|
|
51
|
-
switch (quoteType) {
|
|
52
|
-
case QuoteType.SGX: {
|
|
53
|
-
const parser = new TeeSgxParser();
|
|
54
|
-
const parsedQuote = parser.parseQuote(quote);
|
|
55
|
-
const report = parser.parseReport(parsedQuote.report);
|
|
56
|
-
TeeSignatureVerifier.validateSignatureSgx(report.mrSigner);
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
case QuoteType.TDX: {
|
|
60
|
-
const mrEnclave = TeeParser.getMrEnclave(quote);
|
|
61
|
-
await TeeSignatureVerifier.validateSignature(mrEnclave, ChallengeType.TDX, options);
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
splitChain(chain) {
|
|
67
|
-
const begin = '-----BEGIN CERTIFICATE-----';
|
|
68
|
-
const end = '-----END CERTIFICATE-----';
|
|
69
|
-
return chain
|
|
70
|
-
.split(begin)
|
|
71
|
-
.filter(Boolean)
|
|
72
|
-
.map((cert) => begin.concat(cert.slice(0, cert.indexOf(end)), end));
|
|
73
|
-
}
|
|
74
|
-
findSequenceByOID(hexValue, targetOID) {
|
|
75
|
-
const buffer = util.hexToBytes(hexValue);
|
|
76
|
-
const asn1Data = asn1.fromDer(buffer);
|
|
77
|
-
return this.searchForSequence(asn1Data, targetOID);
|
|
78
|
-
}
|
|
79
|
-
searchForSequence(asn1Data, targetOID) {
|
|
80
|
-
if (asn1Data.type === asn1.Type.SEQUENCE) {
|
|
81
|
-
for (const child of asn1Data.value) {
|
|
82
|
-
if (child.type === asn1.Type.OID) {
|
|
83
|
-
const oid = asn1.derToOid(child.value);
|
|
84
|
-
if (oid === targetOID) {
|
|
85
|
-
return asn1Data;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (Array.isArray(asn1Data.value)) {
|
|
91
|
-
for (const child of asn1Data.value) {
|
|
92
|
-
const result = this.searchForSequence(child, targetOID);
|
|
93
|
-
if (result) {
|
|
94
|
-
return result;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
verifyDataBySignature(data, signature, key) {
|
|
101
|
-
const ellipticEc = new ec('p256');
|
|
102
|
-
return ellipticEc.verify(data, {
|
|
103
|
-
r: signature.subarray(0, 32),
|
|
104
|
-
s: signature.subarray(32),
|
|
105
|
-
}, ellipticEc.keyFromPublic(key, 'hex'));
|
|
106
|
-
}
|
|
107
|
-
checkValidDate(from, to) {
|
|
108
|
-
const now = Date.now();
|
|
109
|
-
return from < now && now < to;
|
|
110
|
-
}
|
|
111
|
-
checkChainForIssuers(pckCert, platformCert, rootCert) {
|
|
112
|
-
return (_.isEqual(pckCert.issuer, platformCert.subject) &&
|
|
113
|
-
_.isEqual(platformCert.issuer, rootCert.subject));
|
|
114
|
-
}
|
|
115
|
-
getCrl(crlData) {
|
|
116
|
-
const crlDer = crlData.startsWith('-----')
|
|
117
|
-
? formatter.pemToBin(crlData)
|
|
118
|
-
: Buffer.from(crlData, 'hex');
|
|
119
|
-
const crlAsn = fromBER(crlDer);
|
|
120
|
-
return new CertificateRevocationList({ schema: crlAsn.result });
|
|
121
|
-
}
|
|
122
|
-
checkCertificatesInCrl(crl, certIds) {
|
|
123
|
-
if (!crl.thisUpdate || !crl.nextUpdate) {
|
|
124
|
-
throw new TeeQuoteValidatorError('Certificate revocation list has no update date field');
|
|
125
|
-
}
|
|
126
|
-
if (!this.checkValidDate(crl.thisUpdate.value.valueOf(), crl.nextUpdate.value.valueOf())) {
|
|
127
|
-
throw new TeeQuoteValidatorError('Certificate revocation list has invalid update date');
|
|
128
|
-
}
|
|
129
|
-
if (crl.revokedCertificates) {
|
|
130
|
-
const isAnyRevoked = crl.revokedCertificates.find((revoked) => certIds.includes(Buffer.from(revoked.userCertificate.valueBlock.valueHexView).toString('hex')));
|
|
131
|
-
if (isAnyRevoked) {
|
|
132
|
-
throw new TeeQuoteValidatorError('Certificate in revokation list');
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
async getCertificates(quote) {
|
|
137
|
-
const platformCrlResult = await axios.get(`${this.baseUrl}/pckcrl?ca=platform&encoding=pem`);
|
|
138
|
-
const platformChain = decodeURIComponent(platformCrlResult.headers['sgx-pck-crl-issuer-chain']);
|
|
139
|
-
const [platformFetchedPem, rootFetchedPem] = this.splitChain(platformChain); // [platform, root]
|
|
140
|
-
const platformFetchedCert = Certificate.fromPEM(Buffer.from(platformFetchedPem));
|
|
141
|
-
const rootFetchedCert = Certificate.fromPEM(Buffer.from(rootFetchedPem));
|
|
142
|
-
if (!this.checkValidDate(platformFetchedCert.validFrom.valueOf(), platformFetchedCert.validTo.valueOf())) {
|
|
143
|
-
throw new TeeQuoteValidatorError('Platform certificate validation date is not valid');
|
|
144
|
-
}
|
|
145
|
-
if (!this.checkValidDate(rootFetchedCert.validFrom.valueOf(), rootFetchedCert.validTo.valueOf())) {
|
|
146
|
-
throw new TeeQuoteValidatorError('Root certificate validation date is not valid');
|
|
147
|
-
}
|
|
148
|
-
if (!_.isEqual(rootFetchedCert.issuer, rootFetchedCert.subject)) {
|
|
149
|
-
throw new TeeQuoteValidatorError('Root certificate is not self-signed');
|
|
150
|
-
}
|
|
151
|
-
if (Buffer.compare(rootFetchedCert.publicKey.keyRaw, INTEL_ROOT_PUB_KEY) !== 0) {
|
|
152
|
-
throw new TeeQuoteValidatorError('Wrong Intel root certificate public key');
|
|
153
|
-
}
|
|
154
|
-
const pckCert = Certificate.fromPEM(Buffer.from(quote.certificates.device.pem));
|
|
155
|
-
const certType = quote.qeCertificationDataType;
|
|
156
|
-
if (!this.checkValidDate(pckCert.validFrom.valueOf(), pckCert.validTo.valueOf())) {
|
|
157
|
-
throw new TeeQuoteValidatorError('PCK certificate validation date is not valid');
|
|
158
|
-
}
|
|
159
|
-
if (certType !== 5) {
|
|
160
|
-
throw new TeeQuoteValidatorError(`Unsupported certification data type: ${certType}`);
|
|
161
|
-
}
|
|
162
|
-
if (rootFetchedPem !== quote.certificates.root.pem) {
|
|
163
|
-
throw new TeeQuoteValidatorError("Invalid SGX root certificate in quote's certificate chain");
|
|
164
|
-
}
|
|
165
|
-
if (!this.checkChainForIssuers(pckCert, platformFetchedCert, rootFetchedCert)) {
|
|
166
|
-
throw new TeeQuoteValidatorError('Invalid issuers in certificates chain');
|
|
167
|
-
}
|
|
168
|
-
const certIds = [
|
|
169
|
-
rootFetchedCert.serialNumber,
|
|
170
|
-
platformFetchedCert.serialNumber,
|
|
171
|
-
pckCert.serialNumber,
|
|
172
|
-
];
|
|
173
|
-
const caCrlUrl = this.isDefault
|
|
174
|
-
? INTEL_SGX_ROOT_CA_URL
|
|
175
|
-
: `${this.baseUrl}/crl?uri=${INTEL_SGX_ROOT_CA_URL}`;
|
|
176
|
-
const intelCrlDer = await axios.get(caCrlUrl, {
|
|
177
|
-
responseType: 'arraybuffer',
|
|
178
|
-
});
|
|
179
|
-
const intelCrlAsn = fromBER(Buffer.from(intelCrlDer.data));
|
|
180
|
-
this.checkCertificatesInCrl(new CertificateRevocationList({ schema: intelCrlAsn.result }), certIds);
|
|
181
|
-
const platformCrl = this.getCrl(platformCrlResult.data);
|
|
182
|
-
this.checkCertificatesInCrl(platformCrl, certIds);
|
|
183
|
-
return { pckCert, rootCertPem: rootFetchedPem };
|
|
184
|
-
}
|
|
185
|
-
async verifyQeReportSignature(quote, pckPublicKey) {
|
|
186
|
-
const signature = Buffer.from(quote.qeReportSignature);
|
|
187
|
-
const reportHash = await this.getSha256Hash(Buffer.from(quote.qeReport));
|
|
188
|
-
return this.verifyDataBySignature(reportHash, signature, pckPublicKey);
|
|
189
|
-
}
|
|
190
|
-
async verifyQeReportData(quote, report) {
|
|
191
|
-
const qeAuthData = quote.qeAuthenticationData;
|
|
192
|
-
const attestationKey = quote.ecdsaAttestationKey;
|
|
193
|
-
const qeReportDataHash = report.dataHash;
|
|
194
|
-
const calculatedHash = await this.getSha256Hash(Buffer.concat([attestationKey, qeAuthData]));
|
|
195
|
-
const result = Buffer.compare(qeReportDataHash, calculatedHash);
|
|
196
|
-
return result === 0;
|
|
197
|
-
}
|
|
198
|
-
async verifyEnclaveReportSignature(quote) {
|
|
199
|
-
const key = Buffer.from(quote.ecdsaAttestationKey);
|
|
200
|
-
const headerBuffer = Buffer.from(quote.rawHeader);
|
|
201
|
-
const reportBuffer = quote.quoteType === QuoteType.SGX
|
|
202
|
-
? Buffer.from(quote.report)
|
|
203
|
-
: Buffer.from(quote.tdQuoteBody);
|
|
204
|
-
const expected = quote.quoteType === QuoteType.SGX
|
|
205
|
-
? Buffer.from(quote.isvEnclaveReportSignature)
|
|
206
|
-
: Buffer.from(quote.quoteSignature);
|
|
207
|
-
const calculatedHash = await this.getSha256Hash(Buffer.concat([headerBuffer, reportBuffer]));
|
|
208
|
-
const ellipticEc = new ec('p256');
|
|
209
|
-
return ellipticEc.verify(calculatedHash, {
|
|
210
|
-
r: expected.subarray(0, 32),
|
|
211
|
-
s: expected.subarray(32),
|
|
212
|
-
}, Buffer.concat([Buffer.from([4]), key]));
|
|
213
|
-
}
|
|
214
|
-
async validateQuoteStructure(quote, report, pckPublicKey) {
|
|
215
|
-
if (!(await this.verifyQeReportSignature(quote, pckPublicKey))) {
|
|
216
|
-
throw new TeeQuoteValidatorError('Wrong QE report signature');
|
|
217
|
-
}
|
|
218
|
-
if (!(await this.verifyQeReportData(quote, report))) {
|
|
219
|
-
throw new TeeQuoteValidatorError('Wrong QE report data');
|
|
220
|
-
}
|
|
221
|
-
if (!(await this.verifyEnclaveReportSignature(quote))) {
|
|
222
|
-
throw new TeeQuoteValidatorError('Wrong enclave report signature');
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
getSgxExtensionData(pckCert) {
|
|
226
|
-
const sgxExtensionData = pckCert.extensions.find((item) => item.oid === SGX_OID);
|
|
227
|
-
if (!sgxExtensionData) {
|
|
228
|
-
throw new TeeQuoteValidatorError('SGX data not found in PCK certificate');
|
|
229
|
-
}
|
|
230
|
-
return sgxExtensionData;
|
|
231
|
-
}
|
|
232
|
-
getDataFromExtension(sgxExtensionData, targetOid, targetType) {
|
|
233
|
-
const rawData = this.findSequenceByOID(sgxExtensionData.value.toString('hex'), targetOid);
|
|
234
|
-
if (!rawData) {
|
|
235
|
-
throw new TeeQuoteValidatorError(`OID ${targetOid} not found in PCK certificate's SGX data`);
|
|
236
|
-
}
|
|
237
|
-
const data = rawData.value.filter((asnElement) => asnElement.type === targetType);
|
|
238
|
-
if (!data.length) {
|
|
239
|
-
throw new TeeQuoteValidatorError(`Data on OID ${targetOid} of type ${targetType} not found`);
|
|
240
|
-
}
|
|
241
|
-
const result = util.bytesToHex(data[0].value);
|
|
242
|
-
return targetType === asn1.Type.OCTETSTRING ? result : parseInt(result, 16).toString();
|
|
243
|
-
}
|
|
244
|
-
async getTcbInfo(fmspc, rootCertPem, quoteType) {
|
|
245
|
-
let tcbUrl = `${this.baseUrl}/tcb?fmspc=${fmspc}`;
|
|
246
|
-
if (quoteType === QuoteType.TDX) {
|
|
247
|
-
tcbUrl = tcbUrl.replace('sgx/certification', 'tdx/certification');
|
|
248
|
-
}
|
|
249
|
-
const tcbData = await axios.get(tcbUrl);
|
|
250
|
-
const tcbInfoHeader = 'tcb-info-issuer-chain';
|
|
251
|
-
const tcbInfoChain = this.splitChain(decodeURIComponent(tcbData.headers[tcbInfoHeader])); // [tcb, root]
|
|
252
|
-
if (tcbInfoChain[1] !== rootCertPem) {
|
|
253
|
-
throw new TeeQuoteValidatorError('Invalid SGX root certificate in TCB chain');
|
|
254
|
-
}
|
|
255
|
-
const tcbCert = Certificate.fromPEM(Buffer.from(tcbInfoChain[0]));
|
|
256
|
-
const key = tcbCert.publicKey.keyRaw;
|
|
257
|
-
const signature = Buffer.from(tcbData.data.signature, 'hex');
|
|
258
|
-
const calculatedhash = await this.getSha256Hash(Buffer.from(JSON.stringify(tcbData.data.tcbInfo)));
|
|
259
|
-
const result = this.verifyDataBySignature(calculatedhash, signature, key);
|
|
260
|
-
if (!result) {
|
|
261
|
-
throw new TeeQuoteValidatorError('TCB info signature is not valid');
|
|
262
|
-
}
|
|
263
|
-
if (tcbData.data.tcbInfo.nextUpdate.valueOf() > Date.now()) {
|
|
264
|
-
throw new TeeQuoteValidatorError('TCB next update date is out of date');
|
|
265
|
-
}
|
|
266
|
-
return tcbData.data;
|
|
267
|
-
}
|
|
268
|
-
async getQEIdentity(rootCertPem, quoteType) {
|
|
269
|
-
let qeIdentityUrl = `${this.baseUrl}/qe/identity`;
|
|
270
|
-
if (quoteType === QuoteType.TDX) {
|
|
271
|
-
qeIdentityUrl = qeIdentityUrl.replace('sgx/certification', 'tdx/certification');
|
|
272
|
-
}
|
|
273
|
-
const qeIdentityData = await axios.get(qeIdentityUrl);
|
|
274
|
-
const qeIdentityHeader = 'sgx-enclave-identity-issuer-chain';
|
|
275
|
-
const qeIdentityChain = this.splitChain(decodeURIComponent(qeIdentityData.headers[qeIdentityHeader])); // [qeIdentity, root]
|
|
276
|
-
if (qeIdentityChain[1] !== rootCertPem) {
|
|
277
|
-
throw new TeeQuoteValidatorError('Invalid SGX root certificate in enclave identity chain');
|
|
278
|
-
}
|
|
279
|
-
const qeIdentityCert = Certificate.fromPEM(Buffer.from(qeIdentityChain[0]));
|
|
280
|
-
const key = qeIdentityCert.publicKey.keyRaw;
|
|
281
|
-
const signature = Buffer.from(qeIdentityData.data.signature, 'hex');
|
|
282
|
-
const calculatedhash = await this.getSha256Hash(Buffer.from(JSON.stringify(qeIdentityData.data.enclaveIdentity)));
|
|
283
|
-
const result = this.verifyDataBySignature(calculatedhash, signature, key);
|
|
284
|
-
if (!result) {
|
|
285
|
-
throw new TeeQuoteValidatorError('Enclave identity signature is not valid');
|
|
286
|
-
}
|
|
287
|
-
if (qeIdentityData.data.enclaveIdentity.nextUpdate.valueOf() > Date.now()) {
|
|
288
|
-
throw new TeeQuoteValidatorError('Enclave identity next update date is out of date');
|
|
289
|
-
}
|
|
290
|
-
return qeIdentityData.data;
|
|
291
|
-
}
|
|
292
|
-
getQEIdentityStatus(report, qeIdentity) {
|
|
293
|
-
const mrSigner = report.mrSigner.toString('hex');
|
|
294
|
-
if (mrSigner.toUpperCase() !== qeIdentity.enclaveIdentity.mrsigner) {
|
|
295
|
-
throw new TeeQuoteValidatorError('Wrong MR signer in QE report');
|
|
296
|
-
}
|
|
297
|
-
if (report.isvProdId !== qeIdentity.enclaveIdentity.isvprodid) {
|
|
298
|
-
throw new TeeQuoteValidatorError('Wrong ISV PROD ID in QE report');
|
|
299
|
-
}
|
|
300
|
-
const tcbLevel = qeIdentity.enclaveIdentity.tcbLevels.find((tcbLevel) => tcbLevel.tcb.isvsvn <= report.isvSvn);
|
|
301
|
-
const status = tcbLevel?.tcbStatus;
|
|
302
|
-
if (status) {
|
|
303
|
-
this.logger.info(`Enclave identity status is ${tcbLevel?.tcbStatus}`);
|
|
304
|
-
return status;
|
|
305
|
-
}
|
|
306
|
-
return QEIdentityStatuses.OutOfDate;
|
|
307
|
-
}
|
|
308
|
-
getTcbStatus(fmspc, pceId, tcbData, sgxExtensionData) {
|
|
309
|
-
if (fmspc.toUpperCase() !== tcbData.tcbInfo.fmspc.toUpperCase()) {
|
|
310
|
-
throw new TeeQuoteValidatorError('Wrong FMSPC in PCK certificate');
|
|
311
|
-
}
|
|
312
|
-
if (pceId !== tcbData.tcbInfo.pceId) {
|
|
313
|
-
throw new TeeQuoteValidatorError('Wrong PCEID in PCK certificate');
|
|
314
|
-
}
|
|
315
|
-
const pceSvn = this.getDataFromExtension(sgxExtensionData, PCESVN_OID, asn1.Type.INTEGER);
|
|
316
|
-
const sgxComponents = [...Array(16).keys()].map((i) => this.getDataFromExtension(sgxExtensionData, `${TCB_OID}.${i + 1}`, asn1.Type.INTEGER));
|
|
317
|
-
const tcbLevel = tcbData.tcbInfo.tcbLevels.find((tcbLevel) => tcbLevel.tcb.pcesvn <= Number(pceSvn) &&
|
|
318
|
-
tcbLevel.tcb.sgxtcbcomponents.every((el, index) => el.svn <= Number(sgxComponents[index])));
|
|
319
|
-
const status = tcbLevel?.tcbStatus;
|
|
320
|
-
if (status) {
|
|
321
|
-
this.logger.info(`TCB status is ${tcbLevel?.tcbStatus}`);
|
|
322
|
-
return status;
|
|
323
|
-
}
|
|
324
|
-
return TCBStatuses.OutOfDate;
|
|
325
|
-
}
|
|
326
|
-
getQuoteValidationStatus(qeIdentityStatus, tcbStatus) {
|
|
327
|
-
if (qeIdentityStatus === QEIdentityStatuses.OutOfDate) {
|
|
328
|
-
if (tcbStatus === TCBStatuses.UpToDate || tcbStatus === TCBStatuses.SWHardeningNeeded) {
|
|
329
|
-
return QuoteValidationStatuses.SecurityPatchNeeded;
|
|
330
|
-
}
|
|
331
|
-
if (tcbStatus === TCBStatuses.OutOfDateConfigurationNeeded ||
|
|
332
|
-
tcbStatus === TCBStatuses.ConfigurationAndSWHardeningNeeded) {
|
|
333
|
-
return QuoteValidationStatuses.SoftwareUpdateNeeded;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
if (qeIdentityStatus === QEIdentityStatuses.Revoked || tcbStatus === TCBStatuses.Revoked) {
|
|
337
|
-
throw new TeeQuoteValidatorError('QE identity or TCB revoked');
|
|
338
|
-
}
|
|
339
|
-
if (tcbStatus === TCBStatuses.UpToDate) {
|
|
340
|
-
return QuoteValidationStatuses.UpToDate;
|
|
341
|
-
}
|
|
342
|
-
if (tcbStatus === TCBStatuses.OutOfDate) {
|
|
343
|
-
return QuoteValidationStatuses.SecurityPatchNeeded;
|
|
344
|
-
}
|
|
345
|
-
if (tcbStatus === TCBStatuses.ConfigurationNeeded) {
|
|
346
|
-
return QuoteValidationStatuses.ConfigurationNeeded;
|
|
347
|
-
}
|
|
348
|
-
return QuoteValidationStatuses.SoftwareUpdateNeeded;
|
|
349
|
-
}
|
|
350
|
-
getQuoteValidationStatusDescription(status) {
|
|
351
|
-
switch (status) {
|
|
352
|
-
case QuoteValidationStatuses.UpToDate:
|
|
353
|
-
return 'The Quote verification passed and is at the latest TCB level.';
|
|
354
|
-
case QuoteValidationStatuses.ConfigurationNeeded:
|
|
355
|
-
return `The SGX platform firmware and SW are at the latest security patching level
|
|
356
|
-
but there are platform hardware configurations may expose the enclave to vulnerabilities.`;
|
|
357
|
-
case QuoteValidationStatuses.SecurityPatchNeeded:
|
|
358
|
-
return `The SGX platform firmware and SW are not at the latest security patching level.
|
|
359
|
-
The platform needs to be patched with firmware and/or software patches.`;
|
|
360
|
-
case QuoteValidationStatuses.SoftwareUpdateNeeded:
|
|
361
|
-
return `The SGX platform firmware and SW are at the latest security patching level but there are
|
|
362
|
-
certain vulnerabilities that can only be mitigated with software mitigations implemented by the enclave.`;
|
|
363
|
-
default:
|
|
364
|
-
return 'Quote verification failed.';
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
async checkQuote(quote, dataBlob) {
|
|
368
|
-
const logger = this.logger.child({ method: this.checkQuote.name });
|
|
369
|
-
const quoteBuffer = Buffer.from(quote);
|
|
370
|
-
const quoteStatus = await this.validate(quoteBuffer);
|
|
371
|
-
if (quoteStatus.quoteValidationStatus !== QuoteValidationStatuses.UpToDate) {
|
|
372
|
-
if (quoteStatus.quoteValidationStatus === QuoteValidationStatuses.Error) {
|
|
373
|
-
throw new Error('Quote is invalid');
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
logger.warn(quoteStatus, 'Quote validation status is not UpToDate');
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
const userDataCheckResult = await this.isQuoteHasUserData(quoteBuffer, Buffer.from(dataBlob));
|
|
380
|
-
if (!userDataCheckResult) {
|
|
381
|
-
throw new Error('Quote has invalid user data');
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
async checkSignature(quoteBuffer) {
|
|
385
|
-
await QuoteValidator.checkSignature(quoteBuffer);
|
|
386
|
-
}
|
|
387
|
-
async validate(quoteBuffer) {
|
|
388
|
-
try {
|
|
389
|
-
const quoteType = TeeParser.determineQuoteType(quoteBuffer);
|
|
390
|
-
const quote = quoteType.type === QuoteType.SGX
|
|
391
|
-
? this.teeSgxParser.parseQuote(quoteBuffer)
|
|
392
|
-
: this.teeTdxParser.parseQuote(quoteBuffer);
|
|
393
|
-
const report = this.teeSgxParser.parseReport(quote.qeReport);
|
|
394
|
-
const { pckCert, rootCertPem } = await this.getCertificates(quote);
|
|
395
|
-
await this.validateQuoteStructure(quote, report, pckCert.publicKey.keyRaw);
|
|
396
|
-
this.logger.info('Quote structure validated successfully');
|
|
397
|
-
const sgxExtensionData = this.getSgxExtensionData(pckCert);
|
|
398
|
-
const fmspc = this.getDataFromExtension(sgxExtensionData, FMSPC_OID, asn1.Type.OCTETSTRING);
|
|
399
|
-
const pceId = this.getDataFromExtension(sgxExtensionData, PCEID_OID, asn1.Type.OCTETSTRING);
|
|
400
|
-
const tcbData = await this.getTcbInfo(fmspc, rootCertPem, quoteType.type);
|
|
401
|
-
const qeIdentity = await this.getQEIdentity(rootCertPem, quoteType.type);
|
|
402
|
-
const qeIdentityStatus = this.getQEIdentityStatus(report, qeIdentity);
|
|
403
|
-
const tcbStatus = this.getTcbStatus(fmspc, pceId, tcbData, sgxExtensionData); // TODO method 'validate' isn't only for tcb - extract this from quote validator
|
|
404
|
-
const quoteValidationStatus = this.getQuoteValidationStatus(qeIdentityStatus, tcbStatus);
|
|
405
|
-
this.logger.info(`Quote validation status is ${quoteValidationStatus}`);
|
|
406
|
-
return {
|
|
407
|
-
quoteValidationStatus,
|
|
408
|
-
description: this.getQuoteValidationStatusDescription(quoteValidationStatus),
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
catch (error) {
|
|
412
|
-
this.logger.error(`Validation error: ${error}`);
|
|
413
|
-
return {
|
|
414
|
-
quoteValidationStatus: QuoteValidationStatuses.Error,
|
|
415
|
-
description: this.getQuoteValidationStatusDescription(QuoteValidationStatuses.Error),
|
|
416
|
-
error,
|
|
417
|
-
};
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
async isQuoteHasUserData(quoteBuffer, userDataBuffer) {
|
|
421
|
-
const quoteType = TeeParser.determineQuoteType(quoteBuffer);
|
|
422
|
-
const quote = quoteType.type === QuoteType.SGX
|
|
423
|
-
? this.teeSgxParser.parseQuote(quoteBuffer)
|
|
424
|
-
: this.teeTdxParser.parseQuote(quoteBuffer);
|
|
425
|
-
let slicedQuoteData;
|
|
426
|
-
const userDataHash = await this.getSha256Hash(userDataBuffer);
|
|
427
|
-
if (quoteType.type === QuoteType.SGX) {
|
|
428
|
-
slicedQuoteData = this.teeSgxParser
|
|
429
|
-
.parseReport(quote.report)
|
|
430
|
-
.userData.slice(0, userDataHash.length);
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
slicedQuoteData = this.teeTdxParser
|
|
434
|
-
.parseBody(quote.tdQuoteBody)
|
|
435
|
-
.reportData.slice(0, userDataHash.length);
|
|
436
|
-
}
|
|
437
|
-
const compareResult = Buffer.compare(slicedQuoteData, userDataHash);
|
|
438
|
-
return compareResult === 0;
|
|
439
|
-
}
|
|
440
|
-
async getSha256Hash(data) {
|
|
441
|
-
const hashInfo = {
|
|
442
|
-
algo: HashAlgorithm.SHA256,
|
|
443
|
-
encoding: Encoding.base64,
|
|
444
|
-
};
|
|
445
|
-
const hashData = await Crypto.createHash(data, hashInfo);
|
|
446
|
-
return Buffer.from(hashData.hash, hashData.encoding);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUXVvdGVWYWxpZGF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdGVlL1F1b3RlVmFsaWRhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUMxQixPQUFPLFFBQVEsTUFBTSxVQUFVLENBQUM7QUFDaEMsT0FBTyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxXQUFXLEVBQWEsTUFBTSxZQUFZLENBQUM7QUFDcEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUNsRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2pDLE9BQU8sQ0FBQyxNQUFNLFFBQVEsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUN6RSxPQUFPLEVBR0wsU0FBUyxHQUlWLE1BQU0sWUFBWSxDQUFDO0FBQ3BCLE9BQU8sVUFBVSxNQUFNLGNBQWMsQ0FBQztBQUV0QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDckQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RixPQUFPLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2pFLE9BQU8sTUFBTSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hDLE9BQU8sRUFBeUIsb0JBQW9CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFM0QsTUFBTSxFQUFFLEVBQUUsRUFBRSxHQUFHLFFBQVEsQ0FBQztBQUN4QixNQUFNLEVBQUUsSUFBSSxF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
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { TcbVerifiedStatus, ConsensusBenchmark } from '@super-protocol/dto-js';
|
|
2
|
-
import { BlockchainId } from '../types/index.js';
|
|
3
|
-
export type TcbData = {
|
|
4
|
-
checkingTcbId: string;
|
|
5
|
-
pubKey: string;
|
|
6
|
-
checkingTcbIds: BlockchainId[];
|
|
7
|
-
checkingTcbMarks: TcbVerifiedStatus[];
|
|
8
|
-
deviceId: string;
|
|
9
|
-
benchmark: ConsensusBenchmark;
|
|
10
|
-
properties: string;
|
|
11
|
-
};
|
|
12
|
-
export type VersionedTcbData = {
|
|
13
|
-
v: number;
|
|
14
|
-
[key: string]: unknown;
|
|
15
|
-
};
|
|
16
|
-
export declare class TcbDataSerializer {
|
|
17
|
-
private static readonly VERSION;
|
|
18
|
-
static serialize(data: TcbData): Uint8Array;
|
|
19
|
-
static deserialize(buffer: Uint8Array): TcbData;
|
|
20
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { decode, encode } from '@msgpack/msgpack';
|
|
2
|
-
export class TcbDataSerializer {
|
|
3
|
-
static VERSION = 1; // Current version of the data structure
|
|
4
|
-
static serialize(data) {
|
|
5
|
-
const serializedData = {
|
|
6
|
-
v: TcbDataSerializer.VERSION,
|
|
7
|
-
quote: data,
|
|
8
|
-
};
|
|
9
|
-
return encode(serializedData, { sortKeys: true });
|
|
10
|
-
}
|
|
11
|
-
static deserialize(buffer) {
|
|
12
|
-
const { v, ...rest } = decode(buffer);
|
|
13
|
-
switch (v) {
|
|
14
|
-
case 1: {
|
|
15
|
-
return rest;
|
|
16
|
-
}
|
|
17
|
-
// Future versions can be handled here with additional cases
|
|
18
|
-
default:
|
|
19
|
-
throw new Error(`Unsupported version: ${v}`);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVGNiU2VyaWFsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZWUvVGNiU2VyaWFsaXplci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBbUJsRCxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLE1BQU0sQ0FBVSxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsd0NBQXdDO0lBRTdFLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBYTtRQUM1QixNQUFNLGNBQWMsR0FBcUI7WUFDdkMsQ0FBQyxFQUFFLGlCQUFpQixDQUFDLE9BQU87WUFDNUIsS0FBSyxFQUFFLElBQUk7U0FDWixDQUFDO1FBRUYsT0FBTyxNQUFNLENBQUMsY0FBYyxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELE1BQU0sQ0FBQyxXQUFXLENBQUMsTUFBa0I7UUFDbkMsTUFBTSxFQUFFLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQXFCLENBQUM7UUFFMUQsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUNWLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDUCxPQUFPLElBQWUsQ0FBQztZQUN6QixDQUFDO1lBQ0QsNERBQTREO1lBQzVEO2dCQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakQsQ0FBQztJQUNILENBQUMifQ==
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { TokenAmount } from './Web3.js';
|
|
2
|
-
export declare enum Status {
|
|
3
|
-
InQueue = 0,
|
|
4
|
-
Deployed = 1,
|
|
5
|
-
NotDeployed = 2,
|
|
6
|
-
Revoked = 3
|
|
7
|
-
}
|
|
8
|
-
export declare enum MigrationNetwork {
|
|
9
|
-
Ethereum = 0,
|
|
10
|
-
BSC = 1,
|
|
11
|
-
Polygon = 2
|
|
12
|
-
}
|
|
13
|
-
export type ParticipantInfo = {
|
|
14
|
-
isRewardClaimed: boolean;
|
|
15
|
-
totalTransactions: number;
|
|
16
|
-
migrationsIndexes: number[];
|
|
17
|
-
};
|
|
18
|
-
export type ParticipantInfoViewed = {
|
|
19
|
-
participant: string;
|
|
20
|
-
rank: number;
|
|
21
|
-
score: number;
|
|
22
|
-
reward: TokenAmount;
|
|
23
|
-
};
|
|
24
|
-
export type TotalParticipantInfo = {
|
|
25
|
-
storedInfo: ParticipantInfo;
|
|
26
|
-
viewedInfo: ParticipantInfoViewed;
|
|
27
|
-
};
|
|
28
|
-
export type Migration = {
|
|
29
|
-
participant: string;
|
|
30
|
-
score: number;
|
|
31
|
-
firstSourceMigration: boolean;
|
|
32
|
-
sourceNetwork: MigrationNetwork;
|
|
33
|
-
status: Status;
|
|
34
|
-
statusChecks: number;
|
|
35
|
-
submittedTimestamp: number;
|
|
36
|
-
sourceAddress: string;
|
|
37
|
-
destinationAddress: string;
|
|
38
|
-
sourceUrl: string;
|
|
39
|
-
destinationUrl: string;
|
|
40
|
-
calculatedTransactionsBlockNumber: number;
|
|
41
|
-
transactions: number;
|
|
42
|
-
};
|
|
43
|
-
export type MigrationWithIndex = {
|
|
44
|
-
migration: Migration;
|
|
45
|
-
index: number;
|
|
46
|
-
};
|
|
47
|
-
export type ParticipantScore = {
|
|
48
|
-
participant: string;
|
|
49
|
-
score: number;
|
|
50
|
-
};
|
|
51
|
-
export type UpdateTxsArgs = {
|
|
52
|
-
migrationIndex: number;
|
|
53
|
-
transactions: number;
|
|
54
|
-
calculatedTransactionsBlockNumber: number;
|
|
55
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export var Status;
|
|
2
|
-
(function (Status) {
|
|
3
|
-
Status[Status["InQueue"] = 0] = "InQueue";
|
|
4
|
-
Status[Status["Deployed"] = 1] = "Deployed";
|
|
5
|
-
Status[Status["NotDeployed"] = 2] = "NotDeployed";
|
|
6
|
-
Status[Status["Revoked"] = 3] = "Revoked";
|
|
7
|
-
})(Status || (Status = {}));
|
|
8
|
-
export var MigrationNetwork;
|
|
9
|
-
(function (MigrationNetwork) {
|
|
10
|
-
MigrationNetwork[MigrationNetwork["Ethereum"] = 0] = "Ethereum";
|
|
11
|
-
MigrationNetwork[MigrationNetwork["BSC"] = 1] = "BSC";
|
|
12
|
-
MigrationNetwork[MigrationNetwork["Polygon"] = 2] = "Polygon";
|
|
13
|
-
})(MigrationNetwork || (MigrationNetwork = {}));
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2FtcGFpZ24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdHlwZXMvQ2FtcGFpZ24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxDQUFOLElBQVksTUFLWDtBQUxELFdBQVksTUFBTTtJQUNoQix5Q0FBTyxDQUFBO0lBQ1AsMkNBQVEsQ0FBQTtJQUNSLGlEQUFXLENBQUE7SUFDWCx5Q0FBTyxDQUFBO0FBQ1QsQ0FBQyxFQUxXLE1BQU0sS0FBTixNQUFNLFFBS2pCO0FBRUQsTUFBTSxDQUFOLElBQVksZ0JBSVg7QUFKRCxXQUFZLGdCQUFnQjtJQUMxQiwrREFBUSxDQUFBO0lBQ1IscURBQUcsQ0FBQTtJQUNILDZEQUFPLENBQUE7QUFDVCxDQUFDLEVBSlcsZ0JBQWdCLEtBQWhCLGdCQUFnQixRQUkzQiJ9
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { RegisterAdminParams } from './types.js';
|
|
2
|
-
import { BlockchainCert } from '../certificates/index.js';
|
|
3
|
-
export declare class AdminService {
|
|
4
|
-
private readonly logger;
|
|
5
|
-
constructor(adminCertificateContractAddress: string);
|
|
6
|
-
registerAdmin(params: RegisterAdminParams): Promise<void>;
|
|
7
|
-
isAdmin(caller: string): Promise<boolean>;
|
|
8
|
-
getAdminData(): Promise<{
|
|
9
|
-
admin: string;
|
|
10
|
-
rootCertId: number;
|
|
11
|
-
certsChain: BlockchainCert[];
|
|
12
|
-
}>;
|
|
13
|
-
}
|