Ejemplo n.º 1
0
void sec_error_print(int errcode, char *prefix)
{
    if (prefix == NULL)
        fprintf(stderr, "%s\n", sec_error(errcode));
    else
        fprintf(stderr, "%s:%s\n", prefix, sec_error(errcode));
}
static int
do_keychain_set_settings(const char *keychainName, SecKeychainSettings newKeychainSettings)
{
	SecKeychainRef keychain = NULL;
	OSStatus result;

	if (keychainName)
	{
		keychain = keychain_open(keychainName);
		if (!keychain)
		{
			result = 1;
			goto cleanup;
		}
	}
	result = SecKeychainSetSettings(keychain, &newKeychainSettings);
	if (result)
	{
		sec_error("SecKeychainSetSettings %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result));
	}

cleanup:
	if (keychain)
		CFRelease(keychain);

	return result;
}
Ejemplo n.º 3
0
void cmd_flash_nand(const char *arg, void *data, unsigned sz)
{
	u8 msg[128] = {0};

	if(sz  == 0)
	{
		fastboot_okay("");
		return;
	}

    //Please DO NOT get any data for reference if security check is not passed
    if(!security_check(&data, &sz, 0, arg))
    {
        sprintf(msg, "\nSecurity deny - Err:0x%x \n", sec_error());
    	dprintf(DBG_LV, msg);
    	fastboot_fail_wrapper(msg);
        return;
    }

	dprintf(DBG_LV, "cmd_flash_nand, data:0x%x\n",*(int*)data);

    if(cmd_flash_nand_img(arg,data,sz))
    {
        //[Security] Notify security check that is the end.
        sz = 0;
        security_check(&data, &sz, IMAGE_TRUNK_SIZE, arg); 
    }
}
static int
do_lock(const char *keychainName)
{
	SecKeychainRef keychain = NULL;
	OSStatus result;

	if (keychainName)
	{
		keychain = keychain_open(keychainName);
		if (!keychain)
		{
			result = 1;
			goto loser;
		}
	}

	result = SecKeychainLock(keychain);
	if (result)
	{
		sec_error("SecKeychainLock %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result));
	}

loser:
	if (keychain)
		CFRelease(keychain);

	return result;
}
Ejemplo n.º 5
0
OSStatus makeMasterPassword(const char *fvmkcName, const char *masterPasswordPassword, uint32 keySizeInBits, SecKeychainRef *keychainRef)
{
    /*
        OSStatus SecFileVaultMakeMasterPassword(CFStringRef masterPasswordPassword);

        *** In the real code, this will be done directly rather than exec'ing a tool, since there are too many parameters to specify
        *** this needs to be done as root, since the keychain will be a system keychain
        /usr/bin/certtool y c k=/Library/Keychains/FileVaultMaster.keychain p=<masterPasswordPassword>
        /usr/bin/certtool c   k=/Library/Keychains/FileVaultMaster.keychain o=/Library/Keychains/FileVaultMaster.cer
        Two steps: create the keychain, then create the keypair
    */

    SecAccessRef initialAccess = NULL;

    if (!masterPasswordPassword)
    {
        sec_error("You must supply a non-empty password");
        return -2;
    }

    //  We return an error if the keychain already exists
    OSStatus status = SecKeychainCreate(fvmkcName, (UInt32) strlen(masterPasswordPassword), masterPasswordPassword, false, initialAccess, keychainRef);
    if (status!=noErr)
    {
		if (status==errSecDuplicateKeychain || status==CSSMERR_DL_DATASTORE_ALREADY_EXISTS)
            sec_error("The keychain file %s already exists", fvmkcName);
        return status;
    }

    // Create the key pair
    char host[PATH_MAX];
	int rx = gethostname(host, sizeof(host));
    if (rx)
        strcpy(host, "localhost");

    CFStringRef hostName = CFSTR("FileVault Recovery Key");		// This is what shows up in Keychain Access display
    CFStringRef userName = CFStringCreateWithCString(kCFAllocatorDefault, host, kCFStringEncodingUTF8);
    CFDataRef certData = NULL;
    printf("Generating a %d bit key pair; this may take several minutes\n", keySizeInBits);
    status = createPair(hostName,userName,*keychainRef,keySizeInBits, &certData);
    if (status)
        sec_error("Error in createPair: %s", sec_errstr(status));
    if (certData)
        CFRelease(certData);

    return status;
}
Ejemplo n.º 6
0
/*
 * Generate a key pair using the CSPDL.
 */
OSStatus generateKeyPair(
	CSSM_CSP_HANDLE 	cspHand,
	CSSM_DL_DB_HANDLE 	dlDbHand,
	CSSM_ALGORITHMS 	keyAlg,				// e.g., CSSM_ALGID_RSA
	uint32				keySizeInBits,
	const char 			*keyLabel,			// C string
	CSSM_KEY_PTR 		*pubKeyPtr,			// mallocd, created, RETURNED
	CSSM_KEY_PTR 		*privKeyPtr)		// mallocd, created, RETURNED
{
	CSSM_KEY_PTR pubKey = (CSSM_KEY_PTR)(APP_MALLOC(sizeof(CSSM_KEY)));
	CSSM_KEY_PTR privKey = (CSSM_KEY_PTR)(APP_MALLOC(sizeof(CSSM_KEY)));
	if((pubKey == NULL) || (privKey == NULL)) {
		return memFullErr;
	}

	CSSM_RETURN crtn;
	CSSM_KEYUSE pubKeyUse;
	CSSM_KEYUSE privKeyUse;

	pubKeyUse = CSSM_KEYUSE_VERIFY | CSSM_KEYUSE_ENCRYPT |
			CSSM_KEYUSE_WRAP;
	privKeyUse = CSSM_KEYUSE_SIGN | CSSM_KEYUSE_DECRYPT |
			CSSM_KEYUSE_UNWRAP;

	crtn = srCspGenKeyPair(cspHand,
		&dlDbHand,
		keyAlg,
		keyLabel,
		(int) strlen(keyLabel) + 1,
		keySizeInBits,
		pubKey,
		pubKeyUse,
		CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF,
		privKey,
		privKeyUse,
		CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_RETURN_REF |
			CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE);

	if(crtn) {
		APP_FREE(pubKey);
		APP_FREE(privKey);
		return paramErr;
	}

	/* bind private key to cert by public key hash */
	crtn = setPubKeyHash(cspHand,
		dlDbHand,
		pubKey,
		keyLabel);
	if(crtn) {
        sec_error("setPubKeyHash: Error setting public key hash. Continuing at peril: %s", sec_errstr(crtn));
	}

	*pubKeyPtr = pubKey;
	*privKeyPtr = privKey;
	return noErr;
}
Ejemplo n.º 7
0
int
keychain_import(int argc, char * const *argv)
{
    int ch;
    int verbose=0;
    const char *keybag=NULL;
    const char *password=NULL;

    while ((ch = getopt(argc, argv, "vk:p:")) != -1)
    {
        switch (ch)
        {
        case 'v':
            verbose++;
            break;
        case 'k':
            keybag=optarg;
            break;
        case 'p':
            password=optarg;
            break;
        default:
            return 2; /* Trigger usage message. */
        }
    }

    argc -= optind;
    argv += optind;

    if(keybag==NULL) {
        sec_error("-k is required\n");
        return 2;
    }

    if (argc != 1) {
        sec_error("<backup> is required\n");
        return 2; /* Trigger usage message. */
    }

    return do_keychain_import(argv[0], keybag, password);
}
Ejemplo n.º 8
0
/* Convert a reference key to a raw key. */
static CSSM_RETURN refKeyToRaw(
	CSSM_CSP_HANDLE	cspHand,
	const CSSM_KEY	*refKey,
	CSSM_KEY_PTR	rawKey)			// RETURNED
{
	CSSM_CC_HANDLE		ccHand;
	CSSM_RETURN			crtn;
	CSSM_ACCESS_CREDENTIALS	creds;

	memset(rawKey, 0, sizeof(CSSM_KEY));
	memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
	crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
			CSSM_ALGID_NONE,
			CSSM_ALGMODE_NONE,
			&creds,				// passPhrase
			NULL,				// wrapping key
			NULL,				// init vector
			CSSM_PADDING_NONE,	// Padding
			0,					// Params
			&ccHand);
	if(crtn) {
		sec_error("CSSM_CSP_CreateSymmetricContext: refKeyToRaw context err: %s", sec_errstr(crtn));
		return crtn;
	}

	crtn = CSSM_WrapKey(ccHand,
		&creds,
		refKey,
		NULL,			// DescriptiveData
		rawKey);
	if(crtn != CSSM_OK) {
		sec_error("CSSM_WrapKey: refKeyToRaw wrap err: %s", sec_errstr(crtn));
		return crtn;
	}
	CSSM_DeleteContext(ccHand);
	return CSSM_OK;
}
Ejemplo n.º 9
0
/* Execute a single command. */
static int
execute_command(int argc, char * const *argv)
{
	const command *c;
	int found = 0;

	/* Nothing to do. */
	if (argc == 0)
		return 0;

	for (c = commands; c->c_name; ++c)
	{
		if (match_command(c->c_name, argv[0]))
		{
			found = 1;
			break;
		}
	}

	if (found)
	{
		int result;

		/* Reset getopt for command proc. */
		optind = 1;
		optreset = 1;

		if (do_verbose)
		{
			int ix;

			fprintf(stderr, "%s", c->c_name);
			for (ix = 1; ix < argc; ++ix)
				fprintf(stderr, " \"%s\"", argv[ix]);
			fprintf(stderr, "\n");
		}

		result = c->c_func(argc, argv);
		if (result == 2)
			fprintf(stderr, "Usage: %s %s\n        %s\n", c->c_name, c->c_usage, c->c_help);

		return result;
	}
	else
	{
		sec_error("unknown command \"%s\"", argv[0]);
		return 1;
	}
}
Ejemplo n.º 10
0
static int
do_keychain_show_info(const char *keychainName)
{
	SecKeychainRef keychain = NULL;
    SecKeychainSettings keychainSettings = { SEC_KEYCHAIN_SETTINGS_VERS1 };
	OSStatus result;

	if (keychainName)
	{
		keychain = keychain_open(keychainName);
		if (!keychain)
		{
			result = 1;
			goto loser;
		}
	}

	result = SecKeychainCopySettings(keychain, &keychainSettings);
	if (result)
	{
		sec_error("SecKeychainCopySettings %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result));
		goto loser;
	}

    fprintf(stderr,"Keychain \"%s\"%s%s",
		keychainName ? keychainName : "<NULL>",
		keychainSettings.lockOnSleep ? " lock-on-sleep" : "",
		keychainSettings.useLockInterval ? " use-lock-interval" : "");
	if (keychainSettings.lockInterval == INT_MAX)
		fprintf(stderr," no-timeout\n");
	else
		fprintf(stderr," timeout=%ds\n", (int)keychainSettings.lockInterval);

loser:
	if (keychain)
		CFRelease(keychain);
	return result;
}
Ejemplo n.º 11
0
/* The help command. */
static int
help(int argc, char * const *argv)
{
	const command *c;

	if (argc > 1)
	{
		char * const *arg;
		for (arg = argv + 1; *arg; ++arg)
		{
			int found = 0;

			for (c = commands; c->c_name; ++c)
			{
				if (match_command(c->c_name, *arg))
				{
					found = 1;
					break;
				}
			}

			if (found)
				printf("Usage: %s %s\n", c->c_name, c->c_usage);
			else
			{
				sec_error("%s: no such command: %s", argv[0], *arg);
				return 1;
			}
		}
	}
	else
	{
		for (c = commands; c->c_name; ++c)
			printf("    %-36s %s\n", c->c_name, c->c_help);
	}

	return 0;
}
BOOL cmd_flash_nand_img(const char *arg, void *data, unsigned sz)
{
	int index;
	u64 offset,size;
	int img_type;
	char *p_type;
	char msg[256];

    index = partition_get_index(arg);
    if(index == -1){
        fastboot_fail_wrapper("partition get index fail");
        return FALSE;
    }
    if(!is_support_flash(index)){
        sprintf(msg,"partition '%s' not support flash\n",arg);
        fastboot_fail_wrapper(msg);
        return FALSE;
    }

    offset = partition_get_offset(index);
    if(offset == (u64)(-1)){
        fastboot_fail_wrapper("partition get offset fail");
        return FALSE;
    }else{
        printf("get offset: 0x%llx\n",offset);
    }
    size = partition_get_size(index);
    if(size == (u64)(-1)){
        fastboot_fail_wrapper("partition get size fail");
        return FALSE;
    }else{
        printf("get size: 0x%llx\n",size);
    }

    if (!strcmp(arg, "boot") || !strcmp(arg, "recovery"))
    {
        if (memcmp((void *)data, BOOT_MAGIC, strlen(BOOT_MAGIC)))
        {
            fastboot_fail_wrapper("image is not a boot image");
            return FALSE;
        }
    }
    {
			char i_type[20] = {0};
			
			get_image_type(data,sz,(char *)i_type);
					
			partition_get_type(index,&p_type);
			
			if(strcmp(i_type,p_type)){
					display_info("[warning]image type is not match with partition type\n");
					dprintf(DBG_LV, "[warning]image type'%s' is not match with partition type'%s'",i_type,p_type);
			}
			if(!strcmp(i_type,"raw data")){
				img_type = RAW_DATA_IMG;	
			}else if(!strcmp(i_type,"yaffs2")){
				img_type = YFFS2_IMG;	
			}else if(!strcmp(i_type,"ubifs")){
				img_type = UBIFS_IMG;	
			}else{
					dprintf(DBG_LV, "image type '%s' unkown\n",i_type);
					display_info("\nimage type unkown");
					return FALSE;
			}
		}
    TIME_START;
    display_info("write flash ....");
    printf("writing %d bytes to '%s' img_type %d\n", sz, arg,img_type);
#if defined(MTK_MLC_NAND_SUPPORT)
    if (nand_write_img((u64)offset, (char*)data, sz,(u64)size,img_type)) {
#else
    if (nand_write_img((u32)offset, (char*)data, sz,(u32)size,img_type)) {
#endif
        fastboot_fail_wrapper("nand  write image failure");
        return FALSE;
    }
    printf("partition '%s' updated\n", arg);
    fastboot_ok_wrapper("write flash sucess",sz);

    return TRUE;
}


void cmd_flash_nand(const char *arg, void *data, unsigned sz)
{
	char msg[128] = {0};

	if(sz  == 0)
	{
		fastboot_okay("");
		return;
	}
	
#ifdef MTK_SECURITY_SW_SUPPORT    
    //Please DO NOT get any data for reference if security check is not passed
    if(!security_check((u8**)&data, &sz, 0, arg))
    {
        sprintf(msg, "\nSecurity deny - Err:0x%x \n", sec_error());
    	dprintf(DBG_LV, msg);
    	fastboot_fail_wrapper(msg);
        return;
    }
#endif

	dprintf(DBG_LV, "cmd_flash_nand, data:0x%x\n",*(int*)data);

    if(cmd_flash_nand_img(arg,data,sz))
    {
        //[Security] Notify security check that is the end.
        sz = 0;
    #ifdef MTK_SECURITY_SW_SUPPORT    
        security_check((u8**)&data, &sz, IMAGE_TRUNK_SIZE, arg); 
    #endif
    }
}
void cmd_flash_emmc(const char *arg, void *data, unsigned sz)
{
	sparse_header_t *sparse_header;
	/* 8 Byte Magic + 2048 Byte xml + Encrypted Data */
	//unsigned int *magic_number = (unsigned int *) data;
	BOOL write_ret = TRUE;
	char msg[128] = {0};
#if 0
	if (magic_number[0] == DECRYPT_MAGIC_0 &&
		magic_number[1] == DECRYPT_MAGIC_1)
	{
#ifdef SSD_ENABLE
		ret = decrypt_scm((u32 **) &data, &sz);
#endif
		if (ret != 0)
		{
			dprintf(CRITICAL, "ERROR: Invalid secure image\n");
			return;
		}
	}
	else if (magic_number[0] == ENCRYPT_MAGIC_0 &&
		magic_number[1] == ENCRYPT_MAGIC_1)
	{
#ifdef SSD_ENABLE
		ret = encrypt_scm((u32 **) &data, &sz);
#endif
		if (ret != 0)
		{
			dprintf(CRITICAL, "ERROR: Encryption Failure\n");
			return;
		}
	}
#endif
	if(sz  == 0)
	{
		fastboot_okay("");
		return;
	}

#ifdef MTK_SECURITY_SW_SUPPORT    
    //[Security] Please DO NOT get any data for reference if security check is not passed
    if(!security_check((u8**)&data, &sz, 0, arg))
    {
        sprintf(msg, "\nSecurity deny - Err:0x%x \n", sec_error());
    	dprintf(DBG_LV, msg);
    	fastboot_fail_wrapper((char*)msg);
        return;
    }
#endif

	sparse_header = (sparse_header_t *) data;

	dprintf(DBG_LV, "cmd_flash_emmc, data:0x%x,, n sparse_header->magic = 0x%x\n",*(int*)data, sparse_header->magic );

	if (sparse_header->magic != SPARSE_HEADER_MAGIC)
	{
		write_ret = cmd_flash_emmc_img(arg, data, sz);
	}
	else
	{
		write_ret = cmd_flash_emmc_sparse_img(arg, data, sz);
	}

    if( write_ret )
    {
        //[Security] Notify security check that is the end.
        sz = 0;
    #ifdef MTK_SECURITY_SW_SUPPORT    
        security_check((u8**)&data, &sz, IMAGE_TRUNK_SIZE, arg); 
    #endif
    }
}
static int
do_keychain_set_password(const char *keychainName, const char* oldPassword, const char* newPassword)
{
	SecKeychainRef keychain = NULL;
	OSStatus result = 1;
	UInt32 oldLen = (oldPassword) ? strlen(oldPassword) : 0;
	UInt32 newLen = (newPassword) ? strlen(newPassword) : 0;
	char *oldPass = (oldPassword) ? (char*)oldPassword : NULL;
	char *newPass = (newPassword) ? (char*)newPassword : NULL;
	char *oldBuf = NULL;
	char *newBuf = NULL;

	if (keychainName)
	{
		keychain = keychain_open(keychainName);
		if (!keychain)
		{
			result = 1;
			goto cleanup;
		}
	}

	if (!oldPass) {
		/* prompt for old password */
		char *pBuf = getpass("Old Password: "******"New Password: "******"Retype New Password: "******"try again");
		goto cleanup;
	}

	/* lock keychain first to remove existing credentials */
	(void)SecKeychainLock(keychain);

	/* change the password */
	result = SecKeychainChangePassword(keychain, oldLen, oldPass, newLen, newPass);
	if (result)
	{
		sec_error("error changing password for \"%s\": %s",
			keychainName ? keychainName : "<NULL>", sec_errstr(result));
	}

cleanup:
	/* if we allocated password buffers, zero and free them */
	if (oldBuf) {
		bzero(oldBuf, PW_BUF_SIZE);
		free(oldBuf);
	}
	if (newBuf) {
		bzero(newBuf, PW_BUF_SIZE);
		free(newBuf);
	}
	if (keychain) {
		CFRelease(keychain);
	}
	return result;
}
Ejemplo n.º 15
0
void
sec_perror(const char *msg, int err)
{
    sec_error("%s: %s", msg, sec_errstr(err));
}
int
keychain_export(int argc, char * const *argv)
{
	int ch, result = 0;

	char *outFile = NULL;
	char *kcName = NULL;
	SecKeychainRef kcRef = NULL;
	SecExternalFormat externFormat = kSecFormatUnknown;
	ItemSpec itemSpec = IS_All;
	int wrapped = 0;
	int doPem = 0;
	const char *passphrase = NULL;

    while ((ch = getopt(argc, argv, "k:o:t:f:P:wph")) != -1)
	{
		switch  (ch)
		{
		case 'k':
			kcName = optarg;
			break;
		case 'o':
			outFile = optarg;
			break;
		case 't':
			if(!strcmp("certs", optarg)) {
				itemSpec = IS_Certs;
			}
			else if(!strcmp("allKeys", optarg)) {
				itemSpec = IS_AllKeys;
			}
			else if(!strcmp("pubKeys", optarg)) {
				itemSpec = IS_PubKeys;
			}
			else if(!strcmp("privKeys", optarg)) {
				itemSpec = IS_PrivKeys;
			}
			else if(!strcmp("identities", optarg)) {
				itemSpec = IS_Identities;
			}
			else if(!strcmp("all", optarg)) {
				itemSpec = IS_All;
			}
			else {
				return 2; /* @@@ Return 2 triggers usage message. */
			}
			break;
		case 'f':
			if(!strcmp("openssl", optarg)) {
				externFormat = kSecFormatOpenSSL;
			}
			else if(!strcmp("openssh1", optarg)) {
				externFormat = kSecFormatSSH;
			}
			else if(!strcmp("openssh2", optarg)) {
				externFormat = kSecFormatSSHv2;
			}
			else if(!strcmp("bsafe", optarg)) {
				externFormat = kSecFormatBSAFE;
			}
			else if(!strcmp("raw", optarg)) {
				externFormat = kSecFormatRawKey;
			}
			else if(!strcmp("pkcs7", optarg)) {
				externFormat = kSecFormatPKCS7;
			}
			else if(!strcmp("pkcs8", optarg)) {
				externFormat = kSecFormatWrappedPKCS8;
			}
			else if(!strcmp("pkcs12", optarg)) {
				externFormat = kSecFormatPKCS12;
			}
			else if(!strcmp("netscape", optarg)) {
				externFormat = kSecFormatNetscapeCertSequence;
			}
			else if(!strcmp("x509", optarg)) {
				externFormat = kSecFormatX509Cert;
			}
			else if(!strcmp("pemseq", optarg)) {
				externFormat = kSecFormatPEMSequence;
			}
			else {
				return 2; /* @@@ Return 2 triggers usage message. */
			}
			break;
		case 'w':
			wrapped = 1;
			break;
		case 'p':
			doPem = 1;
			break;
		case 'P':
			passphrase = optarg;
			break;
		case '?':
		default:
			return 2; /* @@@ Return 2 triggers usage message. */
		}
	}

	if(wrapped) {
		switch(externFormat) {
			case kSecFormatOpenSSL:
			case kSecFormatUnknown:		// i.e., use default
				externFormat = kSecFormatWrappedOpenSSL;
				break;
			case kSecFormatSSH:
				externFormat = kSecFormatWrappedSSH;
				break;
			case kSecFormatSSHv2:
				/* there is no wrappedSSHv2 */
				externFormat = kSecFormatWrappedOpenSSL;
				break;
			case kSecFormatWrappedPKCS8:
				/* proceed */
				break;
			default:
				sec_error("Don't know how to wrap in specified format/type");
				return 2; /* @@@ Return 2 triggers usage message. */
		}
	}

	if(kcName) {
		kcRef = keychain_open(kcName);
		if(kcRef == NULL) {
			return 1;
		}
	}
	result = do_keychain_export(kcRef, externFormat, itemSpec,
		passphrase, doPem, outFile);

	if(kcRef) {
		CFRelease(kcRef);
	}
	return result;
}
Ejemplo n.º 17
0
int
leaks(int argc, char *const *argv)
{
	int result = 1;
	pid_t child;
	pid_t parent = getpid();

	child = fork();
	switch (child)
	{
	case -1:
		/* Fork failed we're hosed. */
		sec_error("fork: %s", strerror(errno));
		break;
	case 0:
	{
		/* child. */
		char **argvec = (char **)malloc((argc + 2) * sizeof(char *));
		char pidstr[8];
		int ix;

		sprintf(pidstr, "%d", parent);
		argvec[0] = "/usr/bin/leaks";
		for (ix = 1; ix < argc; ++ix)
			argvec[ix] = argv[ix];
		argvec[ix] = pidstr;
		argvec[ix + 1] = NULL;

		execv(argvec[0], argvec);
		sec_error("exec: %s", strerror(errno));
		_exit(1);
		break;
	}
	default:
	{
		/* Parent. */
		int status = 0;
		for (;;)
		{
			/* Wait for the child to exit. */
			pid_t waited_pid = waitpid(child, &status, 0);
			if (waited_pid == -1)
			{
				int error = errno;
				/* Keep going if we get interupted but bail out on any
				   other error. */
				if (error == EINTR)
					continue;

				sec_error("waitpid %d: %s", status, strerror(errno));
				break;
			}

			if (WIFEXITED(status))
			{
				if (WEXITSTATUS(status))
				{
					/* Force usage message. */
					result = 2;
					sec_error("leaks exited: %d", result);
				}
				break;
			}
			else if (WIFSIGNALED(status))
			{
				sec_error("leaks terminated by signal: %d", WTERMSIG(status));
				break;
			}
		}
		break;
	}
	}

	return result;
}
int
keychain_import(int argc, char * const *argv)
{
	int ch, result = 0;

	char *inFile = NULL;
	char *kcName = NULL;
	SecKeychainRef kcRef = NULL;
	SecExternalFormat externFormat = kSecFormatUnknown;
	SecExternalItemType itemType = kSecItemTypeUnknown;
	Boolean wrapped = FALSE;
	Boolean nonExtractable = FALSE;
	const char *passphrase = NULL;
	unsigned char *inFileData = NULL;
	unsigned inFileLen = 0;
	CFDataRef inData = NULL;
	unsigned numExtendedAttributes = 0;
	char **attrNames = NULL;
	char **attrValues = NULL;
	Boolean access_specified = FALSE;
	Boolean always_allow = FALSE;
	SecAccessRef access = NULL;
	CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	if(argc < 2) {
		result = 2; /* @@@ Return 2 triggers usage message. */
		goto cleanup;
	}
	inFile = argv[1];
	if((argc == 2) && (inFile[0] == '-')) {
		result = 2;
		goto cleanup;
	}
	optind = 2;

    while ((ch = getopt(argc, argv, "k:t:f:P:wxa:hAT:")) != -1)
	{
		switch  (ch)
		{
		case 'k':
			kcName = optarg;
			break;
		case 't':
			if(!strcmp("pub", optarg)) {
				itemType = kSecItemTypePublicKey;
			}
			else if(!strcmp("priv", optarg)) {
				itemType = kSecItemTypePrivateKey;
			}
			else if(!strcmp("session", optarg)) {
				itemType = kSecItemTypeSessionKey;
			}
			else if(!strcmp("cert", optarg)) {
				itemType = kSecItemTypeCertificate;
			}
			else if(!strcmp("agg", optarg)) {
				itemType = kSecItemTypeAggregate;
			}
			else {
				result = 2; /* @@@ Return 2 triggers usage message. */
				goto cleanup;
			}
			break;
		case 'f':
			if(!strcmp("openssl", optarg)) {
				externFormat = kSecFormatOpenSSL;
			}
			else if(!strcmp("openssh1", optarg)) {
				externFormat = kSecFormatSSH;
			}
			else if(!strcmp("openssh2", optarg)) {
				externFormat = kSecFormatSSHv2;
			}
			else if(!strcmp("bsafe", optarg)) {
				externFormat = kSecFormatBSAFE;
			}
			else if(!strcmp("raw", optarg)) {
				externFormat = kSecFormatRawKey;
			}
			else if(!strcmp("pkcs7", optarg)) {
				externFormat = kSecFormatPKCS7;
			}
			else if(!strcmp("pkcs8", optarg)) {
				externFormat = kSecFormatWrappedPKCS8;
			}
			else if(!strcmp("pkcs12", optarg)) {
				externFormat = kSecFormatPKCS12;
			}
			else if(!strcmp("netscape", optarg)) {
				externFormat = kSecFormatNetscapeCertSequence;
			}
			else if(!strcmp("x509", optarg)) {
				externFormat = kSecFormatX509Cert;
			}
			else if(!strcmp("pemseq", optarg)) {
				externFormat = kSecFormatPEMSequence;
			}
			else {
				result = 2; /* @@@ Return 2 triggers usage message. */
				goto cleanup;
			}
			break;
		case 'w':
			wrapped = TRUE;
			break;
		case 'x':
			nonExtractable = TRUE;
			break;
		case 'P':
			passphrase = optarg;
			break;
		case 'a':
			/* this takes an additional argument */
			if(optind > (argc - 1)) {
				result = 2; /* @@@ Return 2 triggers usage message. */
				goto cleanup;
			}
			attrNames  = (char **)realloc(attrNames, numExtendedAttributes * sizeof(char *));
			attrValues = (char **)realloc(attrValues, numExtendedAttributes * sizeof(char *));
			attrNames[numExtendedAttributes]  = optarg;
			attrValues[numExtendedAttributes] = argv[optind];
			numExtendedAttributes++;
			optind++;
			break;
		case 'A':
			always_allow = TRUE;
			access_specified = TRUE;
			break;
		case 'T':
			if (optarg[0])
			{
				SecTrustedApplicationRef app = NULL;
				OSStatus status = noErr;
				/* check whether the argument specifies an application group */
				const char *groupPrefix = "group://";
				size_t prefixLen = strlen(groupPrefix);
				if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) {
					const char *groupName = &optarg[prefixLen];
					if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) {
						sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status));
					}
				} else {
					if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) {
						sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status));
					}
				}

				if (status) {
					result = 1;
					goto cleanup;
				}

				CFArrayAppendValue(trusted_list, app);
				CFRelease(app);
			}
			access_specified = TRUE;
			break;
		case '?':
		default:
			result = 2; /* @@@ Return 2 triggers usage message. */
			goto cleanup;
		}
	}

	if(wrapped) {
		switch(externFormat) {
			case kSecFormatOpenSSL:
			case kSecFormatUnknown:		// i.e., use default
				externFormat = kSecFormatWrappedOpenSSL;
				break;
			case kSecFormatSSH:
				externFormat = kSecFormatWrappedSSH;
				break;
			case kSecFormatSSHv2:
				/* there is no wrappedSSHv2 */
				externFormat = kSecFormatWrappedOpenSSL;
				break;
			case kSecFormatWrappedPKCS8:
				/* proceed */
				break;
			default:
				fprintf(stderr, "Don't know how to wrap in specified format/type\n");
				result = 2; /* @@@ Return 2 triggers usage message. */
				goto cleanup;
		}
	}

	if(kcName) {
		kcRef = keychain_open(kcName);
		if(kcRef == NULL) {
			return 1;
		}
	}
	if(readFile(inFile, &inFileData, &inFileLen)) {
		sec_error("Error reading infile %s: %s", inFile, strerror(errno));
		result = 1;
		goto cleanup;
	}
	inData = CFDataCreate(NULL, inFileData, inFileLen);
	if(inData == NULL) {
		result = 1;
		goto cleanup;
	}
	free(inFileData);

	if(access_specified)
	{
		char *accessName = NULL;
		CFStringRef fileStr = CFStringCreateWithCString(NULL, inFile, kCFStringEncodingUTF8);
		if (fileStr) {
			CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE);
			if (fileURL) {
				CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL);
				if (nameStr) {
					CFIndex nameLen = CFStringGetLength(nameStr);
					CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8);
					accessName = (char *)malloc(bufLen);
					if (!CFStringGetCString(nameStr, accessName, bufLen-1, kCFStringEncodingUTF8))
						accessName[0]=0;
					nameLen = strlen(accessName);
					char *p = &accessName[nameLen]; // initially points to terminating null
					while (--nameLen > 0) {
						if (*p == '.') { // strip extension, if any
							*p = '\0';
							break;
						}
						p--;
					}
					safe_CFRelease(&nameStr);
				}
				safe_CFRelease(&fileURL);
			}
			safe_CFRelease(&fileStr);
		}

		result = create_access(accessName, always_allow, trusted_list, &access);

		if (accessName) {
			free(accessName);
		}
		if (result != 0) {
			goto cleanup;
		}
	}

	result = do_keychain_import(kcRef, inData, externFormat, itemType, access,
								nonExtractable, passphrase, inFile, attrNames,
								attrValues, numExtendedAttributes);

cleanup:
	safe_CFRelease(&trusted_list);
	safe_CFRelease(&access);
	safe_CFRelease(&kcRef);
	safe_CFRelease(&inData);

	return result;
}
Ejemplo n.º 19
0
/*
 * Find private key by label, modify its Label attr to be the
 * hash of the associated public key.
 */
static CSSM_RETURN setPubKeyHash(
	CSSM_CSP_HANDLE 	cspHand,
	CSSM_DL_DB_HANDLE 	dlDbHand,
	const CSSM_KEY		*pubOrPrivKey,	// to get hash; raw or ref/CSPDL
	const char			*keyLabel)		// look up by this
{
	CSSM_QUERY						query;
	CSSM_SELECTION_PREDICATE		predicate;
	CSSM_DB_UNIQUE_RECORD_PTR		record = NULL;
	CSSM_RETURN						crtn;
	CSSM_DATA						labelData;
	CSSM_HANDLE						resultHand;

	labelData.Data = (uint8 *)keyLabel;
	labelData.Length = strlen(keyLabel) + 1;	// incl. NULL
	query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
	query.Conjunctive = CSSM_DB_NONE;
	query.NumSelectionPredicates = 1;
	predicate.DbOperator = CSSM_DB_EQUAL;

	predicate.Attribute.Info.AttributeNameFormat =
		CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
	predicate.Attribute.Info.Label.AttributeName = "Label";
	predicate.Attribute.Info.AttributeFormat =
		CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
	predicate.Attribute.Value = &labelData;
	query.SelectionPredicate = &predicate;

	query.QueryLimits.TimeLimit = 0;
	query.QueryLimits.SizeLimit = 1;
	query.QueryFlags = 0;

	/* build Record attribute with one attr */
	CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
	CSSM_DB_ATTRIBUTE_DATA attr;
	attr.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
	attr.Info.Label.AttributeName = "Label";
	attr.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;

	recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
	recordAttrs.NumberOfAttributes = 1;
	recordAttrs.AttributeData = &attr;

	crtn = CSSM_DL_DataGetFirst(dlDbHand,
		&query,
		&resultHand,
		&recordAttrs,
		NULL,			// hopefully optional ...theData,
		&record);
	/* abort only on success */
	if(crtn != CSSM_OK) {
		sec_error("CSSM_DL_DataGetFirst: setPubKeyHash: can't find private key: %s", sec_errstr(crtn));
		return crtn;
	}

	/*
	 * If specified key is a ref key, do NULL unwrap for use with raw CSP.
	 * If the CSPDL and SecurityServer support the key digest passthrough
	 * this is unnecessary.
	 */
	CSSM_KEY rawKeyToDigest;
	if(pubOrPrivKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) {
		crtn = refKeyToRaw(cspHand, pubOrPrivKey, &rawKeyToDigest);
		if(crtn) {
            sec_error("setPubKeyHash: Error converting public key to raw format: %s", sec_errstr(crtn));
			return crtn;
		}
	}
	else {
		/* use as is */
		rawKeyToDigest = *pubOrPrivKey;
	}

	/* connect to raw CSP */
	CSSM_CSP_HANDLE rawCspHand = srCspStartup(CSSM_TRUE);
	if(rawCspHand == 0) {
		printf("***Error connecting to raw CSP; aborting.\n");
		return -1;
	}

	/* calculate hash of pub key from private or public part */
	CSSM_DATA_PTR keyDigest = NULL;
	CSSM_CC_HANDLE ccHand;
	crtn = CSSM_CSP_CreatePassThroughContext(rawCspHand,
	 	&rawKeyToDigest,
		&ccHand);
	if(ccHand == 0) {
        sec_error("CSSM_CSP_CreatePassThroughContext: Error calculating public key hash. Aborting: %s", sec_errstr(crtn));
		return -1;
	}
	crtn = CSSM_CSP_PassThrough(ccHand,
		CSSM_APPLECSP_KEYDIGEST,
		NULL,
		(void **)&keyDigest);
	if(crtn) {
        sec_error("CSSM_CSP_PassThrough(PUBKEYHASH): Error calculating public key hash. Aborting: %s", sec_errstr(crtn));
		return crtn;
	}
	if(pubOrPrivKey->KeyHeader.BlobType == CSSM_KEYBLOB_REFERENCE) {
		/* created in refKeyToRaw().... */
		CSSM_FreeKey(cspHand, NULL, &rawKeyToDigest, CSSM_FALSE);
	}
	CSSM_DeleteContext(ccHand);
	CSSM_ModuleDetach(rawCspHand);

	/*
	 * Replace Label attr data with hash.
	 * NOTE: the module which allocated this attribute data - a DL -
	 * was loaded and attached by the Sec layer, not by us. Thus
	 * we can't use the memory allocator functions *we* used when
	 * attaching to the CSPDL - we have to use the ones
	 * which the Sec layer registered with the DL.
	 */
	CSSM_API_MEMORY_FUNCS memFuncs;
	crtn = CSSM_GetAPIMemoryFunctions(dlDbHand.DLHandle, &memFuncs);
	if(crtn) {
        sec_error("CSSM_GetAPIMemoryFunctions(DLHandle): Error: %s", sec_errstr(crtn));
		/* oh well, leak and continue */
	}
	else {
		memFuncs.free_func(attr.Value->Data, memFuncs.AllocRef);
		memFuncs.free_func(attr.Value, memFuncs.AllocRef);
	}
	attr.Value = keyDigest;

	/* modify key attributes */
	crtn = CSSM_DL_DataModify(dlDbHand,
			CSSM_DL_DB_RECORD_PRIVATE_KEY,
			record,
			&recordAttrs,
            NULL,				// DataToBeModified
			CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
	if(crtn) {
        sec_error("CSSM_DL_DataModify(PUBKEYHASH): Error setting public key hash. Aborting: %s", sec_errstr(crtn));
		return crtn;
	}
	crtn = CSSM_DL_DataAbortQuery(dlDbHand, resultHand);
	if(crtn) {
        sec_error("CSSM_DL_DataAbortQuery: Error while stopping query: %s", sec_errstr(crtn));
		/* let's keep going in this case */
	}
	crtn = CSSM_DL_FreeUniqueRecord(dlDbHand, record);
	if(crtn) {
        sec_error("CSSM_DL_FreeUniqueRecord: Error while freeing record: %s", sec_errstr(crtn));
		/* let's keep going in this case */
		crtn = CSSM_OK;
	}

	/* free resources */
    if (keyDigest)
    {
        srAppFree(keyDigest->Data, NULL);
        srAppFree(keyDigest, NULL);
    }
	return CSSM_OK;
}
Ejemplo n.º 20
0
OSStatus createRootCert(
	CSSM_TP_HANDLE		tpHand,
	CSSM_CL_HANDLE		clHand,
	CSSM_CSP_HANDLE		cspHand,
	CSSM_KEY_PTR		subjPubKey,
	CSSM_KEY_PTR		signerPrivKey,
	const char			*hostName,			// CSSMOID_CommonName
	const char 			*userName,			// CSSMOID_Description
	CSSM_ALGORITHMS 	sigAlg,
	const CSSM_OID		*sigOid,
	CSSM_DATA_PTR		certData)			// mallocd and RETURNED
{
	CE_DataAndType 				exts[2];
	CE_DataAndType 				*extp = exts;
	unsigned					numExts;
	CSSM_DATA					refId;		// mallocd by
											//    CSSM_TP_SubmitCredRequest
	CSSM_APPLE_TP_CERT_REQUEST	certReq;
	CSSM_TP_REQUEST_SET			reqSet;
	sint32						estTime;
	CSSM_BOOL					confirmRequired;
	CSSM_TP_RESULT_SET_PTR		resultSet=NULL;
	CSSM_ENCODED_CERT			*encCert=NULL;
	CSSM_APPLE_TP_NAME_OID		subjectNames[2];
	CSSM_TP_CALLERAUTH_CONTEXT 	CallerAuthContext;
	CSSM_FIELD					policyId;

	numExts = 0;

	certReq.challengeString = NULL;

	/* KeyUsage extension */
	extp->type = DT_KeyUsage;
	extp->critical = CSSM_FALSE;
	extp->extension.keyUsage = CE_KU_DigitalSignature |
							   CE_KU_KeyCertSign |
							   CE_KU_KeyEncipherment |
							   CE_KU_DataEncipherment;
	extp++;
	numExts++;

	/* BasicConstraints */
	extp->type = DT_BasicConstraints;
	extp->critical = CSSM_TRUE;
	extp->extension.basicConstraints.cA = CSSM_FALSE;
	extp->extension.basicConstraints.pathLenConstraintPresent = CSSM_FALSE;
	extp++;
	numExts++;

	/* name array */
	subjectNames[0].string 	= hostName;
	subjectNames[0].oid 	= &CSSMOID_CommonName;
	subjectNames[1].string	= userName;
	subjectNames[1].oid 	= &CSSMOID_Description;

	/* certReq */
	certReq.cspHand = cspHand;
	certReq.clHand = clHand;
	randUint32(&certReq.serialNumber);		// random serial number
	certReq.numSubjectNames = 2;
	certReq.subjectNames = subjectNames;

	certReq.numIssuerNames = 0;				// root for now
	certReq.issuerNames = NULL;
	certReq.issuerNameX509 = NULL;
	certReq.certPublicKey = subjPubKey;
	certReq.issuerPrivateKey = signerPrivKey;
	certReq.signatureAlg = sigAlg;
	certReq.signatureOid = *sigOid;
	certReq.notBefore = 0;
	certReq.notAfter = 60 * 60 * 24 * 365;	// seconds from now, one year
	certReq.numExtensions = numExts;
	certReq.extensions = exts;

	reqSet.NumberOfRequests = 1;
	reqSet.Requests = &certReq;

	/* a CSSM_TP_CALLERAUTH_CONTEXT to specify an OID */
	memset(&CallerAuthContext, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
	memset(&policyId, 0, sizeof(CSSM_FIELD));
	policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN;

	CallerAuthContext.Policy.NumberOfPolicyIds = 1;
	CallerAuthContext.Policy.PolicyIds = &policyId;

	CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tpHand,
		NULL,				// PreferredAuthority
		CSSM_TP_AUTHORITY_REQUEST_CERTISSUE,
		&reqSet,
		&CallerAuthContext,
		&estTime,
		&refId);

	if(crtn) {
		sec_error("CSSM_TP_SubmitCredRequest: %s", sec_errstr(crtn));
		goto xit;
	}
	crtn = CSSM_TP_RetrieveCredResult(tpHand,
		&refId,
		NULL,				// CallerAuthCredentials
		&estTime,
		&confirmRequired,
		&resultSet);
	if(crtn) {
		sec_error("CSSM_TP_RetrieveCredResult: %s", sec_errstr(crtn));
		goto xit;
	}
	if(resultSet == NULL) {
		sec_error("CSSM_TP_RetrieveCredResult: returned NULL result set");
		crtn = ioErr;
		goto xit;
	}
	encCert = (CSSM_ENCODED_CERT *)resultSet->Results;
    certData->Length = encCert->CertBlob.Length;
    certData->Data = malloc(encCert->CertBlob.Length);
    if (certData->Data)
        memcpy(certData->Data, encCert->CertBlob.Data, encCert->CertBlob.Length);
	crtn = noErr;

xit:
	/* free resources allocated by TP */
	APP_FREE(refId.Data);
    if (encCert)
    {
        if (encCert->CertBlob.Data)
        {
            APP_FREE(encCert->CertBlob.Data);
        }
        APP_FREE(encCert);
    }
	APP_FREE(resultSet);
	return crtn;
}
static int
do_recode(const char *keychainName1, const char *keychainName2)
{
	SecKeychainRef keychain1 = NULL, keychain2 = NULL;
	CFMutableArrayRef dbBlobArray = NULL;
	CFDataRef dbBlob = NULL, extraData = NULL;
	OSStatus result;

	if (keychainName1)
	{
		keychain1 = keychain_open(keychainName1);
		if (!keychain1)
		{
			result = 1;
			goto loser;
		}
	}

	keychain2 = keychain_open(keychainName2);
	if (!keychain2)
	{
		result = 1;
		goto loser;
	}

	result = SecKeychainCopyBlob(keychain2, &dbBlob);
	if (result)
	{
		sec_error("SecKeychainCopyBlob %s: %s", keychainName2,
			sec_errstr(result));
		goto loser;
	}

	extraData = CFDataCreate(NULL, NULL, 0);

	dbBlobArray = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
	if (dbBlobArray) {
		CFArrayAppendValue(dbBlobArray, dbBlob);
	}

#if !defined MAC_OS_X_VERSION_10_6 || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
	result = SecKeychainRecodeKeychain(keychain1, dbBlob, extraData);
#else
	result = SecKeychainRecodeKeychain(keychain1, dbBlobArray, extraData);
#endif
	if (result)
		sec_error("SecKeychainRecodeKeychain %s, %s: %s", keychainName1,
			keychainName2, sec_errstr(result));

loser:
	if (dbBlobArray)
		CFRelease(dbBlobArray);
	if (dbBlob)
		CFRelease(dbBlob);
	if (extraData)
		CFRelease(extraData);
	if (keychain1)
		CFRelease(keychain1);
	if (keychain2)
		CFRelease(keychain2);

	return result;
}
int write_storage_proc(void *arg)
{
	u8* data = 0;
	u32 data_len = 0;
	char msg[128];
	u64 image_offset = 0;
    u32 round = 0;

	//dprintf(DBG_DCACHE, "   --[%d] Enter write_storage_proc \n", TIME_STAMP);
	for (;;)
	{
		dprintf(DBG_DCACHE, "   --[%d]Wait ID:%d  cache to read, \n", TIME_STAMP, ctx.flipIdxR);
		event_wait(&(ctx.dual_cache[ctx.flipIdxR].content_available));
		dprintf(DBG_DCACHE, "   --[%d]Obtain ID:%d  cache to read, \n", TIME_STAMP, ctx.flipIdxR);
		if(ctx.b_error)
		{
			sprintf(msg, "\nError USB?\n");
			goto error;
		}
		//if has something to write
		if(ctx.dual_cache[ctx.flipIdxR].content_length !=0  || ctx.dual_cache[ctx.flipIdxR].padding_length !=0)
		{
			data = (u8*)(ctx.dual_cache[ctx.flipIdxR].cache_buf);
			data_len = ctx.dual_cache[ctx.flipIdxR].content_length;

		#ifdef MTK_SECURITY_SW_SUPPORT    
			if(!security_check(&data, &data_len, image_offset, NULL))
			{
				//security error.
				sprintf(msg, "\nSecurity deny - Err:0x%x \n", sec_error());
				goto error;
			}
		#endif
			
			image_offset += ctx.dual_cache[ctx.flipIdxR].content_length;

			data -=  ctx.dual_cache[ctx.flipIdxR].padding_length;
			data_len += ctx.dual_cache[ctx.flipIdxR].padding_length;
			//if data_len==0, secure img tail met.

			dprintf(DBG_DCACHE, "   --[%d]Write ID:%d  to EMMC \n", TIME_STAMP, ctx.flipIdxR);
        #ifdef MTK_SECURITY_SW_SUPPORT    			
			if(!write_data(data, data_len, sec_lib_security_get_img_total_size()))
	    #else
            if(!write_data(data, data_len, 0))
	    #endif
			{
				//error
				sprintf(msg, "\nWrite data error. \n");
				goto error;
			}
		}

		//last package, should return;
		if (ctx.dual_cache[ctx.flipIdxR].content_length == 0)
		{
			dprintf(DBG_DCACHE, "  --[%d]Write EMMC Fin\n", TIME_STAMP);

			data_len = 0;
			
		#ifdef MTK_SECURITY_SW_SUPPORT    
            security_check(&data, &data_len, image_offset, NULL); //notify security check that is the end.
        #endif

			if(ctx.boot_like_info.is_boot_like_image)
			{
				//boot image need download_size to flash.
				download_size = sto_info.to_write_data_len;
				//cache using is over, so copy boot image to download_base
				memcpy(download_base, ctx.boot_like_info.boot_like_image_address, download_size);
			}

			event_signal(&ctx.dual_cache[0].cache_available, SIGNAL_RESCHEDULE);//prevent from dead lock.
			event_signal(&ctx.dual_cache[1].cache_available, SIGNAL_RESCHEDULE);
			event_signal(&ctx.thr_end_ev, SIGNAL_RESCHEDULE);
			return 0;
		}

        round++;
		dprintf(DBG_DCACHE, "   --[%d]Notify ID:%d cache writeable\n", TIME_STAMP, ctx.flipIdxR);
		event_signal(&ctx.dual_cache[ctx.flipIdxR].cache_available, SIGNAL_RESCHEDULE); //make this cache writeable again.

		ctx.flipIdxR = cache_shift(ctx.flipIdxR); //change next buffer.
	}
	return 0;
error:
	dprintf(DBG_LV, msg);
	display_info(msg);
	abort_engine(&ctx);
	return (-1);
}
//	find_unique_certificate
//
//	Returns a SecKeychainItemRef for the certificate
//	in the specified keychain (or keychain list)
//	which is a unique match for either the specified name
//	or SHA-1 hash. If more than one match exists, the
//	certificate is not unique and none are returned. Caller is
//	responsible for releasing the item (with CFRelease).
//
SecKeychainItemRef
find_unique_certificate(CFTypeRef keychainOrArray,
	const char *name,
	const char *hash)
{
	OSStatus status = noErr;
	SecKeychainSearchRef searchRef = NULL;
	SecKeychainItemRef uniqueItemRef = NULL;

	status = SecKeychainSearchCreateFromAttributes(keychainOrArray, kSecCertificateItemClass, NULL, &searchRef);
	if (status) {
		return uniqueItemRef;
	}

	// check input hash string and convert to data
	CSSM_DATA hashData = { 0, NULL };
	if (hash) {
		CSSM_SIZE len = strlen(hash)/2;
		hashData.Length = len;
		hashData.Data = (uint8 *)malloc(hashData.Length);
		fromHex(hash, &hashData);
	}

	// filter candidates against the hash (or the name, if no hash provided)
	CFStringRef matchRef = (name) ? CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8) : NULL;
	Boolean exactMatch = FALSE;

	CSSM_DATA certData = { 0, NULL };
	SecKeychainItemRef candidate = NULL;

	while (SecKeychainSearchCopyNext(searchRef, &candidate) == noErr) {
		SecCertificateRef cert = (SecCertificateRef)candidate;
		if (SecCertificateGetData(cert, &certData) != noErr) {
			safe_CFRelease(&candidate);
			continue;
		}
		if (hash) {
			uint8 candidate_sha1_hash[20];
			CSSM_DATA digest;
			digest.Length = sizeof(candidate_sha1_hash);
			digest.Data = candidate_sha1_hash;
			if ((SecDigestGetData(CSSM_ALGID_SHA1, &digest, &certData) == CSSM_OK) &&
				(hashData.Length == digest.Length) &&
				(!memcmp(hashData.Data, digest.Data, digest.Length))) {
				exactMatch = TRUE;
				uniqueItemRef = candidate; // currently retained
				break; // we're done - can't get more exact than this
			}
		} else {
			// copy certificate name
			CFStringRef nameRef = NULL;
			if ((SecCertificateCopyCommonName(cert, &nameRef) != noErr) || nameRef == NULL) {
				safe_CFRelease(&candidate);
				continue; // no name, so no match is possible
			}
			CFIndex nameLen = CFStringGetLength(nameRef);
			CFIndex bufLen = 1 + CFStringGetMaximumSizeForEncoding(nameLen, kCFStringEncodingUTF8);
			char *nameBuf = (char *)malloc(bufLen);
			if (!CFStringGetCString(nameRef, nameBuf, bufLen-1, kCFStringEncodingUTF8))
				nameBuf[0]=0;

			CFRange find = { kCFNotFound, 0 };
			if (nameRef && matchRef)
				find = CFStringFind(nameRef, matchRef, kCFCompareCaseInsensitive | kCFCompareNonliteral);
			Boolean isExact = (find.location == 0 && find.length == nameLen);
			if (find.location == kCFNotFound) {
				free(nameBuf);
				safe_CFRelease(&nameRef);
				safe_CFRelease(&candidate);
				continue; // no match
			}
			if (uniqueItemRef) {	// got two matches
				if (exactMatch && !isExact)	{	// prior is better; ignore this one
					free(nameBuf);
					safe_CFRelease(&nameRef);
					safe_CFRelease(&candidate);
					continue;
				}
				if (exactMatch == isExact) {	// same class of match
					if (CFEqual(uniqueItemRef, candidate)) {	// same certificate
						free(nameBuf);
						safe_CFRelease(&nameRef);
						safe_CFRelease(&candidate);
						continue;
					}
					// ambiguity - must fail
					sec_error("\"%s\" is ambiguous, matches more than one certificate", name);
					free(nameBuf);
					safe_CFRelease(&nameRef);
					safe_CFRelease(&candidate);
					safe_CFRelease(&uniqueItemRef);
					break;
				}
				safe_CFRelease(&uniqueItemRef); // about to replace with this one
			}
			uniqueItemRef = candidate; // currently retained
			exactMatch = isExact;
			free(nameBuf);
			safe_CFRelease(&nameRef);
		}
	}

	safe_CFRelease(&searchRef);
	safe_CFRelease(&matchRef);
	if (hashData.Data) {
		free(hashData.Data);
	}

	return uniqueItemRef;
}
static int do_keychain_export(
	SecKeychainRef		kcRef,
	SecExternalFormat   externFormat,
	ItemSpec			itemSpec,
	const char			*passphrase,
	int					doPem,
	const char			*fileName)
{
	int result = 0;
	CFIndex numItems;
	unsigned numPrivKeys = 0;
	unsigned numPubKeys = 0;
	unsigned numCerts = 0;
	unsigned numIdents = 0;
	OSStatus ortn;
	uint32 expFlags = 0;		// SecItemImportExportFlags
	SecKeyImportExportParameters keyParams;
	CFStringRef	passStr = NULL;
	CFDataRef outData = NULL;
	unsigned len;

	/* gather items */
	CFMutableArrayRef exportItems = CFArrayCreateMutable(NULL, 0,
		&kCFTypeArrayCallBacks);
	switch(itemSpec) {
		case IS_Certs:
			ortn = addKcItems(kcRef, kSecCertificateItemClass, exportItems, &numCerts);
			if(ortn) {
				result = 1;
				goto loser;
			}
			break;

		case IS_PrivKeys:
			ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, exportItems,
				&numPrivKeys);
			if(ortn) {
				result = 1;
				goto loser;
			}
			break;

		case IS_PubKeys:
			ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PUBLIC_KEY, exportItems,
				&numPubKeys);
			if(ortn) {
				result = 1;
				goto loser;
			}
			break;

		case IS_AllKeys:
			ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, exportItems,
				&numPrivKeys);
			if(ortn) {
				result = 1;
				goto loser;
			}
			ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PUBLIC_KEY, exportItems,
				&numPubKeys);
			if(ortn) {
				result = 1;
				goto loser;
			}
			break;

		case IS_All:
			/* No public keys here - PKCS12 doesn't support them */
			ortn = addKcItems(kcRef, kSecCertificateItemClass, exportItems, &numCerts);
			if(ortn) {
				result = 1;
				goto loser;
			}
			ortn = addKcItems(kcRef, CSSM_DL_DB_RECORD_PRIVATE_KEY, exportItems,
				&numPrivKeys);
			if(ortn) {
				result = 1;
				goto loser;
			}
			break;

		case IS_Identities:
			ortn = addIdentities(kcRef, exportItems, &numIdents);
			if(ortn) {
				result = 1;
				goto loser;
			}
			if(numIdents) {
				numPrivKeys += numIdents;
				numCerts    += numIdents;
			}
			break;
		default:
			sec_error("Internal error parsing item_spec");
			result = 1;
			goto loser;
	}

	numItems = CFArrayGetCount(exportItems);
	if(externFormat == kSecFormatUnknown) {
		/* Use default export format per set of items */
		if(numItems > 1) {
			externFormat = kSecFormatPEMSequence;
		}
		else if(numCerts) {
			externFormat = kSecFormatX509Cert;
		}
		else {
			externFormat = kSecFormatOpenSSL;
		}
	}
	if(doPem) {
		expFlags |= kSecItemPemArmour;
	}

	/*
	 * Key related arguments, ignored if we're not exporting keys.
	 * Always specify some kind of passphrase - default is secure passkey.
	 */
	memset(&keyParams, 0, sizeof(keyParams));
	keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
	if(passphrase != NULL) {
		passStr = CFStringCreateWithCString(NULL, passphrase, kCFStringEncodingASCII);
		keyParams.passphrase = passStr;
	}
	else {
		keyParams.flags = kSecKeySecurePassphrase;
	}

	/* Go */
	ortn = SecKeychainItemExport(exportItems, externFormat, expFlags, &keyParams,
		&outData);
	if(ortn) {
		sec_perror("SecKeychainItemExport", ortn);
		result = 1;
		goto loser;
	}

	len = CFDataGetLength(outData);
	if(fileName) {
		int rtn = writeFile(fileName, CFDataGetBytePtr(outData), len);
		if(rtn == 0) {
			if(!do_quiet) {
				fprintf(stderr, "...%u bytes written to %s\n", len, fileName);
			}
		}
		else {
			sec_error("Error writing to %s: %s", fileName, strerror(errno));
			result = 1;
		}
	}
	else {
		int irtn = write(STDOUT_FILENO, CFDataGetBytePtr(outData), len);
		if(irtn != (int)len) {
			perror("write");
		}
	}
loser:
	if(exportItems) {
		CFRelease(exportItems);
	}
	if(passStr) {
		CFRelease(passStr);
	}
	if(outData) {
		CFRelease(outData);
	}
	return result;
}
static int do_keychain_import(
	SecKeychainRef		kcRef,
	CFDataRef			inData,
	SecExternalFormat   externFormat,
	SecExternalItemType itemType,
	SecAccessRef		access,
	Boolean				nonExtractable,
	const char			*passphrase,
	const char			*fileName,
	char				**attrNames,
	char				**attrValues,
	unsigned			numExtendedAttributes)
{
	SecKeyImportExportParameters	keyParams;
	OSStatus		ortn;
	CFStringRef		fileStr;
	CFArrayRef		outArray = NULL;
	int				result = 0;
	int				numCerts = 0;
	int				numKeys = 0;
	int				numIdentities = 0;
	int				tryCount = 0;
	CFIndex			dex;
	CFIndex			numItems = 0;
	CFStringRef		passStr = NULL;
	CFStringRef		promptStr = NULL;
	CFStringRef		retryStr = NULL;

	/*
	 * Specify some kind of passphrase in case caller doesn't know this
	 * is a wrapped object
	 */
	memset(&keyParams, 0, sizeof(SecKeyImportExportParameters));
	keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
	if(passphrase != NULL) {
		passStr = CFStringCreateWithCString(NULL, passphrase, kCFStringEncodingASCII);
		keyParams.passphrase = passStr;
	}
	else {
		keyParams.flags = kSecKeySecurePassphrase;
	}
	if(nonExtractable) {
        // explicitly set the key attributes, omitting the CSSM_KEYATTR_EXTRACTABLE bit
        keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE;
    }
	keyParams.accessRef = access;

	fileStr = CFStringCreateWithCString(NULL, fileName, kCFStringEncodingUTF8);
	if (fileStr) {
		CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE);
		if (fileURL) {
			CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL);
			if (nameStr) {
				safe_CFRelease(&fileStr);
				fileStr = nameStr;
			}
			safe_CFRelease(&fileURL);
		}
	}
	promptStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_MESSAGE, fileStr);
	retryStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_RETRYMESSAGE, fileStr);

	while (TRUE)
	{
		keyParams.alertPrompt = (tryCount == 0) ? promptStr : retryStr;

		ortn = SecKeychainItemImport(inData,
									 fileStr,
									 &externFormat,
									 &itemType,
									 0,		/* flags not used (yet) */
									 &keyParams,
									 kcRef,
									 &outArray);

		if(ortn) {
			if (ortn == errSecPkcs12VerifyFailure && ++tryCount < 3) {
				continue;
			}
			sec_perror("SecKeychainItemImport", ortn);
			result = 1;
			goto cleanup;
		}
		break;
	}

	/*
	 * Parse returned items & report to user
	 */
	if(outArray == NULL) {
		sec_error("No keychain items found");
		result = 1;
		goto cleanup;
	}
	numItems = CFArrayGetCount(outArray);
	for(dex=0; dex<numItems; dex++) {
		CFTypeRef item = CFArrayGetValueAtIndex(outArray, dex);
		CFTypeID itemType = CFGetTypeID(item);
		if(itemType == SecIdentityGetTypeID()) {
			numIdentities++;
		}
		else if(itemType == SecCertificateGetTypeID()) {
			numCerts++;
		}
		else if(itemType == SecKeyGetTypeID()) {
			numKeys++;
		}
		else {
			sec_error("Unexpected item type returned from SecKeychainItemImport");
			result = 1;
			goto cleanup;
		}
	}
	if(numIdentities) {
		char *str;
		if(numIdentities > 1) {
			str = "identities";
		}
		else {
			str = "identity";
		}
		fprintf(stdout, "%d %s imported.\n", numIdentities, str);
	}
	if(numKeys) {
		char *str;
		if(numKeys > 1) {
			str = "keys";
		}
		else {
			str = "key";
		}
		fprintf(stdout, "%d %s imported.\n", numKeys, str);
	}
	if(numCerts) {
		char *str;
		if(numCerts > 1) {
			str = "certificates";
		}
		else {
			str = "certificate";
		}
		fprintf(stdout, "%d %s imported.\n", numCerts, str);
	}

	/* optionally apply extended attributes */
	if(numExtendedAttributes) {
		unsigned attrDex;
		for(attrDex=0; attrDex<numExtendedAttributes; attrDex++) {
			CFStringRef attrNameStr = CFStringCreateWithCString(NULL, attrNames[attrDex],
				kCFStringEncodingASCII);
			CFDataRef attrValueData = CFDataCreate(NULL, (const UInt8 *)attrValues[attrDex],
				strlen(attrValues[attrDex]));
			for(dex=0; dex<numItems; dex++) {
				SecKeychainItemRef itemRef =
					(SecKeychainItemRef)CFArrayGetValueAtIndex(outArray, dex);
				ortn = SecKeychainItemSetExtendedAttribute(itemRef, attrNameStr, attrValueData);
				if(ortn) {
					cssmPerror("SecKeychainItemSetExtendedAttribute", ortn);
					result = 1;
					break;
				}
			}	/* for each imported item */
			CFRelease(attrNameStr);
			CFRelease(attrValueData);
			if(result) {
				break;
			}
		}	/* for each extended attribute */
	}

cleanup:
	safe_CFRelease(&fileStr);
	safe_CFRelease(&outArray);
	safe_CFRelease(&passStr);
	safe_CFRelease(&promptStr);
	safe_CFRelease(&retryStr);

	return result;
}
/* Read the file name into buffer.  On return buffer contains a newly
   malloced buffer or length buffer_size. Return 0 on success and -1 on failure.  */
int
read_file(const char *name, CSSM_DATA *outData)
{
	int fd, result;
	char *buffer = NULL;
	off_t length;
	ssize_t bytes_read;
	
	do {
		fd = open(name, O_RDONLY, 0);
	} while (fd == -1 && errno == EINTR);

	if (fd == -1)
	{
		sec_error("open %s: %s", name, strerror(errno));
		result = -1;
		goto loser;
	}

	length = lseek(fd, 0, SEEK_END);
	if (length == -1)
	{
		sec_error("lseek %s, SEEK_END: %s", name, strerror(errno));
		result = -1;
		goto loser;
	}

	buffer = malloc(length);

	do {
		bytes_read = pread(fd, buffer, length, 0);
	} while (bytes_read == -1 && errno == EINTR);

	if (bytes_read == -1)
	{
		sec_error("pread %s: %s", name, strerror(errno));
		result = -1;
		goto loser;
	}
	if (bytes_read != (ssize_t)length)
	{
		sec_error("read %s: only read %d of %qu bytes", name, bytes_read, length);
		result = -1;
		goto loser;
	}

	do {
		result = close(fd);
	} while (result == -1 && errno == EINTR);
	if (result == -1)
	{
		sec_error("close %s: %s", name, strerror(errno));
		goto loser;
	}

	outData->Data = (uint8 *)buffer;
	outData->Length = (uint32)length;

	return result;

loser:
	if (buffer)
		free(buffer);

	return result;
}