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 36 extern "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 *  87 * and HWDRM pipeline view is following - 88 *  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 */ 402 typedef VAGenericID VAProtectedSessionID; 403 404 /** \brief TEE Execucte Function ID. */ 405 typedef 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 */ 412 typedef 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() */ 433 typedef 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 /** \brief - vtag represents TEE sandbox identification for multiple playback scenario 445 * 446 * If TEE interface is created using VAEntrypointProtectedTEEComm then 447 * vtag is non-zero for multiple playback and vtag is zero for single playback 448 * 449 * If TEE interface is not created using VAEntrypointProtectedTEEComm then 450 * vtag - reserved 451 */ 452 uint64_t vtag; 453 /** \brief reserved bytes for future use, must be zero */ 454 uint32_t va_reserved[VA_PADDING_LOW - 2]; 455 } VAProtectedSessionExecuteBuffer; 456 457 /** 458 * \brief Create a protected session 459 * 460 * Create a protected session 461 * 462 * @param[in] dpy the VA display 463 * @param[in] config_id configuration for the protected session 464 * @param[out] protected_session created protected session id upon return 465 */ 466 VAStatus vaCreateProtectedSession(VADisplay dpy, VAConfigID config_id, 467 VAProtectedSessionID *protected_session); 468 469 /** 470 * \brief Destroy a protected session 471 * 472 * Destroy a protected session 473 * 474 * @param[in] dpy the VA display 475 * @param[in] protected_session protected session to be destroyed 476 */ 477 VAStatus vaDestroyProtectedSession(VADisplay dpy, 478 VAProtectedSessionID protected_session); 479 480 /** 481 * \brief Attach a protected content session to VA context 482 * 483 * Attach a protected content session to the context to enable 484 * decryption/protection 485 * 486 * @param[in] dpy the VA display 487 * @param[in] id the VA decode/encode/vp context 488 * @param[in] protected_session the protected session to attach 489 */ 490 VAStatus vaAttachProtectedSession(VADisplay dpy, VAGenericID id, 491 VAProtectedSessionID protected_session); 492 493 /** 494 * \brief Detach the protected content session from the VA context 495 * 496 * Detach protected content session of the context to disable 497 * decryption/protection 498 * 499 * @param[in] dpy the VA display 500 * @param[in] id TEE client id to be detached 501 */ 502 VAStatus vaDetachProtectedSession(VADisplay dpy, VAGenericID id); 503 504 /** 505 * \brief Execute provides a general mechanism for TEE client tasks execution. 506 * 507 * vaProtectedSessionExecute provides a mechanism for TEE clients to execute 508 * specific tasks. The implementation may differ between IHVs. 509 * This is a synchronous API. 510 * 511 * @param[in] dpy the VA display 512 * @param[in] protected_session the protected session 513 * @param[in,out] buf_id the VA buffer 514 */ 515 VAStatus vaProtectedSessionExecute(VADisplay dpy, 516 VAProtectedSessionID protected_session, 517 VABufferID buf_id); 518 519 /**@}*/ 520 521 #ifdef __cplusplus 522 } 523 #endif 524 525 #endif /* VA_PROT_H */ 526