linux/drivers/gpu/drm/drm_hdcp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2019 Intel Corporation.
   4 *
   5 * Authors:
   6 * Ramalingam C <ramalingam.c@intel.com>
   7 */
   8
   9#include <linux/device.h>
  10#include <linux/err.h>
  11#include <linux/gfp.h>
  12#include <linux/export.h>
  13#include <linux/slab.h>
  14#include <linux/firmware.h>
  15
  16#include <drm/drm_hdcp.h>
  17#include <drm/drm_sysfs.h>
  18#include <drm/drm_print.h>
  19#include <drm/drm_device.h>
  20#include <drm/drm_property.h>
  21#include <drm/drm_mode_object.h>
  22#include <drm/drm_connector.h>
  23
  24#include "drm_internal.h"
  25
  26static inline void drm_hdcp_print_ksv(const u8 *ksv)
  27{
  28        DRM_DEBUG("\t%#02x, %#02x, %#02x, %#02x, %#02x\n",
  29                  ksv[0], ksv[1], ksv[2], ksv[3], ksv[4]);
  30}
  31
  32static u32 drm_hdcp_get_revoked_ksv_count(const u8 *buf, u32 vrls_length)
  33{
  34        u32 parsed_bytes = 0, ksv_count = 0, vrl_ksv_cnt, vrl_sz;
  35
  36        while (parsed_bytes < vrls_length) {
  37                vrl_ksv_cnt = *buf;
  38                ksv_count += vrl_ksv_cnt;
  39
  40                vrl_sz = (vrl_ksv_cnt * DRM_HDCP_KSV_LEN) + 1;
  41                buf += vrl_sz;
  42                parsed_bytes += vrl_sz;
  43        }
  44
  45        /*
  46         * When vrls are not valid, ksvs are not considered.
  47         * Hence SRM will be discarded.
  48         */
  49        if (parsed_bytes != vrls_length)
  50                ksv_count = 0;
  51
  52        return ksv_count;
  53}
  54
  55static u32 drm_hdcp_get_revoked_ksvs(const u8 *buf, u8 **revoked_ksv_list,
  56                                     u32 vrls_length)
  57{
  58        u32 vrl_ksv_cnt, vrl_ksv_sz, vrl_idx = 0;
  59        u32 parsed_bytes = 0, ksv_count = 0;
  60
  61        do {
  62                vrl_ksv_cnt = *buf;
  63                vrl_ksv_sz = vrl_ksv_cnt * DRM_HDCP_KSV_LEN;
  64
  65                buf++;
  66
  67                DRM_DEBUG("vrl: %d, Revoked KSVs: %d\n", vrl_idx++,
  68                          vrl_ksv_cnt);
  69                memcpy((*revoked_ksv_list) + (ksv_count * DRM_HDCP_KSV_LEN),
  70                       buf, vrl_ksv_sz);
  71
  72                ksv_count += vrl_ksv_cnt;
  73                buf += vrl_ksv_sz;
  74
  75                parsed_bytes += (vrl_ksv_sz + 1);
  76        } while (parsed_bytes < vrls_length);
  77
  78        return ksv_count;
  79}
  80
  81static inline u32 get_vrl_length(const u8 *buf)
  82{
  83        return drm_hdcp_be24_to_cpu(buf);
  84}
  85
  86static int drm_hdcp_parse_hdcp1_srm(const u8 *buf, size_t count,
  87                                    u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
  88{
  89        struct hdcp_srm_header *header;
  90        u32 vrl_length, ksv_count;
  91
  92        if (count < (sizeof(struct hdcp_srm_header) +
  93            DRM_HDCP_1_4_VRL_LENGTH_SIZE + DRM_HDCP_1_4_DCP_SIG_SIZE)) {
  94                DRM_ERROR("Invalid blob length\n");
  95                return -EINVAL;
  96        }
  97
  98        header = (struct hdcp_srm_header *)buf;
  99        DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
 100                  header->srm_id,
 101                  be16_to_cpu(header->srm_version), header->srm_gen_no);
 102
 103        WARN_ON(header->reserved);
 104
 105        buf = buf + sizeof(*header);
 106        vrl_length = get_vrl_length(buf);
 107        if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
 108            vrl_length < (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
 109                          DRM_HDCP_1_4_DCP_SIG_SIZE)) {
 110                DRM_ERROR("Invalid blob length or vrl length\n");
 111                return -EINVAL;
 112        }
 113
 114        /* Length of the all vrls combined */
 115        vrl_length -= (DRM_HDCP_1_4_VRL_LENGTH_SIZE +
 116                       DRM_HDCP_1_4_DCP_SIG_SIZE);
 117
 118        if (!vrl_length) {
 119                DRM_ERROR("No vrl found\n");
 120                return -EINVAL;
 121        }
 122
 123        buf += DRM_HDCP_1_4_VRL_LENGTH_SIZE;
 124        ksv_count = drm_hdcp_get_revoked_ksv_count(buf, vrl_length);
 125        if (!ksv_count) {
 126                DRM_DEBUG("Revoked KSV count is 0\n");
 127                return 0;
 128        }
 129
 130        *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
 131        if (!*revoked_ksv_list) {
 132                DRM_ERROR("Out of Memory\n");
 133                return -ENOMEM;
 134        }
 135
 136        if (drm_hdcp_get_revoked_ksvs(buf, revoked_ksv_list,
 137                                      vrl_length) != ksv_count) {
 138                *revoked_ksv_cnt = 0;
 139                kfree(*revoked_ksv_list);
 140                return -EINVAL;
 141        }
 142
 143        *revoked_ksv_cnt = ksv_count;
 144        return 0;
 145}
 146
 147static int drm_hdcp_parse_hdcp2_srm(const u8 *buf, size_t count,
 148                                    u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
 149{
 150        struct hdcp_srm_header *header;
 151        u32 vrl_length, ksv_count, ksv_sz;
 152
 153        if (count < (sizeof(struct hdcp_srm_header) +
 154            DRM_HDCP_2_VRL_LENGTH_SIZE + DRM_HDCP_2_DCP_SIG_SIZE)) {
 155                DRM_ERROR("Invalid blob length\n");
 156                return -EINVAL;
 157        }
 158
 159        header = (struct hdcp_srm_header *)buf;
 160        DRM_DEBUG("SRM ID: 0x%x, SRM Ver: 0x%x, SRM Gen No: 0x%x\n",
 161                  header->srm_id & DRM_HDCP_SRM_ID_MASK,
 162                  be16_to_cpu(header->srm_version), header->srm_gen_no);
 163
 164        if (header->reserved)
 165                return -EINVAL;
 166
 167        buf = buf + sizeof(*header);
 168        vrl_length = get_vrl_length(buf);
 169
 170        if (count < (sizeof(struct hdcp_srm_header) + vrl_length) ||
 171            vrl_length < (DRM_HDCP_2_VRL_LENGTH_SIZE +
 172            DRM_HDCP_2_DCP_SIG_SIZE)) {
 173                DRM_ERROR("Invalid blob length or vrl length\n");
 174                return -EINVAL;
 175        }
 176
 177        /* Length of the all vrls combined */
 178        vrl_length -= (DRM_HDCP_2_VRL_LENGTH_SIZE +
 179                       DRM_HDCP_2_DCP_SIG_SIZE);
 180
 181        if (!vrl_length) {
 182                DRM_ERROR("No vrl found\n");
 183                return -EINVAL;
 184        }
 185
 186        buf += DRM_HDCP_2_VRL_LENGTH_SIZE;
 187        ksv_count = (*buf << 2) | DRM_HDCP_2_KSV_COUNT_2_LSBITS(*(buf + 1));
 188        if (!ksv_count) {
 189                DRM_DEBUG("Revoked KSV count is 0\n");
 190                return 0;
 191        }
 192
 193        *revoked_ksv_list = kcalloc(ksv_count, DRM_HDCP_KSV_LEN, GFP_KERNEL);
 194        if (!*revoked_ksv_list) {
 195                DRM_ERROR("Out of Memory\n");
 196                return -ENOMEM;
 197        }
 198
 199        ksv_sz = ksv_count * DRM_HDCP_KSV_LEN;
 200        buf += DRM_HDCP_2_NO_OF_DEV_PLUS_RESERVED_SZ;
 201
 202        DRM_DEBUG("Revoked KSVs: %d\n", ksv_count);
 203        memcpy(*revoked_ksv_list, buf, ksv_sz);
 204
 205        *revoked_ksv_cnt = ksv_count;
 206        return 0;
 207}
 208
 209static inline bool is_srm_version_hdcp1(const u8 *buf)
 210{
 211        return *buf == (u8)(DRM_HDCP_1_4_SRM_ID << 4);
 212}
 213
 214static inline bool is_srm_version_hdcp2(const u8 *buf)
 215{
 216        return *buf == (u8)(DRM_HDCP_2_SRM_ID << 4 | DRM_HDCP_2_INDICATOR);
 217}
 218
 219static int drm_hdcp_srm_update(const u8 *buf, size_t count,
 220                               u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
 221{
 222        if (count < sizeof(struct hdcp_srm_header))
 223                return -EINVAL;
 224
 225        if (is_srm_version_hdcp1(buf))
 226                return drm_hdcp_parse_hdcp1_srm(buf, count, revoked_ksv_list,
 227                                                revoked_ksv_cnt);
 228        else if (is_srm_version_hdcp2(buf))
 229                return drm_hdcp_parse_hdcp2_srm(buf, count, revoked_ksv_list,
 230                                                revoked_ksv_cnt);
 231        else
 232                return -EINVAL;
 233}
 234
 235static int drm_hdcp_request_srm(struct drm_device *drm_dev,
 236                                u8 **revoked_ksv_list, u32 *revoked_ksv_cnt)
 237{
 238        char fw_name[36] = "display_hdcp_srm.bin";
 239        const struct firmware *fw;
 240        int ret;
 241
 242        ret = request_firmware_direct(&fw, (const char *)fw_name,
 243                                      drm_dev->dev);
 244        if (ret < 0) {
 245                *revoked_ksv_cnt = 0;
 246                *revoked_ksv_list = NULL;
 247                ret = 0;
 248                goto exit;
 249        }
 250
 251        if (fw->size && fw->data)
 252                ret = drm_hdcp_srm_update(fw->data, fw->size, revoked_ksv_list,
 253                                          revoked_ksv_cnt);
 254
 255exit:
 256        release_firmware(fw);
 257        return ret;
 258}
 259
 260/**
 261 * drm_hdcp_check_ksvs_revoked - Check the revoked status of the IDs
 262 *
 263 * @drm_dev: drm_device for which HDCP revocation check is requested
 264 * @ksvs: List of KSVs (HDCP receiver IDs)
 265 * @ksv_count: KSV count passed in through @ksvs
 266 *
 267 * This function reads the HDCP System renewability Message(SRM Table)
 268 * from userspace as a firmware and parses it for the revoked HDCP
 269 * KSVs(Receiver IDs) detected by DCP LLC. Once the revoked KSVs are known,
 270 * revoked state of the KSVs in the list passed in by display drivers are
 271 * decided and response is sent.
 272 *
 273 * SRM should be presented in the name of "display_hdcp_srm.bin".
 274 *
 275 * Format of the SRM table, that userspace needs to write into the binary file,
 276 * is defined at:
 277 * 1. Renewability chapter on 55th page of HDCP 1.4 specification
 278 * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20Specification%20Rev1_4_Secure.pdf
 279 * 2. Renewability chapter on 63rd page of HDCP 2.2 specification
 280 * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf
 281 *
 282 * Returns:
 283 * Count of the revoked KSVs or -ve error number incase of the failure.
 284 */
 285int drm_hdcp_check_ksvs_revoked(struct drm_device *drm_dev, u8 *ksvs,
 286                                u32 ksv_count)
 287{
 288        u32 revoked_ksv_cnt = 0, i, j;
 289        u8 *revoked_ksv_list = NULL;
 290        int ret = 0;
 291
 292        ret = drm_hdcp_request_srm(drm_dev, &revoked_ksv_list,
 293                                   &revoked_ksv_cnt);
 294        if (ret)
 295                return ret;
 296
 297        /* revoked_ksv_cnt will be zero when above function failed */
 298        for (i = 0; i < revoked_ksv_cnt; i++)
 299                for  (j = 0; j < ksv_count; j++)
 300                        if (!memcmp(&ksvs[j * DRM_HDCP_KSV_LEN],
 301                                    &revoked_ksv_list[i * DRM_HDCP_KSV_LEN],
 302                                    DRM_HDCP_KSV_LEN)) {
 303                                DRM_DEBUG("Revoked KSV is ");
 304                                drm_hdcp_print_ksv(&ksvs[j * DRM_HDCP_KSV_LEN]);
 305                                ret++;
 306                        }
 307
 308        kfree(revoked_ksv_list);
 309        return ret;
 310}
 311EXPORT_SYMBOL_GPL(drm_hdcp_check_ksvs_revoked);
 312
 313static struct drm_prop_enum_list drm_cp_enum_list[] = {
 314        { DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
 315        { DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
 316        { DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" },
 317};
 318DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
 319
 320static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = {
 321        { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" },
 322        { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" },
 323};
 324DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name,
 325                 drm_hdcp_content_type_enum_list)
 326
 327/**
 328 * drm_connector_attach_content_protection_property - attach content protection
 329 * property
 330 *
 331 * @connector: connector to attach CP property on.
 332 * @hdcp_content_type: is HDCP Content Type property needed for connector
 333 *
 334 * This is used to add support for content protection on select connectors.
 335 * Content Protection is intentionally vague to allow for different underlying
 336 * technologies, however it is most implemented by HDCP.
 337 *
 338 * When hdcp_content_type is true enum property called HDCP Content Type is
 339 * created (if it is not already) and attached to the connector.
 340 *
 341 * This property is used for sending the protected content's stream type
 342 * from userspace to kernel on selected connectors. Protected content provider
 343 * will decide their type of their content and declare the same to kernel.
 344 *
 345 * Content type will be used during the HDCP 2.2 authentication.
 346 * Content type will be set to &drm_connector_state.hdcp_content_type.
 347 *
 348 * The content protection will be set to &drm_connector_state.content_protection
 349 *
 350 * When kernel triggered content protection state change like DESIRED->ENABLED
 351 * and ENABLED->DESIRED, will use drm_hdcp_update_content_protection() to update
 352 * the content protection state of a connector.
 353 *
 354 * Returns:
 355 * Zero on success, negative errno on failure.
 356 */
 357int drm_connector_attach_content_protection_property(
 358                struct drm_connector *connector, bool hdcp_content_type)
 359{
 360        struct drm_device *dev = connector->dev;
 361        struct drm_property *prop =
 362                        dev->mode_config.content_protection_property;
 363
 364        if (!prop)
 365                prop = drm_property_create_enum(dev, 0, "Content Protection",
 366                                                drm_cp_enum_list,
 367                                                ARRAY_SIZE(drm_cp_enum_list));
 368        if (!prop)
 369                return -ENOMEM;
 370
 371        drm_object_attach_property(&connector->base, prop,
 372                                   DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
 373        dev->mode_config.content_protection_property = prop;
 374
 375        if (!hdcp_content_type)
 376                return 0;
 377
 378        prop = dev->mode_config.hdcp_content_type_property;
 379        if (!prop)
 380                prop = drm_property_create_enum(dev, 0, "HDCP Content Type",
 381                                        drm_hdcp_content_type_enum_list,
 382                                        ARRAY_SIZE(
 383                                        drm_hdcp_content_type_enum_list));
 384        if (!prop)
 385                return -ENOMEM;
 386
 387        drm_object_attach_property(&connector->base, prop,
 388                                   DRM_MODE_HDCP_CONTENT_TYPE0);
 389        dev->mode_config.hdcp_content_type_property = prop;
 390
 391        return 0;
 392}
 393EXPORT_SYMBOL(drm_connector_attach_content_protection_property);
 394
 395/**
 396 * drm_hdcp_update_content_protection - Updates the content protection state
 397 * of a connector
 398 *
 399 * @connector: drm_connector on which content protection state needs an update
 400 * @val: New state of the content protection property
 401 *
 402 * This function can be used by display drivers, to update the kernel triggered
 403 * content protection state changes of a drm_connector such as DESIRED->ENABLED
 404 * and ENABLED->DESIRED. No uevent for DESIRED->UNDESIRED or ENABLED->UNDESIRED,
 405 * as userspace is triggering such state change and kernel performs it without
 406 * fail.This function update the new state of the property into the connector's
 407 * state and generate an uevent to notify the userspace.
 408 */
 409void drm_hdcp_update_content_protection(struct drm_connector *connector,
 410                                        u64 val)
 411{
 412        struct drm_device *dev = connector->dev;
 413        struct drm_connector_state *state = connector->state;
 414
 415        WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
 416        if (state->content_protection == val)
 417                return;
 418
 419        state->content_protection = val;
 420        drm_sysfs_connector_status_event(connector,
 421                                 dev->mode_config.content_protection_property);
 422}
 423EXPORT_SYMBOL(drm_hdcp_update_content_protection);
 424