30 #include <openssl/sha.h> 31 #include <openssl/rsa.h> 32 #include <openssl/evp.h> 33 #include <openssl/x509.h> 45 #define SIG_CERT_TIMEOUT (3 * 60 * 60 * 1000) 47 #define MAX_SIG_CERT_NAME (22) 48 #define MAX_SIG_SIZE (256) 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" : \ 59 #define SIG_DEBUG_PRINT 60 #undef SIG_DEBUG_PRINT 61 #ifdef SIG_DEBUG_PRINT 62 #define PRINT(x) DBG_PRINTF x 110 static void (*sigVerifyCallback)(void) = NULL;
118 static void ProcessSigCache(
void);
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 );
131 static void ClearSigCache(
void);
132 static void ClearCertCache(
void);
134 static void UpdatePendingEntries(
BOOLEAN retrieved);
135 static CertFile* GetLastCertFile(
void);
147 static BOOLEAN ASN1ParseSignature(
149 static BOOLEAN ASN1ParseCertificateIdentifier(
151 static BOOLEAN ASN1ParseKeyIdentifier(
153 static BOOLEAN ASN1ParseAuthorityCertIssuer(
155 static BOOLEAN ASN1ParseAuthorityCertSerialNumber(
157 static BOOLEAN ASN1ParseHashSignatureAlgorithm(
159 static BOOLEAN ASN1ParseSignatureValue(
161 static BOOLEAN ASN1ParseDigestAlgorithm(
163 static BOOLEAN ASN1ParseDigest(
189 PRINT((
"MHEG5IsValidSignature\n"));
192 if (hash->
len > 0 && signature->
len > 0)
194 CalculateSha1(hash, hashDigest);
195 entry = FindCacheEntry(hashDigest, signature);
198 entry = CreateCacheEntry(hashDigest, signature);
201 success = ParseSignature(entry);
202 PRINT((
"Parsing: %s\n", success ?
"TRUE" :
"FALSE"));
252 certCacheInvalid =
TRUE;
253 certRequested =
FALSE;
269 certCacheInvalid =
TRUE;
280 PRINT((
"Calling callback\n"));
292 sigVerifyCallback = callback;
302 static void ProcessSigCache(
void)
306 BOOLEAN finalBefore, finalAfter;
311 while (entry != NULL)
313 finalBefore = IsInFinalState(entry);
317 reprocess = ProcessSigCacheEntry(entry);
321 finalAfter = IsInFinalState(entry);
323 PRINT((
"finalBefore = %d, finalAfter = %d\n", finalBefore, finalAfter));
325 if (!finalBefore && finalAfter)
337 PRINT((
"Calling callback\n"));
351 switch (entry->
state)
377 switch (entry->
state)
380 reprocess = HandleStartState(entry);
383 reprocess = HandleHasCertState(entry);
391 reprocess = HandleVerifiedState(entry);
397 PRINT((
"Unhandled case (state=%d)!\n", entry->
state));
416 certFile = certCache;
417 while (certFile != NULL)
421 cert = GetMatchingCert(entry, certFile);
424 verified = VerifyHashFileSignature(cert, entry);
434 certFile = certFile->
next;
437 if (certFile == NULL)
462 certFile = GetLastCertFile();
463 assert(certFile != NULL);
466 cert = GetMatchingCert(entry, certFile);
469 verified = VerifyHashFileSignature(cert, entry);
498 certFile = certCache;
499 while (certFile != NULL)
502 SHA_DIGEST_LENGTH) == 0)
506 certFile = certFile->
next;
509 if (certFile == NULL || !certFile->
valid || IsTimeToUpdate(certFile))
529 timeToUpdate =
FALSE;
534 if ((currentTime > timestamp) &&
539 else if (currentTime < timestamp)
554 static void RefreshCertCache(
void)
556 PRINT((
"RefreshCertCache\n"));
560 PRINT((
"Start refresh process\n"));
562 certRequested =
TRUE;
564 RequestNextCertFile();
573 static void RequestNextCertFile(
void)
580 assert(certRequested);
582 certFile = GetLastCertFile();
583 if (certFile != NULL)
585 lastId = certFile->
id;
593 sprintf(name,
"DSM://auth.cert.%ld", nextId);
595 requestName.
len = strlen(name);
596 PRINT((
"Requesting %s\n", name));
598 SigCertRetrieved, SigCertRetrievalFailed );
611 static void SigCertRetrieved(
void *userData,
S_CONTENT *content )
617 PRINT((
"SigCertRetrieved\n"));
619 if (certCacheInvalid)
624 certCacheInvalid =
FALSE;
629 RequestNextCertFile();
638 success = AddCertFileToCache( content->
data, content->
size );
641 UpdatePendingEntries(
TRUE);
650 assert(certRequested);
651 RequestNextCertFile();
662 static void SigCertRetrievalFailed(
void *userData )
666 PRINT((
"SigCertRetrievalFailed\n"));
668 if (certCacheInvalid)
673 certCacheInvalid =
FALSE;
678 RequestNextCertFile();
687 assert(certRequested);
688 certRequested =
FALSE;
690 UpdatePendingEntries(
FALSE);
709 PRINT((
"ParseCertFile\n"));
719 count = data[0] << 8 | data[1];
722 for (i = 0; i < count; ++i)
724 if (offset + 3 <= len)
726 size = (data[offset] << 16 | data[offset + 1] << 8 | data[offset + 2]);
728 if (offset + size <= len)
733 (*pLink)->next = NULL;
734 (*pLink)->x509 = ParseX509Cert(data + offset, size);
735 if ((*pLink)->x509 != NULL)
737 pLink = &(*pLink)->
next;
761 if (certFile != NULL)
763 certFile->
next = NULL;
779 static void* ParseX509Cert(
U8BIT *data,
U16BIT len)
786 bio = BIO_new_mem_buf(data, len);
789 x509 = d2i_X509_bio(bio, NULL);
804 static void ClearSigCache(
void)
809 while (entry != NULL)
826 static void ClearCertCache(
void)
832 certFile = certCache;
833 while (certFile != NULL)
835 nextCertFile = certFile->
next;
839 nextCell = cell->
next;
840 X509_free(cell->
x509);
845 certFile = nextCertFile;
851 while (entry != NULL)
877 certFile = ParseCertFile(data, size);
878 if (certFile != NULL)
881 pCertFile = &certCache;
882 while (*pCertFile != NULL)
884 lastId = (*pCertFile)->
id;
885 pCertFile = &(*pCertFile)->
next;
887 *pCertFile = certFile;
888 (*pCertFile)->
id = lastId + 1;
894 (*pCertFile)->valid =
TRUE;
899 CalculateSha1(&cert, (*pCertFile)->certDigest);
913 static void UpdatePendingEntries(
BOOLEAN retrieved)
928 while (entry != NULL)
932 entry->
state = nextState;
943 static CertFile* GetLastCertFile(
void)
947 certFile = certCache;
948 while (certFile != NULL && certFile->
next != NULL)
950 certFile = certFile->
next;
971 nameEqual = IsIssuerNameEqual(entry, cert);
972 numberEqual = IsSerialNumberEqual(entry, cert);
973 if (nameEqual && numberEqual)
993 X509_NAME *x509_name;
1000 x509_name = X509_get_issuer_name(cert->
x509);
1001 if (x509_name != NULL)
1004 nameLen = i2d_X509_NAME(x509_name, &name);
1008 if ((issuerName->
len == nameLen) &&
1009 (memcmp(issuerName->
data, name, nameLen) == 0))
1030 ASN1_INTEGER *x509_number;
1044 x509_number = X509_get_serialNumber(cert->
x509);
1045 if (x509_number != NULL)
1048 numberLen = i2d_ASN1_INTEGER(x509_number, &number);
1054 success = GetAsn1Tag(number, &tag, &
class, &constructed, &offset,
1056 if (success && (tag != 0x02 ||
class != 0x00 || constructed))
1063 success = GetAsn1Length(number, &asn1_length, &offset, limit);
1064 if (success && (offset + asn1_length != limit))
1072 if (((
U32BIT)serialNumber->
len == asn1_length) &&
1073 (memcmp(serialNumber->
data, number + offset, asn1_length) == 0))
1078 OPENSSL_free(number);
1106 pkey = X509_get_pubkey(x509);
1109 rsa = EVP_PKEY_get1_RSA(pkey);
1112 size = RSA_size(rsa);
1119 if (digestInfoLen >= 0)
1121 verified = VerifyDigest(entry, digestInfo, digestInfoLen);
1126 EVP_PKEY_free(pkey);
1149 U8BIT *data = digestInfo;
1151 U32BIT limit = digestInfoLen;
1153 U8BIT digest[SHA_DIGEST_LENGTH];
1158 success = GetAsn1Tag(data, &tag, &
class, &constructed, &offset, limit);
1159 if (success && (tag != 0x10 ||
class != 0x00 || !constructed))
1166 success = GetAsn1Length(data, &asn1_length, &offset, limit);
1167 if (success && (offset + asn1_length != limit))
1175 success = ASN1ParseDigestAlgorithm(data, &offset, limit);
1179 success = ASN1ParseDigest(data, &offset, limit, digest);
1183 if (memcmp(entry->
hashDigest, digest, SHA_DIGEST_LENGTH) == 0)
1205 while (entry != NULL)
1207 if ((memcmp(hashDigest, entry->
hashDigest, SHA_DIGEST_LENGTH) == 0) &&
1212 entry = entry->
next;
1243 memcpy(entry->
hashDigest, hashDigest, SHA_DIGEST_LENGTH);
1244 memset(entry->
certDigest, 0, SHA_DIGEST_LENGTH);
1250 while (*pEntry != NULL)
1252 pEntry = &(*pEntry)->
next;
1282 success = ASN1ParseSignature(entry, data, &offset, limit);
1295 static BOOLEAN ASN1ParseSignature(
1304 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1305 if (success && (tag != 0x10 ||
class != 0x00 || !constructed))
1312 success = GetAsn1Length(data, &asn1_length, offset, limit);
1313 if (success && (*offset + asn1_length != limit))
1321 success = ASN1ParseCertificateIdentifier(entry, data, offset, limit);
1325 success = ASN1ParseHashSignatureAlgorithm(data, offset, limit);
1329 success = ASN1ParseSignatureValue(entry, data, offset, limit);
1343 static BOOLEAN ASN1ParseCertificateIdentifier(
1352 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1353 if (success && (tag != 0x10 ||
class != 0x00 || !constructed))
1360 success = GetAsn1Length(data, &asn1_length, offset, limit);
1361 if (success && (*offset + asn1_length > limit))
1368 success = ASN1ParseKeyIdentifier(entry, data, offset, limit);
1372 success = ASN1ParseAuthorityCertIssuer(entry, data, offset, limit);
1376 success = ASN1ParseAuthorityCertSerialNumber(entry, data, offset, limit);
1390 static BOOLEAN ASN1ParseKeyIdentifier(
1400 origOffset = *offset;
1401 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1402 if (success && (
class != 0x02))
1406 if (success && (tag == 0x00 && constructed))
1409 success = GetAsn1Length(data, &asn1_length, offset, limit);
1410 if (success && (*offset + asn1_length > limit))
1416 *offset += asn1_length;
1421 *offset = origOffset;
1435 static BOOLEAN ASN1ParseAuthorityCertIssuer(
1444 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1445 if (success && (tag != 0x01 ||
class != 0x02 || !constructed))
1452 success = GetAsn1Length(data, &asn1_length, offset, limit);
1453 if (success && (*offset + asn1_length > limit))
1460 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1462 while (success && (tag != 0x04 ||
class != 0x02 || !constructed))
1464 success = GetAsn1Length(data, &asn1_length, offset, limit);
1465 if (success && (*offset + asn1_length > limit))
1472 *offset += asn1_length;
1473 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1476 if (success && (tag == 0x04 &&
class == 0x02 && constructed))
1478 success = GetAsn1Length(data, &asn1_length, offset, limit);
1479 if (success && (*offset + asn1_length > limit))
1489 PRINT((
"directoryName: "));
1490 for (i = 0; i != asn1_length - 1; ++i)
1492 PRINT((
"%02x:", data[*offset + i]));
1494 PRINT((
"%02x\n", data[*offset + asn1_length - 1]));
1502 *offset += asn1_length;
1521 static BOOLEAN ASN1ParseAuthorityCertSerialNumber(
1530 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1531 if (success && (tag != 0x02 ||
class != 0x02 || constructed))
1538 success = GetAsn1Length(data, &asn1_length, offset, limit);
1539 if (success && (*offset + asn1_length > limit))
1549 PRINT((
"authorityCertSerialNumber: "));
1550 for (i = 0; i != asn1_length - 1; ++i)
1552 PRINT((
"%02x:", data[*offset + i]));
1554 PRINT((
"%02x\n", data[*offset + asn1_length - 1]));
1561 data + *offset, asn1_length);
1563 *offset += asn1_length;
1582 static BOOLEAN ASN1ParseHashSignatureAlgorithm(
1594 static U8BIT sha1objectIdentifer[] = { 43, 14, 3, 2, 26 };
1596 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1597 if (success && (tag != 0x06 ||
class != 0x00 || constructed))
1604 success = GetAsn1Length(data, &asn1_length, offset, limit);
1605 if (success && (asn1_length !=
sizeof(sha1objectIdentifer)))
1612 if (memcmp(data + *offset, sha1objectIdentifer, asn1_length) != 0)
1618 *offset += asn1_length;
1633 static BOOLEAN ASN1ParseSignatureValue(
1642 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1643 if (success && (tag != 0x03 ||
class != 0x00 || constructed))
1650 success = GetAsn1Length(data, &asn1_length, offset, limit);
1651 if (success && (*offset + asn1_length != limit))
1656 if (success && (asn1_length < 2 || data[*offset] != 0))
1670 *offset += asn1_length;
1689 static BOOLEAN ASN1ParseDigestAlgorithm(
1702 static U8BIT sha1objectIdentifer[] = { 43, 14, 3, 2, 26 };
1704 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1705 if (success && (tag != 0x10 ||
class != 0x00 || !constructed))
1712 success = GetAsn1Length(data, &asn1_length, offset, limit);
1713 if (success && (*offset + asn1_length > limit))
1720 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1721 if (success && (tag != 0x06 ||
class != 0x00 || constructed))
1729 success = GetAsn1Length(data, &asn1_length, offset, limit);
1730 if (success && (asn1_length !=
sizeof(sha1objectIdentifer)))
1737 if (memcmp(data + *offset, sha1objectIdentifer, asn1_length) != 0)
1743 *offset += asn1_length;
1748 origOffset = *offset;
1749 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1750 if (success && (tag == 0x05 &&
class == 0x00 && !constructed))
1753 success = GetAsn1Length(data, &asn1_length, offset, limit);
1754 if (success && (asn1_length != 0))
1763 *offset = origOffset;
1778 static BOOLEAN ASN1ParseDigest(
1787 success = GetAsn1Tag(data, &tag, &
class, &constructed, offset, limit);
1788 if (success && (tag != 0x04 ||
class != 0x00 || constructed))
1795 success = GetAsn1Length(data, &asn1_length, offset, limit);
1796 if (success && ((asn1_length != SHA_DIGEST_LENGTH) ||
1797 (*offset + asn1_length != limit)))
1805 memcpy(digest, data + *offset, SHA_DIGEST_LENGTH);
1806 *offset += asn1_length;
1822 EVP_DigestInit(&ctx, EVP_sha1());
1823 EVP_DigestUpdate(&ctx, data->
data, data->
len);
1824 EVP_DigestFinal(&ctx, digest, NULL);
1848 *
class = (data[i] & 0xc0) >> 6;
1849 if ((data[i] & 0x20) >> 5)
1851 *constructed =
TRUE;
1855 *constructed =
FALSE;
1857 *tag = data[i] & 0x1f;
1861 while (i + 1 < limit)
1864 *tag |= data[i] & 0x7f;
1865 if ((data[i] & 0x80) == 0)
1911 lenlen = data[i] & 0x7f;
1914 while (lenlen > 0 && i < limit)
U32BIT STB_OSGetClockMilliseconds(void)
Get Current Computer Clock Time.
U8BIT hashDigest[SHA_DIGEST_LENGTH]
U8BIT certDigest[SHA_DIGEST_LENGTH]
Functions relating to HTTPS Signature Certificates.
MHEG5Bool MHEG5stringEqual(MHEG5String *s1, MHEG5String *s2)
Compare two Strings (case sensitive!)
MHEG5String authorityCertSerialNumber
unsigned char * STR_DataAlloc(unsigned int size)
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...
MHEG5String MHEG5stringCopy(MHEG5String source)
<Function description>="">
#define FRP_CACHE_DEFAULT
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
void MHEG5SetSigVerifyCallback(void(*callback)(void))
Sets the callback to be called when pending requests are resolved.
struct sSigCacheEntry * next
This file defines the profile for the MHEG engine.
struct sCertLink CertLink
struct sCertFile CertFile
U8BIT certDigest[SHA_DIGEST_LENGTH]
void MHEG5InvalidateSigCertCache(void)
Invalidate the certificates in the certificate cache.
Mheg5 logging and debug printing.
File interface functions to DSMCC component.
MHEG5SigVerifyStatus_t MHEG5IsValidSignature(MHEG5String *hash, MHEG5String *signature)
Check whether the signature is valid.
void MHEG5ClearSigCertCache(void)
Clear the signature certificate cache and all related information.
#define USE_UNWANTED_PARAM(param)
MHEG5String directoryName
#define ENTRY_STATE_STRING(e)
struct sSigCacheEntry SigCacheEntry
MHEG5String signatureValue
#define MAX_SIG_CERT_NAME
Header file - Function prototypes for operating system.