node-tpm2 0.0.4-beta.3 → 0.0.5-beta.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/README.md +396 -88
- package/api.js +233 -0
- package/docs/api-reference.md +1029 -0
- package/docs/roadmap.md +216 -0
- package/docs/windows-pcp.md +21 -0
- package/examples/nv-smoke.mjs +77 -0
- package/index.d.ts +89 -23
- package/native.cjs +65 -52
- package/native.d.ts +76 -0
- package/package.json +12 -10
package/api.js
CHANGED
|
@@ -66,6 +66,46 @@ export class TpmError extends Error {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function parseTpmHandle(handle) {
|
|
70
|
+
if (typeof handle === 'number') {
|
|
71
|
+
return `0x${handle.toString(16).padStart(8, '0')}`;
|
|
72
|
+
}
|
|
73
|
+
return handle;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function createKeyHandle(publicKeyDer, keyBlob) {
|
|
77
|
+
return {
|
|
78
|
+
export() {
|
|
79
|
+
return {
|
|
80
|
+
public: Buffer.from(keyBlob.public),
|
|
81
|
+
private: Buffer.from(keyBlob.private),
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
get publicKeyDer() {
|
|
86
|
+
return Buffer.from(publicKeyDer);
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
sign: wrapNative(async (digest) => {
|
|
90
|
+
requireNative('signKeyBlob');
|
|
91
|
+
const sig = await native.signKeyBlob({
|
|
92
|
+
keyBlob,
|
|
93
|
+
digest,
|
|
94
|
+
});
|
|
95
|
+
return Buffer.from(sig);
|
|
96
|
+
}),
|
|
97
|
+
|
|
98
|
+
decrypt: wrapNative(async (cipher) => {
|
|
99
|
+
requireNative('decryptKeyBlob');
|
|
100
|
+
const plain = await native.decryptKeyBlob({
|
|
101
|
+
keyBlob,
|
|
102
|
+
cipher,
|
|
103
|
+
});
|
|
104
|
+
return Buffer.from(plain);
|
|
105
|
+
}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
69
109
|
function createAkHandle(akPublicDer, akBlob) {
|
|
70
110
|
return {
|
|
71
111
|
/** Wrapped TPM2B_PUBLIC + TPM2B_PRIVATE for persistence (no persistent TPM handle). */
|
|
@@ -114,6 +154,102 @@ function createTpmHandle() {
|
|
|
114
154
|
requireNative('pcrRead');
|
|
115
155
|
return native.pcrRead(selection, bank);
|
|
116
156
|
}),
|
|
157
|
+
|
|
158
|
+
/** Extend a PCR digest in the SHA-256 bank. */
|
|
159
|
+
extend: wrapNative(async (index, digest) => {
|
|
160
|
+
requireNative('pcrExtend');
|
|
161
|
+
await native.pcrExtend(index, digest);
|
|
162
|
+
}),
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
random: {
|
|
166
|
+
/** Read `count` bytes from the TPM RNG (GetRandom). */
|
|
167
|
+
bytes: wrapNative(async (count) => {
|
|
168
|
+
requireNative('randomBytes');
|
|
169
|
+
const buf = await native.randomBytes(count);
|
|
170
|
+
return Buffer.from(buf);
|
|
171
|
+
}),
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
nv: {
|
|
175
|
+
readPublic: wrapNative(async (handle) => {
|
|
176
|
+
requireNative('nvReadPublic');
|
|
177
|
+
return native.nvReadPublic(parseTpmHandle(handle));
|
|
178
|
+
}),
|
|
179
|
+
|
|
180
|
+
read: wrapNative(async (handle, offset, size, auth) => {
|
|
181
|
+
requireNative('nvRead');
|
|
182
|
+
const buf = await native.nvRead(
|
|
183
|
+
parseTpmHandle(handle),
|
|
184
|
+
offset ?? undefined,
|
|
185
|
+
size ?? undefined,
|
|
186
|
+
auth ?? undefined,
|
|
187
|
+
);
|
|
188
|
+
return Buffer.from(buf);
|
|
189
|
+
}),
|
|
190
|
+
|
|
191
|
+
write: wrapNative(async (handle, data, offset, auth) => {
|
|
192
|
+
requireNative('nvWrite');
|
|
193
|
+
await native.nvWrite({
|
|
194
|
+
handle: parseTpmHandle(handle),
|
|
195
|
+
data,
|
|
196
|
+
offset: offset ?? undefined,
|
|
197
|
+
auth: auth ?? undefined,
|
|
198
|
+
});
|
|
199
|
+
}),
|
|
200
|
+
|
|
201
|
+
define: wrapNative(async (opts) => {
|
|
202
|
+
requireNative('nvDefine');
|
|
203
|
+
await native.nvDefine({
|
|
204
|
+
handle: parseTpmHandle(opts.handle),
|
|
205
|
+
size: opts.size,
|
|
206
|
+
auth: opts.auth ?? undefined,
|
|
207
|
+
ownerAuth: opts.ownerAuth ?? undefined,
|
|
208
|
+
});
|
|
209
|
+
}),
|
|
210
|
+
|
|
211
|
+
undefine: wrapNative(async (handle, ownerAuth) => {
|
|
212
|
+
requireNative('nvUndefine');
|
|
213
|
+
await native.nvUndefine({
|
|
214
|
+
handle: parseTpmHandle(handle),
|
|
215
|
+
ownerAuth: ownerAuth ?? undefined,
|
|
216
|
+
});
|
|
217
|
+
}),
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
keys: {
|
|
221
|
+
create: wrapNative(async (opts) => {
|
|
222
|
+
requireNative('createKey');
|
|
223
|
+
const result = await native.createKey({
|
|
224
|
+
keyType: opts?.type,
|
|
225
|
+
sign: opts?.sign,
|
|
226
|
+
decrypt: opts?.decrypt,
|
|
227
|
+
});
|
|
228
|
+
return createKeyHandle(result.publicKeyDer, result.keyBlob);
|
|
229
|
+
}),
|
|
230
|
+
|
|
231
|
+
load: wrapNative(async (blob) => {
|
|
232
|
+
requireNative('keyBlobPublicDer');
|
|
233
|
+
const publicKeyDer = await native.keyBlobPublicDer(blob);
|
|
234
|
+
return createKeyHandle(publicKeyDer, blob);
|
|
235
|
+
}),
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
seal: {
|
|
239
|
+
seal: wrapNative(async (opts) => {
|
|
240
|
+
requireNative('seal');
|
|
241
|
+
const buf = await native.seal({
|
|
242
|
+
data: opts.data,
|
|
243
|
+
pcrSelection: opts.pcrSelection,
|
|
244
|
+
});
|
|
245
|
+
return Buffer.from(buf);
|
|
246
|
+
}),
|
|
247
|
+
|
|
248
|
+
unseal: wrapNative(async (blob) => {
|
|
249
|
+
requireNative('unseal');
|
|
250
|
+
const plain = await native.unseal(blob);
|
|
251
|
+
return Buffer.from(plain);
|
|
252
|
+
}),
|
|
117
253
|
},
|
|
118
254
|
|
|
119
255
|
attest: {
|
|
@@ -202,12 +338,25 @@ export const Tpm = {
|
|
|
202
338
|
return this.getFixedProperties();
|
|
203
339
|
},
|
|
204
340
|
|
|
341
|
+
/** Flat: TPM RNG bytes (GetRandom). Prefer `tpm.random.bytes` on an open handle. */
|
|
342
|
+
randomBytes: wrapNative(async (count) => {
|
|
343
|
+
requireNative('randomBytes');
|
|
344
|
+
const buf = await native.randomBytes(count);
|
|
345
|
+
return Buffer.from(buf);
|
|
346
|
+
}),
|
|
347
|
+
|
|
205
348
|
/** Flat native binding: PCR read. Prefer `tpm.pcr.read` on an open handle. */
|
|
206
349
|
pcrRead: wrapNative(async (selection, bank) => {
|
|
207
350
|
requireNative('pcrRead');
|
|
208
351
|
return native.pcrRead(selection, bank);
|
|
209
352
|
}),
|
|
210
353
|
|
|
354
|
+
/** Flat native binding: PCR extend. Prefer `tpm.pcr.extend` on an open handle. */
|
|
355
|
+
pcrExtend: wrapNative(async (index, digest) => {
|
|
356
|
+
requireNative('pcrExtend');
|
|
357
|
+
await native.pcrExtend(index, digest);
|
|
358
|
+
}),
|
|
359
|
+
|
|
211
360
|
/** Flat native binding: ReadPublic. */
|
|
212
361
|
readPublic: wrapNative(async (handle) => {
|
|
213
362
|
requireNative('readPublic');
|
|
@@ -245,4 +394,88 @@ export const Tpm = {
|
|
|
245
394
|
requireNative('activateCredential');
|
|
246
395
|
return native.activateCredential(opts);
|
|
247
396
|
}),
|
|
397
|
+
|
|
398
|
+
createKey: wrapNative(async (opts) => {
|
|
399
|
+
requireNative('createKey');
|
|
400
|
+
const result = await native.createKey({
|
|
401
|
+
keyType: opts?.type,
|
|
402
|
+
sign: opts?.sign,
|
|
403
|
+
decrypt: opts?.decrypt,
|
|
404
|
+
});
|
|
405
|
+
return {
|
|
406
|
+
publicKeyDer: result.publicKeyDer,
|
|
407
|
+
keyBlob: result.keyBlob,
|
|
408
|
+
};
|
|
409
|
+
}),
|
|
410
|
+
|
|
411
|
+
signKeyBlob: wrapNative(async (opts) => {
|
|
412
|
+
requireNative('signKeyBlob');
|
|
413
|
+
const sig = await native.signKeyBlob(opts);
|
|
414
|
+
return Buffer.from(sig);
|
|
415
|
+
}),
|
|
416
|
+
|
|
417
|
+
decryptKeyBlob: wrapNative(async (opts) => {
|
|
418
|
+
requireNative('decryptKeyBlob');
|
|
419
|
+
const plain = await native.decryptKeyBlob(opts);
|
|
420
|
+
return Buffer.from(plain);
|
|
421
|
+
}),
|
|
422
|
+
|
|
423
|
+
nvRead: wrapNative(async (handle, offset, size, auth) => {
|
|
424
|
+
requireNative('nvRead');
|
|
425
|
+
const buf = await native.nvRead(
|
|
426
|
+
parseTpmHandle(handle),
|
|
427
|
+
offset ?? undefined,
|
|
428
|
+
size ?? undefined,
|
|
429
|
+
auth ?? undefined,
|
|
430
|
+
);
|
|
431
|
+
return Buffer.from(buf);
|
|
432
|
+
}),
|
|
433
|
+
|
|
434
|
+
nvWrite: wrapNative(async (handle, data, offset, auth) => {
|
|
435
|
+
requireNative('nvWrite');
|
|
436
|
+
await native.nvWrite({
|
|
437
|
+
handle: parseTpmHandle(handle),
|
|
438
|
+
data,
|
|
439
|
+
offset: offset ?? undefined,
|
|
440
|
+
auth: auth ?? undefined,
|
|
441
|
+
});
|
|
442
|
+
}),
|
|
443
|
+
|
|
444
|
+
nvReadPublic: wrapNative(async (handle) => {
|
|
445
|
+
requireNative('nvReadPublic');
|
|
446
|
+
return native.nvReadPublic(parseTpmHandle(handle));
|
|
447
|
+
}),
|
|
448
|
+
|
|
449
|
+
nvDefine: wrapNative(async (opts) => {
|
|
450
|
+
requireNative('nvDefine');
|
|
451
|
+
await native.nvDefine({
|
|
452
|
+
handle: parseTpmHandle(opts.handle),
|
|
453
|
+
size: opts.size,
|
|
454
|
+
auth: opts.auth ?? undefined,
|
|
455
|
+
ownerAuth: opts.ownerAuth ?? undefined,
|
|
456
|
+
});
|
|
457
|
+
}),
|
|
458
|
+
|
|
459
|
+
nvUndefine: wrapNative(async (handle, ownerAuth) => {
|
|
460
|
+
requireNative('nvUndefine');
|
|
461
|
+
await native.nvUndefine({
|
|
462
|
+
handle: parseTpmHandle(handle),
|
|
463
|
+
ownerAuth: ownerAuth ?? undefined,
|
|
464
|
+
});
|
|
465
|
+
}),
|
|
466
|
+
|
|
467
|
+
seal: wrapNative(async (opts) => {
|
|
468
|
+
requireNative('seal');
|
|
469
|
+
const buf = await native.seal({
|
|
470
|
+
data: opts.data,
|
|
471
|
+
pcrSelection: opts.pcrSelection,
|
|
472
|
+
});
|
|
473
|
+
return Buffer.from(buf);
|
|
474
|
+
}),
|
|
475
|
+
|
|
476
|
+
unseal: wrapNative(async (blob) => {
|
|
477
|
+
requireNative('unseal');
|
|
478
|
+
const plain = await native.unseal(blob);
|
|
479
|
+
return Buffer.from(plain);
|
|
480
|
+
}),
|
|
248
481
|
};
|