1/*
2 * Copyright (c) 2020 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL INTEL AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file va_prot.h
27 * \brief Protected content API.
28 *
29 * This file contains the \ref api_prot "Protected content API".
30 */
31
32#ifndef VA_PROT_H
33#define VA_PROT_H
34
35#ifdef __cplusplus
36extern "C" {
37#endif
38
39/**
40 * \defgroup api_prot Protected content API
41 *
42 * @{
43 * \section prolouge Prolouge
44 * Video streaming is ubiquitous and the support for video streaming is widely
45 * available across client open systems such as PCs, MACs, Chromebooks etc. and
46 * closed systems such as settop box, smart TVs, DVDs etc. By default,
47 * video streaming is not considered premium due to various constraints such as
48 * resolution, quality, production cost etc. but recently streaming of premium
49 * video(1080p+) has become norm. The streaming of premium video in open systems
50 * such as PCs, MACs, Chromebooks etc. makes video particularly susceptible to
51 * piracy (due to non-video playback usages of such systems) resulting in
52 * millions of dollars of loss to content creators.
53 *
54 * Digital Rights Management(DRM) has been proposed to stop piracy of premium
55 * video streams across a wide spectrum. There are some known open/closed DRM
56 * standards such as [Widevine by Google](https://www.widevine.com/),
57 * [PlayReady by Microsoft](https://www.microsoft.com/playready/),
58 * [FairPlay by Apple](https://developer.apple.com/streaming/fps/),
59 * [Merlin by Sony](https://www.marlin-community.com/), etc... Each DRM
60 * standard has its properties but all DRM standards support a common
61 * mechanism. This common mechanism involves cryptographical method for
62 * authenticating the client system, delivering bitstream and required
63 * cryptographic assets to client system and then cryptographically processing
64 * bitstream in client system. The cryptographic methods used in these steps
65 * are asymmetric such as RSA, DH etc. and symmetric such as AES CTR, CBC etc.
66 * encryption mechanisms. The authentication of client system, delivery of
67 * bitstream and cryptographic assets to client system is performed using
68 * asymmetric cryptographic mechanism while bitstream is encrypted and processed
69 * using symmetric cryptographic. In DRM world, authentication of client system,
70 * delivery of bitstream and required cryptographic assets to client system is
71 * loosely called provisioning and license acquisition while the processing of
72 * cryptographically secure bitstream is divided as video decryption/decoding,
73 * audio decryption/playback, video display. Besides DRM standards, Video/Audio
74 * bitstream encryption standard such as
75 * [Common Encryption Standard(CENC)](https://www.iso.org/standard/76597.html)
76 * provides a mechanism to normalize bitstream encryption methods across vendors
77 * while providing flexibility.
78 *
79 * \section DRM Pipeline
80 * Most DRM standards execute the following deep pipeline to playback
81 * contents on client systems from streaming servers - provisioning uses
82 * provisioning servers, licence aquisition uses license servers, video
83 * bitstream delivery uses content servers and decryption/decoding, audio
84 * bitstream delivery uses content servers and decyption/playback,
85 * display/playback. The system level HWDRM sequence diagram is following -
86 * ![HWDRM sequence diagram](https://user-images.githubusercontent.com/75039699/102427278-df284e80-3fc5-11eb-9a3e-129b5f6b567a.png)
87 * and HWDRM pipeline view is following -
88 * ![HWDRM pipeline view](https://user-images.githubusercontent.com/75039699/102427357-04b55800-3fc6-11eb-8b8c-f34fc44ec061.png)
89 *
90 * \section LibVA Protected Content APIs
91 * The LibVA Protected APIs are designed to enable DRM capabilities or
92 * facilitate isolated communicaiton with TEE.
93 * The VAEntrypointProtectedTEEComm is to define interfaces for Application
94 * to TEE direct communication to perform various TEE centric operations
95 * such as standalone provisioning of platform at factory or provisioning
96 * TEE for other usages, providing TEE capabilities etc.
97 * The VAEntrypointProtectedContent is to define interfaces for protected
98 * video playback using HWDRM. This entry point co-ordinates assets across
99 * TEE/GPU/Display for HWDRM playback.
100 *
101 * The difference between Protected Content and Protected TEE Communication
102 * is that Protected Content Entrypoint does not provide isolated entry
103 * point for TEE and invokes TEE only from HWDRM perspective.
104 *
105 * Protected Content Entrypoint
106 * The most of DRM standards execute following deep pipeline to playback
107 * contents on client systems from streaming servers - provisioning uses
108 * provisioning servers, licence aquisition uses license servers, video
109 * bitstream delivery uses content servers and decryption/decoding, audio
110 * bitstream delivery uses content servers and decyption/playback,
111 * display/playback.
112 *
113 * The Provisioning and License aquisition implementations are Independent
114 * Hardware Vendor (IHV) specific but most IHVs use some form of Trusted
115 * Execution Environment (TEE) to prepare client platform or system for DRM
116 * content playback. The provisioning operations use provisioning servers (as
117 * instructed in DRM standard) and client system TEE. The communication between
118 * provisioning servers and client system TEE uses asymmetic cryptographic
119 * mechanism. This step provides a way to establish root-of-trust between
120 * client system and streaming servers. Once root-of-trust is established then
121 * client system requests for license aquisition for a particular streaming
122 * title. The license aquisition involves communication between licensing
123 * servers and TEE using asymmetic cryptographic mechanism. At end of this step,
124 * client system TEE has required assets to decrypt/decode. Although these
125 * communication does not direcly involve video aspect of GPU but **facilitate
126 * GPU required assets to playback premium contents**.
127 *
128 * To support DRM standard requirements in playback pipeline, OSes and HWs
129 * incorporate various methods to protect full playback pipeline. These
130 * methods of protection could be SW based or HW based. The SW based protection
131 * mechanism of DRMs is called SWDRM while HW based protection mechanism is
132 * called HWDRM. There is no previous support in LibVA to support either DRM
133 * mechanism.
134 *
135 * For DRM capabilities, APIs inolve creation of protected session to
136 * communicate with TEE and then using these protected sessions to process
137 * video/audio data. The philophashy behind these API is to leverage existing
138 * LibVA infrastructure as much as possible.
139 *
140 * Note: TEE could be any secure HW device such as ME-FW or FPGA Secure
141 * Enclave or NPU Secure Enclave. There are 2 concepts here – TEE Type such
142 * as ME-FW or FPGA or NPU; TEE Type Client such as for AMT or HDCP or
143 * something else etc.
144 *
145 * \section description Detailed Description
146 * The Protected content API provides a general mechanism for opening
147 * protected session with TEE and if required then \ref priming GPU/Display.
148 * The behavior of protected session API depends on parameterization/
149 * configuration of protected session. Just for TEE tasks, protected
150 * session is parameterized/configured as TEE Communication while for
151 * HWDRM, protected session is parameterized/confgured as Protected
152 * Content.
153 *
154 * TEE Communication Entrypoint
155 * With TEE Communication parameterization/configuration, client
156 * executes TEE workloads in TEE with TEE Communication protected
157 * session.
158 *
159 * Protected Content Entrypoint
160 * With Protected Content parameterization/configuration, client
161 * executes HWDRM playback workloads HW accelerating protected video
162 * content decryption/decoding with protected content session.
163 *
164 * Before calling vaCreateProtectedSession, VAConfigID is obtained using
165 * existing libva mechanism to determine configuration parameters of
166 * protected session. The VAConfigID is determined in this way so that
167 * Protected Session implementation aligns with existing libva implementation.
168 * After obtaining VAConfigID, Protected Session needs to be created but
169 * note this is a session and not a context. Refer VAProtectedSessionID
170 * for more details.
171 *
172 * Note:- Protected session represents session object that has all security
173 * information needed for Secure Enclave to operate certain operations.
174 *
175 * \subsection priming Priming
176 * Priming is used to refer various types of initializations. For example,
177 * if license acquisition is being performed then priming means that TEE is
178 * already provisioned aka TEE has some sort of "cryptographic" whitelist of
179 * servers that TEE will use to do license acquisition for video playback. If
180 * HWDRM video playback is being performed then priming means that HWDRM
181 * eco-system TEE/GPU/Display has proper keys to do proper video playback etc.
182 *
183 * Protected content API uses the following paradigm for protected content
184 * session:
185 * - \ref api_pc_caps
186 * - \ref api_pc_setup
187 * - \ref api_pc_exec
188 * - \ref api_pc_attach
189 *
190 * \subsection api_pc_caps Query for supported cipher mode, block size, mode
191 *
192 * Checking whether protected content is supported can be performed with
193 * vaQueryConfigEntrypoints() and the profile argument set to
194 * #VAProfileProtected. If protected content is supported, then the list of
195 * returned entry-points will include #VAEntrypointProtectedContent
196 *
197 * \code
198 * VAEntrypoint *entrypoints;
199 * int i, num_entrypoints, supportsProtectedContent = 0;
200 *
201 * num_entrypoints = vaMaxNumEntrypoints();
202 * entrypoints = malloc(num_entrypoints * sizeof(entrypoints[0]);
203 * vaQueryConfigEntrypoints(va_dpy, VAProfileProtected, entrypoints,
204 * &num_entrypoints);
205 *
206 * for (i = 0; !supportsProtectedContent && i < num_entrypoints; i++) {
207 * if (entrypoints[i] == VAEntrypointProtectedContent)
208 * supportsProtectedContent = 1;
209 * }
210 * \endcode
211 *
212 * Then, the vaGetConfigAttributes() function is used to query the protected
213 * session capabilities.
214 *
215 * \code
216 * VAConfigAttrib attribs;
217 * attribs[0].type = VAConfigAttribProtectedContentCipherAlgorithm;
218 * attribs[1].type = VAConfigAttribProtectedContentCipherBlockSize;
219 * attribs[2].type = VAConfigAttribProtectedContentCipherMode;
220 * attribs[3].type = VAConfigAttribProtectedContentCipherSampleType;
221 * attribs[4].type = VAConfigAttribProtectedContentUsage;
222 * vaGetConfigAttributes(va_dpy, VAProfileProtected,
223 * VAEntrypointProtectedContent, attribs, 5);
224 * if ((attribs[1].value & VA_PC_CIPHER_AES) == 0) {
225 * // not find desired cipher algorithm
226 * assert(0);
227 * }
228 * if ((attribs[2].value & VA_PC_BLOCK_SIZE_128) == 0) {
229 * // not find desired block size
230 * assert(0);
231 * }
232 * if ((attribs[3].value & VA_PC_CIPHER_MODE_CBC) == 0) {
233 * // not find desired counter mode
234 * assert(0);
235 * }
236 * if ((attribs[4].value & VA_PC_SAMPLE_TYPE_SUBSAMPLE) == 0) {
237 * // not find desired sample type
238 * assert(0);
239 * }
240 * if ((attribs[5].value & VA_PC_USAGE_WIDEVINE) == 0) {
241 * // not find desired usage
242 * assert(0);
243 * }
244 * \endcode
245 *
246 * \subsection api_pc_setup Set up a protected content session
247 *
248 * TEE Communication Entrypoint
249 * The protected content session provides a TEE session that is used to extract
250 * TEE information. This information could be used to peform TEE operations.
251 *
252 * Protected Content Entrypoint
253 * The protected content session can be attached to VA decode/encode/vp context
254 * to do decryption/protection in the pipeline.
255 * Before creating a protected content session, it needs to create a config
256 * first via vaCreateConfig(). Then using this config id to create a protected
257 * content session via vaCreateProtectedSession().
258 *
259 * The general control flow is demonstrated by the following pseudo-code:
260 * \code
261 * // Create config
262 * VAConfigID config_id;
263 *
264 * attribs[0].value = VA_PC_CIPHER_AES;
265 * attribs[1].value = VA_PC_BLOCK_SIZE_128;
266 * attribs[2].value = VA_PC_CIPHER_MODE_CBC;
267 * attribs[3].value = VA_PC_SAMPLE_TYPE_SUBSAMPLE;
268 * attribs[4].value = VA_PC_USAGE_WIDEVINE;
269 * va_status = vaCreateConfig(va_dpy, VAProfileProtected,
270 * VAEntrypointProtectedContent, attribs, 5, &config_id);
271 * CHECK_VASTATUS(va_status, "vaCreateConfig");
272 * \endcode
273 *
274 * Once the config is set up, we can create protected content session via
275 vaCreateProtectedSession().
276 * \code
277 * // Create a protected session
278 * VAProtectedSessionID crypto_session;
279 *
280 * va_status = vaCreateProtectedSession(va_dpy, config_id, &crypto_session);
281 * CHECK_VASTATUS(va_status, "vaCreateProtectedSession");
282 * \endcode
283 *
284 * \subsection api_pc_exec TEE communication via vaProtectedSessionExecute()
285 *
286 * TEE Communication Entrypoint
287 * App needs to communicate with TEE to get TEE information or \ref priming
288 * "prime" TEE with information that will be utilized for future TEE
289 * operations/tasks.
290 *
291 * Protected Content Entrypoint
292 * Before starting decryption/encryption operation in GPU, app may need to
293 * communicate with TEE to get encrypted assets for \ref priming HWDRM pipeline
294 * for decryption. App need to call vaProtectedSessionExecute() to get this
295 * asset. The following pseudo-code demonstrates getting session assets via
296 * vaProtectedSessionExecute() as an example.
297 *
298 * In this example, the vaCreateBuffer is called with exec_buffer mainly becasue TEE
299 * Communication Entrypoint buffers are CPU bound and buffer size is small enough to
300 * have extra copy operation without impacting performance.
301 *
302 * \code
303 * uint32_t app_id = 0xFF;
304 * VABufferID buffer;
305 * VAProtectedSessionExecuteBuffer exec_buff = {0};
306 *
307 * exec_buff.function_id = GET_SESSION_ID;
308 * exec_buff.input.data = nullptr;
309 * exec_buff.input.data_size = 0;
310 * exec_buff.output.data = &app_id;
311 * exec_buff.output.max_data_size = sizeof(app_id);
312 * va_status = vaCreateBuffer(
313 * va_dpy,
314 * crypto_session,
315 * (VABufferType) VAProtectedSessionExecuteBufferType,
316 * sizeof(exec_buff),
317 * 1,
318 * &exec_buff,
319 * &buffer);
320 *
321 * va_status = vaProtectedSessionExecute(va_dpy, crypto_session, buffer);
322 *
323 * vaDestroyBuffer(va_dpy, buffer);
324 * \endcode
325 *
326 * \subsection api_pc_attach Attach/Detach protected content session to the VA
327 * context which want to enable/disable decryption/protection
328 *
329 * Protected content session is attached to VA decode/encode/vp context to
330 * enable protected decoding/encoding/video processing per frame or entire
331 * stream. If protected session attached per frame then application has 2
332 * options for decoding/encoding skip processing i.e. accomodating clear
333 * frames - 1. Application could do detach after each frame is processed
334 * to process clear frame 2. Application could remains attached to decode/
335 * encode session but specify enryption byte length to 0.
336 * The video processing does not has option #2 mainly because API does
337 * not provide skip processing.
338 *
339 * \code
340 * vaAttachProtectedSession(va_dpy, decode_ctx, crypto_session);
341 * foreach (iteration) {
342 * vaBeginPicture(va_dpy, decode_ctx, surface);
343 * ...
344 * vaRenderPicture(va_dpy, decode_ctx, &buf_id1, 1);
345 * vaRenderPicture(va_dpy, decode_ctx, &buf_id2, 1);
346 * // Buffer holding encryption parameters, i.e. VAEncryptionParameterBufferType buffer
347 * vaRenderPicture(va_dpy, decode_ctx, &buf_id_enc_param, 1);
348 * ...
349 * vaEndPicture(va_dpy, decode_ctx);
350 * }
351 * vaDetachProtectedSession(va_dpy, decode_ctx);
352 * \endcode
353 *
354 * or it could be frame-by-frame attaching/detaching as following:
355 *
356 * \code
357 * foreach (iteration) {
358 * if (encrypted)
359 * vaAttachProtectedSession(va_dpy, decode_ctx, crypto_session);
360
361 * vaBeginPicture(va_dpy, decode_ctx, surface);
362 * ...
363 * vaRenderPicture(va_dpy, decode_ctx, &buf_id1, 1);
364 * vaRenderPicture(va_dpy, decode_ctx, &buf_id2, 1);
365 * // Buffer holding encryption parameters, i.e. VAEncryptionParameterBufferType buffer
366 * vaRenderPicture(va_dpy, decode_ctx, &buf_id_enc_param, 1);
367 * ...
368 * vaEndPicture(va_dpy, decode_ctx);
369 *
370 * if (encrypted)
371 * vaDetachProtectedSession(va_dpy, decode_ctx);
372
373 * // check encrypted variable for next frame
374 * }
375 * \endcode
376 */
377
378/**
379 * ProtectedSessions and Contexts
380 *
381 * According to #VAContextID, Context represents a "virtual" video decode,
382 * encode or video processing pipeline. Surfaces are render targets for a given
383 * context. The data in the surfaces are not accessible to the client except if
384 * derived image is supported and the internal data format of the surface is
385 * implementation specific. Application can create a video decode, encode or
386 * processing context which represents a "virtualized" hardware device.
387 *
388 * Since Protected Session does not virtualize any HW device or build any
389 * pipeline but rather accessorize existing virtualized HW device or pipeline
390 * to operate in protected mode so we decided to create separate function.
391 * Beside this, a virtualized HW device or pipeline could own several protected
392 * sessions and operate in those protected modes without ever re-creating
393 * virtualization of HW device or re-building HW pipeline (an unique protected
394 * environment multiplexing capability in Intel HW).
395 *
396 * The returned protected_session represents a notion of Host and TEE clients
397 * while representing protection status in GPU and Display.
398 *
399 * Both contexts and protected sessions are identified by unique IDs and its
400 * implementation specific internals are kept opaque to the clients
401 */
402typedef VAGenericID VAProtectedSessionID;
403
404/** \brief TEE Execucte Function ID. */
405typedef enum _VA_TEE_EXEC_FUNCTION_ID {
406 VA_TEE_EXECUTE_FUNCTION_ID_PASS_THROUGH = 0x00000001,
407 VA_TEE_EXECUTE_FUNCTION_ID_GET_FIRMWARE_VERSION = 0x00000002,
408
409} VA_TEE_EXECUTE_FUNCTION_ID;
410
411/** \brief Input/Output buffer of VAProtectedSessionExecuteBuffer */
412typedef struct _VAProtectedSessionBuffer {
413 /*
414 * This is used when this buffer refer to output buffer. The maximum size of
415 * data that the driver can return in the output buffer. It is not used for
416 * input buffer.
417 */
418 uint32_t max_data_size;
419 /*
420 * If it is used for input buffer, it is the size of the input data. If it is
421 * used for output buffer, it is the returns size of the output data written
422 * by the driver.
423 */
424 uint32_t data_size;
425 /*
426 * data pointer of this buffer
427 */
428 void *data;
429 uint32_t va_reserved[VA_PADDING_LOW];
430} VAProtectedSessionBuffer;
431
432/** \brief Buffer for vaProtectedSessionExecute() */
433typedef struct _VAProtectedSessionExecuteBuffer {
434 /** \brief Specify the function to execute. It is IHV's implementation
435 * specific */
436 uint32_t function_id;
437 /** \brief Input buffer */
438 VAProtectedSessionBuffer input;
439 /** \brief Output buffer */
440 VAProtectedSessionBuffer output;
441 /** \brief Return the result of this function. The status result is IHV's
442 * implementation specific */
443 uint32_t status;
444 uint32_t va_reserved[VA_PADDING_LOW];
445} VAProtectedSessionExecuteBuffer;
446
447/**
448 * \brief Create a protected session
449 *
450 * Create a protected session
451 *
452 * @param[in] dpy the VA display
453 * @param[in] config_id configuration for the protected session
454 * @param[out] protected_session created protected session id upon return
455 */
456VAStatus vaCreateProtectedSession(VADisplay dpy, VAConfigID config_id,
457 VAProtectedSessionID *protected_session);
458
459/**
460 * \brief Destroy a protected session
461 *
462 * Destroy a protected session
463 *
464 * @param[in] dpy the VA display
465 * @param[in] protected_session protected session to be destroyed
466 */
467VAStatus vaDestroyProtectedSession(VADisplay dpy,
468 VAProtectedSessionID protected_session);
469
470/**
471 * \brief Attach a protected content session to VA context
472 *
473 * Attach a protected content session to the context to enable
474 * decryption/protection
475 *
476 * @param[in] dpy the VA display
477 * @param[in] id the VA decode/encode/vp context
478 * @param[in] protected_session the protected session to attach
479 */
480VAStatus vaAttachProtectedSession(VADisplay dpy, VAGenericID id,
481 VAProtectedSessionID protected_session);
482
483/**
484 * \brief Detach the protected content session from the VA context
485 *
486 * Detach protected content session of the context to disable
487 * decryption/protection
488 *
489 * @param[in] dpy the VA display
490 * @param[in] id TEE client id to be detached
491 */
492VAStatus vaDetachProtectedSession(VADisplay dpy, VAGenericID id);
493
494/**
495 * \brief Execute provides a general mechanism for TEE client tasks execution.
496 *
497 * vaProtectedSessionExecute provides a mechanism for TEE clients to execute
498 * specific tasks. The implementation may differ between IHVs.
499 * This is a synchronous API.
500 *
501 * @param[in] dpy the VA display
502 * @param[in] protected_session the protected session
503 * @param[in,out] buf_id the VA buffer
504 */
505VAStatus vaProtectedSessionExecute(VADisplay dpy,
506 VAProtectedSessionID protected_session,
507 VABufferID buf_id);
508
509/**@}*/
510
511#ifdef __cplusplus
512}
513#endif
514
515#endif /* VA_PROT_H */
516

source code of include/va/va_prot.h