summaryrefslogtreecommitdiff
path: root/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
blob: f438c16563a791ad443d612550e93d7bc6869185 (plain)
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
/** @file
  EDKII Device Security library for SPDM device.
  It follows the SPDM Specification.

Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "SpdmSecurityLibInternal.h"

/**
  Helper function to quickly determine whether device authentication boot is enabled.

  @retval     TRUE    device authentication boot is verifiably enabled.
  @retval     FALSE   device authentication boot is either disabled or an error prevented checking.

**/
BOOLEAN
EFIAPI
IsDeviceAuthBootEnabled (
  VOID
  )
{
  EFI_STATUS  Status;
  UINT8       *DeviceAuthBootMode;

  DeviceAuthBootMode = NULL;

  Status = GetEfiGlobalVariable2 (EFI_DEVICE_AUTH_BOOT_MODE_NAME, (VOID **)&DeviceAuthBootMode, NULL);
  //
  // Skip verification if DeviceAuthBootMode variable doesn't exist.
  //
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "Cannot check DeviceAuthBootMode variable %r \n ", Status));
    return FALSE;
  }

  //
  // Skip verification if DeviceAuthBootMode is disabled but not AuditMode
  //
  if (*DeviceAuthBootMode == DEVICE_AUTH_BOOT_MODE_DISABLE) {
    FreePool (DeviceAuthBootMode);
    return FALSE;
  } else {
    FreePool (DeviceAuthBootMode);
    return TRUE;
  }
}

/**
  The device driver uses this service to authenticate and measure an SPDM device.

  @param[in]  SpdmDeviceInfo            The SPDM context for the device.
  @param[in]  SecurityPolicy            The security policy of this device.
  @param[out] SecurityState             A pointer to security state if this device.

  @retval EFI_SUCCESS   The TCG SPDM device measurement context is returned.
  @retval EFI_UNSUPPORTED  The TCG SPDM device measurement context is unsupported.

**/
EFI_STATUS
EFIAPI
SpdmDeviceAuthenticationAndMeasurement (
  IN  EDKII_SPDM_DEVICE_INFO        *SpdmDeviceInfo,
  IN  EDKII_DEVICE_SECURITY_POLICY  *SecurityPolicy,
  OUT EDKII_DEVICE_SECURITY_STATE   *SecurityState
  )
{
  EFI_STATUS           Status;
  SPDM_DEVICE_CONTEXT  *SpdmDeviceContext;
  UINT8                AuthState;
  UINT8                SlotId;
  BOOLEAN              IsValidCertChain;
  BOOLEAN              RootCertMatch;

  if ((PcdGet32 (PcdTcgPfpMeasurementRevision) < TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_106) ||
      (PcdGet8 (PcdEnableSpdmDeviceAuthentication) == 0))
  {
    return EFI_UNSUPPORTED;
  }

  SpdmDeviceContext = CreateSpdmDeviceContext (SpdmDeviceInfo, SecurityState);
  if (SpdmDeviceContext == NULL) {
    return EFI_UNSUPPORTED;
  }

  Status           = EFI_SUCCESS;
  AuthState        = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
  SlotId           = 0;
  IsValidCertChain = FALSE;
  RootCertMatch    = FALSE;

  if (((SecurityPolicy->AuthenticationPolicy & EDKII_DEVICE_AUTHENTICATION_REQUIRED) != 0) ||
      ((SecurityPolicy->MeasurementPolicy & EDKII_DEVICE_MEASUREMENT_REQUIRED) != 0))
  {
    Status = DoDeviceCertificate (SpdmDeviceContext, &AuthState, &SlotId, SecurityState, &IsValidCertChain, &RootCertMatch);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "DoDeviceCertificate failed - %r\n", Status));
      goto Ret;
    } else if ((AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG) ||
               (AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID))
    {
      goto Ret;
    }
  }

  if (((SecurityPolicy->AuthenticationPolicy & EDKII_DEVICE_AUTHENTICATION_REQUIRED) != 0) && (IsDeviceAuthBootEnabled ())) {
    Status = DoDeviceAuthentication (SpdmDeviceContext, &AuthState, SlotId, IsValidCertChain, RootCertMatch, SecurityState);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "DoDeviceAuthentication failed - %r\n", Status));
      goto Ret;
    } else if ((AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG) ||
               (AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID))
    {
      goto Ret;
    }
  }

  if ((SecurityPolicy->MeasurementPolicy & EDKII_DEVICE_MEASUREMENT_REQUIRED) != 0) {
    Status = DoDeviceMeasurement (SpdmDeviceContext, SlotId, SecurityState);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "DoDeviceMeasurement failed - %r\n", Status));
    }
  }

Ret:
  DestroySpdmDeviceContext (SpdmDeviceContext);

  return Status;
}

/**
  This function will get SpdmIoProtocol via Context.

  @param[in]   SpdmContext   The SPDM context for the device.

  return the pointer of Spdm Io protocol

**/
VOID *
EFIAPI
SpdmGetIoProtocolViaSpdmContext (
  IN VOID  *SpdmContext
  )
{
  return GetSpdmIoProtocolViaSpdmContext (SpdmContext);
}