/* * Calculate per-link MAC by pathname */ static int32_t calc_link_mac_v1(struct mtd_format_v1 *fmt, loc_t *loc, unsigned char *result, struct crypt_inode_info *info, struct master_cipher_info *master) { int32_t ret; unsigned char nmtd_link_key[16]; CMAC_CTX *cctx; size_t len; ret = get_nmtd_link_key(loc, master, nmtd_link_key); if (ret) { gf_log("crypt", GF_LOG_ERROR, "Can not get nmtd link key"); return -1; } cctx = CMAC_CTX_new(); if (!cctx) { gf_log("crypt", GF_LOG_ERROR, "CMAC_CTX_new failed"); return -1; } ret = CMAC_Init(cctx, nmtd_link_key, sizeof(nmtd_link_key), EVP_aes_128_cbc(), 0); if (!ret) { gf_log("crypt", GF_LOG_ERROR, "CMAC_Init failed"); CMAC_CTX_free(cctx); return -1; } ret = CMAC_Update(cctx, get_NMTD_V1(info), SIZE_OF_NMTD_V1); if (!ret) { gf_log("crypt", GF_LOG_ERROR, "CMAC_Update failed"); CMAC_CTX_free(cctx); return -1; } ret = CMAC_Final(cctx, result, &len); CMAC_CTX_free(cctx); if (!ret) { gf_log("crypt", GF_LOG_ERROR, "CMAC_Final failed"); return -1; } return 0; }
static int32_t create_format_v1(unsigned char *wire, loc_t *loc, struct crypt_inode_info *info, struct master_cipher_info *master) { int32_t ret; struct mtd_format_v1 *fmt; unsigned char mtd_key[16]; AES_KEY EMTD_KEY; unsigned char nmtd_link_key[16]; uint32_t ad; GCM128_CONTEXT *gctx; fmt = (struct mtd_format_v1 *)wire; fmt->minor_id = info->nr_minor; fmt->alg_id = AES_CIPHER_ALG; fmt->dkey_factor = master->m_dkey_size >> KEY_FACTOR_BITS; fmt->block_bits = master->m_block_bits; fmt->mode_id = master->m_mode; /* * retrieve keys for the parts of metadata */ ret = get_emtd_file_key(info, master, mtd_key); if (ret) return ret; ret = get_nmtd_link_key(loc, master, nmtd_link_key); if (ret) return ret; AES_set_encrypt_key(mtd_key, sizeof(mtd_key)*8, &EMTD_KEY); gctx = CRYPTO_gcm128_new(&EMTD_KEY, (block128_f)AES_encrypt); /* TBD: Check return values */ CRYPTO_gcm128_setiv(gctx, info->oid, sizeof(uuid_t)); ad = htole32(MTD_LOADER_V1); ret = CRYPTO_gcm128_aad(gctx, (const unsigned char *)&ad, sizeof(ad)); if (ret) { gf_log("crypt", GF_LOG_ERROR, " CRYPTO_gcm128_aad failed"); CRYPTO_gcm128_release(gctx); return ret; } ret = CRYPTO_gcm128_encrypt(gctx, get_EMTD_V1(fmt), get_EMTD_V1(fmt), SIZE_OF_EMTD_V1); if (ret) { gf_log("crypt", GF_LOG_ERROR, " CRYPTO_gcm128_encrypt failed"); CRYPTO_gcm128_release(gctx); return ret; } /* * set MAC of encrypted part of metadata */ CRYPTO_gcm128_tag(gctx, get_EMTD_V1_MAC(fmt), SIZE_OF_EMTD_V1_MAC); CRYPTO_gcm128_release(gctx); /* * set the first MAC of non-encrypted part of metadata */ return create_link_mac_v1(fmt, 0, loc, info, master); }