void CDeleteRetrieveCertificate::PerformAction(TRequestStatus& aStatus)
	{
	TRequestStatus* status = &aStatus;
	switch (iState)
		{
		case EIdle:
			//get the certs
			iState = EDeletingCert;
			//get the certs
			GetCerts(aStatus);
			if (aStatus == KErrNoMemory)
				{
				iState = EFinished;
				}
			break;

		case EDeletingCert:
			{
 			if (iNotificationSubscribed)
 				{
 				iNotifier = CCertStoreChangeNotifier::NewL(iNotifierFlag);
 				iNotifier->StartNotification();
 				iState = ECheckNotification;
 				}
 			else
 				{
 				iState = EGettingCerts;
 				}
			//delete the cert
			DeleteCert(aStatus);
			break;
			}

 		case ECheckNotification:
 			{
 			TInt ret=KErrNone;
 			if (!iNotifierFlag)
 				{
 				ret=KErrGeneral;
 				}
 			if (ret!=KErrNone)
 				{
 				iState = EFinished;	
 				}
 			else
 				{
 				iState = EGettingCerts;
 				}
 			TRequestStatus* status = &aStatus;
 			User::RequestComplete(status, ret);
 			}
 			break;
		case EGettingCerts:
			{
			iState = EFinished;
			//get the cert
			RetrieveCerts(aStatus);
			break;
			}
		case EFinished:
			{
			if (aStatus == iExpectedResult)
				{
				iResult = ETrue;
				}
			else
				{
				iResult = EFalse;
				}
			if (aStatus == KErrNoMemory)
				{	
				iState = EIdle;
				}
			else
				{
				iFinished = ETrue;
				}
			User::RequestComplete(status, aStatus.Int());
			}
			break;
		default:
			{
			//some kind of error behaviour
			}
		}
	}
void CDeleteCertificate::PerformAction(TRequestStatus& aStatus)
	{
	if (aStatus != KErrNone)
		{
		iState = EFinished;
		}
	
	switch (iState)
		{
		case EIdle:
			//get the certs
			if (iCertInfos.Count() > 0)
				{
				iCertInfos.Close();	//	JCS added for multiple delete case
				}

			iState = EGettingCerts;
			//get the certs
			GetCerts(aStatus);
			break;
			
		case EGettingCerts:
			{
 			if (iNotificationSubscribed)
 				{
 				if (!iNotifier)
 					{
	 				iNotifier = CCertStoreChangeNotifier::NewL(iNotifierFlag);
 					iNotifier->StartNotification();			
 					}
 				iState = ECheckNotification;
 				}
 			else
 				{
 				iState = EFinished;
 				}
			DeleteCert(aStatus);
			}
			break;

 		case ECheckNotification:
 			{
 			iState = EFinished;
 			if (iNotifierFlag)
	 			{
 				TRequestStatus* status = &aStatus;
 				User::RequestComplete(status, KErrNone);
	 			}
			else
				{
				iNotifier->SetCompleteStatus(&aStatus);
				}			
 			}

 			break;

		case EFinished:
			{
			if (aStatus == iExpectedResult)
				{
				iResult = ETrue;
				}
			else
				{
				iResult = EFalse;
				}
			if (aStatus == KErrNoMemory)
				{	
				iState = EIdle;
				}
			else
				{
				iFinished = ETrue;
				}
			TRequestStatus* status = &aStatus;
			User::RequestComplete(status, aStatus.Int());
			}
			break;
			
		default:
			User::Invariant();
		}
	}
Exemplo n.º 3
0
s32 Download_IOS(IOS **ios, u32 iosnr, u32 revision)
{
	s32 ret;

	ret = Init_IOS(ios);
	if (ret < 0)
	{
		printf("Out of memory\n");
		goto err;
	}

	tmd *tmd_data  = NULL;
	u32 cnt;
	//static bool network_initialized = false;
	char buf[32];
	
	if (!network_initialized)
	{
		printf("Initializing network...");
		while (1) 
		{
			ret = net_init ();
			if (ret < 0) 
			{
				//if (ret != -EAGAIN) 
				if (ret != -11) 
				{
					printf ("net_init failed: %d\n", ret);
					goto err;
				}
			}
			if (!ret) break;
			usleep(100000);
			printf(".");
		}
		printf("done\n");
		network_initialized = true;
	}

	printf("Loading certs...\n");
	ret = GetCerts(&((*ios)->certs), &((*ios)->certs_size));
	if (ret < 0)
	{
		printf ("Loading certs from nand failed, ret = %d\n", ret);
		goto err;	
	}

	if ((*ios)->certs == NULL || (*ios)->certs_size == 0)
	{
		printf("certs error\n");
		ret = -1;
		goto err;		
	}

	if (!IS_VALID_SIGNATURE((*ios)->certs))
	{
		printf("Error: Bad certs signature!\n");
		ret = -1;
		goto err;
	}
	
	printf("Loading TMD...\n");
	sprintf(buf, "tmd.%u", revision);
	u8 *tmd_buffer = NULL;
	ret = get_nus_object(1, iosnr, buf, &tmd_buffer, &((*ios)->tmd_size));
	if (ret < 0)
	{
		printf("Loading tmd failed, ret = %u\n", ret);
		goto err;	
	}

	if (tmd_buffer == NULL || (*ios)->tmd_size == 0)
	{
		printf("TMD error\n");
		ret = -1;
		goto err;		
	}
	
	(*ios)->tmd_size = SIGNED_TMD_SIZE((signed_blob *)tmd_buffer);
 	(*ios)->tmd = MEM2_memalign(32, (*ios)->tmd_size);
	if ((*ios)->tmd == NULL)
	{
		printf("Out of memory\n");
		ret = -1;
		goto err;		
	}
	memcpy((*ios)->tmd, tmd_buffer, (*ios)->tmd_size);
	free(tmd_buffer);
	
	if (!IS_VALID_SIGNATURE((*ios)->tmd))
	{
		printf("Error: Bad TMD signature!\n");
		ret = -1;
		goto err;
	}

	printf("Loading ticket...\n");
	u8 *ticket_buffer = NULL;
	ret = get_nus_object(1, iosnr, "cetk", &ticket_buffer, &((*ios)->ticket_size));
	if (ret < 0)
	{
		printf("Loading ticket failed, ret = %u\n", ret);
		goto err;	
	}

	if (ticket_buffer == NULL || (*ios)->ticket_size == 0)
	{
		printf("ticket error\n");
		ret = -1;
		goto err;		
	}

	(*ios)->ticket_size = SIGNED_TIK_SIZE((signed_blob *)ticket_buffer);
 	(*ios)->ticket = MEM2_memalign(32, (*ios)->ticket_size);
	if ((*ios)->ticket == NULL)
	{
		printf("Out of memory\n");
		ret = -1;
		goto err;		
	}
	memcpy((*ios)->ticket, ticket_buffer, (*ios)->ticket_size);
	free(ticket_buffer);
	
	if(!IS_VALID_SIGNATURE((*ios)->ticket))
	{
		printf("Error: Bad ticket signature!\n");
		ret = -1;
		goto err;
	}

	/* Get TMD info */
	tmd_data = (tmd *)SIGNATURE_PAYLOAD((*ios)->tmd);

	printf("Checking titleid and revision...\n");
	if (TITLE_UPPER(tmd_data->title_id) != 1 || TITLE_LOWER(tmd_data->title_id) != iosnr)
	{
		printf("IOS has titleid: %08x%08x but expected was: %08x%08x\n", TITLE_UPPER(tmd_data->title_id), TITLE_LOWER(tmd_data->title_id), 1, iosnr);
		ret = -1;
		goto err;
	}

	if (tmd_data->title_version != revision)
	{
		printf("IOS has revision: %u but expected was: %u\n", tmd_data->title_version, revision);
		ret = -1;
		goto err;
	}

	ret = set_content_count(*ios, tmd_data->num_contents);
	if (ret < 0)
	{
		printf("Out of memory\n");
		goto err;
	}

	printf("Loading contents");
	for (cnt = 0; cnt < tmd_data->num_contents; cnt++) 
	{
		printf(".");
		tmd_content *content = &tmd_data->contents[cnt];

		/* Encrypted content size */
		(*ios)->buffer_size[cnt] = round_up((u32)content->size, 64);

		sprintf(buf, "%08x", content->cid);
   
		ret = get_nus_object(1, iosnr, buf, &((*ios)->encrypted_buffer[cnt]), &((*ios)->buffer_size[cnt]));

		if ((*ios)->buffer_size[cnt] % 16) 
		{
			printf("Content %u size is not a multiple of 16\n", cnt);
			ret = -1;
			goto err;
		}

   		if ((*ios)->buffer_size[cnt] < (u32)content->size) 
		{
			printf("Content %u size is too small\n", cnt);
			ret = -1;
			goto err;
   		} 

		(*ios)->decrypted_buffer[cnt] = MEM2_memalign(32, (*ios)->buffer_size[cnt]);
		if (!(*ios)->decrypted_buffer[cnt])
		{
			printf("Out of memory\n");
			ret = -1;
			goto err;
		}

	}
	printf("done\n");
	
	printf("Reading file into memory complete.\n");

	printf("Decrypting IOS...\n");
	decrypt_IOS(*ios);

	tmd_content *p_cr = TMD_CONTENTS(tmd_data);
	sha1 hash;
	int i;

	printf("Checking hashes...\n");
	for (i=0;i < (*ios)->content_count;i++)
	{
		SHA1((*ios)->decrypted_buffer[i], (u32)p_cr[i].size, hash);
		if (memcmp(p_cr[i].hash, hash, sizeof hash) != 0)
		{
			printf("Wrong hash for content #%u\n", i);
			ret = -1;
			goto err;
		}
	}	

	goto out;

err:
	free_IOS(ios);

out:
	return ret;
}