MHEG5  18.9.0
MHEG5 Documentation
mh5sig.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 <openssl/sha.h>
31 #include <openssl/rsa.h>
32 #include <openssl/evp.h>
33 #include <openssl/x509.h>
34 
35 #include "mh5profile.h"
36 #include "mh5sig.h"
37 #include "mh5memory.h"
38 #include "mh5fileorm.h"
39 #include "mh5debug.h" /*tracing*/
40 #include "stb_os.h"
41 
42 /*---constant definitions for this file--------------------------------------*/
43 
44 /* Official timeout is 4hrs but to be on the safe side, refresh after 3hrs */
45 #define SIG_CERT_TIMEOUT (3 * 60 * 60 * 1000)
46 
47 #define MAX_SIG_CERT_NAME (22)
48 #define MAX_SIG_SIZE (256)
49 
50 #define ENTRY_STATE_STRING(e) \
51  ((e)->state == ENTRY_STATE_START ? "ENTRY_STATE_START" : \
52  (e)->state == ENTRY_STATE_VERIFIED ? "ENTRY_STATE_VERIFIED" : \
53  (e)->state == ENTRY_STATE_NOT_VERIFIED ? "ENTRY_STATE_NOT_VERIFIED" : \
54  (e)->state == ENTRY_STATE_WAIT_FOR_CERT ? "ENTRY_STATE_WAIT_FOR_CERT" : \
55  (e)->state == ENTRY_STATE_HAS_CERT ? "ENTRY_STATE_HAS_CERT" : \
56  (e)->state == ENTRY_STATE_NO_CERT ? "ENTRY_STATE_NO_CERT" : \
57  "UNKNOWN")
58 
59 #define SIG_DEBUG_PRINT
60 #undef SIG_DEBUG_PRINT
61 #ifdef SIG_DEBUG_PRINT
62 #define PRINT(x) DBG_PRINTF x
63 #else
64 #define PRINT(x)
65 #endif
66 
67 
68 /*---local typedef structs for this file-------------------------------------*/
69 typedef enum
70 {
78 
79 typedef struct sSigCacheEntry
80 {
82  U8BIT hashDigest[SHA_DIGEST_LENGTH];
83  U8BIT certDigest[SHA_DIGEST_LENGTH];
91 
92 typedef struct sCertLink
93 {
94  struct sCertLink *next;
95  X509 *x509;
96 } CertLink;
97 
98 typedef struct sCertFile
99 {
100  struct sCertFile *next;
104  U8BIT certDigest[SHA_DIGEST_LENGTH];
106 } CertFile;
107 
108 /*---local (static) variable declarations for this file----------------------*/
109 
110 static void (*sigVerifyCallback)(void) = NULL;
111 static SigCacheEntry *sigCache = NULL;
112 static CertFile *certCache = NULL;
113 static BOOLEAN certRequested = FALSE;
114 static BOOLEAN certCacheInvalid = FALSE;
115 
116 /*---local function prototypes for this file---------------------------------*/
117 
118 static void ProcessSigCache(void);
119 static BOOLEAN IsInFinalState(SigCacheEntry *entry);
120 static BOOLEAN ProcessSigCacheEntry(SigCacheEntry *entry);
121 static BOOLEAN HandleStartState(SigCacheEntry *entry);
122 static BOOLEAN HandleHasCertState(SigCacheEntry *entry);
123 static BOOLEAN HandleVerifiedState(SigCacheEntry *entry);
124 static MHEG5Bool IsTimeToUpdate(CertFile *certFile);
125 static void RefreshCertCache(void);
126 static void RequestNextCertFile(void);
127 static void SigCertRetrieved( void *userData, S_CONTENT *content );
128 static void SigCertRetrievalFailed( void *userData );
129 static CertFile* ParseCertFile(U8BIT *data, U32BIT len);
130 static void* ParseX509Cert(U8BIT *data, U16BIT len);
131 static void ClearSigCache(void);
132 static void ClearCertCache(void);
133 static BOOLEAN AddCertFileToCache(U8BIT *data, S32BIT size);
134 static void UpdatePendingEntries(BOOLEAN retrieved);
135 static CertFile* GetLastCertFile(void);
136 static CertLink* GetMatchingCert(SigCacheEntry *entry, CertFile *certFile);
137 static BOOLEAN IsIssuerNameEqual(SigCacheEntry *entry, CertLink *cert);
138 static BOOLEAN IsSerialNumberEqual(SigCacheEntry *entry, CertLink *cert);
139 static BOOLEAN VerifyHashFileSignature(CertLink *cert, SigCacheEntry *entry);
140 static BOOLEAN VerifyDigest(SigCacheEntry *entry, U8BIT *digestInfo,
141  S32BIT digestInfoLen);
142 static SigCacheEntry* FindCacheEntry(U8BIT *hashDigest,
144 static SigCacheEntry* CreateCacheEntry(U8BIT *hashDigest,
146 static BOOLEAN ParseSignature(SigCacheEntry *entry);
147 static BOOLEAN ASN1ParseSignature(
148  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit);
149 static BOOLEAN ASN1ParseCertificateIdentifier(
150  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit);
151 static BOOLEAN ASN1ParseKeyIdentifier(
152  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit);
153 static BOOLEAN ASN1ParseAuthorityCertIssuer(
154  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit);
155 static BOOLEAN ASN1ParseAuthorityCertSerialNumber(
156  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit);
157 static BOOLEAN ASN1ParseHashSignatureAlgorithm(
158  U8BIT *data, U32BIT *offset, U32BIT limit);
159 static BOOLEAN ASN1ParseSignatureValue(
160  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit);
161 static BOOLEAN ASN1ParseDigestAlgorithm(
162  U8BIT *data, U32BIT *offset, U32BIT limit);
163 static BOOLEAN ASN1ParseDigest(
164  U8BIT *data, U32BIT *offset, U32BIT limit, U8BIT *digest);
165 static void CalculateSha1(MHEG5String *data, U8BIT digest[]);
166 static BOOLEAN GetAsn1Tag(U8BIT *data, U32BIT *tag, U8BIT *class,
167  BOOLEAN *constructed, U32BIT *offset, U32BIT limit);
168 static BOOLEAN GetAsn1Length(U8BIT *data, U32BIT *length, U32BIT *offset,
169  U32BIT limit);
170 
171 /*---global function definitions---------------------------------------------*/
172 
183 {
184  U8BIT hashDigest[SHA_DIGEST_LENGTH];
185  SigCacheEntry *entry;
186  MHEG5SigVerifyStatus_t status;
187  BOOLEAN success;
188 
189  PRINT(("MHEG5IsValidSignature\n"));
190 
191  status = MHEG5_SIG_NOT_VERIFIED;
192  if (hash->len > 0 && signature->len > 0)
193  {
194  CalculateSha1(hash, hashDigest);
195  entry = FindCacheEntry(hashDigest, signature);
196  if (entry == NULL)
197  {
198  entry = CreateCacheEntry(hashDigest, signature);
199  if (entry != NULL)
200  {
201  success = ParseSignature(entry);
202  PRINT(("Parsing: %s\n", success ? "TRUE" : "FALSE"));
203  if (!success)
204  {
205  /* Remember this for later */
207  }
208  }
209  }
210 
211  if (entry != NULL)
212  {
213  ProcessSigCache();
214 
215  PRINT(("entry->state = %s\n", ENTRY_STATE_STRING(entry)));
216 
217  if (entry->state == ENTRY_STATE_VERIFIED)
218  {
219  /* Found matching certificates, validated signature */
220  status = MHEG5_SIG_VERIFIED;
221  }
222  else if (entry->state == ENTRY_STATE_NOT_VERIFIED)
223  {
224  /* Could not find matching, verifying certificate */
225  status = MHEG5_SIG_NOT_VERIFIED;
226  }
227  else
228  {
229  /* Still checking */
230  status = MHEG5_SIG_CHECK_PENDING;
231  }
232  }
233  }
234 
235  return status;
236 }
237 
243 {
244  ClearSigCache();
245  ClearCertCache();
246 
247  if (certRequested)
248  {
249  /* When the certificate is loaded (or fails to load), the cache will
250  * be cleared
251  */
252  certCacheInvalid = TRUE;
253  certRequested = FALSE;
254  TRACE(TFILE, (""))
255  }
256 }
257 
263 {
264  if (certRequested)
265  {
266  /* Flag the cache as invalid, so that when the certificate is loaded,
267  * the cache can be refreshed from the start.
268  */
269  certCacheInvalid = TRUE;
270  /* certRequested = FALSE; <- if do this, can have it hang (NDT003 scn7) */
271  TRACE(TFILE, (""))
272  }
273  else
274  {
275  /* Cache is "idle", so we can just clear it */
276  ClearCertCache();
277  }
278 
279  /* Awake existing requests */
280  PRINT(("Calling callback\n"));
281  sigVerifyCallback();
282 }
283 
290 void MHEG5SetSigVerifyCallback(void (*callback)(void))
291 {
292  sigVerifyCallback = callback;
293 }
294 
295 /*---local function definitions----------------------------------------------*/
296 
297 
302 static void ProcessSigCache(void)
303 {
304  SigCacheEntry *entry;
305  BOOLEAN call;
306  BOOLEAN finalBefore, finalAfter;
307  BOOLEAN reprocess;
308 
309  call = FALSE;
310  entry = sigCache;
311  while (entry != NULL)
312  {
313  finalBefore = IsInFinalState(entry);
314 
315  do
316  {
317  reprocess = ProcessSigCacheEntry(entry);
318  }
319  while (reprocess);
320 
321  finalAfter = IsInFinalState(entry);
322 
323  PRINT(("finalBefore = %d, finalAfter = %d\n", finalBefore, finalAfter));
324 
325  if (!finalBefore && finalAfter)
326  {
327  /* Need to notify the hash verification mechanism that there's new
328  * information.
329  */
330  call = TRUE;
331  }
332  entry = entry->next;
333  }
334 
335  if (call)
336  {
337  PRINT(("Calling callback\n"));
338  sigVerifyCallback();
339  }
340 }
341 
347 static BOOLEAN IsInFinalState(SigCacheEntry *entry)
348 {
349  BOOLEAN final;
350 
351  switch (entry->state)
352  {
355  final = TRUE;
356  break;
357  default:
358  final = FALSE;
359  }
360 
361  return final;
362 }
363 
370 static BOOLEAN ProcessSigCacheEntry(SigCacheEntry *entry)
371 {
372  BOOLEAN reprocess;
373 
374  PRINT(("State: %s\n", ENTRY_STATE_STRING(entry)));
375 
376  reprocess = FALSE;
377  switch (entry->state)
378  {
379  case ENTRY_STATE_START:
380  reprocess = HandleStartState(entry);
381  break;
383  reprocess = HandleHasCertState(entry);
384  break;
385  case ENTRY_STATE_NO_CERT:
386  /* Move entry to final state */
388  reprocess = TRUE;
389  break;
391  reprocess = HandleVerifiedState(entry);
392  break;
394  /* Nothing to do */
395  break;
396  default:
397  PRINT(("Unhandled case (state=%d)!\n", entry->state));
398  break;
399  }
400 
401  return reprocess;
402 }
403 
410 static BOOLEAN HandleStartState(SigCacheEntry *entry)
411 {
412  BOOLEAN verified;
413  CertFile *certFile;
414  CertLink *cert;
415 
416  certFile = certCache;
417  while (certFile != NULL)
418  {
419  if (certFile->valid)
420  {
421  cert = GetMatchingCert(entry, certFile);
422  if (cert != NULL)
423  {
424  verified = VerifyHashFileSignature(cert, entry);
425  if (verified)
426  {
427  entry->state = ENTRY_STATE_VERIFIED;
428  memcpy(entry->certDigest, certFile->certDigest,
429  SHA_DIGEST_LENGTH);
430  break;
431  }
432  }
433  }
434  certFile = certFile->next;
435  }
436 
437  if (certFile == NULL)
438  {
439  /* Could not find matching, verifying certificate in cache */
441  RefreshCertCache();
442  }
443 
444  return FALSE;
445 }
446 
453 static BOOLEAN HandleHasCertState(SigCacheEntry *entry)
454 {
455  CertFile *certFile;
456  CertLink *cert;
457  BOOLEAN verified;
458  BOOLEAN reprocess;
459 
460  assert(entry->state == ENTRY_STATE_HAS_CERT);
461 
462  certFile = GetLastCertFile();
463  assert(certFile != NULL);
464 
465  verified = FALSE;
466  cert = GetMatchingCert(entry, certFile);
467  if (cert != NULL)
468  {
469  verified = VerifyHashFileSignature(cert, entry);
470  }
471 
472  if (verified)
473  {
474  entry->state = ENTRY_STATE_VERIFIED;
475  memcpy(entry->certDigest, certFile->certDigest, SHA_DIGEST_LENGTH);
476  reprocess = TRUE;
477  }
478  else
479  {
481  reprocess = FALSE;
482  }
483 
484  return reprocess;
485 }
486 
494 static BOOLEAN HandleVerifiedState(SigCacheEntry *entry)
495 {
496  CertFile *certFile;
497 
498  certFile = certCache;
499  while (certFile != NULL)
500  {
501  if (memcmp(entry->certDigest, certFile->certDigest,
502  SHA_DIGEST_LENGTH) == 0)
503  {
504  break;
505  }
506  certFile = certFile->next;
507  }
508 
509  if (certFile == NULL || !certFile->valid || IsTimeToUpdate(certFile))
510  {
511  /* Certificate is not available or expired, need to refresh the cache */
513  RefreshCertCache();
514  }
515 
516  return FALSE;
517 }
518 
523 static MHEG5Bool IsTimeToUpdate(CertFile *certFile)
524 {
525  MHEG5Bool timeToUpdate;
526  U32BIT currentTime;
528 
529  timeToUpdate = FALSE;
530 
531  currentTime = STB_OSGetClockMilliseconds();
532  timestamp = certFile->timestamp;
533 
534  if ((currentTime > timestamp) &&
535  (currentTime - timestamp > SIG_CERT_TIMEOUT))
536  {
537  timeToUpdate = TRUE;
538  }
539  else if (currentTime < timestamp)
540  {
541  /* overflow - all bets are off */
542  timeToUpdate = TRUE;
543  }
544 
545  return timeToUpdate;
546 }
547 
554 static void RefreshCertCache(void)
555 {
556  PRINT(("RefreshCertCache\n"));
557 
558  if (!certRequested)
559  {
560  PRINT(("Start refresh process\n"));
561  TRACE(TFILE, (""))
562  certRequested = TRUE;
563  ClearCertCache();
564  RequestNextCertFile();
565  }
566 }
567 
573 static void RequestNextCertFile(void)
574 {
575  CertFile *certFile;
576  char name[MAX_SIG_CERT_NAME];
577  MHEG5String requestName;
578  MHEG5Int lastId, nextId;
579 
580  assert(certRequested);
581 
582  certFile = GetLastCertFile();
583  if (certFile != NULL)
584  {
585  lastId = certFile->id;
586  }
587  else
588  {
589  lastId = 0;
590  }
591  nextId = lastId + 1;
592 
593  sprintf(name, "DSM://auth.cert.%ld", nextId);
594  requestName.data = (U8BIT *)name;
595  requestName.len = strlen(name);
596  PRINT(("Requesting %s\n", name));
597  (void)MHEG5FileOrmGet( requestName, FRP_CERT | FRP_CACHE_DEFAULT, NULL,
598  SigCertRetrieved, SigCertRetrievalFailed );
599 }
600 
611 static void SigCertRetrieved( void *userData, S_CONTENT *content )
612 {
613  BOOLEAN success;
614 
615  USE_UNWANTED_PARAM(userData);
616 
617  PRINT(("SigCertRetrieved\n"));
618 
619  if (certCacheInvalid)
620  {
621  /* Cache is invalid - need to get rid of newly loaded certificate and
622  * start again
623  */
624  certCacheInvalid = FALSE;
625  ClearCertCache();
626  if (certRequested)
627  {
628  /* After the cache was invalidated it was also refreshed */
629  RequestNextCertFile();
630  }
631  else
632  {
633  TRACE(TERROR, (""))
634  }
635  }
636  else
637  {
638  success = AddCertFileToCache( content->data, content->size );
639  if (success)
640  {
641  UpdatePendingEntries(TRUE);
642  ProcessSigCache();
643  }
644  else
645  {
646  TRACE(TERROR, (""))
647  }
648 
649  /* Cache is being refreshed, get the next certificate */
650  assert(certRequested);
651  RequestNextCertFile();
652  }
653 }
654 
662 static void SigCertRetrievalFailed(void *userData )
663 {
664  USE_UNWANTED_PARAM(userData);
665 
666  PRINT(("SigCertRetrievalFailed\n"));
667 
668  if (certCacheInvalid)
669  {
670  /* Cache is invalid - need to get rid of newly loaded certificate and
671  * start again
672  */
673  certCacheInvalid = FALSE;
674  ClearCertCache();
675  if (certRequested)
676  {
677  /* After the cache was invalidated it was also refreshed */
678  RequestNextCertFile();
679  }
680  else
681  {
682  TRACE(TERROR, (""))
683  }
684  }
685  else
686  {
687  assert(certRequested);
688  certRequested = FALSE;
689 
690  UpdatePendingEntries(FALSE);
691  ProcessSigCache();
692  }
693 }
694 
702 static CertFile* ParseCertFile(U8BIT *data, U32BIT len)
703 {
704  U32BIT offset, size;
705  U16BIT count, i;
706  CertLink *list, **pLink;
707  CertFile *certFile;
708 
709  PRINT(("ParseCertFile\n"));
710 
711  list = NULL;
712  pLink = &list;
713 
714  count = 0;
715  offset = 2;
716 
717  if (len > 2)
718  {
719  count = data[0] << 8 | data[1];
720  }
721 
722  for (i = 0; i < count; ++i)
723  {
724  if (offset + 3 <= len)
725  {
726  size = (data[offset] << 16 | data[offset + 1] << 8 | data[offset + 2]);
727  offset += 3;
728  if (offset + size <= len)
729  {
730  *pLink = MHEG5getMem(sizeof **pLink);
731  if (*pLink != NULL)
732  {
733  (*pLink)->next = NULL;
734  (*pLink)->x509 = ParseX509Cert(data + offset, size);
735  if ((*pLink)->x509 != NULL)
736  {
737  pLink = &(*pLink)->next;
738  }
739  else
740  {
741  /* Cannot parse / create certificate, skip */
742  MHEG5freeMem(*pLink);
743  *pLink = NULL;
744  }
745  }
746  offset += size;
747  }
748  else
749  {
750  /* corrupt */
751  }
752  }
753  else
754  {
755  /* corrupt */
756  break;
757  }
758  }
759 
760  certFile = MHEG5getMem(sizeof *certFile);
761  if (certFile != NULL)
762  {
763  certFile->next = NULL;
764  certFile->id = 0;
765  certFile->timestamp = 0;
766  certFile->valid = FALSE;
767  certFile->certList = list;
768  }
769 
770  return certFile;
771 }
772 
779 static void* ParseX509Cert(U8BIT *data, U16BIT len)
780 {
781  BIO *bio;
782  X509 *x509;
783  void *cert;
784 
785  cert = NULL;
786  bio = BIO_new_mem_buf(data, len);
787  if (bio != NULL)
788  {
789  x509 = d2i_X509_bio(bio, NULL);
790  if (x509 != NULL)
791  {
792  cert = x509;
793  }
794  BIO_free(bio);
795  }
796 
797  return cert;
798 }
799 
804 static void ClearSigCache(void)
805 {
806  SigCacheEntry *entry, *next;
807 
808  entry = sigCache;
809  while (entry != NULL)
810  {
811  next = entry->next;
816  MHEG5freeMem(entry);
817  entry = next;
818  }
819  sigCache = NULL;
820 }
821 
826 static void ClearCertCache(void)
827 {
828  CertFile *certFile, *nextCertFile;
829  CertLink *cell, *nextCell;
830  SigCacheEntry *entry;
831 
832  certFile = certCache;
833  while (certFile != NULL)
834  {
835  nextCertFile = certFile->next;
836  cell = certFile->certList;
837  while (cell != NULL)
838  {
839  nextCell = cell->next;
840  X509_free(cell->x509);
841  MHEG5freeMem(cell);
842  cell = nextCell;
843  }
844  MHEG5freeMem(certFile);
845  certFile = nextCertFile;
846  }
847  certCache = NULL;
848 
849  /* When the cache is cleared, entries must be invalidated */
850  entry = sigCache;
851  while (entry != NULL)
852  {
853  if (entry->state != ENTRY_STATE_WAIT_FOR_CERT)
854  {
855  entry->state = ENTRY_STATE_START;
856  }
857  entry = entry->next;
858  }
859 }
860 
867 static BOOLEAN AddCertFileToCache(U8BIT *data, S32BIT size)
868 {
869  CertFile *certFile;
870  CertFile **pCertFile;
871  U32BIT lastId;
872  MHEG5String cert;
873  BOOLEAN success;
874 
875  success = FALSE;
876 
877  certFile = ParseCertFile(data, size);
878  if (certFile != NULL)
879  {
880  lastId = 0;
881  pCertFile = &certCache;
882  while (*pCertFile != NULL)
883  {
884  lastId = (*pCertFile)->id;
885  pCertFile = &(*pCertFile)->next;
886  }
887  *pCertFile = certFile;
888  (*pCertFile)->id = lastId + 1;
889 
890  /* Update timestamp */
891  (*pCertFile)->timestamp = STB_OSGetClockMilliseconds();
892 
893  /* Retrieved certificates are initially valid */
894  (*pCertFile)->valid = TRUE;
895 
896  /* Update digest */
897  cert.data = data;
898  cert.len = size;
899  CalculateSha1(&cert, (*pCertFile)->certDigest);
900 
901  success = TRUE;
902  }
903 
904  return success;
905 }
906 
913 static void UpdatePendingEntries(BOOLEAN retrieved)
914 {
915  SigCacheEntry *entry;
916  SigEntryState nextState;
917 
918  if (retrieved)
919  {
920  nextState = ENTRY_STATE_HAS_CERT;
921  }
922  else
923  {
924  nextState = ENTRY_STATE_NO_CERT;
925  }
926 
927  entry = sigCache;
928  while (entry != NULL)
929  {
930  if (entry->state == ENTRY_STATE_WAIT_FOR_CERT)
931  {
932  entry->state = nextState;
933  }
934  entry = entry->next;
935  }
936 }
937 
943 static CertFile* GetLastCertFile(void)
944 {
945  CertFile *certFile;
946 
947  certFile = certCache;
948  while (certFile != NULL && certFile->next != NULL)
949  {
950  certFile = certFile->next;
951  }
952 
953  return certFile;
954 }
955 
962 static CertLink* GetMatchingCert(SigCacheEntry *entry, CertFile *certFile)
963 {
964  CertLink *cert;
965  BOOLEAN nameEqual;
966  BOOLEAN numberEqual;
967 
968  cert = certFile->certList;
969  while (cert != NULL)
970  {
971  nameEqual = IsIssuerNameEqual(entry, cert);
972  numberEqual = IsSerialNumberEqual(entry, cert);
973  if (nameEqual && numberEqual)
974  {
975  break;
976  }
977  cert = cert->next;
978  }
979 
980  return cert;
981 }
982 
990 static BOOLEAN IsIssuerNameEqual(SigCacheEntry *entry, CertLink *cert)
991 {
992  MHEG5String *issuerName;
993  X509_NAME *x509_name;
994  U8BIT *name;
995  S32BIT nameLen;
996  BOOLEAN equal;
997 
998  equal = FALSE;
999 
1000  x509_name = X509_get_issuer_name(cert->x509);
1001  if (x509_name != NULL)
1002  {
1003  name = NULL;
1004  nameLen = i2d_X509_NAME(x509_name, &name);
1005  if (name != NULL)
1006  {
1007  issuerName = &entry->directoryName;
1008  if ((issuerName->len == nameLen) &&
1009  (memcmp(issuerName->data, name, nameLen) == 0))
1010  {
1011  equal = TRUE;
1012  }
1013  OPENSSL_free(name);
1014  }
1015  }
1016 
1017  return equal;
1018 }
1019 
1027 static BOOLEAN IsSerialNumberEqual(SigCacheEntry *entry, CertLink *cert)
1028 {
1029  MHEG5String *serialNumber;
1030  ASN1_INTEGER *x509_number;
1031  U8BIT *number;
1032  U32BIT numberLen;
1033  U32BIT offset;
1034  U32BIT limit;
1035  U32BIT tag;
1036  U32BIT asn1_length;
1037  U8BIT class;
1038  BOOLEAN constructed;
1039  BOOLEAN success;
1040  BOOLEAN equal;
1041 
1042  equal = FALSE;
1043 
1044  x509_number = X509_get_serialNumber(cert->x509);
1045  if (x509_number != NULL)
1046  {
1047  number = NULL;
1048  numberLen = i2d_ASN1_INTEGER(x509_number, &number);
1049  if (number != NULL)
1050  {
1051  /* Parse DER-encoded number */
1052  limit = numberLen;
1053  offset = 0;
1054  success = GetAsn1Tag(number, &tag, &class, &constructed, &offset,
1055  limit);
1056  if (success && (tag != 0x02 || class != 0x00 || constructed))
1057  {
1058  success = FALSE;
1059  }
1060  if (success)
1061  {
1062  /* INTEGER */
1063  success = GetAsn1Length(number, &asn1_length, &offset, limit);
1064  if (success && (offset + asn1_length != limit))
1065  {
1066  success = FALSE;
1067  }
1068  }
1069  if (success)
1070  {
1071  serialNumber = &entry->authorityCertSerialNumber;
1072  if (((U32BIT)serialNumber->len == asn1_length) &&
1073  (memcmp(serialNumber->data, number + offset, asn1_length) == 0))
1074  {
1075  equal = TRUE;
1076  }
1077  }
1078  OPENSSL_free(number);
1079  }
1080  }
1081 
1082  return equal;
1083 }
1084 
1093 static BOOLEAN VerifyHashFileSignature(CertLink *cert, SigCacheEntry *entry)
1094 {
1095  X509 *x509;
1096  EVP_PKEY *pkey;
1097  RSA *rsa;
1098  int size;
1099  U8BIT digestInfo[MAX_SIG_SIZE];
1100  int digestInfoLen;
1101  BOOLEAN verified;
1102 
1103  verified = FALSE;
1104 
1105  x509 = cert->x509;
1106  pkey = X509_get_pubkey(x509);
1107  if (pkey != NULL)
1108  {
1109  rsa = EVP_PKEY_get1_RSA(pkey);
1110  if (rsa != NULL)
1111  {
1112  size = RSA_size(rsa);
1113  if ((size <= MAX_SIG_SIZE) && (size == entry->signatureValue.len))
1114  {
1115  digestInfoLen = RSA_public_decrypt(entry->signatureValue.len,
1116  entry->signatureValue.data,
1117  digestInfo, rsa,
1118  RSA_PKCS1_PADDING);
1119  if (digestInfoLen >= 0)
1120  {
1121  verified = VerifyDigest(entry, digestInfo, digestInfoLen);
1122  }
1123  }
1124  RSA_free(rsa);
1125  }
1126  EVP_PKEY_free(pkey);
1127  }
1128 
1129  return verified;
1130 }
1131 
1140 static BOOLEAN VerifyDigest(SigCacheEntry *entry, U8BIT *digestInfo,
1141  S32BIT digestInfoLen)
1142 {
1143  U32BIT tag;
1144  U32BIT asn1_length;
1145  U8BIT class;
1146  BOOLEAN constructed;
1147  BOOLEAN success;
1148 
1149  U8BIT *data = digestInfo;
1150  U32BIT offset = 0;
1151  U32BIT limit = digestInfoLen;
1152 
1153  U8BIT digest[SHA_DIGEST_LENGTH];
1154  BOOLEAN verified;
1155 
1156  verified = FALSE;
1157 
1158  success = GetAsn1Tag(data, &tag, &class, &constructed, &offset, limit);
1159  if (success && (tag != 0x10 || class != 0x00 || !constructed))
1160  {
1161  success = FALSE;
1162  }
1163  if (success)
1164  {
1165  /* SEQUENCE */
1166  success = GetAsn1Length(data, &asn1_length, &offset, limit);
1167  if (success && (offset + asn1_length != limit))
1168  {
1169  success = FALSE;
1170  }
1171  }
1172 
1173  if (success)
1174  {
1175  success = ASN1ParseDigestAlgorithm(data, &offset, limit);
1176  }
1177  if (success)
1178  {
1179  success = ASN1ParseDigest(data, &offset, limit, digest);
1180  }
1181  if (success)
1182  {
1183  if (memcmp(entry->hashDigest, digest, SHA_DIGEST_LENGTH) == 0)
1184  {
1185  verified = TRUE;
1186  }
1187  }
1188 
1189  return verified;
1190 }
1191 
1199 static SigCacheEntry* FindCacheEntry(U8BIT *hashDigest,
1201 {
1202  SigCacheEntry *entry;
1203 
1204  entry = sigCache;
1205  while (entry != NULL)
1206  {
1207  if ((memcmp(hashDigest, entry->hashDigest, SHA_DIGEST_LENGTH) == 0) &&
1208  (MHEG5stringEqual(&entry->signature, signature)))
1209  {
1210  break;
1211  }
1212  entry = entry->next;
1213  }
1214 
1215  return entry;
1216 }
1217 
1225 static SigCacheEntry* CreateCacheEntry(U8BIT *hashDigest,
1226  MHEG5String *signature)
1227 {
1228  SigCacheEntry *entry;
1229  SigCacheEntry **pEntry;
1230 
1231  entry = MHEG5getMem(sizeof *entry);
1232  if (entry != NULL)
1233  {
1234  entry->next = NULL;
1235  entry->signatureValue.len = 0;
1236  entry->signatureValue.data = NULL;
1237  entry->authorityCertSerialNumber.len = 0;
1238  entry->authorityCertSerialNumber.data = NULL;
1239  entry->directoryName.len = 0;
1240  entry->directoryName.data = 0;
1241  entry->lastCertChecked = 0;
1242  entry->state = ENTRY_STATE_START;
1243  memcpy(entry->hashDigest, hashDigest, SHA_DIGEST_LENGTH);
1244  memset(entry->certDigest, 0, SHA_DIGEST_LENGTH);
1245  entry->signature = MHEG5stringCopy(*signature);
1246  if (entry->signature.len > 0)
1247  {
1248  /* Add to signature cache */
1249  pEntry = &sigCache;
1250  while (*pEntry != NULL)
1251  {
1252  pEntry = &(*pEntry)->next;
1253  }
1254  *pEntry = entry;
1255  }
1256  else
1257  {
1258  MHEG5freeMem(entry);
1259  entry = NULL;
1260  }
1261  }
1262 
1263  return entry;
1264 }
1265 
1271 static BOOLEAN ParseSignature(SigCacheEntry *entry)
1272 {
1273  U8BIT *data;
1274  U32BIT offset;
1275  U32BIT limit;
1276  BOOLEAN success;
1277 
1278  offset = 0;
1279  data = entry->signature.data;
1280  limit = entry->signature.len;
1281 
1282  success = ASN1ParseSignature(entry, data, &offset, limit);
1283 
1284  return success;
1285 }
1286 
1295 static BOOLEAN ASN1ParseSignature(
1296  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit)
1297 {
1298  U32BIT tag;
1299  U32BIT asn1_length;
1300  U8BIT class;
1301  BOOLEAN constructed;
1302  BOOLEAN success;
1303 
1304  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1305  if (success && (tag != 0x10 || class != 0x00 || !constructed))
1306  {
1307  success = FALSE;
1308  }
1309  if (success)
1310  {
1311  /* SEQUENCE */
1312  success = GetAsn1Length(data, &asn1_length, offset, limit);
1313  if (success && (*offset + asn1_length != limit))
1314  {
1315  success = FALSE;
1316  }
1317  }
1318 
1319  if (success)
1320  {
1321  success = ASN1ParseCertificateIdentifier(entry, data, offset, limit);
1322  }
1323  if (success)
1324  {
1325  success = ASN1ParseHashSignatureAlgorithm(data, offset, limit);
1326  }
1327  if (success)
1328  {
1329  success = ASN1ParseSignatureValue(entry, data, offset, limit);
1330  }
1331 
1332  return success;
1333 }
1334 
1343 static BOOLEAN ASN1ParseCertificateIdentifier(
1344  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit)
1345 {
1346  U32BIT tag;
1347  U32BIT asn1_length;
1348  U8BIT class;
1349  BOOLEAN constructed;
1350  BOOLEAN success;
1351 
1352  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1353  if (success && (tag != 0x10 || class != 0x00 || !constructed))
1354  {
1355  success = FALSE;
1356  }
1357  if (success)
1358  {
1359  /* SEQUENCE */
1360  success = GetAsn1Length(data, &asn1_length, offset, limit);
1361  if (success && (*offset + asn1_length > limit))
1362  {
1363  success = FALSE;
1364  }
1365  }
1366  if (success)
1367  {
1368  success = ASN1ParseKeyIdentifier(entry, data, offset, limit);
1369  }
1370  if (success)
1371  {
1372  success = ASN1ParseAuthorityCertIssuer(entry, data, offset, limit);
1373  }
1374  if (success)
1375  {
1376  success = ASN1ParseAuthorityCertSerialNumber(entry, data, offset, limit);
1377  }
1378 
1379  return success;
1380 }
1381 
1390 static BOOLEAN ASN1ParseKeyIdentifier(
1391  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit)
1392 {
1393  U32BIT tag;
1394  U32BIT asn1_length;
1395  U8BIT class;
1396  BOOLEAN constructed;
1397  BOOLEAN success;
1398  U32BIT origOffset;
1399 
1400  origOffset = *offset;
1401  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1402  if (success && (class != 0x02))
1403  {
1404  success = FALSE;
1405  }
1406  if (success && (tag == 0x00 && constructed))
1407  {
1408  /* keyIdentifier - skip */
1409  success = GetAsn1Length(data, &asn1_length, offset, limit);
1410  if (success && (*offset + asn1_length > limit))
1411  {
1412  success = FALSE;
1413  }
1414  if (success)
1415  {
1416  *offset += asn1_length;
1417  }
1418  }
1419  else
1420  {
1421  *offset = origOffset;
1422  }
1423 
1424  return success;
1425 }
1426 
1435 static BOOLEAN ASN1ParseAuthorityCertIssuer(
1436  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit)
1437 {
1438  U32BIT tag;
1439  U32BIT asn1_length;
1440  U8BIT class;
1441  BOOLEAN constructed;
1442  BOOLEAN success;
1443 
1444  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1445  if (success && (tag != 0x01 || class != 0x02 || !constructed))
1446  {
1447  success = FALSE;
1448  }
1449  if (success)
1450  {
1451  /* authorityCertIssuer */
1452  success = GetAsn1Length(data, &asn1_length, offset, limit);
1453  if (success && (*offset + asn1_length > limit))
1454  {
1455  success = FALSE;
1456  }
1457  }
1458  if (success)
1459  {
1460  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1461  }
1462  while (success && (tag != 0x04 || class != 0x02 || !constructed))
1463  {
1464  success = GetAsn1Length(data, &asn1_length, offset, limit);
1465  if (success && (*offset + asn1_length > limit))
1466  {
1467  success = FALSE;
1468  }
1469  if (success)
1470  {
1471  /* Skip */
1472  *offset += asn1_length;
1473  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1474  }
1475  }
1476  if (success && (tag == 0x04 && class == 0x02 && constructed))
1477  {
1478  success = GetAsn1Length(data, &asn1_length, offset, limit);
1479  if (success && (*offset + asn1_length > limit))
1480  {
1481  success = FALSE;
1482  }
1483  }
1484  if (success)
1485  {
1486  /* directoryName */
1487  {
1488  U32BIT i;
1489  PRINT(("directoryName: "));
1490  for (i = 0; i != asn1_length - 1; ++i)
1491  {
1492  PRINT(("%02x:", data[*offset + i]));
1493  }
1494  PRINT(("%02x\n", data[*offset + asn1_length - 1]));
1495  }
1496 
1497  entry->directoryName.data = STR_DataAlloc(asn1_length);
1498  if (entry->directoryName.data != NULL)
1499  {
1500  memcpy(entry->directoryName.data, data + *offset, asn1_length);
1501  entry->directoryName.len = asn1_length;
1502  *offset += asn1_length;
1503  }
1504  else
1505  {
1506  success = FALSE;
1507  }
1508  }
1509 
1510  return success;
1511 }
1512 
1521 static BOOLEAN ASN1ParseAuthorityCertSerialNumber(
1522  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit)
1523 {
1524  U32BIT tag;
1525  U32BIT asn1_length;
1526  U8BIT class;
1527  BOOLEAN constructed;
1528  BOOLEAN success;
1529 
1530  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1531  if (success && (tag != 0x02 || class != 0x02 || constructed))
1532  {
1533  success = FALSE;
1534  }
1535  if (success)
1536  {
1537  /* authorityCertSerialNumber */
1538  success = GetAsn1Length(data, &asn1_length, offset, limit);
1539  if (success && (*offset + asn1_length > limit))
1540  {
1541  success = FALSE;
1542  }
1543  }
1544  if (success)
1545  {
1546  /* Copy serial number into entry */
1547  {
1548  U32BIT i;
1549  PRINT(("authorityCertSerialNumber: "));
1550  for (i = 0; i != asn1_length - 1; ++i)
1551  {
1552  PRINT(("%02x:", data[*offset + i]));
1553  }
1554  PRINT(("%02x\n", data[*offset + asn1_length - 1]));
1555  }
1556 
1557  entry->authorityCertSerialNumber.data = STR_DataAlloc(asn1_length);
1558  if (entry->authorityCertSerialNumber.data != NULL)
1559  {
1560  memcpy(entry->authorityCertSerialNumber.data,
1561  data + *offset, asn1_length);
1562  entry->authorityCertSerialNumber.len = asn1_length;
1563  *offset += asn1_length;
1564  }
1565  else
1566  {
1567  success = FALSE;
1568  }
1569  }
1570 
1571  return success;
1572 }
1573 
1582 static BOOLEAN ASN1ParseHashSignatureAlgorithm(
1583  U8BIT *data, U32BIT *offset, U32BIT limit)
1584 {
1585  U32BIT tag;
1586  U32BIT asn1_length;
1587  U8BIT class;
1588  BOOLEAN constructed;
1589  BOOLEAN success;
1590 
1591  /* sha-1 OBJECT IDENTIFIER ::=
1592  * { iso(1) identified-organization(3) oiw(14) secsig(3) algorithm(2) 26 }
1593  */
1594  static U8BIT sha1objectIdentifer[] = { 43, 14, 3, 2, 26 };
1595 
1596  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1597  if (success && (tag != 0x06 || class != 0x00 || constructed))
1598  {
1599  success = FALSE;
1600  }
1601  if (success)
1602  {
1603  /* OBJECT IDENTIFIER */
1604  success = GetAsn1Length(data, &asn1_length, offset, limit);
1605  if (success && (asn1_length != sizeof(sha1objectIdentifer)))
1606  {
1607  success = FALSE;
1608  }
1609  }
1610  if (success)
1611  {
1612  if (memcmp(data + *offset, sha1objectIdentifer, asn1_length) != 0)
1613  {
1614  success = FALSE;
1615  }
1616  if (success)
1617  {
1618  *offset += asn1_length;
1619  }
1620  }
1621 
1622  return success;
1623 }
1624 
1633 static BOOLEAN ASN1ParseSignatureValue(
1634  SigCacheEntry *entry, U8BIT *data, U32BIT *offset, U32BIT limit)
1635 {
1636  U32BIT tag;
1637  U32BIT asn1_length;
1638  U8BIT class;
1639  BOOLEAN constructed;
1640  BOOLEAN success;
1641 
1642  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1643  if (success && (tag != 0x03 || class != 0x00 || constructed))
1644  {
1645  success = FALSE;
1646  }
1647  if (success)
1648  {
1649  /* BIT STRING (last item in the sequence) */
1650  success = GetAsn1Length(data, &asn1_length, offset, limit);
1651  if (success && (*offset + asn1_length != limit))
1652  {
1653  success = FALSE;
1654  }
1655  }
1656  if (success && (asn1_length < 2 || data[*offset] != 0))
1657  {
1658  /* Make sure the signature value is in whole bytes */
1659  success = FALSE;
1660  }
1661  if (success)
1662  {
1663  /* Copy signature value into entry */
1664  entry->signatureValue.data = STR_DataAlloc(asn1_length - 1);
1665  if (entry->signatureValue.data != NULL)
1666  {
1667  memcpy(entry->signatureValue.data, data + *offset + 1,
1668  asn1_length - 1);
1669  entry->signatureValue.len = asn1_length - 1;
1670  *offset += asn1_length;
1671  }
1672  else
1673  {
1674  success = FALSE;
1675  }
1676  }
1677 
1678  return success;
1679 }
1680 
1689 static BOOLEAN ASN1ParseDigestAlgorithm(
1690  U8BIT *data, U32BIT *offset, U32BIT limit)
1691 {
1692  U32BIT tag;
1693  U32BIT asn1_length;
1694  U8BIT class;
1695  BOOLEAN constructed;
1696  BOOLEAN success;
1697  U32BIT origOffset;
1698 
1699  /* sha-1 OBJECT IDENTIFIER ::=
1700  * { iso(1) identified-organization(3) oiw(14) secsig(3) algorithm(2) 26 }
1701  */
1702  static U8BIT sha1objectIdentifer[] = { 43, 14, 3, 2, 26 };
1703 
1704  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1705  if (success && (tag != 0x10 || class != 0x00 || !constructed))
1706  {
1707  success = FALSE;
1708  }
1709  if (success)
1710  {
1711  /* SEQUENCE */
1712  success = GetAsn1Length(data, &asn1_length, offset, limit);
1713  if (success && (*offset + asn1_length > limit))
1714  {
1715  success = FALSE;
1716  }
1717  }
1718  if (success)
1719  {
1720  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1721  if (success && (tag != 0x06 || class != 0x00 || constructed))
1722  {
1723  success = FALSE;
1724  }
1725  }
1726  if (success)
1727  {
1728  /* OBJECT IDENTIFIER */
1729  success = GetAsn1Length(data, &asn1_length, offset, limit);
1730  if (success && (asn1_length != sizeof(sha1objectIdentifer)))
1731  {
1732  success = FALSE;
1733  }
1734  }
1735  if (success)
1736  {
1737  if (memcmp(data + *offset, sha1objectIdentifer, asn1_length) != 0)
1738  {
1739  success = FALSE;
1740  }
1741  if (success)
1742  {
1743  *offset += asn1_length;
1744  }
1745  }
1746  if (success)
1747  {
1748  origOffset = *offset;
1749  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1750  if (success && (tag == 0x05 && class == 0x00 && !constructed))
1751  {
1752  /* Optional NULL (parameters for digest algorithm) */
1753  success = GetAsn1Length(data, &asn1_length, offset, limit);
1754  if (success && (asn1_length != 0))
1755  {
1756  success = FALSE;
1757  }
1758  }
1759  else
1760  {
1761  /* Parameters are optional, but parsing has been successful so far */
1762  success = TRUE;
1763  *offset = origOffset;
1764  }
1765  }
1766 
1767  return success;
1768 }
1769 
1778 static BOOLEAN ASN1ParseDigest(
1779  U8BIT *data, U32BIT *offset, U32BIT limit, U8BIT *digest)
1780 {
1781  U32BIT tag;
1782  U32BIT asn1_length;
1783  U8BIT class;
1784  BOOLEAN constructed;
1785  BOOLEAN success;
1786 
1787  success = GetAsn1Tag(data, &tag, &class, &constructed, offset, limit);
1788  if (success && (tag != 0x04 || class != 0x00 || constructed))
1789  {
1790  success = FALSE;
1791  }
1792  if (success)
1793  {
1794  /* OCTET STRING (last item in the sequence) */
1795  success = GetAsn1Length(data, &asn1_length, offset, limit);
1796  if (success && ((asn1_length != SHA_DIGEST_LENGTH) ||
1797  (*offset + asn1_length != limit)))
1798  {
1799  success = FALSE;
1800  }
1801  }
1802  if (success)
1803  {
1804  /* Copy digest value */
1805  memcpy(digest, data + *offset, SHA_DIGEST_LENGTH);
1806  *offset += asn1_length;
1807  }
1808 
1809  return success;
1810 }
1811 
1818 static void CalculateSha1(MHEG5String *data, U8BIT digest[])
1819 {
1820  EVP_MD_CTX ctx;
1821 
1822  EVP_DigestInit(&ctx, EVP_sha1());
1823  EVP_DigestUpdate(&ctx, data->data, data->len);
1824  EVP_DigestFinal(&ctx, digest, NULL);
1825 }
1826 
1837 static BOOLEAN GetAsn1Tag(U8BIT *data, U32BIT *tag, U8BIT *class,
1838  BOOLEAN *constructed, U32BIT *offset, U32BIT limit)
1839 {
1840  U32BIT i;
1841  BOOLEAN success;
1842 
1843  success = FALSE;
1844 
1845  i = *offset;
1846  if (i < limit)
1847  {
1848  *class = (data[i] & 0xc0) >> 6;
1849  if ((data[i] & 0x20) >> 5)
1850  {
1851  *constructed = TRUE;
1852  }
1853  else
1854  {
1855  *constructed = FALSE;
1856  }
1857  *tag = data[i] & 0x1f;
1858  if (*tag == 0x1f)
1859  {
1860  *tag = 0;
1861  while (i + 1 < limit)
1862  {
1863  *tag <<= 7;
1864  *tag |= data[i] & 0x7f;
1865  if ((data[i] & 0x80) == 0)
1866  {
1867  success = TRUE;
1868  break;
1869  }
1870  ++i;
1871  }
1872  }
1873  else
1874  {
1875  success = TRUE;
1876  }
1877  ++i;
1878  }
1879 
1880  if (success)
1881  {
1882  *offset = i;
1883  }
1884 
1885  return success;
1886 }
1887 
1896 static BOOLEAN GetAsn1Length(U8BIT *data, U32BIT *length, U32BIT *offset,
1897  U32BIT limit)
1898 {
1899  U32BIT i;
1900  U8BIT lenlen;
1901  BOOLEAN success;
1902 
1903  success = FALSE;
1904 
1905  i = *offset;
1906  if (i < limit)
1907  {
1908  *length = data[i];
1909  if (*length & 0x80)
1910  {
1911  lenlen = data[i] & 0x7f;
1912  ++i;
1913  *length = 0;
1914  while (lenlen > 0 && i < limit)
1915  {
1916  *length <<= 8;
1917  *length |= data[i];
1918  --lenlen;
1919  ++i;
1920  }
1921  if (lenlen == 0)
1922  {
1923  success = TRUE;
1924  }
1925  }
1926  else
1927  {
1928  ++i;
1929  success = TRUE;
1930  }
1931  }
1932 
1933  if (success)
1934  {
1935  *offset = i;
1936  }
1937 
1938  return success;
1939 }
1940 
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
#define PRINT(x)
Definition: mh5sig.c:64
U8BIT hashDigest[SHA_DIGEST_LENGTH]
Definition: mh5sig.c:82
U8BIT certDigest[SHA_DIGEST_LENGTH]
Definition: mh5sig.c:104
Functions relating to HTTPS Signature Certificates.
U32BIT size
Definition: fs_types.h:54
MHEG5Bool MHEG5stringEqual(MHEG5String *s1, MHEG5String *s2)
Compare two Strings (case sensitive!)
Definition: mh5base.c:710
const char * data
Definition: mh5gate.c:56
#define MAX_SIG_SIZE
Definition: mh5sig.c:48
MHEG5String authorityCertSerialNumber
Definition: mh5sig.c:86
unsigned char * STR_DataAlloc(unsigned int size)
Definition: glue_memory.c:596
#define MHEG5getMem
Definition: glue_memory.h:93
CertLink * certList
Definition: mh5sig.c:105
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
SigEntryState state
Definition: mh5sig.c:89
MHEG5String MHEG5stringCopy(MHEG5String source)
<Function description>="">
Definition: mh5base.c:574
#define FRP_CACHE_DEFAULT
Definition: mh5fileorm.h:38
U32BIT lastCertChecked
Definition: mh5sig.c:88
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
void MHEG5SetSigVerifyCallback(void(*callback)(void))
Sets the callback to be called when pending requests are resolved.
Definition: mh5sig.c:290
struct sSigCacheEntry * next
Definition: mh5sig.c:81
uint8_t U8BIT
Definition: techtype.h:82
long MHEG5Int
Definition: mh5base.h:73
U32BIT id
Definition: mh5sig.c:101
SigEntryState
Definition: mh5sig.c:69
#define SIG_CERT_TIMEOUT
Definition: mh5sig.c:45
struct sCertFile * next
Definition: mh5sig.c:100
#define MHEG5freeMem
Definition: glue_memory.h:94
This file defines the profile for the MHEG engine.
short MHEG5Bool
Definition: mh5base.h:71
MHEG5Byte * data
Definition: mh5base.h:85
struct sCertLink CertLink
int len
Definition: mh5gate.c:57
struct sCertFile CertFile
int32_t S32BIT
Definition: techtype.h:87
U8BIT certDigest[SHA_DIGEST_LENGTH]
Definition: mh5sig.c:83
void MHEG5InvalidateSigCertCache(void)
Invalidate the certificates in the certificate cache.
Definition: mh5sig.c:262
uint16_t U16BIT
Definition: techtype.h:84
Mheg5 logging and debug printing.
File interface functions to DSMCC component.
redirection include
MHEG5SigVerifyStatus_t MHEG5IsValidSignature(MHEG5String *hash, MHEG5String *signature)
Check whether the signature is valid.
Definition: mh5sig.c:181
BOOLEAN valid
Definition: mh5sig.c:103
#define FALSE
Definition: techtype.h:68
MHEG5SigVerifyStatus_t
Definition: mh5sig.h:37
MHEG5Int len
Definition: mh5base.h:84
void MHEG5ClearSigCertCache(void)
Clear the signature certificate cache and all related information.
Definition: mh5sig.c:242
U8BIT * data
Definition: fs_types.h:55
U8BIT BOOLEAN
Definition: techtype.h:99
#define USE_UNWANTED_PARAM(param)
Definition: techtype.h:48
#define TRUE
Definition: techtype.h:69
Definition: mh5sig.c:79
U32BIT timestamp
Definition: mh5sig.c:102
MHEG5String directoryName
Definition: mh5sig.c:87
#define ENTRY_STATE_STRING(e)
Definition: mh5sig.c:50
struct sSigCacheEntry SigCacheEntry
MHEG5String signatureValue
Definition: mh5sig.c:85
uint32_t U32BIT
Definition: techtype.h:86
#define FRP_CERT
Definition: mh5fileorm.h:46
#define MAX_SIG_CERT_NAME
Definition: mh5sig.c:47
#define TRACE(t, x)
Definition: glue_debug.h:118
Header file - Function prototypes for operating system.
MHEG5String signature
Definition: mh5sig.c:84