MHEG-5  19.3.0
MHEG-5 Documentation
mh5tls.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2010 Ocean Blue Software Ltd
4  *
5  * This file is part of a DTVKit Software Component
6  * You are permitted to copy, modify or distribute this file subject to the terms
7  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
8  *
9  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
10  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
11  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * If you or your organisation is not a member of DTVKit then you have access
14  * to this source code outside of the terms of the licence agreement
15  * and you are expected to delete this and any associated files immediately.
16  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
17  *******************************************************************************/
25 /*---includes for this file--------------------------------------------------*/
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 
30 #include "mh5profile.h"
31 #include "mh5tls.h"
32 #include "mh5memory.h"
33 #include "http_interface.h"
34 #include "mh5fileorm.h"
35 #include "stb_os.h"
36 
37 /*---constant definitions for this file--------------------------------------*/
38 #define TLS_CERT_TIMEOUT (24 * 60 * 60 * 1000)
39 #define MAX_TLS_CERT_NAME (22)
40 #define MAX_CALLBACKS (5)
41 
42 /*#define TLS_DEBUG_PRINT*/
43 
44 #ifdef TLS_DEBUG_PRINT
45 #define PRINT(x) DBG_PRINTF x
46 #else
47 #define PRINT(x)
48 #endif
49 
50 
51 /*---local typedef structs for this file-------------------------------------*/
52 /* Enumerated type to tell the state of the TLS certificate refresh process */
53 typedef enum
54 {
55  TLS_CERT_STATE_SYNC,
56  TLS_CERT_STATE_ASYNC,
57  TLS_CERT_STATE_VALID,
58  TLS_CERT_STATE_INVALID
59 } TlsCertRefreshState;
60 
61 /*---local (static) variable declarations for this file----------------------*/
62 static void(*tlsCallback[MAX_CALLBACKS]) (void);
63 static U16BIT callbackCount = 0;
64 static U32BIT lastCertStoreUpdate = 0;
65 static MHEG5Int lastRequestNumber = 0;
66 static MHEG5Bool lastRequestFailed = MHEG5FALSE;
67 static TlsCertRefreshState certRequestState = TLS_CERT_STATE_VALID;
68 
69 
70 /*---local function prototypes for this file---------------------------------*/
71 static MHEG5Bool IsTimeToUpdate(void);
72 static void ClearTlsCertStore(void);
73 static void TlsCertRetrieved( void *userData, S_CONTENT *content );
74 static void AddCertificates( U8BIT *certData, U32BIT certLen );
75 static void TlsCertRetrievalFailed( void *userData );
76 static void NotifyTlsReady(void);
77 
78 /*---global function definitions---------------------------------------------*/
79 
87 {
88  ClearTlsCertStore();
89 }
90 
96 {
97  ClearTlsCertStore();
98 
99  if (certRequestState == TLS_CERT_STATE_ASYNC)
100  {
101  /* A certificate has been requested - need to make sure it doesn't
102  * actually get used
103  */
104  certRequestState = TLS_CERT_STATE_INVALID;
105  }
106 }
107 
113 {
114  U32BIT count;
115 
116  count = httpGetTlsCertStoreCount();
117 
118  return count;
119 }
120 
126 MHEG5TlsCertRequestStatus MHEG5GetNextTlsCertificate(void)
127 {
128  MHEG5TlsCertRequestStatus status;
129  MHEG5Int currentRequestNumber;
130  char name[MAX_TLS_CERT_NAME];
131  MHEG5String requestName;
132 
133  status = MHEG5_TLS_CERT_REQUEST_PENDING;
134 
135  if (lastRequestFailed)
136  {
137  /* Certificate store is still valid, no point in trying again */
138  status = MHEG5_TLS_CERT_REQUEST_FAILURE;
139  }
140 
141  if (certRequestState == TLS_CERT_STATE_VALID)
142  {
143  if (IsTimeToUpdate())
144  {
145  ClearTlsCertStore();
146  }
147 
148  if (!lastRequestFailed)
149  {
150  certRequestState = TLS_CERT_STATE_SYNC;
151 
152  currentRequestNumber = lastRequestNumber;
153  sprintf(name, "DSM://auth.tls.%ld", lastRequestNumber + 1);
154  requestName.data = (U8BIT *)name;
155  requestName.len = strlen(name);
156  (void)MHEG5FileOrmGet( requestName, FRP_CERT | FRP_CACHE_DEFAULT, NULL,
157  TlsCertRetrieved, TlsCertRetrievalFailed);
158 
159  if (certRequestState == TLS_CERT_STATE_VALID)
160  {
161  if (currentRequestNumber == lastRequestNumber)
162  {
163  /* No new certificates, request failed */
164  status = MHEG5_TLS_CERT_REQUEST_FAILURE;
165  }
166  else
167  {
168  /* Something new to test, request succeeded */
169  status = MHEG5_TLS_CERT_REQUEST_SUCCESS;
170  }
171  }
172  else
173  {
174  /* The request is not valid, so it was asynchronous */
175  certRequestState = TLS_CERT_STATE_ASYNC;
176  }
177  }
178  }
179 
180  return status;
181 }
182 
189 void MHEG5AddTlsCertificateCallback(void (*loadCallback)(void))
190 {
191  if (callbackCount < MAX_CALLBACKS)
192  {
193  tlsCallback[callbackCount] = loadCallback;
194  callbackCount++;
195  }
196 }
197 
198 /*---local function definitions----------------------------------------------*/
199 
200 
205 static MHEG5Bool IsTimeToUpdate(void)
206 {
207  MHEG5Bool timeToUpdate;
208  U32BIT currentTime;
209 
210  timeToUpdate = FALSE;
211 
212  /* Check if TLS certificates should be updated */
213  currentTime = STB_OSGetClockMilliseconds();
214  if (lastCertStoreUpdate == 0)
215  {
216  timeToUpdate = TRUE;
217  }
218  else if ((currentTime > lastCertStoreUpdate) &&
219  (currentTime - lastCertStoreUpdate) > TLS_CERT_TIMEOUT)
220  {
221  timeToUpdate = TRUE;
222  }
223  else if (currentTime < lastCertStoreUpdate)
224  {
225  /* overflow */
226  timeToUpdate = TRUE;
227  }
228 
229  return timeToUpdate;
230 }
231 
236 static void ClearTlsCertStore(void)
237 {
239  lastCertStoreUpdate = 0;
240  lastRequestNumber = 0;
241  lastRequestFailed = MHEG5FALSE;
242 }
243 
254 static void TlsCertRetrieved( void *userData, S_CONTENT *content )
255 {
256  USE_UNWANTED_PARAM(userData);
257 
258  if (certRequestState == TLS_CERT_STATE_INVALID)
259  {
260  /* Certificate store has been invalidated - ignore the file and
261  * call the TLS callback
262  */
263  certRequestState = TLS_CERT_STATE_VALID;
264  NotifyTlsReady();
265  }
266  else if (certRequestState != TLS_CERT_STATE_VALID)
267  {
268  /* Request is still active, update HTTP module */
269  AddCertificates( content->data, content->size );
270 
271  /* Update state */
272  ++lastRequestNumber;
273 
274  /* Call TLS callback, but only if response was asynchronous */
275  if (certRequestState == TLS_CERT_STATE_ASYNC)
276  {
277  NotifyTlsReady();
278  }
279 
280  certRequestState = TLS_CERT_STATE_VALID;
281  }
282 }
283 
290 static void AddCertificates(U8BIT *certData, U32BIT certLen)
291 {
292  U32BIT size;
293  U16BIT count;
294 
295  count = 0;
296  if (certLen > 2)
297  {
298  count = certData[0] << 8 | certData[1];
299  }
300 
301  /* TLS certificate files should only contain a single certificate */
302  if (count == 1)
303  {
304  if (certLen >= 5)
305  {
306  size = (certData[2] << 16 | certData[3] << 8 | certData[4]);
307  if (size + 5 == certLen)
308  {
309  httpAddTlsCertToStore(certData + 5, size);
310  }
311  else
312  {
313  /* invalid size */
314 #ifdef TLS_DEBUG
315  DBG_PRINTF("Invalid certificate size\n");
316 #endif
317  }
318  }
319  else
320  {
321  /* invalid certificate file length */
322 #ifdef TLS_DEBUG
323  DBG_PRINTF("Invalid certificate file length\n");
324 #endif
325  }
326  }
327 
328  if (lastRequestNumber == 0)
329  {
330  /* First request, remember update time (even if invalid certificate) */
331  lastCertStoreUpdate = STB_OSGetClockMilliseconds();
332  }
333 }
334 
342 void TlsCertRetrievalFailed(void *userData)
343 {
344  USE_UNWANTED_PARAM(userData);
345 
346  if (certRequestState == TLS_CERT_STATE_INVALID)
347  {
348  /* Certificate store has been invalidated - ignore the file and
349  * call the TLS callback
350  */
351  certRequestState = TLS_CERT_STATE_VALID;
352  NotifyTlsReady();
353  }
354  else
355  {
356  lastRequestFailed = MHEG5TRUE;
357  if (lastCertStoreUpdate == 0)
358  {
359  /* First attempt failed - no certificates */
360  lastCertStoreUpdate = STB_OSGetClockMilliseconds();
361  }
362 
363  /* Call TLS callback, but only if response was asynchronous */
364  if (certRequestState == TLS_CERT_STATE_ASYNC)
365  {
366  NotifyTlsReady();
367  }
368  }
369 
370  certRequestState = TLS_CERT_STATE_VALID;
371 }
372 
377 static void NotifyTlsReady(void)
378 {
379  U16BIT i;
380 
381  for (i = 0; i < callbackCount; i++)
382  {
383  if (tlsCallback[i] != NULL)
384  {
385  tlsCallback[i]();
386  }
387  }
388 }
389 
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
Manages the interface between MHEG5 Engine and the HTTP component.
MHEG5TlsCertRequestStatus MHEG5GetNextTlsCertificate(void)
Issues a request to load the next TLS certificate from the DSM-CC object carousel.
Definition: mh5tls.c:126
void MHEG5InvalidateTlsCertStore(void)
Invalidate the TLS certificate store.
Definition: mh5tls.c:95
void MHEG5AddTlsCertificateCallback(void(*loadCallback)(void))
Add a callback function to be called when pending requests are resolved.
Definition: mh5tls.c:189
void * MHEG5FileOrmGet(MHEG5String name, U16BIT priority, void *userData, F_CB_Good cbGood, F_CB_Fail cbFail)
Get a file. The file will be loaded and one of the callback functions called when request is resolved...
Definition: mh5fileorm.c:1179
void MHEG5ClearTlsCertStore(void)
Clear the TLS certificate store.
Definition: mh5tls.c:86
This file defines the profile for the MHEG engine.
void httpClearTlsCertStore(void)
Clear TLS certificate store.
File interface functions to DSMCC component.
redirection include
Functions relating to TLS certificate store.
void httpAddTlsCertToStore(U8BIT *certData, U32BIT certLen)
Add TLS certificate to store.
U32BIT MHEG5GetTlsCertStoreCount(void)
Return number of TLS certificates in the TLS certificate store.
Definition: mh5tls.c:112
U32BIT httpGetTlsCertStoreCount(void)
Return number of TLS certificate in the certificate store.
Header file - Function prototypes for operating system.