• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #if !defined(_MSC_VER) && defined(USE_PLATFORM_EPS)
37 #include <stdlib.h>
38 #include <memory.h>
39 #include <time.h>
40 #include <unistd.h>
41 #include <net/if.h>
42 #include <sys/ioctl.h>
43 #include <netinet/in.h>
44 #include <stdio.h>
45 #include <libudev.h>
46 #include <sys/stat.h>
47 
48 #include "Tpm.h"
49 #include "Platform_fp.h"
50 
51 #define DEVICEID_SIZE 48
52 
53 // This extension is needed as TPM2B_STRING only define TPM2B variable when #GLOBAL_C is defined.
54 #define TPM2B_STRING_EXTENSION(name, value)                 \
55 TPM2B_STRING(name, value);                                  \
56 const TPM2B_##name##_ name##_ = STRING_INITIALIZER(value);  \
57 const TPM2B *name = &name##_.b
58 
59 TPM2B_STRING_EXTENSION(EPS_CREATION, "EPS Creation");
60 
61 // Definition for Device ID value.
62 TPM2B_TYPE(DEVICEID, DEVICEID_SIZE);
63 const unsigned int MAC_ADDRESS_MAXIMUM_SIZE = 6;
64 
65 // This value is used to store device id derived from hardware parameters.
66 static TPM2B_DEVICEID deviceID = {0};
67 static BOOL isDeviceIDSet = FALSE;
68 
69 // Read mac address of the device and copy over to the given buffer.
70 // Returns 0 for success and -1 for error.
71 
GetMacAddress()72 static int GetMacAddress()
73 {
74     struct ifreq interfaceRequest = {0};
75     struct ifconf interfaceConfiguration = {0};
76     char interfaceConfigurationBuffer[1024] = {0};
77 
78     int inetSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
79     if (inetSocket == -1)
80     {
81         return -1;
82     }
83 
84     interfaceConfiguration.ifc_len = sizeof(interfaceConfigurationBuffer);
85     interfaceConfiguration.ifc_buf = interfaceConfigurationBuffer;
86     if((ioctl(inetSocket, SIOCGIFCONF, &interfaceConfiguration)) == -1)
87     {
88         close(inetSocket);
89         return -1;
90     }
91 
92     struct ifreq* intefaceRequestStart = interfaceConfiguration.ifc_req;
93     const struct ifreq* const interfaceRequestEnd = intefaceRequestStart + (interfaceConfiguration.ifc_len / sizeof(struct ifreq));
94 
95     int32_t result = -1;
96 
97     for (; intefaceRequestStart != interfaceRequestEnd; ++intefaceRequestStart)
98     {
99         strcpy(interfaceRequest.ifr_name, intefaceRequestStart->ifr_name);
100         if (ioctl(inetSocket, SIOCGIFFLAGS, &interfaceRequest) == 0)
101         {
102             // don't count loopback
103             if ((interfaceRequest.ifr_flags & IFF_LOOPBACK) == 0)
104             {
105                 if (ioctl(inetSocket, SIOCGIFHWADDR, &interfaceRequest) == 0)
106                 {
107                     result = 0;
108                     break;
109                 }
110             }
111         }
112         else
113         {
114             break;
115         }
116     }
117 
118     if (result == 0)
119     {
120         unsigned int size = deviceID.t.size <= MAC_ADDRESS_MAXIMUM_SIZE ? deviceID.t.size : MAC_ADDRESS_MAXIMUM_SIZE;
121         memcpy(deviceID.t.buffer, interfaceRequest.ifr_hwaddr.sa_data, size);
122     }
123 
124     close(inetSocket);
125     return result;
126 }
127 
128 // Read primary harddisk/emmc disk serial id from device and copy over to the given buffer.
129 // Returns 0 for success and -1 for error.
130 
GetDiskSerialNumber()131 static int GetDiskSerialNumber()
132 {
133     struct udev *ud = NULL;
134     struct stat statbuf;
135     struct udev_device *device = NULL;
136     struct udev_list_entry *entry = NULL;
137     int result = -1;
138 
139     ud = udev_new();
140     if (NULL == ud)
141     {
142         return result;
143     }
144     else
145     {
146 
147         const unsigned int diskDeviceNamesSize = 2;
148         const char *diskDeviceNames[] = {
149             "/dev/sda", // primary hard disk.
150             "/dev/mmcblk0" // primary eMMC disk.
151         };
152 
153         unsigned int i = 0;
154         while (i < diskDeviceNamesSize)
155         {
156             if (0 == stat(diskDeviceNames[i], &statbuf))
157             {
158                 break;
159             }
160             i++;
161         }
162 
163         if (i == diskDeviceNamesSize)
164         {
165             goto Cleanup;
166         }
167 
168         const char blockDeviceType = 'b';
169         device = udev_device_new_from_devnum(ud, blockDeviceType, statbuf.st_rdev);
170         if (NULL == device)
171         {
172             goto Cleanup;
173         }
174         else
175         {
176             entry = udev_device_get_properties_list_entry(device);
177             while (NULL != entry)
178             {
179                 if (0 == strcmp(udev_list_entry_get_name(entry),
180                     "ID_SERIAL"))
181                 {
182                     break;
183                 }
184 
185                 entry = udev_list_entry_get_next(entry);
186             }
187 
188             if(entry == NULL)
189             {
190                 goto Cleanup;
191             }
192 
193             const char* serialNumber = udev_list_entry_get_value(entry);
194             size_t serialNumberLength = strlen(serialNumber);
195 
196             size_t dataCopyLength = deviceID.t.size - MAC_ADDRESS_MAXIMUM_SIZE;
197             if (serialNumberLength < dataCopyLength)
198             {
199                 dataCopyLength = serialNumberLength;
200             }
201 
202             memcpy(deviceID.t.buffer, serialNumber, dataCopyLength);
203 
204             result = 0;
205         }
206 
207 Cleanup:
208         if(device)
209         {
210             udev_device_unref(device);
211         }
212 
213         (void)udev_unref(ud);
214         return result;
215     }
216 }
217 
218 #if defined(SIMULATION) && (SIMULATION == YES)
219 // Get device id from hardware parameters.
220 // CAUTION: Primary seeds derived from device unique IDs are guaranteed to remain the same as long as the reference
221 //  implementation manufactures its NV state on the same device. Since this implementation of GetDeviceID() relies
222 //  solely on publicly accessible values (storage device serial numbers and networking card MAC address), it can
223 //  only be used for the simulation purposes, as it cannot be used to produce a secret value.
224 // pre-requisites - assumes that MAC address or disk device (i.e. /dev/sda or /dev/mmcblk0) present on the device.
GetDeviceID()225 TPM_RC GetDeviceID()
226 {
227     if(isDeviceIDSet == FALSE)
228     {
229         if(GetMacAddress() == 0)
230         {
231             isDeviceIDSet = TRUE;
232         }
233 
234         if(GetDiskSerialNumber() == 0)
235         {
236             isDeviceIDSet = TRUE;
237         }
238 
239         if(isDeviceIDSet == FALSE)
240         {
241             return TPM_RC_FAILURE;
242         }
243     }
244 
245     return TPM_RC_SUCCESS;
246 }
247 #endif
248 
GetSeed(UINT16 size,uint8_t * seed,const TPM2B * purpose)249 void GetSeed(UINT16 size, uint8_t *seed, const TPM2B *purpose)
250 {
251     RAND_STATE rand;
252 
253     TPM_RC result = GetDeviceID();
254     if(result != TPM_RC_SUCCESS)
255     {
256         LOG_FAILURE(FATAL_ERROR_INTERNAL);
257         return;
258     }
259 
260     result = DRBG_InstantiateSeeded(&rand.drbg, &deviceID.b, purpose, NULL, NULL);
261     if(result != TPM_RC_SUCCESS)
262     {
263         LOG_FAILURE(FATAL_ERROR_INTERNAL);
264         return;
265     }
266 
267     if(DRBG_Generate(&rand, seed, size) == 0)
268     {
269         LOG_FAILURE(FATAL_ERROR_INTERNAL);
270     }
271     return;
272 }
273 
274 void
_plat__GetEPS(UINT16 size,uint8_t * seed)275 _plat__GetEPS(
276     UINT16 size,
277     uint8_t *seed
278     )
279 {
280     // Ignore GCC warning.
281     (void)EPS_CREATION_;
282     GetSeed(size, seed, EPS_CREATION);
283 }
284 
285 #endif