@microsoft/ccf-app 5.0.0-dev0 → 5.0.0-dev10
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/crypto.d.ts +5 -1
- package/crypto.js +5 -1
- package/global.d.ts +74 -3
- package/global.js +2 -0
- package/package.json +3 -2
- package/polyfill.js +70 -13
- package/snp_attestation.d.ts +4 -0
- package/snp_attestation.js +12 -0
- package/textcodec.d.ts +26 -0
- package/textcodec.js +53 -0
package/crypto.d.ts
CHANGED
|
@@ -11,13 +11,17 @@ export declare const generateRsaKeyPair: (size: number, exponent?: number | unde
|
|
|
11
11
|
*/
|
|
12
12
|
export declare const generateEcdsaKeyPair: (curve: string) => import("./global.js").CryptoKeyPair;
|
|
13
13
|
/**
|
|
14
|
-
* @inheritDoc global!CCFCrypto.
|
|
14
|
+
* @inheritDoc global!CCFCrypto.generateEddsaKeyPair
|
|
15
15
|
*/
|
|
16
16
|
export declare const generateEddsaKeyPair: (curve: string) => import("./global.js").CryptoKeyPair;
|
|
17
17
|
/**
|
|
18
18
|
* @inheritDoc global!CCFCrypto.wrapKey
|
|
19
19
|
*/
|
|
20
20
|
export declare const wrapKey: (key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: import("./global.js").WrapAlgoParams) => ArrayBuffer;
|
|
21
|
+
/**
|
|
22
|
+
* @inheritDoc global!CCFCrypto.unwrapKey
|
|
23
|
+
*/
|
|
24
|
+
export declare const unwrapKey: (key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: import("./global.js").WrapAlgoParams) => ArrayBuffer;
|
|
21
25
|
/**
|
|
22
26
|
* @inheritDoc global!CCFCrypto.sign
|
|
23
27
|
*/
|
package/crypto.js
CHANGED
|
@@ -27,13 +27,17 @@ export const generateRsaKeyPair = ccf.crypto.generateRsaKeyPair;
|
|
|
27
27
|
*/
|
|
28
28
|
export const generateEcdsaKeyPair = ccf.crypto.generateEcdsaKeyPair;
|
|
29
29
|
/**
|
|
30
|
-
* @inheritDoc global!CCFCrypto.
|
|
30
|
+
* @inheritDoc global!CCFCrypto.generateEddsaKeyPair
|
|
31
31
|
*/
|
|
32
32
|
export const generateEddsaKeyPair = ccf.crypto.generateEddsaKeyPair;
|
|
33
33
|
/**
|
|
34
34
|
* @inheritDoc global!CCFCrypto.wrapKey
|
|
35
35
|
*/
|
|
36
36
|
export const wrapKey = ccf.crypto.wrapKey;
|
|
37
|
+
/**
|
|
38
|
+
* @inheritDoc global!CCFCrypto.unwrapKey
|
|
39
|
+
*/
|
|
40
|
+
export const unwrapKey = ccf.crypto.unwrapKey;
|
|
37
41
|
/**
|
|
38
42
|
* @inheritDoc global!CCFCrypto.sign
|
|
39
43
|
*/
|
package/global.d.ts
CHANGED
|
@@ -298,7 +298,7 @@ export interface CCFCrypto {
|
|
|
298
298
|
/**
|
|
299
299
|
* Generate an EdDSA key pair.
|
|
300
300
|
*
|
|
301
|
-
* @param curve The name of the curve.
|
|
301
|
+
* @param curve The name of the curve. Only "curve25519" and "x25519" are supported.
|
|
302
302
|
*/
|
|
303
303
|
generateEddsaKeyPair(curve: string): CryptoKeyPair;
|
|
304
304
|
/**
|
|
@@ -308,6 +308,13 @@ export interface CCFCrypto {
|
|
|
308
308
|
* on the wrapping algorithm that is used (`wrapAlgo`).
|
|
309
309
|
*/
|
|
310
310
|
wrapKey(key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: WrapAlgoParams): ArrayBuffer;
|
|
311
|
+
/**
|
|
312
|
+
* Unwraps a key using a wrapping key.
|
|
313
|
+
*
|
|
314
|
+
* Constraints on the `key` and `wrappingKey` parameters depend
|
|
315
|
+
* on the wrapping algorithm that is used (`wrapAlgo`).
|
|
316
|
+
*/
|
|
317
|
+
unwrapKey(key: ArrayBuffer, wrappingKey: ArrayBuffer, wrapAlgo: WrapAlgoParams): ArrayBuffer;
|
|
311
318
|
/**
|
|
312
319
|
* Generate a digest (hash) of the given data.
|
|
313
320
|
*/
|
|
@@ -355,7 +362,7 @@ export interface CCFCrypto {
|
|
|
355
362
|
rsaPemToJwk(pem: string, kid?: string): JsonWebKeyRSAPrivate;
|
|
356
363
|
/**
|
|
357
364
|
* Converts an EdDSA public key as PEM to JSON Web Key (JWK) object.
|
|
358
|
-
*
|
|
365
|
+
* Only Curve25519 and X25519 are supported.
|
|
359
366
|
*
|
|
360
367
|
* @param pem EdDSA public key as PEM
|
|
361
368
|
* @param kid Key identifier (optional)
|
|
@@ -363,7 +370,7 @@ export interface CCFCrypto {
|
|
|
363
370
|
pubEddsaPemToJwk(pem: string, kid?: string): JsonWebKeyEdDSAPublic;
|
|
364
371
|
/**
|
|
365
372
|
* Converts an EdDSA private key as PEM to JSON Web Key (JWK) object.
|
|
366
|
-
*
|
|
373
|
+
* Only Curve25519 and X25519 are supported.
|
|
367
374
|
*
|
|
368
375
|
* @param pem EdDSA private key as PEM
|
|
369
376
|
* @param kid Key identifier (optional)
|
|
@@ -608,3 +615,67 @@ export interface OpenEnclave {
|
|
|
608
615
|
*/
|
|
609
616
|
verifyOpenEnclaveEvidence(format: string | undefined, evidence: ArrayBuffer, endorsements?: ArrayBuffer): EvidenceClaims;
|
|
610
617
|
}
|
|
618
|
+
export interface TcbVersion {
|
|
619
|
+
boot_loader: number;
|
|
620
|
+
tee: number;
|
|
621
|
+
snp: number;
|
|
622
|
+
microcode: number;
|
|
623
|
+
}
|
|
624
|
+
export interface SnpAttestationResult {
|
|
625
|
+
attestation: {
|
|
626
|
+
version: number;
|
|
627
|
+
guest_svn: number;
|
|
628
|
+
policy: {
|
|
629
|
+
abi_minor: number;
|
|
630
|
+
abi_major: number;
|
|
631
|
+
smt: number;
|
|
632
|
+
migrate_ma: number;
|
|
633
|
+
debug: number;
|
|
634
|
+
single_socket: number;
|
|
635
|
+
};
|
|
636
|
+
family_id: ArrayBuffer;
|
|
637
|
+
image_id: ArrayBuffer;
|
|
638
|
+
vmpl: number;
|
|
639
|
+
signature_algo: number;
|
|
640
|
+
platform_version: TcbVersion;
|
|
641
|
+
platform_info: {
|
|
642
|
+
smt_en: number;
|
|
643
|
+
tsme_en: number;
|
|
644
|
+
};
|
|
645
|
+
flags: {
|
|
646
|
+
author_key_en: number;
|
|
647
|
+
mask_chip_key: number;
|
|
648
|
+
signing_key: number;
|
|
649
|
+
};
|
|
650
|
+
report_data: ArrayBuffer;
|
|
651
|
+
measurement: ArrayBuffer;
|
|
652
|
+
host_data: ArrayBuffer;
|
|
653
|
+
id_key_digest: ArrayBuffer;
|
|
654
|
+
author_key_digest: ArrayBuffer;
|
|
655
|
+
report_id: ArrayBuffer;
|
|
656
|
+
report_id_ma: ArrayBuffer;
|
|
657
|
+
reported_tcb: TcbVersion;
|
|
658
|
+
chip_id: ArrayBuffer;
|
|
659
|
+
committed_tcb: TcbVersion;
|
|
660
|
+
current_minor: number;
|
|
661
|
+
current_build: number;
|
|
662
|
+
current_major: number;
|
|
663
|
+
committed_build: number;
|
|
664
|
+
committed_minor: number;
|
|
665
|
+
committed_major: number;
|
|
666
|
+
launch_tcb: TcbVersion;
|
|
667
|
+
signature: {
|
|
668
|
+
r: ArrayBuffer;
|
|
669
|
+
s: ArrayBuffer;
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
uvm_endorsements?: {
|
|
673
|
+
did: string;
|
|
674
|
+
feed: string;
|
|
675
|
+
svn: string;
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
export declare const snp_attestation: SnpAttestation;
|
|
679
|
+
export interface SnpAttestation {
|
|
680
|
+
verifySnpAttestation(evidence: ArrayBuffer, endorsements: ArrayBuffer, uvm_endorsements?: ArrayBuffer, endorsed_tcb?: string): SnpAttestationResult;
|
|
681
|
+
}
|
package/global.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/ccf-app",
|
|
3
|
-
"version": "5.0.0-
|
|
3
|
+
"version": "5.0.0-dev10",
|
|
4
4
|
"description": "CCF app support package",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -25,10 +25,11 @@
|
|
|
25
25
|
"chai": "^4.3.4",
|
|
26
26
|
"colors": "1.4.0",
|
|
27
27
|
"cross-env": "^7.0.3",
|
|
28
|
+
"get-func-name": "3.0.0",
|
|
28
29
|
"mocha": "^10.0.0",
|
|
29
30
|
"node-forge": "^1.2.0",
|
|
30
31
|
"ts-node": "^10.4.0",
|
|
31
|
-
"typedoc": "^0.
|
|
32
|
+
"typedoc": "^0.25.0",
|
|
32
33
|
"typescript": "^5.0.2"
|
|
33
34
|
}
|
|
34
35
|
}
|
package/polyfill.js
CHANGED
|
@@ -207,19 +207,32 @@ class CCFPolyfill {
|
|
|
207
207
|
return ecdsaKeyPair;
|
|
208
208
|
},
|
|
209
209
|
generateEddsaKeyPair(curve) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
210
|
+
if (curve === "curve25519") {
|
|
211
|
+
return jscrypto.generateKeyPairSync("ed25519", {
|
|
212
|
+
publicKeyEncoding: {
|
|
213
|
+
type: "spki",
|
|
214
|
+
format: "pem",
|
|
215
|
+
},
|
|
216
|
+
privateKeyEncoding: {
|
|
217
|
+
type: "pkcs8",
|
|
218
|
+
format: "pem",
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
if (curve !== "x25519")
|
|
224
|
+
throw new Error("Unsupported curve for EdDSA key pair generation: " + curve);
|
|
225
|
+
return jscrypto.generateKeyPairSync("x25519", {
|
|
226
|
+
publicKeyEncoding: {
|
|
227
|
+
type: "spki",
|
|
228
|
+
format: "pem",
|
|
229
|
+
},
|
|
230
|
+
privateKeyEncoding: {
|
|
231
|
+
type: "pkcs8",
|
|
232
|
+
format: "pem",
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
}
|
|
223
236
|
},
|
|
224
237
|
wrapKey(key, wrappingKey, parameters) {
|
|
225
238
|
if (parameters.name === "RSA-OAEP") {
|
|
@@ -252,6 +265,41 @@ class CCFPolyfill {
|
|
|
252
265
|
throw new Error("unsupported wrapAlgo.name");
|
|
253
266
|
}
|
|
254
267
|
},
|
|
268
|
+
unwrapKey(wrappedKey, unwrappingKey, unwrapAlgo) {
|
|
269
|
+
if (unwrapAlgo.name == "RSA-OAEP") {
|
|
270
|
+
return nodeBufToArrBuf(jscrypto.privateDecrypt({
|
|
271
|
+
key: Buffer.from(unwrappingKey),
|
|
272
|
+
oaepHash: "sha256",
|
|
273
|
+
padding: jscrypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
274
|
+
}, new Uint8Array(wrappedKey)));
|
|
275
|
+
}
|
|
276
|
+
else if (unwrapAlgo.name == "AES-KWP") {
|
|
277
|
+
const iv = Buffer.from("A65959A6", "hex"); // defined in RFC 5649
|
|
278
|
+
const decipher = jscrypto.createDecipheriv("id-aes256-wrap-pad", new Uint8Array(unwrappingKey), iv);
|
|
279
|
+
return nodeBufToArrBuf(Buffer.concat([
|
|
280
|
+
decipher.update(new Uint8Array(wrappedKey)),
|
|
281
|
+
decipher.final(),
|
|
282
|
+
]));
|
|
283
|
+
}
|
|
284
|
+
else if (unwrapAlgo.name == "RSA-OAEP-AES-KWP") {
|
|
285
|
+
const keyInfo = jscrypto.createPrivateKey(Buffer.from(unwrappingKey));
|
|
286
|
+
// asymmetricKeyDetails added in Node.js 15.7.0, we're at 16.
|
|
287
|
+
console.log(`Modulus length: `, keyInfo?.asymmetricKeyDetails?.modulusLength);
|
|
288
|
+
const modulusLengthInBytes = (keyInfo?.asymmetricKeyDetails?.modulusLength || 2048) / 8;
|
|
289
|
+
const wrap1 = wrappedKey.slice(0, modulusLengthInBytes);
|
|
290
|
+
const wrap2 = wrappedKey.slice(modulusLengthInBytes);
|
|
291
|
+
const aesKey = this.unwrapKey(wrap1, unwrappingKey, {
|
|
292
|
+
name: "RSA-OAEP",
|
|
293
|
+
label: unwrapAlgo.label,
|
|
294
|
+
});
|
|
295
|
+
return this.unwrapKey(wrap2, aesKey, {
|
|
296
|
+
name: "AES-KWP",
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
throw new Error("unsupported unwrapAlgo.name");
|
|
301
|
+
}
|
|
302
|
+
},
|
|
255
303
|
digest(algorithm, data) {
|
|
256
304
|
if (algorithm === "SHA-256") {
|
|
257
305
|
return nodeBufToArrBuf(jscrypto.createHash("sha256").update(new Uint8Array(data)).digest());
|
|
@@ -456,6 +504,9 @@ class CCFPolyfill {
|
|
|
456
504
|
wrapKey(key, wrappingKey, parameters) {
|
|
457
505
|
return this.crypto.wrapKey(key, wrappingKey, parameters);
|
|
458
506
|
}
|
|
507
|
+
unwrapKey(key, wrappingKey, parameters) {
|
|
508
|
+
return this.crypto.unwrapKey(key, wrappingKey, parameters);
|
|
509
|
+
}
|
|
459
510
|
digest(algorithm, data) {
|
|
460
511
|
return this.crypto.digest(algorithm, data);
|
|
461
512
|
}
|
|
@@ -479,6 +530,12 @@ class OpenEnclavePolyfill {
|
|
|
479
530
|
}
|
|
480
531
|
}
|
|
481
532
|
globalThis.openenclave = new OpenEnclavePolyfill();
|
|
533
|
+
class SnpAttestationPolyfill {
|
|
534
|
+
verifySnpAttestation(evidence, endorsements, uvm_endorsements, endorsed_tcb) {
|
|
535
|
+
throw new Error("Method not implemented.");
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
globalThis.snp_attestation = new SnpAttestationPolyfill();
|
|
482
539
|
function nodeBufToArrBuf(buf) {
|
|
483
540
|
// Note: buf.buffer is not safe, see docs.
|
|
484
541
|
const arrBuf = new ArrayBuffer(buf.byteLength);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @inheritDoc global!SnpAttestation.verifySnpAttestation
|
|
3
|
+
*/
|
|
4
|
+
export declare const verifySnpAttestation: (evidence: ArrayBuffer, endorsements: ArrayBuffer, uvm_endorsements?: ArrayBuffer | undefined, endorsed_tcb?: string | undefined) => import("./global").SnpAttestationResult;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the Apache 2.0 License.
|
|
3
|
+
/**
|
|
4
|
+
* The `snp_attestation` module provides SNP Attestation Validation.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { snp_attestation } from "./global";
|
|
9
|
+
/**
|
|
10
|
+
* @inheritDoc global!SnpAttestation.verifySnpAttestation
|
|
11
|
+
*/
|
|
12
|
+
export const verifySnpAttestation = snp_attestation.verifySnpAttestation;
|
package/textcodec.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type TextEncoderEncodeIntoResult = {
|
|
2
|
+
read?: number;
|
|
3
|
+
written?: number;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* TextEncoder can be used to encode string to Uint8Array.
|
|
7
|
+
*/
|
|
8
|
+
export declare class TextEncoder {
|
|
9
|
+
/**
|
|
10
|
+
* Always returns "utf-8".
|
|
11
|
+
*/
|
|
12
|
+
readonly encoding: string;
|
|
13
|
+
/**
|
|
14
|
+
* Returns Uint8Array containing UTF-8 encoded text.
|
|
15
|
+
* @param input Input string to encode.
|
|
16
|
+
* @returns Encoded bytes.
|
|
17
|
+
*/
|
|
18
|
+
encode(input: string): Uint8Array;
|
|
19
|
+
/**
|
|
20
|
+
* Not implemented.
|
|
21
|
+
* @param input
|
|
22
|
+
* @param output
|
|
23
|
+
* @throws Always throws an Error object.
|
|
24
|
+
*/
|
|
25
|
+
encodeInto(input: string, output: Uint8Array): TextEncoderEncodeIntoResult;
|
|
26
|
+
}
|
package/textcodec.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2
|
+
// Licensed under the Apache 2.0 License.
|
|
3
|
+
/**
|
|
4
|
+
* The `textcodec` module provides access to TextEncoder Web API class.
|
|
5
|
+
*
|
|
6
|
+
* Example:
|
|
7
|
+
* ```
|
|
8
|
+
* import * as ccftextcodec from '@microsoft/ccf-app/textcodec.js';
|
|
9
|
+
*
|
|
10
|
+
* const bytes = new ccftextcodec.TextEncoder().encode("foo")
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* If you need TextEncoder Web API as a globally accessible class:
|
|
14
|
+
* ```
|
|
15
|
+
* import * as ccftextcodec from '@microsoft/ccf-app/textcodec.js';
|
|
16
|
+
*
|
|
17
|
+
* if (globalThis != undefined && (globalThis as any).TextEncoder == undefined) {
|
|
18
|
+
* (globalThis as any).TextEncoder = ccftextcodec.TextEncoder;
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
import { ccf } from "./global.js";
|
|
26
|
+
/**
|
|
27
|
+
* TextEncoder can be used to encode string to Uint8Array.
|
|
28
|
+
*/
|
|
29
|
+
export class TextEncoder {
|
|
30
|
+
constructor() {
|
|
31
|
+
/**
|
|
32
|
+
* Always returns "utf-8".
|
|
33
|
+
*/
|
|
34
|
+
this.encoding = "utf-8";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Returns Uint8Array containing UTF-8 encoded text.
|
|
38
|
+
* @param input Input string to encode.
|
|
39
|
+
* @returns Encoded bytes.
|
|
40
|
+
*/
|
|
41
|
+
encode(input) {
|
|
42
|
+
return new Uint8Array(ccf.strToBuf(input));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Not implemented.
|
|
46
|
+
* @param input
|
|
47
|
+
* @param output
|
|
48
|
+
* @throws Always throws an Error object.
|
|
49
|
+
*/
|
|
50
|
+
encodeInto(input, output) {
|
|
51
|
+
throw new Error("Not implemented");
|
|
52
|
+
}
|
|
53
|
+
}
|