예제 #1
0
int print_block(Block_Content *blk, char *comment) {
	unsigned int	i;
	unsigned char   md5val[MD5_STRING_LEN];
	
	if (comment != NULL) printf("%s :\n", comment);
	for (i = 0; i < blk->block_size; i++) printf("%02x", blk->block_cont[i]);
	printf("\n");

	calculate_md5(blk, md5val);
	printf("md5sum : ");
	print_md5(md5val);
	
	return 0;
}
예제 #2
0
int calculate_sha256(struct crypto_hash *hash_tfm, char *dst, char *src, int len)
{
	int ret = -1;
	unsigned long flag;
	struct scatterlist sg;
	struct hash_desc desc = {
		.tfm = hash_tfm,
		.flags = 0
	};

	spin_lock_irqsave(&fmp_tfm_lock, flag);
	sg_init_one(&sg, (u8 *)src, len);

	if (!desc.tfm) {
		desc.tfm = crypto_alloc_hash(SHA256_HASH, 0,
					     CRYPTO_ALG_ASYNC);
		if (IS_ERR(desc.tfm)) {
			printk(KERN_ERR "%s: Error attemping to allocate crypto context\n", __func__);
			goto out;
		}
		hash_tfm = desc.tfm;
	}

	ret = crypto_hash_init(&desc);
	if (ret) {
		printk(KERN_ERR
		       "%s: Error initializing crypto hash; ret = [%d]\n",
		       __func__, ret);
		goto out;
	}
	ret = crypto_hash_update(&desc, &sg, len);
	if (ret) {
		printk(KERN_ERR
		       "%s: Error updating crypto hash; ret = [%d]\n",
		       __func__, ret);
		goto out;
	}
	ret = crypto_hash_final(&desc, dst);
	if (ret) {
		printk(KERN_ERR
		       "%s: Error finalizing crypto hash; ret = [%d]\n",
		       __func__, ret);
		goto out;
	}

out:
	spin_unlock_irqrestore(&fmp_tfm_lock, flag);
	return ret;
}

int calculate_md5(struct crypto_hash *hash_tfm, char *dst, char *src, int len)
{
	int ret = -1;
	unsigned long flag;
	struct scatterlist sg;
	struct hash_desc desc = {
		.tfm = hash_tfm,
		.flags = 0
	};

	spin_lock_irqsave(&fmp_tfm_lock, flag);
	sg_init_one(&sg, (u8 *)src, len);

	if (!desc.tfm) {
		desc.tfm = crypto_alloc_hash(DEFAULT_HASH, 0,
					     CRYPTO_ALG_ASYNC);
		if (IS_ERR(desc.tfm)) {
			printk(KERN_ERR "%s: Error attemping to allocate crypto context\n", __func__);
			goto out;
		}
		hash_tfm = desc.tfm;
	}

	ret = crypto_hash_init(&desc);
	if (ret) {
		printk(KERN_ERR
		       "%s: Error initializing crypto hash; ret = [%d]\n",
		       __func__, ret);
		goto out;
	}
	ret = crypto_hash_update(&desc, &sg, len);
	if (ret) {
		printk(KERN_ERR
		       "%s: Error updating crypto hash; ret = [%d]\n",
		       __func__, ret);
		goto out;
	}
	ret = crypto_hash_final(&desc, dst);
	if (ret) {
		printk(KERN_ERR
		       "%s: Error finalizing crypto hash; ret = [%d]\n",
		       __func__, ret);
		goto out;
	}

out:
	spin_unlock_irqrestore(&fmp_tfm_lock, flag);
	return ret;
}

int file_enc_derive_iv(struct address_space *mapping, loff_t offset, char *extent_iv)
{
	char src[FMP_MAX_IV_BYTES + FMP_MAX_OFFSET_BYTES];
	int ret;

	memcpy(src, mapping->iv, FMP_MAX_IV_BYTES);
	memset(src + FMP_MAX_IV_BYTES, 0, FMP_MAX_OFFSET_BYTES);
	snprintf(src + FMP_MAX_IV_BYTES, FMP_MAX_OFFSET_BYTES, "%lld", offset);

#ifdef CONFIG_CRYPTO_FIPS
	if (mapping->cc_enable)
		ret = calculate_sha256(mapping->hash_tfm, extent_iv, src, FMP_MAX_IV_BYTES + FMP_MAX_OFFSET_BYTES);
	else
#endif
		ret = calculate_md5(mapping->hash_tfm, extent_iv, src, FMP_MAX_IV_BYTES + FMP_MAX_OFFSET_BYTES);
	if (ret) {
		printk(KERN_ERR "%s: Error attempting to compute generating IV for a page; ret = [%d]\n", __func__, ret);
		goto out;
	}

out:
	return ret;
}
int nandroid_backup_md5_gen(const char *backup_path) {
    DIR *dp;
    FILE *fd;
    int i = 0;
    int j = 0;
    int len = 0;
    int ret = 0;
    int filecount = 0;

    // Dynamically allocated, free them at the end
    char *filenames[MAX_FILES_CHECKED];
    char *filepaths[MAX_FILES_CHECKED];

    char path[PATH_MAX];
    snprintf(path, PATH_MAX, "%s", backup_path);
    len = strlen(path);
    if (path[len-1] == '/')
        path[len-1] = '\0';

    ui_print("Generating MD5 checksums...\n");

    // Read files available in backup path
    dp = opendir(path);
    if (dp != NULL) {
        struct dirent *ep;
        while ((ep = readdir(dp)) && i < MAX_FILES_CHECKED) {
            if (strcmp(ep->d_name, ".") != 0 && strcmp(ep->d_name, "..") != 0
                    && strcmp(ep->d_name, "recovery.log") != 0
                    && strcmp(ep->d_name, "nandroid.md5") != 0) {
                len = strlen(ep->d_name);
                filenames[i] = malloc(sizeof(char[len+1]));
                snprintf(filenames[i], len+1, "%s", ep->d_name);

                len += 1 + strlen(path);
                filepaths[i] = malloc(sizeof(char[len+1]));
                snprintf(filepaths[i], len+1, "%s/%s", path, ep->d_name);
                i++;
            }
        }
        closedir(dp);
        filecount = i;
    }
    if (filecount == 0) {
        ret = -1;
        LOGE("No files found in %s for MD5 generation\n", path);
        goto out;
    }

    // Prepare backup_path/nandroid.md5 for writing
    char md5path[PATH_MAX];
    snprintf(md5path, PATH_MAX, "%s/%s", path, "nandroid.md5");
    fd = fopen(md5path, "w");
    if (fd == NULL) {
        ret = -1;
        LOGE("Unable to create nandroid.md5\n");
        goto out;
    }

    // Generate MD5s and save to nandroid.md5
    char md5calc[HASH_LENGTH+1];
    char tmp[PATH_MAX];
    for (i = 0; i < filecount; i++) {
        if (calculate_md5(md5calc, filepaths[i]) != 0) {
            LOGE("Unable to generate MD5 for %s\n", filenames[i]);
            // Attempt to continue for other files
        } else {
            snprintf(tmp, PATH_MAX, "%s  %s\n", md5calc, filenames[i]);
            fputs(tmp, fd);
        }
    }
    fclose(fd);
    ui_print("MD5 checksums generated\n");

out:
    for (i = 0; i < filecount; i++) {
        free(filenames[i]);
        free(filepaths[i]);
    }

    return ret;
}
int nandroid_restore_md5_check(const char *backup_path, unsigned char flags) {
    DIR *dp;
    FILE *fd;
    int i = 0;
    int j = 0;
    int len = 0;
    int ret = 0;
    int filecount = 0;
    int md5count = 0;
    int use_ui = is_ui_initialized();

    if (empty_nandroid_bitmask(flags)) {
        LOGE("Nothing selected for restore.\n");
        return -1;
    }

    // Dynamically allocated, free them at the end
    char *filenames[MAX_FILES_CHECKED];
    char *filepaths[MAX_FILES_CHECKED];
    char *md5files[MAX_FILES_CHECKED];
    char *md5hashes[MAX_FILES_CHECKED];
    int mf_allocated = 0; // for MissingFiles *mf
    int mm_allocated = 0; // for MissingFiles *mm

    char path[PATH_MAX];
    snprintf(path, PATH_MAX, "%s", backup_path);
    len = strlen(path);
    if (path[len-1] == '/')
        path[len-1] = '\0';

    ui_print("Checking MD5 sums...\n");

    // Read files available in backup path
    dp = opendir(path);
    if (dp != NULL) {
        struct dirent *ep;
        while ((ep = readdir(dp)) && i < MAX_FILES_CHECKED) {
            if (is_selected_for_restore(ep->d_name, flags)) {
                len = strlen(ep->d_name);
                filenames[i] = malloc(sizeof(char[len+1]));
                snprintf(filenames[i], len+1, "%s", ep->d_name);

                len += 1 + strlen(path);
                filepaths[i] = malloc(sizeof(char[len+1]));
                snprintf(filepaths[i], len+1, "%s/%s", path, ep->d_name);
                i++;
            }
        }
        closedir(dp);
        filecount = i;
    }
    if (filecount == 0) {
        ret = -1;
        LOGE("No backup files found in %s\n", path);
        goto out;
    }

    // Read files + hashes available in nandroid.md5
    i = 0;
    char md5path[PATH_MAX];
    snprintf(md5path, PATH_MAX, "%s/%s", path, "nandroid.md5");
    fd = fopen(md5path, "r");
    if (fd != NULL) {
        char tmp[PATH_MAX];
        while (fgets(tmp, PATH_MAX, fd) && i < MAX_FILES_CHECKED) {
            if (tmp[strlen(tmp)-1] == '\n')
                tmp[strlen(tmp)-1] = '\0';
            if (is_selected_for_restore(tmp, flags)) {
                md5hashes[i] = malloc(sizeof(char[HASH_LENGTH+1]));
                snprintf(md5hashes[i], HASH_LENGTH+1, "%s", tmp);

                // md5 hash is followed by two spaces
                len = strlen(tmp) - (HASH_LENGTH+2);
                md5files[i] = malloc(sizeof(char[len+1]));
                snprintf(md5files[i], len+1, "%s", &tmp[HASH_LENGTH+2]);
                i++;
            }
        }
        fclose(fd);
        md5count = i;
    }

#if DEBUG_MD5_CHECKER
    LOGI("[MD5] backup_path: %s\n", path);
    for (i = 0; i < filecount; i++) {
        LOGI("[MD5] files in path: %s\n", filenames[i]);
    }
    for (i = 0; i < md5count; i++) {
        LOGI("[MD5] reference: %s: %s\n", md5files[i], md5hashes[i]);
    }
#endif

    // Cross-reference files in directory to those in nandroid.md5
    // Mark files that are in nandroid.md5 but not in directory (potentially fatal)
    int foundfile;
    int totalmissing = 0;
    MissingFiles *mm = malloc(md5count * sizeof(MissingFiles));
    mm_allocated = 1;
    for (i = 0; i < md5count; i++) {
        foundfile = 0;
        for (j = 0; j < filecount; j++) {
            if (strcmp(md5files[i], filenames[j]) == 0) {
                mm[i] = (MissingFiles){ 0, "" };
                foundfile = 1;
            }
        }
        if (!foundfile) {
            mm[i] = (MissingFiles){ 1, md5files[i] };
            totalmissing++;
        }
    }

    // Warn user of failure for missing files
    if (totalmissing && use_ui) {
        int uiback = ui_is_showing_back_button();
        ui_set_showing_back_button(0);

        const char* headers[totalmissing+8];
        headers[0] = "Backup files are missing:";
        int hi = 1;
        for (i = 0; i < md5count; i++) {
            if (mm[i].is_missing)
                headers[hi++] = mm[i].filename;
        }
        headers[totalmissing+1] = "";
        headers[totalmissing+2] = "Attempting to restore any";
        headers[totalmissing+3] = "of these will fail.";
        headers[totalmissing+4] = "";
        headers[totalmissing+5] = "Continue anyways?";
        headers[totalmissing+6] = "";
        headers[totalmissing+7] = NULL;

        static char* list[] = { "Yes", "No", NULL };

        int chosen_item = get_menu_selection(headers, list, 0, 0);
        if (chosen_item == 0) {
            ui_set_showing_back_button(uiback);
        } else {
            ret = -1;
            ui_set_showing_back_button(uiback);
            LOGE("Aborting\n");
            goto out;
        }
    } else if (totalmissing) {
        // No UI, so no prompt possible; fail the restore
        ret = -1;
        LOGE("Backup files are missing:\n");
        for (i = 0; i < md5count; i++) {
            if (mm[i].is_missing)
                LOGE("%s\n", mm[i].filename);
        }
        LOGE("Aborting\n");
        goto out;
    }

    // Cross-reference files in directory to those in nandroid.md5
    // Mark files that are in directory but not in nandroid.md5 (non-fatal)
    totalmissing = 0;
    MissingFiles *mf = malloc(filecount * sizeof(MissingFiles));
    mf_allocated = 1;
    for (i = 0; i < filecount; i++) {
        foundfile = 0;
        // Ignore files that are not scheduled for restore
        if (!is_selected_for_restore(filenames[i], flags)) {
            mf[i] = (MissingFiles){ 0, "" };
            continue;
        }
        for (j = 0; j < md5count; j++) {
            if (strcmp(filenames[i], md5files[j]) == 0) {
                mf[i] = (MissingFiles){ 0, "" };
                foundfile = 1;
            }
        }
        if (!foundfile) {
            mf[i] = (MissingFiles){ 1, filenames[i] };
            totalmissing++;
        }
    }

    // Warn user about missing md5 references for files
    if (totalmissing && use_ui) {
        int uiback = ui_is_showing_back_button();
        ui_set_showing_back_button(0);

        const char* headers[totalmissing+5];
        headers[0] = "Could not find reference MD5 for:";
        int hi = 1;
        for (i = 0; i < filecount; i++) {
            if (mf[i].is_missing)
                headers[hi++] = mf[i].filename;
        }
        headers[totalmissing+1] = "";
        headers[totalmissing+2] = "Continue anyways?";
        headers[totalmissing+3] = "";
        headers[totalmissing+4] = NULL;

        static char* list[] = { "Yes", "No", NULL };

        int chosen_item = get_menu_selection(headers, list, 0, 0);
        if (chosen_item == 0) {
            ui_set_showing_back_button(uiback);
        } else{
            ret = -1;
            ui_set_showing_back_button(uiback);
            LOGE("Aborting\n");
            goto out;
        }
    } else if (totalmissing) {
        // No UI, so no prompt possible; fail the restore
        ret = -1;
        LOGE("Could not find reference MD5 for:\n");
        for (i = 0; i < filecount; i++) {
            if (mf[i].is_missing)
                LOGE("%s\n", mf[i].filename);
        }
        LOGE("Aborting\n");
        goto out;
    }

    // Compare MD5s of non-missing files that are selected for restore
    int md5matches = 0;
    char md5calc[HASH_LENGTH+1];
    for (i = 0; i < filecount; i++) {
        if (!is_selected_for_restore(filenames[i], flags))
            continue;
        for (j = 0; j < md5count; j++) {
            if (strcmp(filenames[i], md5files[j]) == 0) {
                if (calculate_md5(md5calc, filepaths[i]) != 0) {
                    ret = -1;
                    LOGE("Unable to check MD5 of %s\nAborting\n", filenames[i]);
                    goto out;
                }
                if (strcmp(md5calc, md5hashes[j]) != 0) {
                    ret = -1;
                    LOGE("MD5 mismatch for %s\nAborting\n", filenames[i]);
                    goto out;
                } else {
                    md5matches++;
                }
            }
        }
    }
    if (md5matches) {
        ui_print("All MD5 checksums verified\n");
    } else {
        ui_print("No MD5 verification performed\n");
    }

out:
    if (mf_allocated)
        free(mf);
    if (mm_allocated)
        free(mm);
    for (i = 0; i < filecount; i++) {
        free(filenames[i]);
        free(filepaths[i]);
    }
    for (i = 0; i < md5count; i++) {
        free(md5files[i]);
        free(md5hashes[i]);
    }

    return ret;
}