hdcp1_execution.c (15941B)
1/* 2 * Copyright 2019 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 * 24 */ 25 26#include "hdcp.h" 27 28static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp) 29{ 30 uint64_t n = 0; 31 uint8_t count = 0; 32 u8 bksv[sizeof(n)] = { }; 33 34 memcpy(bksv, hdcp->auth.msg.hdcp1.bksv, sizeof(hdcp->auth.msg.hdcp1.bksv)); 35 n = *(uint64_t *)bksv; 36 37 while (n) { 38 count++; 39 n &= (n - 1); 40 } 41 return (count == 20) ? MOD_HDCP_STATUS_SUCCESS : 42 MOD_HDCP_STATUS_HDCP1_INVALID_BKSV; 43} 44 45static inline enum mod_hdcp_status check_ksv_ready(struct mod_hdcp *hdcp) 46{ 47 if (is_dp_hdcp(hdcp)) 48 return (hdcp->auth.msg.hdcp1.bstatus & DP_BSTATUS_READY) ? 49 MOD_HDCP_STATUS_SUCCESS : 50 MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY; 51 return (hdcp->auth.msg.hdcp1.bcaps & DRM_HDCP_DDC_BCAPS_KSV_FIFO_READY) ? 52 MOD_HDCP_STATUS_SUCCESS : 53 MOD_HDCP_STATUS_HDCP1_KSV_LIST_NOT_READY; 54} 55 56static inline enum mod_hdcp_status check_hdcp_capable_dp(struct mod_hdcp *hdcp) 57{ 58 return (hdcp->auth.msg.hdcp1.bcaps & DP_BCAPS_HDCP_CAPABLE) ? 59 MOD_HDCP_STATUS_SUCCESS : 60 MOD_HDCP_STATUS_HDCP1_NOT_CAPABLE; 61} 62 63static inline enum mod_hdcp_status check_r0p_available_dp(struct mod_hdcp *hdcp) 64{ 65 enum mod_hdcp_status status; 66 if (is_dp_hdcp(hdcp)) { 67 status = (hdcp->auth.msg.hdcp1.bstatus & 68 DP_BSTATUS_R0_PRIME_READY) ? 69 MOD_HDCP_STATUS_SUCCESS : 70 MOD_HDCP_STATUS_HDCP1_R0_PRIME_PENDING; 71 } else { 72 status = MOD_HDCP_STATUS_INVALID_OPERATION; 73 } 74 return status; 75} 76 77static inline enum mod_hdcp_status check_link_integrity_dp( 78 struct mod_hdcp *hdcp) 79{ 80 return (hdcp->auth.msg.hdcp1.bstatus & 81 DP_BSTATUS_LINK_FAILURE) ? 82 MOD_HDCP_STATUS_HDCP1_LINK_INTEGRITY_FAILURE : 83 MOD_HDCP_STATUS_SUCCESS; 84} 85 86static inline enum mod_hdcp_status check_no_reauthentication_request_dp( 87 struct mod_hdcp *hdcp) 88{ 89 return (hdcp->auth.msg.hdcp1.bstatus & DP_BSTATUS_REAUTH_REQ) ? 90 MOD_HDCP_STATUS_HDCP1_REAUTH_REQUEST_ISSUED : 91 MOD_HDCP_STATUS_SUCCESS; 92} 93 94static inline enum mod_hdcp_status check_no_max_cascade(struct mod_hdcp *hdcp) 95{ 96 enum mod_hdcp_status status; 97 98 if (is_dp_hdcp(hdcp)) 99 status = DRM_HDCP_MAX_CASCADE_EXCEEDED(hdcp->auth.msg.hdcp1.binfo_dp >> 8) 100 ? MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE 101 : MOD_HDCP_STATUS_SUCCESS; 102 else 103 status = DRM_HDCP_MAX_CASCADE_EXCEEDED(hdcp->auth.msg.hdcp1.bstatus >> 8) 104 ? MOD_HDCP_STATUS_HDCP1_MAX_CASCADE_EXCEEDED_FAILURE 105 : MOD_HDCP_STATUS_SUCCESS; 106 return status; 107} 108 109static inline enum mod_hdcp_status check_no_max_devs(struct mod_hdcp *hdcp) 110{ 111 enum mod_hdcp_status status; 112 113 if (is_dp_hdcp(hdcp)) 114 status = DRM_HDCP_MAX_DEVICE_EXCEEDED(hdcp->auth.msg.hdcp1.binfo_dp) ? 115 MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE : 116 MOD_HDCP_STATUS_SUCCESS; 117 else 118 status = DRM_HDCP_MAX_DEVICE_EXCEEDED(hdcp->auth.msg.hdcp1.bstatus) ? 119 MOD_HDCP_STATUS_HDCP1_MAX_DEVS_EXCEEDED_FAILURE : 120 MOD_HDCP_STATUS_SUCCESS; 121 return status; 122} 123 124static inline uint8_t get_device_count(struct mod_hdcp *hdcp) 125{ 126 return is_dp_hdcp(hdcp) ? 127 DRM_HDCP_NUM_DOWNSTREAM(hdcp->auth.msg.hdcp1.binfo_dp) : 128 DRM_HDCP_NUM_DOWNSTREAM(hdcp->auth.msg.hdcp1.bstatus); 129} 130 131static inline enum mod_hdcp_status check_device_count(struct mod_hdcp *hdcp) 132{ 133 /* Avoid device count == 0 to do authentication */ 134 if (0 == get_device_count(hdcp)) { 135 return MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE; 136 } 137 138 /* Some MST display may choose to report the internal panel as an HDCP RX. 139 * To update this condition with 1(because the immediate repeater's internal 140 * panel is possibly not included in DEVICE_COUNT) + get_device_count(hdcp). 141 * Device count must be greater than or equal to tracked hdcp displays. 142 */ 143 return ((1 + get_device_count(hdcp)) < get_active_display_count(hdcp)) ? 144 MOD_HDCP_STATUS_HDCP1_DEVICE_COUNT_MISMATCH_FAILURE : 145 MOD_HDCP_STATUS_SUCCESS; 146} 147 148static enum mod_hdcp_status wait_for_active_rx(struct mod_hdcp *hdcp, 149 struct mod_hdcp_event_context *event_ctx, 150 struct mod_hdcp_transition_input_hdcp1 *input) 151{ 152 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 153 154 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 155 event_ctx->unexpected_event = 1; 156 goto out; 157 } 158 159 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv, 160 &input->bksv_read, &status, 161 hdcp, "bksv_read")) 162 goto out; 163 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 164 &input->bcaps_read, &status, 165 hdcp, "bcaps_read")) 166 goto out; 167out: 168 return status; 169} 170 171static enum mod_hdcp_status exchange_ksvs(struct mod_hdcp *hdcp, 172 struct mod_hdcp_event_context *event_ctx, 173 struct mod_hdcp_transition_input_hdcp1 *input) 174{ 175 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 176 177 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 178 event_ctx->unexpected_event = 1; 179 goto out; 180 } 181 182 if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_create_session, 183 &input->create_session, &status, 184 hdcp, "create_session")) 185 goto out; 186 if (!mod_hdcp_execute_and_set(mod_hdcp_write_an, 187 &input->an_write, &status, 188 hdcp, "an_write")) 189 goto out; 190 if (!mod_hdcp_execute_and_set(mod_hdcp_write_aksv, 191 &input->aksv_write, &status, 192 hdcp, "aksv_write")) 193 goto out; 194 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bksv, 195 &input->bksv_read, &status, 196 hdcp, "bksv_read")) 197 goto out; 198 if (!mod_hdcp_execute_and_set(validate_bksv, 199 &input->bksv_validation, &status, 200 hdcp, "bksv_validation")) 201 goto out; 202 if (hdcp->auth.msg.hdcp1.ainfo) { 203 if (!mod_hdcp_execute_and_set(mod_hdcp_write_ainfo, 204 &input->ainfo_write, &status, 205 hdcp, "ainfo_write")) 206 goto out; 207 } 208out: 209 return status; 210} 211 212static enum mod_hdcp_status computations_validate_rx_test_for_repeater( 213 struct mod_hdcp *hdcp, 214 struct mod_hdcp_event_context *event_ctx, 215 struct mod_hdcp_transition_input_hdcp1 *input) 216{ 217 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 218 219 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 220 event_ctx->unexpected_event = 1; 221 goto out; 222 } 223 224 if (!mod_hdcp_execute_and_set(mod_hdcp_read_r0p, 225 &input->r0p_read, &status, 226 hdcp, "r0p_read")) 227 goto out; 228 if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_rx, 229 &input->rx_validation, &status, 230 hdcp, "rx_validation")) 231 goto out; 232 if (hdcp->connection.is_repeater) { 233 if (!hdcp->connection.link.adjust.hdcp1.postpone_encryption) 234 if (!mod_hdcp_execute_and_set( 235 mod_hdcp_hdcp1_enable_encryption, 236 &input->encryption, &status, 237 hdcp, "encryption")) 238 goto out; 239 } else { 240 if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption, 241 &input->encryption, &status, 242 hdcp, "encryption")) 243 goto out; 244 if (is_dp_mst_hdcp(hdcp)) 245 if (!mod_hdcp_execute_and_set( 246 mod_hdcp_hdcp1_enable_dp_stream_encryption, 247 &input->stream_encryption_dp, &status, 248 hdcp, "stream_encryption_dp")) 249 goto out; 250 } 251out: 252 return status; 253} 254 255static enum mod_hdcp_status authenticated(struct mod_hdcp *hdcp, 256 struct mod_hdcp_event_context *event_ctx, 257 struct mod_hdcp_transition_input_hdcp1 *input) 258{ 259 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 260 261 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 262 event_ctx->unexpected_event = 1; 263 goto out; 264 } 265 266 mod_hdcp_execute_and_set(mod_hdcp_hdcp1_link_maintenance, 267 &input->link_maintenance, &status, 268 hdcp, "link_maintenance"); 269out: 270 return status; 271} 272 273static enum mod_hdcp_status wait_for_ready(struct mod_hdcp *hdcp, 274 struct mod_hdcp_event_context *event_ctx, 275 struct mod_hdcp_transition_input_hdcp1 *input) 276{ 277 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 278 279 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK && 280 event_ctx->event != MOD_HDCP_EVENT_CPIRQ && 281 event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 282 event_ctx->unexpected_event = 1; 283 goto out; 284 } 285 286 if (is_dp_hdcp(hdcp)) { 287 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 288 &input->bstatus_read, &status, 289 hdcp, "bstatus_read")) 290 goto out; 291 if (!mod_hdcp_execute_and_set(check_link_integrity_dp, 292 &input->link_integrity_check, &status, 293 hdcp, "link_integrity_check")) 294 goto out; 295 if (!mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, 296 &input->reauth_request_check, &status, 297 hdcp, "reauth_request_check")) 298 goto out; 299 } else { 300 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 301 &input->bcaps_read, &status, 302 hdcp, "bcaps_read")) 303 goto out; 304 } 305 if (!mod_hdcp_execute_and_set(check_ksv_ready, 306 &input->ready_check, &status, 307 hdcp, "ready_check")) 308 goto out; 309out: 310 return status; 311} 312 313static enum mod_hdcp_status read_ksv_list(struct mod_hdcp *hdcp, 314 struct mod_hdcp_event_context *event_ctx, 315 struct mod_hdcp_transition_input_hdcp1 *input) 316{ 317 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 318 uint8_t device_count; 319 320 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 321 event_ctx->unexpected_event = 1; 322 goto out; 323 } 324 325 if (is_dp_hdcp(hdcp)) { 326 if (!mod_hdcp_execute_and_set(mod_hdcp_read_binfo, 327 &input->binfo_read_dp, &status, 328 hdcp, "binfo_read_dp")) 329 goto out; 330 } else { 331 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 332 &input->bstatus_read, &status, 333 hdcp, "bstatus_read")) 334 goto out; 335 } 336 if (!mod_hdcp_execute_and_set(check_no_max_cascade, 337 &input->max_cascade_check, &status, 338 hdcp, "max_cascade_check")) 339 goto out; 340 if (!mod_hdcp_execute_and_set(check_no_max_devs, 341 &input->max_devs_check, &status, 342 hdcp, "max_devs_check")) 343 goto out; 344 if (!mod_hdcp_execute_and_set(check_device_count, 345 &input->device_count_check, &status, 346 hdcp, "device_count_check")) 347 goto out; 348 device_count = get_device_count(hdcp); 349 hdcp->auth.msg.hdcp1.ksvlist_size = device_count*5; 350 if (!mod_hdcp_execute_and_set(mod_hdcp_read_ksvlist, 351 &input->ksvlist_read, &status, 352 hdcp, "ksvlist_read")) 353 goto out; 354 if (!mod_hdcp_execute_and_set(mod_hdcp_read_vp, 355 &input->vp_read, &status, 356 hdcp, "vp_read")) 357 goto out; 358 if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_validate_ksvlist_vp, 359 &input->ksvlist_vp_validation, &status, 360 hdcp, "ksvlist_vp_validation")) 361 goto out; 362 if (input->encryption != PASS) 363 if (!mod_hdcp_execute_and_set(mod_hdcp_hdcp1_enable_encryption, 364 &input->encryption, &status, 365 hdcp, "encryption")) 366 goto out; 367 if (is_dp_mst_hdcp(hdcp)) 368 if (!mod_hdcp_execute_and_set( 369 mod_hdcp_hdcp1_enable_dp_stream_encryption, 370 &input->stream_encryption_dp, &status, 371 hdcp, "stream_encryption_dp")) 372 goto out; 373out: 374 return status; 375} 376 377static enum mod_hdcp_status determine_rx_hdcp_capable_dp(struct mod_hdcp *hdcp, 378 struct mod_hdcp_event_context *event_ctx, 379 struct mod_hdcp_transition_input_hdcp1 *input) 380{ 381 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 382 383 if (event_ctx->event != MOD_HDCP_EVENT_CALLBACK) { 384 event_ctx->unexpected_event = 1; 385 goto out; 386 } 387 388 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bcaps, 389 &input->bcaps_read, &status, 390 hdcp, "bcaps_read")) 391 goto out; 392 if (!mod_hdcp_execute_and_set(check_hdcp_capable_dp, 393 &input->hdcp_capable_dp, &status, 394 hdcp, "hdcp_capable_dp")) 395 goto out; 396out: 397 return status; 398} 399 400static enum mod_hdcp_status wait_for_r0_prime_dp(struct mod_hdcp *hdcp, 401 struct mod_hdcp_event_context *event_ctx, 402 struct mod_hdcp_transition_input_hdcp1 *input) 403{ 404 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 405 406 if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ && 407 event_ctx->event != MOD_HDCP_EVENT_WATCHDOG_TIMEOUT) { 408 event_ctx->unexpected_event = 1; 409 goto out; 410 } 411 412 if (!mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 413 &input->bstatus_read, &status, 414 hdcp, "bstatus_read")) 415 goto out; 416 if (!mod_hdcp_execute_and_set(check_r0p_available_dp, 417 &input->r0p_available_dp, &status, 418 hdcp, "r0p_available_dp")) 419 goto out; 420out: 421 return status; 422} 423 424static enum mod_hdcp_status authenticated_dp(struct mod_hdcp *hdcp, 425 struct mod_hdcp_event_context *event_ctx, 426 struct mod_hdcp_transition_input_hdcp1 *input) 427{ 428 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 429 430 if (event_ctx->event != MOD_HDCP_EVENT_CPIRQ) { 431 event_ctx->unexpected_event = 1; 432 goto out; 433 } 434 435 if (status == MOD_HDCP_STATUS_SUCCESS) 436 mod_hdcp_execute_and_set(mod_hdcp_read_bstatus, 437 &input->bstatus_read, &status, 438 hdcp, "bstatus_read"); 439 if (status == MOD_HDCP_STATUS_SUCCESS) 440 mod_hdcp_execute_and_set(check_link_integrity_dp, 441 &input->link_integrity_check, &status, 442 hdcp, "link_integrity_check"); 443 if (status == MOD_HDCP_STATUS_SUCCESS) 444 mod_hdcp_execute_and_set(check_no_reauthentication_request_dp, 445 &input->reauth_request_check, &status, 446 hdcp, "reauth_request_check"); 447out: 448 return status; 449} 450 451uint8_t mod_hdcp_execute_and_set( 452 mod_hdcp_action func, uint8_t *flag, 453 enum mod_hdcp_status *status, struct mod_hdcp *hdcp, char *str) 454{ 455 *status = func(hdcp); 456 if (*status == MOD_HDCP_STATUS_SUCCESS && *flag != PASS) { 457 HDCP_INPUT_PASS_TRACE(hdcp, str); 458 *flag = PASS; 459 } else if (*status != MOD_HDCP_STATUS_SUCCESS && *flag != FAIL) { 460 HDCP_INPUT_FAIL_TRACE(hdcp, str); 461 *flag = FAIL; 462 } 463 return (*status == MOD_HDCP_STATUS_SUCCESS); 464} 465 466enum mod_hdcp_status mod_hdcp_hdcp1_execution(struct mod_hdcp *hdcp, 467 struct mod_hdcp_event_context *event_ctx, 468 struct mod_hdcp_transition_input_hdcp1 *input) 469{ 470 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 471 472 switch (current_state(hdcp)) { 473 case H1_A0_WAIT_FOR_ACTIVE_RX: 474 status = wait_for_active_rx(hdcp, event_ctx, input); 475 break; 476 case H1_A1_EXCHANGE_KSVS: 477 status = exchange_ksvs(hdcp, event_ctx, input); 478 break; 479 case H1_A2_COMPUTATIONS_A3_VALIDATE_RX_A6_TEST_FOR_REPEATER: 480 status = computations_validate_rx_test_for_repeater(hdcp, 481 event_ctx, input); 482 break; 483 case H1_A45_AUTHENTICATED: 484 status = authenticated(hdcp, event_ctx, input); 485 break; 486 case H1_A8_WAIT_FOR_READY: 487 status = wait_for_ready(hdcp, event_ctx, input); 488 break; 489 case H1_A9_READ_KSV_LIST: 490 status = read_ksv_list(hdcp, event_ctx, input); 491 break; 492 default: 493 status = MOD_HDCP_STATUS_INVALID_STATE; 494 break; 495 } 496 497 return status; 498} 499 500enum mod_hdcp_status mod_hdcp_hdcp1_dp_execution(struct mod_hdcp *hdcp, 501 struct mod_hdcp_event_context *event_ctx, 502 struct mod_hdcp_transition_input_hdcp1 *input) 503{ 504 enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; 505 506 switch (current_state(hdcp)) { 507 case D1_A0_DETERMINE_RX_HDCP_CAPABLE: 508 status = determine_rx_hdcp_capable_dp(hdcp, event_ctx, input); 509 break; 510 case D1_A1_EXCHANGE_KSVS: 511 status = exchange_ksvs(hdcp, event_ctx, input); 512 break; 513 case D1_A23_WAIT_FOR_R0_PRIME: 514 status = wait_for_r0_prime_dp(hdcp, event_ctx, input); 515 break; 516 case D1_A2_COMPUTATIONS_A3_VALIDATE_RX_A5_TEST_FOR_REPEATER: 517 status = computations_validate_rx_test_for_repeater( 518 hdcp, event_ctx, input); 519 break; 520 case D1_A4_AUTHENTICATED: 521 status = authenticated_dp(hdcp, event_ctx, input); 522 break; 523 case D1_A6_WAIT_FOR_READY: 524 status = wait_for_ready(hdcp, event_ctx, input); 525 break; 526 case D1_A7_READ_KSV_LIST: 527 status = read_ksv_list(hdcp, event_ctx, input); 528 break; 529 default: 530 status = MOD_HDCP_STATUS_INVALID_STATE; 531 break; 532 } 533 534 return status; 535}