29 #include <openssl/evp.h> 40 #define GET_16BITS_FROM_ARRAY(X, Y) ((X[Y] << 8) | X[Y + 1]) 47 HASH_FILE_WAITING_FOR_HASH,
48 HASH_FILE_WAITING_FOR_SIG,
49 HASH_FILE_WAITING_FOR_HASH_AND_SIG,
50 HASH_FILE_WAITING_FOR_CERT,
77 HashFileState_t state;
78 MHEG5Bool sameAsPrevious;
79 U32BIT signatureIndex;
90 static void (*VerificationCallback)(void) = NULL;
97 static U8BIT* GetHashfileUrl(
const U8BIT *url);
99 static MHEG5Bool LoadHashfile(U8BIT *url);
100 static void HashLoadFailCallback(
void *userData );
101 static void HashLoadedCallback(
void *userData,
S_CONTENT *content );
102 static void FreeDigestList(
HashDigest *listStart);
106 static MHEG5Bool CheckUrlPath(U8BIT *url,
HashfileData *hashfile);
107 static MHEG5Bool CheckHashes(U8BIT *content, U32BIT contentLength,
HashDigest *digest);
109 static void SigLoadedCallback(
void *userData,
S_CONTENT *content );
110 static void SigLoadFailCallback(
void *userData );
112 static MHEG5Bool LoadNextSignatureFile(
HashfileData *hashfile);
113 static void CertCallback(
void);
114 static MHEG5ContentVerification_t GetFailureStatus(
HashfileData *hashFile);
115 static MHEG5ContentVerification_t VerifyUrl(U8BIT *url, U8BIT *content, U32BIT length,
HashfileData *hashFile);
130 VerificationCallback = callback;
144 listEntry = hashfileList;
150 nextEntry = listEntry->next;
153 if (listEntry->url != NULL)
155 MHEG5freeMem(listEntry->url);
158 hashData = &listEntry->hashData;
160 if (hashData->data != &noFile && hashData->data != NULL)
162 MHEG5freeMem(hashData->data);
165 FreeDigestList(listEntry->digestList);
166 listEntry->digestList = NULL;
168 MHEG5freeMem(listEntry);
171 listEntry = nextEntry;
188 MHEG5ContentVerification_t status;
192 hashfileUrl = GetHashfileUrl(url);
193 if (hashfileUrl == NULL)
195 return CONTENT_NOT_VERIFIED_NEW;
198 hashFile = FindHashInfo(hashfileUrl);
199 if (hashFile != NULL)
201 switch (hashFile->state)
203 case HASH_FILE_RELOAD:
204 success = ReloadHashfile(hashFile);
205 if (success == MHEG5TRUE)
207 status = CONTENT_VERIFICATION_PENDING;
211 status = GetFailureStatus(hashFile);
215 case HASH_FILE_WAITING_FOR_HASH:
216 case HASH_FILE_WAITING_FOR_SIG:
217 case HASH_FILE_WAITING_FOR_HASH_AND_SIG:
218 case HASH_FILE_WAITING_FOR_CERT:
219 case HASH_FILE_VERIFYING:
221 status = CONTENT_VERIFICATION_PENDING;
224 case HASH_FILE_VERIFIED:
225 status = VerifyUrl(url, content, length, hashFile);
227 case HASH_FILE_FAILED:
228 status = GetFailureStatus(hashFile);
231 status = CONTENT_NOT_VERIFIED_NEW;
236 MHEG5freeMem(hashfileUrl);
240 success = LoadHashfile(hashfileUrl);
243 status = CONTENT_VERIFICATION_PENDING;
248 MHEG5freeMem(hashfileUrl);
250 status = CONTENT_NOT_VERIFIED_NEW;
261 static MHEG5ContentVerification_t GetFailureStatus(
HashfileData *hashFile)
263 MHEG5ContentVerification_t status;
264 if (hashFile->sameAsPrevious)
266 status = CONTENT_NOT_VERIFIED_SAME;
270 status = CONTENT_NOT_VERIFIED_NEW;
279 static MHEG5ContentVerification_t VerifyUrl(U8BIT *url, U8BIT *content, U32BIT length,
HashfileData *hashFile)
283 MHEG5ContentVerification_t status;
285 success = MHEG5FALSE;
286 status = GetFailureStatus(hashFile);
288 if (hashFile->digestCount == 0)
290 success = CheckUrlPath(url, hashFile);
293 status = CONTENT_VERIFIED_UNSIGNED;
298 digest = FindDigestForUrl(url, hashFile);
301 success = CheckHashes(content, length, digest);
305 status = CONTENT_VERIFIED_SIGNED;
323 listEntry = hashfileList;
325 while (listEntry != NULL)
327 differ = strcmp((
char *)url, (
char *)listEntry->url);
334 listEntry = listEntry->next;
346 static U8BIT* GetHashfileUrl(
const U8BIT *url)
351 U8BIT *hashfileName = (U8BIT *)
"auth.hash";
352 U32BIT hashfileNameLen = strlen((
char *)hashfileName);
354 slash = (U8BIT *)strrchr((
char *)url,
'/');
355 assert(slash != NULL);
356 length = slash - url + 1;
358 hashfileUrl = MHEG5getMem(length + hashfileNameLen + 1);
359 if (hashfileUrl != NULL)
361 memcpy(hashfileUrl, url, length);
362 memcpy(hashfileUrl + length, hashfileName, hashfileNameLen);
363 hashfileUrl[length + hashfileNameLen] =
'\0';
380 hashName.data = hashfile->url;
381 hashName.len = strlen((
char *)hashfile->url);
383 hashfile->state = HASH_FILE_WAITING_FOR_HASH_AND_SIG;
385 (
void *)hashfile, HashLoadedCallback, HashLoadFailCallback );
386 hashfile->signatureIndex = 0;
387 success = LoadNextSignatureFile(hashfile);
390 if (hashfile->hashData.data == &noFile)
392 hashfile->sameAsPrevious = MHEG5TRUE;
396 hashfile->hashData.data = &noFile;
397 hashfile->sameAsPrevious = MHEG5FALSE;
399 hashfile->state = HASH_FILE_FAILED;
410 static MHEG5Bool LoadHashfile(U8BIT *url)
416 success = MHEG5FALSE;
420 if (listEntry != NULL)
422 listEntry->url = url;
423 listEntry->hashData.len = 0;
424 listEntry->hashData.data = NULL;
425 listEntry->state = HASH_FILE_WAITING_FOR_HASH;
426 listEntry->digestCount = 0;
427 listEntry->sameAsPrevious = MHEG5FALSE;
429 listEntry->signatureIndex = 0;
430 listEntry->signature.len = 0;
431 listEntry->signature.data = NULL;
433 listEntry->digestList = NULL;
436 listEntry->next = hashfileList;
437 listEntry->previous = NULL;
438 hashfileList = listEntry;
439 hashfileList->previous = listEntry;
443 hashName.len = strlen((
char *)url);
445 listEntry->state = HASH_FILE_WAITING_FOR_HASH_AND_SIG;
447 (
void *)listEntry, HashLoadedCallback, HashLoadFailCallback);
449 success = LoadNextSignatureFile(listEntry);
460 static void HashLoadedCallback(
void *userData,
S_CONTENT *content )
471 listEntry = hashfileList;
475 while (listEntry != NULL)
477 if (listEntry == cacheHandle)
481 listEntry = listEntry->next;
484 if (listEntry != NULL)
486 currentFile = &cacheHandle->hashData;
489 fileBuffer.data = MHEG5getMem(content->size);
490 if (fileBuffer.data != NULL)
492 memcpy(fileBuffer.data, content->data, content->size);
493 fileBuffer.len = content->size;
495 if (fileBuffer.len != currentFile->len)
497 cacheHandle->sameAsPrevious = MHEG5FALSE;
499 else if (currentFile->data == NULL || currentFile->data == &noFile)
501 cacheHandle->sameAsPrevious = MHEG5FALSE;
505 differ = memcmp(fileBuffer.data, currentFile->data, content->size);
508 cacheHandle->sameAsPrevious = MHEG5TRUE;
512 cacheHandle->sameAsPrevious = MHEG5FALSE;
517 if (currentFile->data != NULL && currentFile->data != &noFile)
519 MHEG5freeMem(currentFile->data);
522 FreeDigestList(listEntry->digestList);
523 listEntry->digestList = NULL;
526 currentFile->data = fileBuffer.data;
527 currentFile->len = fileBuffer.len;
529 success = ParseHashfile(cacheHandle);
532 if (cacheHandle->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG)
534 cacheHandle->state = HASH_FILE_WAITING_FOR_SIG;
538 assert(cacheHandle->state == HASH_FILE_WAITING_FOR_HASH);
539 VerifyHashfile(cacheHandle);
544 if (cacheHandle->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG)
546 cacheHandle->state = HASH_FILE_WAITING_FOR_SIG;
550 cacheHandle->state = HASH_FILE_FAILED;
557 if (cacheHandle->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG)
559 cacheHandle->state = HASH_FILE_WAITING_FOR_SIG;
563 cacheHandle->state = HASH_FILE_FAILED;
566 cacheHandle->hashData.len = 0;
567 if (cacheHandle->hashData.data != &noFile)
569 cacheHandle->hashData.data = &noFile;
570 cacheHandle->sameAsPrevious = MHEG5FALSE;
574 cacheHandle->sameAsPrevious = MHEG5TRUE;
579 if (call && VerificationCallback != NULL)
581 VerificationCallback();
590 static void HashLoadFailCallback(
void *userData )
602 listEntry = hashfileList;
603 while (listEntry != NULL)
605 if (listEntry == cacheHandle)
609 listEntry = listEntry->next;
612 if (listEntry != NULL)
615 hashData = &cacheHandle->hashData;
617 if (hashData->data != NULL)
619 if (hashData->data == &noFile)
621 cacheHandle->sameAsPrevious = MHEG5TRUE;
625 MHEG5freeMem(hashData->data);
627 hashData->data = &noFile;
628 cacheHandle->sameAsPrevious = MHEG5FALSE;
634 hashData->data = &noFile;
635 cacheHandle->sameAsPrevious = MHEG5FALSE;
638 if (cacheHandle->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG)
640 cacheHandle->state = HASH_FILE_WAITING_FOR_SIG;
644 cacheHandle->state = HASH_FILE_FAILED;
650 if (call && VerificationCallback != NULL)
652 VerificationCallback();
670 MHEG5Bool continueParsing;
680 if (hashfile != NULL && hashfile->hashData.data != &noFile)
682 fileSize = hashfile->hashData.len;
683 fileData = hashfile->hashData.data;
684 dataEnd = fileData + fileSize;
687 FreeDigestList(hashfile->digestList);
688 hashfile->digestList = NULL;
698 digestCount = GET_16BITS_FROM_ARRAY(fileData, 0);
701 continueParsing = MHEG5TRUE;
705 success = MHEG5FALSE;
706 continueParsing = MHEG5FALSE;
712 if (digestCount == 0)
714 if (fileData + 2 <= dataEnd)
716 hashfile->digestPathname.len = GET_16BITS_FROM_ARRAY(fileData, 0);
718 hashfile->digestPathname.data = fileData;
722 success = MHEG5FALSE;
732 previousDigest = NULL;
733 for (i = 0; i < digestCount; i++)
737 hashfile->digestList = MHEG5getMem(
sizeof(
HashDigest));
738 if (hashfile->digestList != NULL)
740 hashfile->digestList->next = previousDigest;
741 if (fileData + 1 <= dataEnd)
758 continueParsing = MHEG5FALSE;
764 continueParsing = MHEG5FALSE;
770 hashfile->digestList = previousDigest;
771 continueParsing = MHEG5FALSE;
776 if (fileData + 2 <= dataEnd)
778 nameCount = GET_16BITS_FROM_ARRAY(fileData, 0);
783 continueParsing = MHEG5FALSE;
785 if (continueParsing && nameCount != 1)
787 continueParsing = MHEG5FALSE;
793 if (fileData + 1 <= dataEnd)
795 nameLength = *fileData;
800 continueParsing = MHEG5FALSE;
806 if (fileData + nameLength <= dataEnd)
809 fileData += nameLength;
813 continueParsing = MHEG5FALSE;
819 if (fileData + digestLength <= dataEnd)
822 fileData += digestLength;
826 continueParsing = MHEG5FALSE;
832 hashfile->digestList->name = name;
833 hashfile->digestList->nameLength = nameLength;
834 hashfile->digestList->type = type;
835 hashfile->digestList->digestLength = digestLength;
836 hashfile->digestList->digest = digest;
837 previousDigest = hashfile->digestList;
844 hashfile->digestCount = digestCount;
855 static void FreeDigestList(
HashDigest *listStart)
860 while (current != NULL)
862 next = current->next;
863 MHEG5freeMem(current);
879 hashfileUrl = GetHashfileUrl(url);
880 if (hashfileUrl != NULL)
882 hashfile = FindHashInfo(hashfileUrl);
885 MHEG5freeMem(hashfileUrl);
887 if (hashfile != NULL)
889 if (hashfile->state == HASH_FILE_FAILED ||
890 hashfile->state == HASH_FILE_VERIFIED)
892 hashfile->state = HASH_FILE_RELOAD;
893 if (hashfile->signature.data)
895 MHEG5freeMem(hashfile->signature.data);
896 hashfile->signature.data = NULL;
897 hashfile->signature.len = 0;
899 hashfile->signatureIndex = 0;
924 name = (U8BIT *)strrchr((
char *)url,
'/') + 1;
925 assert(name != NULL);
926 nameLength = strlen((
char *)name);
928 digest = hashfile->digestList;
929 while (digest != NULL)
931 if (nameLength == digest->nameLength)
933 differ = memcmp(name, digest->name, digest->nameLength);
939 digest = digest->next;
952 static MHEG5Bool CheckUrlPath(U8BIT *url,
HashfileData *hashfile)
954 U16BIT urlDirectoryLength;
955 U8BIT *hashDirectory;
956 U16BIT hashDirectoryLength;
963 if (hashfile->digestCount != 0)
965 success = MHEG5FALSE;
970 slash = (U8BIT *)strrchr((
char *)url,
'/');
971 urlDirectoryLength = slash - url;
972 hashDirectoryLength = (U16BIT)hashfile->digestPathname.len;
973 hashDirectory = hashfile->digestPathname.data;
975 if (hashDirectoryLength == 0 || hashDirectoryLength > urlDirectoryLength)
977 success = MHEG5FALSE;
982 differ = MHEG5strncmp(hashDirectory, url, hashDirectoryLength );
985 success = MHEG5FALSE;
990 if (hashDirectory[hashDirectoryLength - 1] !=
'/' &&
991 url[hashDirectoryLength] !=
'/')
993 success = MHEG5FALSE;
1008 static MHEG5Bool CheckHashes(U8BIT *content, U32BIT contentLength,
HashDigest *digest)
1012 U8BIT contentDigest[EVP_MAX_MD_SIZE];
1017 switch (digest->type)
1020 success = MHEG5TRUE;
1026 EVP_DigestInit(&ctx, EVP_sha1());
1027 EVP_DigestUpdate(&ctx, content, contentLength);
1028 digestSize = EVP_MD_CTX_size(&ctx);
1029 EVP_DigestFinal(&ctx, contentDigest, NULL);
1032 differ = memcmp(contentDigest, digest->digest, digestSize);
1035 success = MHEG5TRUE;
1039 success = MHEG5FALSE;
1053 prefix[4] = (U8BIT)(contentLength >> 24);
1054 prefix[5] = (U8BIT)(contentLength >> 16);
1055 prefix[6] = (U8BIT)(contentLength >> 8);
1056 prefix[7] = (U8BIT)contentLength;
1059 EVP_DigestInit(&ctx, EVP_sha1());
1060 EVP_DigestUpdate(&ctx, prefix, 8);
1061 EVP_DigestUpdate(&ctx, content, contentLength);
1062 digestSize = EVP_MD_CTX_size(&ctx);
1063 EVP_DigestFinal(&ctx, contentDigest, NULL);
1066 differ = memcmp(contentDigest, digest->digest, digestSize);
1069 success = MHEG5TRUE;
1073 success = MHEG5FALSE;
1078 success = MHEG5FALSE;
1087 static void SigLoadFailCallback(
void *userData )
1094 listEntry = hashfileList;
1097 while (listEntry != NULL)
1099 if (listEntry == cacheHandle)
1103 listEntry = listEntry->next;
1105 if (listEntry != NULL)
1108 if (listEntry->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG)
1110 listEntry->state = HASH_FILE_WAITING_FOR_HASH;
1114 assert(listEntry->state == HASH_FILE_WAITING_FOR_SIG);
1115 listEntry->state = HASH_FILE_FAILED;
1120 if (call && VerificationCallback)
1122 VerificationCallback();
1130 static void SigLoadedCallback(
void *userData,
S_CONTENT *content )
1138 listEntry = hashfileList;
1141 while (listEntry != NULL)
1143 if (listEntry == cacheHandle)
1147 listEntry = listEntry->next;
1150 if (listEntry != NULL)
1152 currentFile = &cacheHandle->signature;
1155 if (currentFile->data)
1157 MHEG5freeMem(currentFile->data);
1158 currentFile->data = NULL;
1162 currentFile->data = MHEG5getMem(content->size);
1163 if (currentFile->data != NULL)
1165 currentFile->len = content->size;
1166 memcpy(currentFile->data, content->data, content->size);
1168 if (cacheHandle->state == HASH_FILE_WAITING_FOR_SIG)
1170 VerifyHashfile(cacheHandle);
1175 assert(cacheHandle->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG);
1176 cacheHandle->state = HASH_FILE_WAITING_FOR_HASH;
1181 currentFile->len = 0;
1182 if (cacheHandle->state == HASH_FILE_WAITING_FOR_HASH_AND_SIG)
1184 cacheHandle->state = HASH_FILE_WAITING_FOR_HASH;
1188 cacheHandle->state = HASH_FILE_FAILED;
1194 if (call && VerificationCallback)
1196 VerificationCallback();
1207 MHEG5SigVerifyStatus_t status;
1209 if ((hashfile->signature.data != NULL) &&
1210 (hashfile->hashData.data != &noFile))
1215 case MHEG5_SIG_VERIFIED:
1216 hashfile->state = HASH_FILE_VERIFIED;
1217 if (VerificationCallback)
1219 VerificationCallback();
1222 case MHEG5_SIG_NOT_VERIFIED:
1223 hashfile->state = HASH_FILE_WAITING_FOR_SIG;
1224 LoadNextSignatureFile(hashfile);
1226 case MHEG5_SIG_CHECK_PENDING:
1227 hashfile->state = HASH_FILE_WAITING_FOR_CERT;
1236 hashfile->state = HASH_FILE_FAILED;
1245 static MHEG5Bool LoadNextSignatureFile(
HashfileData *hashfile)
1251 success = MHEG5FALSE;
1253 sigUrl = GetNextSigUrl(hashfile);
1256 sigName.data = sigUrl;
1257 sigName.len = strlen((
char *)sigUrl);
1259 (
void *)hashfile, SigLoadedCallback, SigLoadFailCallback );
1261 MHEG5freeMem(sigUrl);
1262 if (hashfile->state == HASH_FILE_FAILED)
1264 success = MHEG5FALSE;
1268 success = MHEG5TRUE;
1289 sigName = (U8BIT *)
"auth.sig.";
1290 sigNameLen = strlen((
char *)sigName);
1292 slash = (U8BIT *)strrchr((
char *)hashfile->url,
'/');
1293 assert(slash != NULL);
1294 length = slash - hashfile->url + 1;
1296 sigUrl = MHEG5getMem(length + sigNameLen + 7);
1299 memcpy(sigUrl, hashfile->url, length);
1300 memcpy(sigUrl + length, sigName, sigNameLen);
1302 hashfile->signatureIndex++;
1304 sprintf((
char *)(sigUrl + length + sigNameLen),
"%u", (
unsigned int)hashfile->signatureIndex);
1316 static void CertCallback(
void)
1320 cacheEntry = hashfileList;
1321 while (cacheEntry != NULL)
1323 if (cacheEntry->state == HASH_FILE_WAITING_FOR_CERT)
1325 VerifyHashfile(cacheEntry);
1327 cacheEntry = cacheEntry->next;
Functions relating to HTTPS Signature Certificates.
void MHEG5ResetVerification(void)
Reset the state of the verification subsystem.
void MHEG5SetVerificationCallback(void(*callback)(void))
Register a callback to be fired when the state of the verification file changes.
void MHEG5ResetHashFile(U8BIT *url)
Reset the state and clear cache of the hashfile associated with a content file.
MHEG5ContentVerification_t MHEG5IsContentVerified(U8BIT *url, U8BIT *content, U32BIT length)
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...
Functions relating to HTTPS Content Verification.
MHEG5SigVerifyStatus_t MHEG5IsValidSignature(MHEG5String *hash, MHEG5String *signature)
Check whether the signature is valid.
File interface functions to DSMCC component.
void MHEG5SetSigVerifyCallback(void(*callback)(void))
Sets the callback to be called when pending requests are resolved.
Header file - Function prototypes for operating system.