Example #1
0
kaa_error_t aes_encrypt_decrypt_block(int mode, const uint8_t *input,
        uint8_t *output, const uint8_t *key)
{
    if (input == NULL) {
        return KAA_ERR_BADPARAM;
    }

    if (mode != MBEDTLS_AES_ENCRYPT && mode != MBEDTLS_AES_DECRYPT) {
        return KAA_ERR_BADPARAM;
    }

    static bool initialized = false;
    static mbedtls_aes_context aes_ctx;

    if (!initialized) {
        mbedtls_aes_init(&aes_ctx);
        initialized = true;
    }

    /* KAA_SESSION_KEY_LENGTH * 8 - size in bits */
    if (mode == MBEDTLS_AES_ENCRYPT) {
        mbedtls_aes_setkey_enc(&aes_ctx, key, KAA_SESSION_KEY_LENGTH * 8);
    } else {
        mbedtls_aes_setkey_dec(&aes_ctx, key, KAA_SESSION_KEY_LENGTH * 8);
    }
    mbedtls_aes_crypt_ecb(&aes_ctx, mode, input, output);

    return KAA_ERR_NONE;
}
Example #2
0
CVolumeWiiCrypted::CVolumeWiiCrypted(std::unique_ptr<IBlobReader> reader, u64 _VolumeOffset,
                                     const unsigned char* _pVolumeKey)
    : m_pReader(std::move(reader)), m_AES_ctx(std::make_unique<mbedtls_aes_context>()),
      m_VolumeOffset(_VolumeOffset), m_dataOffset(0x20000), m_LastDecryptedBlockOffset(-1)
{
  mbedtls_aes_setkey_dec(m_AES_ctx.get(), _pVolumeKey, 128);
}
Example #3
0
bool esp32_fs_crypt_init(void) {
  uint8_t tmp[32];
  uint32_t addr = 0;
  for (addr = 0; addr < spi_flash_get_chip_size(); addr += 32) {
    mgos_wdt_feed();
    if (spi_flash_read(addr, tmp, sizeof(tmp)) != ESP_OK) {
      LOG(LL_ERROR, ("SPI read error at 0x%x", addr));
      return false;
    }
    int j;
    for (j = 0; j < sizeof(tmp); j++) {
      if (tmp[j] != 0xff) break;
    }
    if (j < sizeof(tmp)) continue;
    /* Found a suitably empty location, now decrypt it. */
    if (spi_flash_read_encrypted(addr, tmp, sizeof(tmp)) != ESP_OK) {
      LOG(LL_ERROR, ("SPI encrypted read error at 0x%x", addr));
      return false;
    }
    /* Now in tmp we have 32 x 0xff processed with the flash encryption key. */
    mbedtls_aes_init(&s_aes_ctx_enc);
    mbedtls_aes_setkey_enc(&s_aes_ctx_enc, tmp, 256);
    mbedtls_aes_init(&s_aes_ctx_dec);
    mbedtls_aes_setkey_dec(&s_aes_ctx_dec, tmp, 256);
    LOG(LL_INFO, ("FS encryption key set up, seed @ 0x%x", addr));
    return true;
  }
  LOG(LL_ERROR, ("Could not a suitable seed area for FS encryption"));
  return false;
}
struct crypto_cipher *  fast_crypto_cipher_init(enum crypto_cipher_alg alg,
					  const uint8_t *iv, const uint8_t *key,
					  size_t key_len)
{
    struct fast_crypto_cipher *ctx;

    ctx = (struct fast_crypto_cipher *)os_zalloc(sizeof(*ctx));
    if (ctx == NULL) {
        return NULL;
    }
    
    ctx->alg = alg;

    switch (alg) {
        case CRYPTO_CIPHER_ALG_RC4:
            if (key_len > sizeof(ctx->u.rc4.key)) {
	        os_free(ctx);
	        return NULL;
            }
            ctx->u.rc4.keylen = key_len;
            os_memcpy(ctx->u.rc4.key, key, key_len);
            break;
        case CRYPTO_CIPHER_ALG_AES:                
            mbedtls_aes_init(&(ctx->u.aes.ctx_enc));
            mbedtls_aes_setkey_enc(&(ctx->u.aes.ctx_enc), key, 256);
            mbedtls_aes_init(&(ctx->u.aes.ctx_dec));
            mbedtls_aes_setkey_dec(&(ctx->u.aes.ctx_dec), key, 256);               
            os_memcpy(ctx->u.aes.cbc, iv, AES_BLOCK_SIZE);
            break;
#ifdef CONFIG_DES3
        case CRYPTO_CIPHER_ALG_3DES:
            if (key_len != 24) {
	        os_free(ctx);
	        return NULL;
            }
            des3_key_setup(key, &ctx->u.des3.key);
            os_memcpy(ctx->u.des3.cbc, iv, 8);
            break;
#endif
#ifdef CONFIG_DES
        case CRYPTO_CIPHER_ALG_DES:
            if (key_len != 8) {
	        os_free(ctx);
	        return NULL;
            }
            des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
            os_memcpy(ctx->u.des.cbc, iv, 8);
            break;
#endif
        default:
            os_free(ctx);
            return NULL;
    }

    return (struct crypto_cipher *)ctx;
}
Example #5
0
bool CVolumeWiiCrypted::ChangePartition(u64 offset)
{
  m_VolumeOffset = offset;
  m_LastDecryptedBlockOffset = -1;

  u8 volume_key[16];
  DiscIO::VolumeKeyForPartition(*m_pReader, offset, volume_key);
  mbedtls_aes_setkey_dec(m_AES_ctx.get(), volume_key, 128);
  return true;
}
Example #6
0
std::vector<u8> CNANDContentLoader::AESDecode(const u8* key, u8* iv, const u8* src, u32 size)
{
	mbedtls_aes_context aes_ctx;
	std::vector<u8> buffer(size);

	mbedtls_aes_setkey_dec(&aes_ctx, key, 128);
	mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, size, iv, src, buffer.data());

	return buffer;
}
Example #7
0
//AES/CBC/PKCS5Padding
//key只能是16、24、32个ASSCII字符组成的串儿
unsigned char* aes_cbc_pkcs5padding_decode(unsigned char *input, size_t inputLength, size_t *outputLength, const char *key) {
    size_t keyLength = strlen(key);
    printf("keyLength = %zu\n", keyLength);
    
    if (keyLength != 32 && keyLength != 24 && keyLength != 16) {
        perror("key必须是16、24、32个ASSCII字符组成的串\n");
        return NULL;
    }
    
    mbedtls_aes_context aes;
    
    //初始向量,一般是一个随机数组成的,长度必须是块大小,一个块是16字节,也就是16个ASCII字符
    unsigned char iv[16];
    memcpy(iv, key, keyLength);
    
    //解密后的数据长度
    unsigned char *output = (unsigned char *)calloc(inputLength, sizeof(unsigned char));
    
    //设置加密的key,并初始化
    mbedtls_aes_setkey_dec(&aes, (unsigned char*)key, keyLength * 8);
    
    //加密数据
    mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, inputLength, iv, input, output);
    
    int outputLastIndex = inputLength - 1;

    //取出output最后一个字节,转成数字
    unsigned int lastValue = output[outputLastIndex];
    printf("lastValue = %d\n", lastValue);
    if (lastValue > 0 && lastValue <= 16) {
        int j = outputLastIndex;
        while(output[j] == lastValue) {
            j--;
        }
        printf("j = %d\n", j);
        *outputLength = j + 1;
        outputLastIndex = j;
    }

    size_t inputHexLength = 2 * inputLength + 1;
    char inputHex[inputHexLength];
    memset(inputHex, 0, inputHexLength);
    bytes2HexStr(inputHex, input, inputLength);
    
    size_t outputHexLength = 2 * inputLength + 1;
    char outputHex[outputHexLength];
    memset(outputHex, 0, outputHexLength);
    bytes2HexStr(outputHex, output, inputLength);

    printf("aesDecode(%s, %s)=%s\n", inputHex, key, outputHex);
    
    return output;
}
Example #8
0
	int AESContext::setKeyDec(State & state, mbedtls_aes_context * context){
		Stack * stack = state.stack;
		if (stack->is<LUA_TSTRING>(1)){
			const std::string key = stack->toLString(1);
			unsigned int realBits = key.length() * 8;
			unsigned int keyBits;

			if (stack->is<LUA_TNUMBER>(2)){
				keyBits = stack->to<int>(2);
				if (keyBits > realBits){
					keyBits = realBits;
				}
			}
			else{
				keyBits = realBits;
			}


			stack->push<int>(mbedtls_aes_setkey_dec(context, reinterpret_cast<const unsigned char*>(key.c_str()), keyBits));
			return 1;
		}
		return 0;
	}
Example #9
0
void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey)
{
	CBlobBigEndianReader Reader(_rReader);

	u8 SubKey[16];
	_rReader.Read(offset + 0x1bf, 16, SubKey);

	u8 IV[16];
	memset(IV, 0, 16);
	_rReader.Read(offset + 0x44c, 8, IV);

	bool usingKoreanKey = false;
	// Issue: 6813
	// Magic value is at partition's offset + 0x1f1 (1byte)
	// If encrypted with the Korean key, the magic value would be 1
	// Otherwise it is zero
	if (Reader.Read8(0x3) == 'K' && Reader.Read8(offset + 0x1f1) == 1)
		usingKoreanKey = true;

	mbedtls_aes_context AES_ctx;
	mbedtls_aes_setkey_dec(&AES_ctx, (usingKoreanKey ? s_master_key_korean : s_master_key), 128);

	mbedtls_aes_crypt_cbc(&AES_ctx, MBEDTLS_AES_DECRYPT, 16, IV, SubKey, VolumeKey);
}
Example #10
0
int mbedtls_aes_self_test(int verbose)
{
    (void)verbose;

    /* 128-bit Key 2b7e151628aed2a6abf7158809cf4f3c */
    const uint8_t       key_128b[16] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
                                  0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
    mbedtls_aes_context aes;
    int                 retval = 0;

    uint8_t input[16]   = {0};
    uint8_t output[16]  = {0};
    uint8_t decrypt[16] = {0};

    strcpy((char *)input, (const char *)"hw_aes_test");

    mbedtls_aes_init(&aes);

    retval = mbedtls_aes_setkey_enc(&aes, (const unsigned char *)key_128b, 128);
    VerifyOrExit(retval != 0, retval = -1);

    retval = mbedtls_aes_setkey_dec(&aes, (const unsigned char *)key_128b, 128);
    VerifyOrExit(retval != 0, retval = -1);

    retval = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, input, output);
    VerifyOrExit(retval != 0, retval = -1);

    retval = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, output, decrypt);
    VerifyOrExit(retval != 0, retval = -1);

    mbedtls_aes_free(&aes);

exit:

    return retval;
}
Example #11
0
IPCCommandResult WFSI::IOCtl(const IOCtlRequest& request)
{
  s32 return_error_code = IPC_SUCCESS;

  switch (request.request)
  {
  case IOCTL_WFSI_IMPORT_TITLE_INIT:
  {
    u32 tmd_addr = Memory::Read_U32(request.buffer_in);
    u32 tmd_size = Memory::Read_U32(request.buffer_in + 4);

    m_patch_type = static_cast<PatchType>(Memory::Read_U32(request.buffer_in + 32));
    m_continue_install = Memory::Read_U32(request.buffer_in + 36);

    INFO_LOG(IOS_WFS, "IOCTL_WFSI_IMPORT_TITLE_INIT: patch type %d, continue install: %s",
             m_patch_type, m_continue_install ? "true" : "false");

    if (m_patch_type == PatchType::PATCH_TYPE_2)
    {
      const std::string content_dir =
          StringFromFormat("/vol/%s/title/%s/%s/content", m_device_name.c_str(),
                           m_current_group_id_str.c_str(), m_current_title_id_str.c_str());

      File::Rename(WFS::NativePath(content_dir + "/default.dol"),
                   WFS::NativePath(content_dir + "/_default.dol"));
    }

    if (!IOS::ES::IsValidTMDSize(tmd_size))
    {
      ERROR_LOG(IOS_WFS, "IOCTL_WFSI_IMPORT_TITLE_INIT: TMD size too large (%d)", tmd_size);
      return_error_code = IPC_EINVAL;
      break;
    }
    std::vector<u8> tmd_bytes;
    tmd_bytes.resize(tmd_size);
    Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
    m_tmd.SetBytes(std::move(tmd_bytes));

    IOS::ES::TicketReader ticket = m_ios.GetES()->FindSignedTicket(m_tmd.GetTitleId());
    if (!ticket.IsValid())
    {
      return_error_code = -11028;
      break;
    }

    memcpy(m_aes_key, ticket.GetTitleKey(m_ios.GetIOSC()).data(), sizeof(m_aes_key));
    mbedtls_aes_setkey_dec(&m_aes_ctx, m_aes_key, 128);

    SetImportTitleIdAndGroupId(m_tmd.GetTitleId(), m_tmd.GetGroupId());

    if (m_patch_type == PatchType::PATCH_TYPE_1)
      CancelPatchImport(m_continue_install);
    else if (m_patch_type == PatchType::NOT_A_PATCH)
      CancelTitleImport(m_continue_install);

    break;
  }

  case IOCTL_WFSI_PREPARE_PROFILE:
    m_base_extract_path = StringFromFormat("/vol/%s/tmp/", m_device_name.c_str());
    // Fall through intended.

  case IOCTL_WFSI_PREPARE_CONTENT:
  {
    const char* ioctl_name = request.request == IOCTL_WFSI_PREPARE_PROFILE ?
                                 "IOCTL_WFSI_PREPARE_PROFILE" :
                                 "IOCTL_WFSI_PREPARE_CONTENT";

    // Initializes the IV from the index of the content in the TMD contents.
    u32 content_id = Memory::Read_U32(request.buffer_in + 8);
    IOS::ES::Content content_info;
    if (!m_tmd.FindContentById(content_id, &content_info))
    {
      WARN_LOG(IOS_WFS, "%s: Content id %08x not found", ioctl_name, content_id);
      return_error_code = -10003;
      break;
    }

    memset(m_aes_iv, 0, sizeof(m_aes_iv));
    m_aes_iv[0] = content_info.index >> 8;
    m_aes_iv[1] = content_info.index & 0xFF;
    INFO_LOG(IOS_WFS, "%s: Content id %08x found at index %d", ioctl_name, content_id,
             content_info.index);

    m_arc_unpacker.Reset();
    break;
  }

  case IOCTL_WFSI_IMPORT_PROFILE:
  case IOCTL_WFSI_IMPORT_CONTENT:
  {
    const char* ioctl_name = request.request == IOCTL_WFSI_IMPORT_PROFILE ?
                                 "IOCTL_WFSI_IMPORT_PROFILE" :
                                 "IOCTL_WFSI_IMPORT_CONTENT";

    u32 content_id = Memory::Read_U32(request.buffer_in + 0xC);
    u32 input_ptr = Memory::Read_U32(request.buffer_in + 0x10);
    u32 input_size = Memory::Read_U32(request.buffer_in + 0x14);
    INFO_LOG(IOS_WFS, "%s: %08x bytes of data at %08x from content id %d", ioctl_name, input_size,
             input_ptr, content_id);

    std::vector<u8> decrypted(input_size);
    mbedtls_aes_crypt_cbc(&m_aes_ctx, MBEDTLS_AES_DECRYPT, input_size, m_aes_iv,
                          Memory::GetPointer(input_ptr), decrypted.data());

    m_arc_unpacker.AddBytes(decrypted);
    break;
  }

  case IOCTL_WFSI_IMPORT_CONTENT_END:
  case IOCTL_WFSI_IMPORT_PROFILE_END:
  {
    const char* ioctl_name = request.request == IOCTL_WFSI_IMPORT_PROFILE_END ?
                                 "IOCTL_WFSI_IMPORT_PROFILE_END" :
                                 "IOCTL_WFSI_IMPORT_CONTENT_END";
    INFO_LOG(IOS_WFS, "%s", ioctl_name);

    auto callback = [this](const std::string& filename, const std::vector<u8>& bytes) {
      INFO_LOG(IOS_WFS, "Extract: %s (%zd bytes)", filename.c_str(), bytes.size());

      std::string path = WFS::NativePath(m_base_extract_path + "/" + filename);
      File::CreateFullPath(path);
      File::IOFile f(path, "wb");
      if (!f)
      {
        ERROR_LOG(IOS_WFS, "Could not extract %s to %s", filename.c_str(), path.c_str());
        return;
      }
      f.WriteBytes(bytes.data(), bytes.size());
    };
    m_arc_unpacker.Extract(callback);

    // Technically not needed, but let's not keep large buffers in RAM for no
    // reason if we can avoid it.
    m_arc_unpacker.Reset();
    break;
  }

  case IOCTL_WFSI_FINALIZE_TITLE_INSTALL:
  {
    std::string tmd_path;
    if (m_patch_type == NOT_A_PATCH)
    {
      std::string title_install_dir = StringFromFormat("/vol/%s/_install/%s", m_device_name.c_str(),
                                                       m_import_title_id_str.c_str());
      std::string title_final_dir =
          StringFromFormat("/vol/%s/title/%s/%s", m_device_name.c_str(),
                           m_import_group_id_str.c_str(), m_import_title_id_str.c_str());
      File::Rename(WFS::NativePath(title_install_dir), WFS::NativePath(title_final_dir));

      tmd_path = StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd",
                                  m_device_name.c_str(), m_import_group_id_str.c_str(),
                                  m_import_title_id_str.c_str(), m_import_title_id);
    }
    else
    {
      std::string patch_dir =
          StringFromFormat("/vol/%s/title/%s/%s/_patch", m_device_name.c_str(),
                           m_current_group_id_str.c_str(), m_current_title_id_str.c_str());
      File::DeleteDirRecursively(WFS::NativePath(patch_dir));

      tmd_path = StringFromFormat("/vol/%s/title/%s/%s/meta/%016" PRIx64 ".tmd",
                                  m_device_name.c_str(), m_current_group_id_str.c_str(),
                                  m_current_title_id_str.c_str(), m_import_title_id);
    }

    File::IOFile tmd_file(WFS::NativePath(tmd_path), "wb");
    tmd_file.WriteBytes(m_tmd.GetBytes().data(), m_tmd.GetBytes().size());
    break;
  }

  case IOCTL_WFSI_FINALIZE_PATCH_INSTALL:
  {
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_FINALIZE_PATCH_INSTALL");
    if (m_patch_type != NOT_A_PATCH)
    {
      std::string current_title_dir =
          StringFromFormat("/vol/%s/title/%s/%s", m_device_name.c_str(),
                           m_current_group_id_str.c_str(), m_current_title_id_str.c_str());
      std::string patch_dir = current_title_dir + "/_patch";
      File::CopyDir(WFS::NativePath(patch_dir), WFS::NativePath(current_title_dir), true);
    }
    break;
  }

  case IOCTL_WFSI_DELETE_TITLE:
    // Bytes 0-4: ??
    // Bytes 4-8: game id
    // Bytes 1c-1e: title id?
    WARN_LOG(IOS_WFS, "IOCTL_WFSI_DELETE_TITLE: unimplemented");
    break;

  case IOCTL_WFSI_GET_VERSION:
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_GET_VERSION");
    Memory::Write_U32(0x20, request.buffer_out);
    break;

  case IOCTL_WFSI_IMPORT_TITLE_CANCEL:
  {
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_IMPORT_TITLE_CANCEL");

    bool continue_install = Memory::Read_U32(request.buffer_in) != 0;
    if (m_patch_type == PatchType::NOT_A_PATCH)
      return_error_code = CancelTitleImport(continue_install);
    else if (m_patch_type == PatchType::PATCH_TYPE_1 || m_patch_type == PatchType::PATCH_TYPE_2)
      return_error_code = CancelPatchImport(continue_install);
    else
      return_error_code = WFS_EINVAL;

    m_tmd = {};
    break;
  }

  case IOCTL_WFSI_INIT:
  {
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_INIT");
    u64 tid;
    if (GetIOS()->GetES()->GetTitleId(&tid) < 0)
    {
      ERROR_LOG(IOS_WFS, "IOCTL_WFSI_INIT: Could not get title id.");
      return_error_code = IPC_EINVAL;
      break;
    }

    IOS::ES::TMDReader tmd = GetIOS()->GetES()->FindInstalledTMD(tid);
    SetCurrentTitleIdAndGroupId(tmd.GetTitleId(), tmd.GetGroupId());
    break;
  }

  case IOCTL_WFSI_SET_DEVICE_NAME:
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_SET_DEVICE_NAME");
    m_device_name = Memory::GetString(request.buffer_in);
    break;

  case IOCTL_WFSI_APPLY_TITLE_PROFILE:
  {
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_APPLY_TITLE_PROFILE");

    if (m_patch_type == NOT_A_PATCH)
    {
      std::string install_directory = StringFromFormat("/vol/%s/_install", m_device_name.c_str());
      if (!m_continue_install && File::IsDirectory(WFS::NativePath(install_directory)))
      {
        File::DeleteDirRecursively(WFS::NativePath(install_directory));
      }

      m_base_extract_path = StringFromFormat("%s/%s/content", install_directory.c_str(),
                                             m_import_title_id_str.c_str());
      File::CreateFullPath(WFS::NativePath(m_base_extract_path));
      File::CreateDir(WFS::NativePath(m_base_extract_path));

      for (auto dir : {"work", "meta", "save"})
      {
        std::string path = StringFromFormat("%s/%s/%s", install_directory.c_str(),
                                            m_import_title_id_str.c_str(), dir);
        File::CreateDir(WFS::NativePath(path));
      }

      std::string group_path = StringFromFormat("/vol/%s/title/%s", m_device_name.c_str(),
                                                m_import_group_id_str.c_str());
      File::CreateFullPath(WFS::NativePath(group_path));
      File::CreateDir(WFS::NativePath(group_path));
    }
    else
    {
      m_base_extract_path =
          StringFromFormat("/vol/%s/title/%s/%s/_patch/content", m_device_name.c_str(),
                           m_current_group_id_str.c_str(), m_current_title_id_str.c_str());
      File::CreateFullPath(WFS::NativePath(m_base_extract_path));
      File::CreateDir(WFS::NativePath(m_base_extract_path));
    }

    break;
  }

  case IOCTL_WFSI_GET_TMD:
  {
    u64 subtitle_id = Memory::Read_U64(request.buffer_in);
    u32 address = Memory::Read_U32(request.buffer_in + 24);
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_GET_TMD: subtitle ID %016" PRIx64, subtitle_id);

    u32 tmd_size;
    return_error_code =
        GetTmd(m_current_group_id, m_current_title_id, subtitle_id, address, &tmd_size);
    Memory::Write_U32(tmd_size, request.buffer_out);
    break;
  }

  case IOCTL_WFSI_GET_TMD_ABSOLUTE:
  {
    u64 subtitle_id = Memory::Read_U64(request.buffer_in);
    u32 address = Memory::Read_U32(request.buffer_in + 24);
    u16 group_id = Memory::Read_U16(request.buffer_in + 36);
    u32 title_id = Memory::Read_U32(request.buffer_in + 32);
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_GET_TMD_ABSOLUTE: tid %08x, gid %04x, subtitle ID %016" PRIx64,
             title_id, group_id, subtitle_id);

    u32 tmd_size;
    return_error_code = GetTmd(group_id, title_id, subtitle_id, address, &tmd_size);
    Memory::Write_U32(tmd_size, request.buffer_out);
    break;
  }

  case IOCTL_WFSI_SET_FST_BUFFER:
  {
    INFO_LOG(IOS_WFS, "IOCTL_WFSI_SET_FST_BUFFER: address %08x, size %08x", request.buffer_in,
             request.buffer_in_size);
    break;
  }

  case IOCTL_WFSI_NOOP:
    break;

  case IOCTL_WFSI_LOAD_DOL:
  {
    std::string path =
        StringFromFormat("/vol/%s/title/%s/%s/content", m_device_name.c_str(),
                         m_current_group_id_str.c_str(), m_current_title_id_str.c_str());

    u32 dol_addr = Memory::Read_U32(request.buffer_in + 0x18);
    u32 max_dol_size = Memory::Read_U32(request.buffer_in + 0x14);
    u16 dol_extension_id = Memory::Read_U16(request.buffer_in + 0x1e);

    if (dol_extension_id == 0)
    {
      path += "/default.dol";
    }
    else
    {
      path += StringFromFormat("/extension%d.dol", dol_extension_id);
    }

    INFO_LOG(IOS_WFS, "IOCTL_WFSI_LOAD_DOL: loading %s at address %08x (size %d)", path.c_str(),
             dol_addr, max_dol_size);

    File::IOFile fp(WFS::NativePath(path), "rb");
    if (!fp)
    {
      WARN_LOG(IOS_WFS, "IOCTL_WFSI_LOAD_DOL: no such file or directory: %s", path.c_str());
      return_error_code = WFS_ENOENT;
      break;
    }

    u32 real_dol_size = fp.GetSize();
    if (dol_addr == 0)
    {
      // Write the expected size to the size parameter, in the input.
      Memory::Write_U32(real_dol_size, request.buffer_in + 0x14);
    }
    else
    {
      fp.ReadBytes(Memory::GetPointer(dol_addr), max_dol_size);
    }
    Memory::Write_U32(real_dol_size, request.buffer_out);
    break;
  }

  case IOCTL_WFSI_CHECK_HAS_SPACE:
    WARN_LOG(IOS_WFS, "IOCTL_WFSI_CHECK_HAS_SPACE: returning true");

    // TODO(wfs): implement this properly.
    //       1 is returned if there is free space, 0 otherwise.
    //
    // WFSI builds a path depending on the import state
    //   /vol/VOLUME_ID/title/GROUP_ID/GAME_ID
    //   /vol/VOLUME_ID/_install/GAME_ID
    // then removes everything after the last path separator ('/')
    // it then calls WFSISrvGetFreeBlkNum (ioctl 0x5a, aliased to 0x5b) with that path.
    // If the ioctl fails, WFSI returns 0.
    // If the ioctl succeeds, WFSI returns 0 or 1 depending on the three u32s in the input buffer
    // and the three u32s returned by WFSSRV (TODO: figure out what it does)
    return_error_code = 1;
    break;

  default:
    // TODO(wfs): Should be returning an error. However until we have
    // everything properly stubbed it's easier to simulate the methods
    // succeeding.
    request.DumpUnknown(GetDeviceName(), LogTypes::IOS, LogTypes::LWARNING);
    Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
    break;
  }

  return GetDefaultReply(return_error_code);
}
Example #12
0
int main( void )
{
    FILE *f;

    int ret;
    size_t n, buflen;
    mbedtls_net_context server_fd;

    unsigned char *p, *end;
    unsigned char buf[2048];
    unsigned char hash[32];
    const char *pers = "dh_client";

    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_rsa_context rsa;
    mbedtls_dhm_context dhm;
    mbedtls_aes_context aes;

    mbedtls_net_init( &server_fd );
    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 );
    mbedtls_dhm_init( &dhm );
    mbedtls_aes_init( &aes );
    mbedtls_ctr_drbg_init( &ctr_drbg );

    /*
     * 1. Setup the RNG
     */
    mbedtls_printf( "\n  . Seeding the random number generator" );
    fflush( stdout );

    mbedtls_entropy_init( &entropy );
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
        goto exit;
    }

    /*
     * 2. Read the server's public RSA key
     */
    mbedtls_printf( "\n  . Reading public key from rsa_pub.txt" );
    fflush( stdout );

    if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
    {
        ret = 1;
        mbedtls_printf( " failed\n  ! Could not open rsa_pub.txt\n" \
                "  ! Please run rsa_genkey first\n\n" );
        goto exit;
    }

    mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );

    if( ( ret = mbedtls_mpi_read_file( &rsa.N, 16, f ) ) != 0 ||
        ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_mpi_read_file returned %d\n\n", ret );
        goto exit;
    }

    rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3;

    fclose( f );

    /*
     * 3. Initiate the connection
     */
    mbedtls_printf( "\n  . Connecting to tcp/%s/%s", SERVER_NAME,
                                             SERVER_PORT );
    fflush( stdout );

    if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME,
                                         SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_net_connect returned %d\n\n", ret );
        goto exit;
    }

    /*
     * 4a. First get the buffer length
     */
    mbedtls_printf( "\n  . Receiving the server's DH parameters" );
    fflush( stdout );

    memset( buf, 0, sizeof( buf ) );

    if( ( ret = mbedtls_net_recv( &server_fd, buf, 2 ) ) != 2 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_net_recv returned %d\n\n", ret );
        goto exit;
    }

    n = buflen = ( buf[0] << 8 ) | buf[1];
    if( buflen < 1 || buflen > sizeof( buf ) )
    {
        mbedtls_printf( " failed\n  ! Got an invalid buffer length\n\n" );
        goto exit;
    }

    /*
     * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P
     */
    memset( buf, 0, sizeof( buf ) );

    if( ( ret = mbedtls_net_recv( &server_fd, buf, n ) ) != (int) n )
    {
        mbedtls_printf( " failed\n  ! mbedtls_net_recv returned %d\n\n", ret );
        goto exit;
    }

    p = buf, end = buf + buflen;

    if( ( ret = mbedtls_dhm_read_params( &dhm, &p, end ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_dhm_read_params returned %d\n\n", ret );
        goto exit;
    }

    if( dhm.len < 64 || dhm.len > 512 )
    {
        ret = 1;
        mbedtls_printf( " failed\n  ! Invalid DHM modulus size\n\n" );
        goto exit;
    }

    /*
     * 5. Check that the server's RSA signature matches
     *    the SHA-256 hash of (P,G,Ys)
     */
    mbedtls_printf( "\n  . Verifying the server's RSA signature" );
    fflush( stdout );

    p += 2;

    if( ( n = (size_t) ( end - p ) ) != rsa.len )
    {
        ret = 1;
        mbedtls_printf( " failed\n  ! Invalid RSA signature size\n\n" );
        goto exit;
    }

    mbedtls_sha1( buf, (int)( p - 2 - buf ), hash );

    if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC,
                                  MBEDTLS_MD_SHA256, 0, hash, p ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_rsa_pkcs1_verify returned %d\n\n", ret );
        goto exit;
    }

    /*
     * 6. Send our public value: Yc = G ^ Xc mod P
     */
    mbedtls_printf( "\n  . Sending own public value to server" );
    fflush( stdout );

    n = dhm.len;
    if( ( ret = mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, n,
                                 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_dhm_make_public returned %d\n\n", ret );
        goto exit;
    }

    if( ( ret = mbedtls_net_send( &server_fd, buf, n ) ) != (int) n )
    {
        mbedtls_printf( " failed\n  ! mbedtls_net_send returned %d\n\n", ret );
        goto exit;
    }

    /*
     * 7. Derive the shared secret: K = Ys ^ Xc mod P
     */
    mbedtls_printf( "\n  . Shared secret: " );
    fflush( stdout );

    if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n,
                                 mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_dhm_calc_secret returned %d\n\n", ret );
        goto exit;
    }

    for( n = 0; n < 16; n++ )
        mbedtls_printf( "%02x", buf[n] );

    /*
     * 8. Setup the AES-256 decryption key
     *
     * This is an overly simplified example; best practice is
     * to hash the shared secret with a random value to derive
     * the keying material for the encryption/decryption keys,
     * IVs and MACs.
     */
    mbedtls_printf( "...\n  . Receiving and decrypting the ciphertext" );
    fflush( stdout );

    mbedtls_aes_setkey_dec( &aes, buf, 256 );

    memset( buf, 0, sizeof( buf ) );

    if( ( ret = mbedtls_net_recv( &server_fd, buf, 16 ) ) != 16 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_net_recv returned %d\n\n", ret );
        goto exit;
    }

    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
    buf[16] = '\0';
    mbedtls_printf( "\n  . Plaintext is \"%s\"\n\n", (char *) buf );

exit:

    mbedtls_net_free( &server_fd );

    mbedtls_aes_free( &aes );
    mbedtls_rsa_free( &rsa );
    mbedtls_dhm_free( &dhm );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );

#if defined(_WIN32)
    mbedtls_printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Example #13
0
static NO_INLINE JsVar *jswrap_crypto_AEScrypt(JsVar *message, JsVar *key, JsVar *options, bool encrypt) {
  int err;

  unsigned char iv[16]; // initialisation vector
  memset(iv, 0, 16);

  CryptoMode mode = CM_CBC;

  if (jsvIsObject(options)) {
    JsVar *ivVar = jsvObjectGetChild(options, "iv", 0);
    if (ivVar) {
      jsvIterateCallbackToBytes(ivVar, iv, sizeof(iv));
      jsvUnLock(ivVar);
    }
    JsVar *modeVar = jsvObjectGetChild(options, "mode", 0);
    if (!jsvIsUndefined(modeVar))
      mode = jswrap_crypto_getMode(modeVar);
    jsvUnLock(modeVar);
    if (mode == CM_NONE) return 0;
  } else if (!jsvIsUndefined(options)) {
    jsError("'options' must be undefined, or an Object");
    return 0;
  }



  mbedtls_aes_context aes;
  mbedtls_aes_init( &aes );

  JSV_GET_AS_CHAR_ARRAY(messagePtr, messageLen, message);
  if (!messagePtr) return 0;

  JSV_GET_AS_CHAR_ARRAY(keyPtr, keyLen, key);
  if (!keyPtr) return 0;

  if (encrypt)
    err = mbedtls_aes_setkey_enc( &aes, (unsigned char*)keyPtr, (unsigned int)keyLen*8 );
  else
    err = mbedtls_aes_setkey_dec( &aes, (unsigned char*)keyPtr, (unsigned int)keyLen*8 );
  if (err) {
    jswrap_crypto_error(err);
    return 0;
  }

  char *outPtr = 0;
  JsVar *outVar = jsvNewArrayBufferWithPtr((unsigned int)messageLen, &outPtr);
  if (!outPtr) {
    jsError("Not enough memory for result");
    return 0;
  }



  switch (mode) {
  case CM_CBC:
    err = mbedtls_aes_crypt_cbc( &aes,
                     encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT,
                     messageLen,
                     iv,
                     (unsigned char*)messagePtr,
                     (unsigned char*)outPtr );
    break;
  case CM_CFB:
    err = mbedtls_aes_crypt_cfb8( &aes,
                     encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT,
                     messageLen,
                     iv,
                     (unsigned char*)messagePtr,
                     (unsigned char*)outPtr );
    break;
  case CM_CTR: {
    size_t nc_off = 0;
    unsigned char nonce_counter[16];
    unsigned char stream_block[16];
    memset(nonce_counter, 0, sizeof(nonce_counter));
    memset(stream_block, 0, sizeof(stream_block));
    err = mbedtls_aes_crypt_ctr( &aes,
                     messageLen,
                     &nc_off,
                     nonce_counter,
                     stream_block,
                     (unsigned char*)messagePtr,
                     (unsigned char*)outPtr );
    break;
  }
  case CM_ECB: {
    size_t i = 0;
    while (!err && i+15 < messageLen) {
      err = mbedtls_aes_crypt_ecb( &aes,
                       encrypt ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT,
                       (unsigned char*)&messagePtr[i],
                       (unsigned char*)&outPtr[i] );
      i += 16;
    }
    break;
  }
  default:
    err = MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
    break;
  }

  mbedtls_aes_free( &aes );
  if (!err) {
    return outVar;
  } else {
    jswrap_crypto_error(err);
    jsvUnLock(outVar);
    return 0;
  }
}
Example #14
0
static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key,
                                unsigned int key_bitlen )
{
    return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen );
}
Example #15
0
/**
* Block symmetric ciphers.
* Please note that linker-override is possible, but dynamic override is generally
*   preferable to avoid clobbering all symmetric support.
*
* @param uint8_t* Buffer containing plaintext.
* @param int      Length of plaintext.
* @param uint8_t* Target buffer for ciphertext.
* @param int      Length of output.
* @param uint8_t* Buffer containing the symmetric key.
* @param int      Length of the key, in bits.
* @param uint8_t* IV. Caller's responsibility to use correct size.
* @param Cipher   The cipher by which to encrypt.
* @param uint32_t Options to the optionation.
* @return true if the root function ought to defer.
*/
int __attribute__((weak)) wrapped_sym_cipher(uint8_t* in, int in_len, uint8_t* out, int out_len, uint8_t* key, int key_len, uint8_t* iv, Cipher ci, uint32_t opts) {
  if (cipher_deferred_handling(ci)) {
    // If overriden by user implementation.
    return _sym_overrides[ci](in, in_len, out, out_len, key, key_len, iv, ci, opts);
  }
  int8_t ret = -1;
  switch (ci) {
    #if defined(MBEDTLS_AES_C)
      case Cipher::SYM_AES_256_CBC:
      case Cipher::SYM_AES_192_CBC:
      case Cipher::SYM_AES_128_CBC:
        {
          mbedtls_aes_context ctx;
          if (opts & OP_ENCRYPT) {
            mbedtls_aes_setkey_enc(&ctx, key, (unsigned int) key_len);
          }
          else {
            mbedtls_aes_setkey_dec(&ctx, key, (unsigned int) key_len);
          }
          ret = mbedtls_aes_crypt_cbc(&ctx, _cipher_opcode(ci, opts), in_len, iv, in, out);
          mbedtls_aes_free(&ctx);
        }
        break;
    #endif

    #if defined(MBEDTLS_RSA_C)
      case Cipher::ASYM_RSA:
        {
          mbedtls_ctr_drbg_context ctr_drbg;
          mbedtls_ctr_drbg_init(&ctr_drbg);
          size_t olen = 0;
          mbedtls_pk_context ctx;
          mbedtls_pk_init(&ctx);
          if (opts & OP_ENCRYPT) {
            ret = mbedtls_pk_encrypt(&ctx, in, in_len, out, &olen, out_len, mbedtls_ctr_drbg_random, &ctr_drbg);
          }
          else {
            ret = mbedtls_pk_decrypt(&ctx, in, in_len, out, &olen, out_len, mbedtls_ctr_drbg_random, &ctr_drbg);
          }
          mbedtls_pk_free(&ctx);
        }
        break;
    #endif

    #if defined(MBEDTLS_BLOWFISH_C)
      case Cipher::SYM_BLOWFISH_CBC:
        {
          mbedtls_blowfish_context ctx;
          mbedtls_blowfish_setkey(&ctx, key, key_len);
          ret = mbedtls_blowfish_crypt_cbc(&ctx, _cipher_opcode(ci, opts), in_len, iv, in, out);
          mbedtls_blowfish_free(&ctx);
        }
        break;
    #endif

    #if defined(WRAPPED_SYM_NULL)
      case Cipher::SYM_NULL:
        memcpy(out, in, in_len);
        ret = 0;
        break;
    #endif

    default:
      break;
  }
  return ret;
}