1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
ash / components / arc / mojom / oemcrypto.mojom [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Next MinVersion: 5
// The original version of this file lives in the Chromium repository at:
// src/components/arc/mojom/oemcrypto.mojom
// This file defines the mojo interface between Android, Chrome and the
// Chrome OS daemon for the Widevine L1 OEMCrypto implementation used in ARC++.
// This file matches what's in Widevine's OEMCryptoCENC.h file closely and all
// methods are documented there.
// Version 1 of this interface supported OEMCrypto v11 and is now deprecated.
// Version 2 supports OEMCrypto v14.
// Version 3 maintains backwards compatibility with version 2 and supports
// OEMCrypto v15.
// Version 4 maintains backwards compatibility and supports OEMCrypto v16.
// Version 5 adds the v16 CopyBuffer variant.
module arc.mojom;
[Stable, Extensible]
enum OemCryptoResult {
SUCCESS = 0,
ERROR_INIT_FAILED = 1,
ERROR_TERMINATE_FAILED = 2,
ERROR_OPEN_FAILURE = 3,
ERROR_CLOSE_FAILURE = 4,
ERROR_ENTER_SECURE_PLAYBACK_FAILED = 5,
ERROR_EXIT_SECURE_PLAYBACK_FAILED = 6,
ERROR_SHORT_BUFFER = 7,
ERROR_NO_DEVICE_KEY = 8,
ERROR_NO_ASSET_KEY = 9,
ERROR_KEYBOX_INVALID = 10,
ERROR_NO_KEYDATA = 11,
ERROR_NO_CW = 12,
ERROR_DECRYPT_FAILED = 13,
ERROR_WRITE_KEYBOX = 14,
ERROR_WRAP_KEYBOX = 15,
ERROR_BAD_MAGIC = 16,
ERROR_BAD_CRC = 17,
ERROR_NO_DEVICEID = 18,
ERROR_RNG_FAILED = 19,
ERROR_RNG_NOT_SUPPORTED = 20,
ERROR_SETUP = 21,
ERROR_OPEN_SESSION_FAILED = 22,
ERROR_CLOSE_SESSION_FAILED = 23,
ERROR_INVALID_SESSIONS = 24,
ERROR_NOT_IMPLEMENTED = 25,
ERROR_NO_CONTENT_KEY = 26,
ERROR_CONTROL_INVALID = 27,
ERROR_UNKNOWN_FAILURE = 28,
ERROR_INVALID_CONTEXT = 29,
ERROR_SIGNATURE_FAILURE = 30,
ERROR_TOO_MANY_SESSIONS = 31,
ERROR_INVALID_NONCE = 32,
ERROR_TOO_MANY_KEYS = 33,
ERROR_DEVICE_NOT_RSA_PROVISIONED = 34,
ERROR_INVALID_RSA_KEY = 35,
ERROR_KEY_EXPIRED = 36,
ERROR_INSUFFICIENT_RESOURCES = 37,
ERROR_INSUFFICIENT_HDCP = 38,
ERROR_BUFFER_TOO_LARGE = 39,
[MinVersion=2] WARNING_GENERATION_SKEW = 40, // Warning, not an error.
[MinVersion=2] ERROR_GENERATION_SKEW = 41,
[MinVersion=2] LOCAL_DISPLAY_ONLY = 42, // Info, not an error.
[MinVersion=2] ERROR_ANALOG_OUTPUT = 43,
[MinVersion=2] ERROR_WRONG_PST = 44,
[MinVersion=2] ERROR_WRONG_KEYS = 45,
[MinVersion=2] ERROR_MISSING_MASTER = 46,
[MinVersion=2] ERROR_LICENSE_INACTIVE = 47,
[MinVersion=2] ERROR_ENTRY_NEEDS_UPDATE = 48,
[MinVersion=2] ERROR_ENTRY_IN_USE = 49,
[MinVersion=2] ERROR_USAGE_TABLE_UNRECOVERABLE = 50, // Reserved. Do not use.
[MinVersion=2] KEY_NOT_LOADED = 51,
[MinVersion=2] KEY_NOT_ENTITLED = 52,
[MinVersion=3] ERROR_BAD_HASH = 53,
[MinVersion=3] ERROR_OUTPUT_TOO_LARGE = 54,
[MinVersion=3] ERROR_SESSION_LOST_STATE = 55,
[MinVersion=3] ERROR_SYSTEM_INVALIDATED = 56,
[MinVersion=4] ERROR_LICENSE_RELOAD = 57,
[MinVersion=4] ERROR_MULTIPLE_USAGE_ENTRIES = 58,
[MinVersion=4] WARNING_MIXED_OUTPUT_PROTECTION = 59,
[MinVersion=4] ODK_ERROR_CORE_MESSAGE = 1000,
[MinVersion=4] ODK_SET_TIMER = 1001,
[MinVersion=4] ODK_DISABLE_TIMER = 1002,
[MinVersion=4] ODK_TIMER_EXPIRED = 1003,
[MinVersion=4] ODK_UNSUPPORTED_API = 1004,
[MinVersion=4] ODK_STALE_RENEWAL = 1005,
};
[Stable]
struct OemCryptoSecureBuffer {
// buffer_handle should be passed to the ProtectedBufferManager service in
// the GPU in order to retrieve the shared memory handle that corresponds
// to the actual secure buffer. It should then be mapped and data written at
// offset up until offset + max_length.
handle buffer_handle;
uint32 max_length;
uint32 offset;
};
[Stable, Extensible]
enum OemCryptoCipherMode {
CIPHER_MODE_CTR = 0,
CIPHER_MODE_CBC = 1,
};
[Stable, Extensible]
enum OemCryptoLicenseType {
CONTENT_LICENSE = 0,
ENTITLEMENT_LICENSE = 1,
};
[Stable]
struct OemCryptoSubstring {
uint32 offset;
uint32 length;
};
[Stable]
struct OemCryptoKeyObjectV14 {
uint32 key_id_offset;
uint32 key_id_length;
uint32 key_data_iv_offset;
uint32 key_data_offset;
uint32 key_data_length;
uint32 key_control_iv_offset;
uint32 key_control_offset;
OemCryptoCipherMode cipher_mode;
};
[Stable]
struct OemCryptoKeyObject {
OemCryptoSubstring key_id;
OemCryptoSubstring key_data_iv;
OemCryptoSubstring key_data;
OemCryptoSubstring key_control_iv;
OemCryptoSubstring key_control;
};
[Stable]
struct OemCryptoEntitledContentKeyObjectV14 {
array<uint8> entitlement_key_id;
array<uint8> content_key_id;
array<uint8, 16> content_key_data_iv;
array<uint8> content_key_data;
};
[Stable]
struct OemCryptoEntitledContentKeyObject {
OemCryptoSubstring entitlement_key_id;
OemCryptoSubstring content_key_id;
OemCryptoSubstring content_key_data_iv;
OemCryptoSubstring content_key_data;
};
[Stable]
struct OemCryptoKeyRefreshObjectV14 {
uint32 key_id_offset;
uint32 key_id_length;
bool has_key_control_iv;
uint32 key_control_iv_offset;
uint32 key_control_offset;
};
[Stable]
struct OemCryptoKeyRefreshObject {
OemCryptoSubstring key_id;
OemCryptoSubstring key_control_iv;
OemCryptoSubstring key_control;
};
[Stable, Extensible]
enum OemCryptoAlgorithm {
AES_CBC_128_NO_PADDING = 0,
HMAC_SHA265 = 1,
};
[Stable]
struct OemCryptoCencEncryptPatternDesc {
uint32 encrypt;
uint32 skip;
uint32 offset;
};
[Stable, Extensible]
enum OemCryptoUsageEntryStatus {
UNUSED = 0,
ACTIVE = 1,
INACTIVE = 2,
INACTIVE_USED = 3,
INACTIVE_UNUSED = 4,
};
[Stable]
struct OemCryptoPstReport {
array<uint8, 20> signature;
uint8 status;
uint8 clock_security_level;
uint64 seconds_since_license_received;
uint64 seconds_since_first_decrypt;
uint64 seconds_since_last_decrypt;
};
[Stable, Extensible]
enum OemCryptoRsaPaddingScheme {
SIGN_RSASSA_PSS = 1,
SIGN_PKCS1_BLOCK1 = 2,
};
[Stable, Extensible]
enum OemCryptoHdcpCapability {
HDCP_NONE = 0,
HDCP_V1 = 1,
HDCP_V2 = 2,
HDCP_V2_1 = 3,
HDCP_V2_2 = 4,
HDCP_V2_3 = 5,
HDCP_NO_DIGITAL_OUTPUT = 0xFF,
};
[Stable, Extensible]
enum OemCryptoProvisioningMethod {
PROVISIONING_ERROR = 0,
DRM_CERTIFICATE = 1,
KEYBOX = 2,
OEM_CERTIFICATE = 3,
};
[Stable, Extensible]
enum OemCryptoPrivateKey {
RSA_PRIVATE_KEY = 0,
ECC_PRIVATE_KEY = 1,
};
[Stable]
struct SubSampleDescription {
uint32 num_bytes_clear;
uint32 num_bytes_encrypted;
uint8 subsample_flags;
uint32 block_offset;
};
// This is the interface that implements all the calls that map to the
// OEMCrypto API itself.
// Next method ID: 77
[Stable, Uuid="ed3807bc-7bce-472d-be4f-68774e613ace"]
interface OemCryptoService {
InitializeDeprecated@0() => (OemCryptoResult result);
[MinVersion=2] Initialize@36(uint32 oemcrypto_version)
=> (OemCryptoResult result);
Terminate@1() => (OemCryptoResult result);
OpenSession@2() => (OemCryptoResult result, uint32 session);
CloseSession@3(uint32 session) => (OemCryptoResult result);
GenerateDerivedKeys@4(uint32 session, array<uint8> mac_key_context,
array<uint8> enc_key_context)
=> (OemCryptoResult result);
GenerateNonce@5(uint32 session) => (OemCryptoResult result, uint32 nonce);
GenerateSignature@6(uint32 session, array<uint8> message)
=> (OemCryptoResult result, array<uint8>? signature);
// The offset values are offsets into the message parameter for those values.
// If they have a length and it's zero, then they are NULL; if there is no
// length param then a bool param is there to indicate presence.
LoadKeysV11OrV12@7(uint32 session, array<uint8> message,
array<uint8> signature, bool has_enc_mac_keys,
uint32 enc_mac_keys_iv_offset,
uint32 enc_mac_keys_offset,
array<OemCryptoKeyObjectV14> key_array,
uint32 pst_offset, uint32 pst_length)
=> (OemCryptoResult result);
RefreshKeysV14@8(uint32 session, array<uint8> message,
array<uint8> signature,
array<OemCryptoKeyRefreshObjectV14> key_array)
=> (OemCryptoResult result);
QueryKeyControl@9(uint32 session, array<uint8> key_id)
=> (OemCryptoResult result, array<uint8>? key_control_block);
SelectKeyV13@10(uint32 session, array<uint8> key_id)
=> (OemCryptoResult result);
DecryptCencV15@11(uint32 session, array<uint8> data, bool is_encrypted,
array<uint8, 16> iv, uint32 block_offset,
OemCryptoSecureBuffer? secure_buffer,
OemCryptoCencEncryptPatternDesc pattern)
=> (OemCryptoResult result, array<uint8>? decrypted_data);
GenericEncrypt@12(uint32 session, array<uint8> data, array<uint8, 16> iv,
OemCryptoAlgorithm algorithm) =>
(OemCryptoResult result, array<uint8>? encrypted_data);
GenericDecrypt@13(uint32 session, array<uint8> data, array<uint8, 16> iv,
OemCryptoAlgorithm algorithm) =>
(OemCryptoResult result, array<uint8>? decrypted_data);
GenericSign@14(uint32 session, array<uint8> data,
OemCryptoAlgorithm algorithm) =>
(OemCryptoResult result, array<uint8>? signature);
GenericVerify@15(uint32 session, array<uint8> data,
OemCryptoAlgorithm algorithm, array<uint8> signature) =>
(OemCryptoResult result);
CopyBufferV14@16(array<uint8> data, OemCryptoSecureBuffer out_buffer)
=> (OemCryptoResult result);
LoadTestKeyboxV13@17() => (OemCryptoResult result);
IsRootKeyCertificateValid@18() => (OemCryptoResult result);
GetDeviceId@19() => (OemCryptoResult result, array<uint8>? device_id);
GetKeyData@20() => (OemCryptoResult result, array<uint8>? key_data);
GetRandom@21(uint32 length) => (OemCryptoResult result, array<uint8>? data);
GetNumberOfOpenSessions@22() => (OemCryptoResult result, uint32 num);
GetMaxNumberOfSessions@23() => (OemCryptoResult result, uint32 max);
RewrapDeviceRsaKey@24(uint32 session, array<uint8> message,
array<uint8> signature, uint32 nonce_offset,
uint32 enc_rsa_key_offset, uint32 enc_rsa_key_length,
uint32 enc_rsa_key_iv_offset)
=> (OemCryptoResult result, array<uint8>? wrapped_key);
LoadDeviceRsaKey@25(uint32 session, array<uint8> wrapped_rsa_key)
=> (OemCryptoResult result);
GenerateRsaSignature@26(uint32 session, array<uint8> message,
OemCryptoRsaPaddingScheme padding_scheme)
=> (OemCryptoResult result, array<uint8>? signature);
DeriveKeysFromSessionKey@27(uint32 session, array<uint8> enc_session_key,
array<uint8> mac_key_context,
array<uint8> enc_key_context)
=> (OemCryptoResult result);
SecurityPatchLevel@28() => (uint8 security_patch_level);
GetHdcpCapability@29() => (OemCryptoResult result,
OemCryptoHdcpCapability current,
OemCryptoHdcpCapability maximum);
UpdateUsageTable@30() => (OemCryptoResult result);
DeactivateUsageEntryV12@31(array<uint8> pst) => (OemCryptoResult result);
ReportUsage@32(uint32 session, array<uint8> pst)
=> (OemCryptoResult result, OemCryptoPstReport? report);
DeleteUsageEntry@33(uint32 session, uint32 pst_offset, uint32 pst_length,
array<uint8> message, array<uint8> signature) =>
(OemCryptoResult result);
ForceDeleteUsageEntry@34(array<uint8> pst) => (OemCryptoResult result);
DeleteOldUsageTable@35() => (OemCryptoResult result);
[MinVersion=2] GetProvisioningMethod@37()
=> (OemCryptoProvisioningMethod result);
[MinVersion=2] SupportedCertificates@38() => (uint32 result);
[MinVersion=2] IsSrmUpdateSupported@39() => (bool result);
[MinVersion=2] GetCurrentSrmVersion@40()
=> (OemCryptoResult result, uint16 version);
[MinVersion=2] LoadSrm@41(array<uint8> buffer) => (OemCryptoResult result);
[MinVersion=2] RemoveSrm@42() => (OemCryptoResult result);
// |avail_header_length| is the buffer size this was called with from Android.
// We need to specify that so we know if we can complete this call for real or
// instead just need to return the needed buffer size because execution of
// this call has side effects.
[MinVersion=2] CreateUsageTableHeader@43(uint32 avail_header_length)
=> (OemCryptoResult result, array<uint8>? header);
[MinVersion=2] LoadUsageTableHeader@44(array<uint8> buffer)
=> (OemCryptoResult result);
[MinVersion=2] CreateNewUsageEntry@45(uint32 session)
=> (OemCryptoResult result, uint32 usage_entry_number);
[MinVersion=2] LoadUsageEntry@46(uint32 session, uint32 index,
array<uint8> buffer) =>
(OemCryptoResult result);
// |avail_header_length| and |avail_entry_length| are the buffer sizes this
// was called with from Android. We need to specify that so we know if we can
// complete this call for real or instead just need to return the needed
// buffer size because execution of this call has side effects.
[MinVersion=2] UpdateUsageEntry@47(uint32 session, uint32 avail_header_length,
uint32 avail_entry_length)
=> (OemCryptoResult result, array<uint8>? header, array<uint8>? entry);
[MinVersion=2] DeactivateUsageEntry@48(uint32 session, array<uint8> pst)
=> (OemCryptoResult result);
// |avail_header_length| is the buffer size this was called with from Android.
// We need to specify that so we know if we can complete this call for real or
// instead just need to return the needed buffer size because execution of
// this call has side effects.
[MinVersion=2] ShrinkUsageTableHeader@49(uint32 new_entry_count,
uint32 avail_header_length)
=> (OemCryptoResult result, array<uint8>? header);
[MinVersion=2] MoveEntry@50(uint32 session, uint32 new_index)
=> (OemCryptoResult result);
[MinVersion=2] CopyOldUsageEntry@51(uint32 session, array<uint8> pst)
=> (OemCryptoResult result);
[MinVersion=2] CreateOldUsageEntry@52(uint64 time_since_license_received,
uint64 time_since_first_decrypt,
uint64 time_since_last_decrypt,
OemCryptoUsageEntryStatus status,
array<uint8> server_mac_key,
array<uint8> client_mac_key,
array<uint8> pst) =>
(OemCryptoResult result);
[MinVersion=2] GetAnalogOutputFlags@53() => (uint32 result);
[MinVersion=2] LoadTestKeybox@54(array<uint8> buffer) =>
(OemCryptoResult result);
[MinVersion=2]
LoadEntitledContentKeysV14@55(
uint32 session, array<OemCryptoEntitledContentKeyObjectV14> key_array)
=> (OemCryptoResult result);
[MinVersion=2] SelectKey@56(uint32 session, array<uint8> content_key_id,
OemCryptoCipherMode cipher_mode) =>
(OemCryptoResult result);
[MinVersion=2] LoadKeysV14@57(uint32 session, array<uint8> message,
array<uint8> signature, bool has_enc_mac_keys,
uint32 enc_mac_keys_iv_offset,
uint32 enc_mac_keys_offset,
array<OemCryptoKeyObjectV14> key_array,
uint32 pst_offset, uint32 pst_length,
array<uint8> srm_requirement,
OemCryptoLicenseType license_type) =>
(OemCryptoResult result);
[MinVersion=3] LoadKeys@58(uint32 session, array<uint8> message,
array<uint8> signature,
OemCryptoSubstring enc_mac_keys_iv,
OemCryptoSubstring enc_mac_keys,
array<OemCryptoKeyObject> key_array,
OemCryptoSubstring pst,
OemCryptoSubstring srm_restriction_data,
OemCryptoLicenseType license_type) =>
(OemCryptoResult result);
[MinVersion=3] ResourceRatingTier@59() => (uint32 rating_tier);
[MinVersion=3] BuildInformation@60() => (string build_information);
[MinVersion=3] RefreshKeys@61(uint32 session, array<uint8> message,
array<uint8> signature,
array<OemCryptoKeyRefreshObject> key_array)
=> (OemCryptoResult result);
[MinVersion=3] LoadEntitledContentKeys@62(
uint32 session, array<uint8> message,
array<OemCryptoEntitledContentKeyObject> key_array)
=> (OemCryptoResult result);
[MinVersion=4] GetOemPublicCertificate@63()
=> (OemCryptoResult result, array<uint8>? public_cert);
[MinVersion=4] MaximumUsageTableHeaderSize@64() => (uint32 size);
[MinVersion=4] IsAntiRollbackHwPresent@65() => (bool result);
[MinVersion=4] MinorApiVersion@66() => (uint32 version);
[MinVersion=4] PrepAndSignLicenseRequest@67(uint32 session,
array<uint8> message,
uint32 core_message_size,
uint32 avail_signature_size)
=> (OemCryptoResult result, uint32 core_message_size,
array<uint8>? message, array<uint8>? signature);
[MinVersion=4] PrepAndSignRenewalRequest@68(uint32 session,
array<uint8> message,
uint32 core_message_size,
uint32 avail_signature_size)
=> (OemCryptoResult result, uint32 core_message_size,
array<uint8>? message, array<uint8>? signature);
[MinVersion=4] PrepAndSignProvisioningRequest@69(uint32 session,
array<uint8> message,
uint32 core_message_size,
uint32 avail_signature_size)
=> (OemCryptoResult result, uint32 core_message_size,
array<uint8>? message, array<uint8>? signature);
[MinVersion=4] LoadLicense@70(uint32 session, array<uint8> message,
uint32 core_message_length,
array<uint8> signature)
=> (OemCryptoResult result);
[MinVersion=4] LoadRenewal@71(uint32 session, array<uint8> message,
uint32 core_message_length,
array<uint8> signature)
=> (OemCryptoResult result);
[MinVersion=4] LoadProvisioning@72(uint32 session, array<uint8> message,
uint32 core_message_length,
array<uint8> signature,
uint32 avail_wrapped_private_key_size)
=> (OemCryptoResult result, array<uint8>? wrapped_private_key);
[MinVersion=4] LoadOemPrivateKey@73(uint32 session)
=> (OemCryptoResult result);
[MinVersion=4] LoadDrmPrivateKey@74(uint32 session,
OemCryptoPrivateKey key_type,
array<uint8> wrapped_private_key)
=> (OemCryptoResult result);
// For decrypting to a secure buffer, pass in the secure_buffer parameter,
// otherwise it will return the contents decrypted into a clear buffer in the
// returned array. It will only do that if the drm policy allows it.
[MinVersion=4] DecryptCenc@75(uint32 session, array<uint8> data,
array<uint8, 16> iv,
array<SubSampleDescription> sub_samples,
OemCryptoCencEncryptPatternDesc pattern,
OemCryptoSecureBuffer? secure_buffer)
=> (OemCryptoResult result, array<uint8>? decrypted_data);
[MinVersion=5] CopyBuffer@76(uint32 session, array<uint8> data,
OemCryptoSecureBuffer out_buffer,
uint8 subsample_flags)
=> (OemCryptoResult result);
};
// OemCryptoService is implemented as another service outside of the Browser
// process, so we need to proxy a connection to it through ArcBridge initially.
// This interface is implemented in the Browser process and also in the daemon
// that runs in Chrome OS.
// Next Method ID: 1
interface OemCryptoHost {
Connect@0(pending_receiver<OemCryptoService> oemcryptor);
};
// OemCryptoInstance is implemented in the liboemcrypto.so library that runs in
// Android and handles the Android side of the ArcBridge connection.
// Deprecated method IDs: 0
// Next Method ID: 2
interface OemCryptoInstance {
// Establishes full-duplex communication with the host.
[MinVersion=1] Init@1(pending_remote<OemCryptoHost> host_remote) => ();
};