docs: Remove current docs and link to the new location
All current documentation has been transferred to a new git called
optee_docs [1]. The output from optee_docs will be rendered using Sphinx
and hosted at optee.readthedocs.io [2]. The new documentation git will
also be part of the regular OP-TEE releases. For completeness, it will
also be included in our manifests making up a full OP-TEE developer
setup.
[1] https://github.com/OP-TEE/optee_docs
[2] https://optee.readthedocs.io
Signed-off-by: Joakim Bech <joakim.bech@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/README.md b/README.md
index 839e3c2..08a24ab 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,11 @@
# OP-TEE Sample Applications
-## Contents
-1. [Introduction](#1-introduction)
-2. [List of sample applications](#2-list-of-sample-applications)
-3. [How to build a Trusted Application](#3-how-to-build-a-trusted-application)
+This git contains source code for sample host and Trusted Application that can
+be used directly in the OP-TEE project.
+All official OP-TEE documentation has moved to http://optee.readthedocs.io. The
+information that used to be here in this git can be found under
+[optee_examples].
-## 1. Introduction
-This document describes the sample applications that are included in the OP-TEE,
-that aim to showcase specific functionality and use case.
+// OP-TEE core maintainers
-For sake of simplicity, all OP-TEE example test application are prefixed with
-`optee_example_`.
-
----
-## 2. List of sample applications
-
-Directory **hello_world/**:
-* A very simple Trusted Application to answer a hello command and incrementing
-an integer value.
-* Test application: `optee_example_hello_world`
-* Trusted application UUID: 8aaaf200-2450-11e4-abe2-0002a5d5c51b
-
-Directory **random/**:
-* Generates a random UUID using capabilities of TEE API (`TEE_GenerateRandom()`).
-* Test application: `optee_example_random`
-* Trusted application UUID: b6c53aba-9669-4668-a7f2-205629d00f86
-
-Directory **aes/**:
-* Runs an AES encryption and decryption from a TA using the GPD TEE Internal
-Core API. Non secure test application provides the key, initial vector and
-ciphered data.
-* Test application: `optee_example_aes`
-* Trusted application UUID: 5dbac793-f574-4871-8ad3-04331ec17f24
-
-Directory **secure_storage/**:
-* A Trusted Application to read/write raw data into the
-OP-TEE secure storage using the GPD TEE Internal Core API.
-* Test application: `optee_example_secure_storage`
-* Trusted application UUID: f4e750bb-1437-4fbf-8785-8d3580c34994
-
-Directory **acipher/**:
-* Generates an RSA key pair of specified size and encrypts a supplied string
- with it using the GPD TEE Internal Core API.
-* Test application: `optee_example_acipher`
-* Trusted application UUID: a734eed9-d6a1-4244-aa50-7c99719e7b7b
-
-## 3. How to build a Trusted Application
-[TA basics] documentation presents the basics for implementing and building
-an OP-TEE trusted application.
-
-One can also refer to the examples provided: source files and make scripts.
-
-[TA basics]: ./docs/TA_basics.md
+[optee_examples]: https://optee.readthedocs.io/building/gits/optee_examples/optee_examples.html
diff --git a/docs/TA_basics.md b/docs/TA_basics.md
deleted file mode 100644
index 2573353..0000000
--- a/docs/TA_basics.md
+++ /dev/null
@@ -1,304 +0,0 @@
-Basics for Development of OP-TEE Trusted Applications
-=====================================================
-
-This document show how to implement a basic trusted application for OP-TEE,
-using the OP-TEE devkit to build and sign the trusted application binary.
-
-In this document, a trusted application running in the OP-TEE os is referred
-to as a TA.
-
-### Contents
-1. [TA Minimal Source Files](#1-ta-minimal-source-files)
-2. [TA Makefile Script Basics](#2-ta-makefile-script-basics)
-3. [Android Build Environment](#3-android-build-environment)
-4. [TA Entry Points Implementation Basics](#4-ta-entry-points-implementation-basics)
-5. [TA Properties Basics](#5-ta-properties-basics)
-6. [Specific cares on TA invocation parameters](#6-specific-cares-on-ta-invocation-parameters)
-
-
----
-# 1. TA Minimal Source Files
-
-Trusted Application Makefile must be designed to rely on OP-TEE devkit
-resources in order to successfully build the target application. The OP-TEE
-devkit is built (maybe installed) when one builds (installs) the optee_os.
-
-To build a TA, one must provide:
-
-- **Makefile**, a make script that should set some configuration variables and
- include the devkit make script.
-
-- **sub.mk**, a make script that lists the sources to build (local source files,
- subdirectories to parse, source file specific build directives).
-
-- **user_ta_header_defines.h**, a specific ANSI-C header file to define most of
- the TA properties.
-
-- A implementation of at least the TA entry points, as extern functions:
- `TA_CreateEntryPoint()`, `TA_DestroyEntryPoint()`,
- `TA_OpenSessionEntryPoint()`, `TA_CloseSessionEntryPoint()`,
- `TA_InvokeCommandEntryPoint()`
-
-Looking at example hello_world:
-```
-hello_world/
-├── ...
-└── ta
- ├── Makefile BINARY=<uuid>
- ├── Android.mk Android way to invoke the Makefile
- ├── sub.mk srcs-y += hello_world_ta.c
- ├── include
- │ └── hello_world_ta.h Header exported to non-secure: TA commands API
- ├── hello_world_ta.c Implementation of TA entry points
- └── user_ta_header_defines.h TA_UUID, TA_FLAGS, TA_DATA/STACK_SIZE, ...
-```
-
----
-# 2. TA Makefile Script Basics
-
-## 2.1. Devkit Makefile Requirements
-
-The devkit make script is located in the devkit filetree at path
-**mk/ta_dev_kit.mk**.
-
-The make script supports rules `all` and `clean` to build a TA or
-a library and clean the built objects.
-
-The make script expects some configuration variables:
-
-- Variable `TA_DEV_KIT_DIR`
-
- Base directory of the devkit. Used the devkit itself to locate its tools.
-
-- Variables `BINARY` and `LIBNAME`
-
- `BINARY` and `LIBNAME` are exclusives.
-
- If building a TA, `BINARY` shall provide the TA filename used to load the TA.
- The built signed TA binary file will be named `${BINARY}.ta`.
- In native OP-TEE, it is the TA uuid, used by tee-supplicant to identify TAs.
-
- if building a static library (that will be later linked by a TA),
- `LIBNAME` shall provide the name of the library. The generated library
- binary file will be named `lib${LIBNAME}.a`
-
-- Variables `CROSS_COMPILE` and `CROSS_COMPILE32`
-
- Cross compiler for the TA or the library source files. `CROSS_COMPILE32`
- is optional. It allows to target AArch32 builds on AArch64 capable systems.
- On AArch32 systems, `CROSS_COMPILE32` defaults to `CROSS_COMPILE`.
-
-Some optional configuration variables can be supported, check optee_os
-delivery. For examples:
-
-- Variable `O`
-
- Base directory for build objects filetree. If not set, devit defaults to
- **./out** from the TA source tree base directory.
-
-A typical makefile to drive the build of a TA is:
-```make
-# Append specific configuration to the C source build (here log=info)
-# The UUID for the Trusted Application
-BINARY=8aaaf200-2450-11e4-abe2-0002a5d5c51b
-
-# Source the devkit make script
-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
-```
-
-## 2.2. Listing Source Files to Build and Build directives
-
-The make script expects that current directory contains a file `sub.mk` that
-is the entry point for listing the source files to build and other specific
-build directives.
-
-Following are examples of directive one can implement in a sub.mk make script:
-
-* `srcs-y += hello_world_ta.c`\
- Adds **./hello_world_ta.c** from current directory to the list of the source
- file to build and link.
-
-* `global-incdirs-y += include/`\
- Includes path **./include/** from the current directory to the include path.
-
-* `cflags-hello_world_ta.c-y += -Wno-strict-prototypes`\
- Adds directive `-Wno-strict-prototypes` to the build directive of
- **./hello_world_ta.c** specific source file.
-
-* `cflags-remove-hello_world_ta.c-y += -Wno-strict-prototypes`\
- Removes directive `-Wno-strict-prototypes` from the build directives of
- **./hello_world_ta.c** specific source file.
-
-* `libnames += foo`\
- Adds the static library `foo` to the list of the linker directives:
- `-lfoo`.
-
-* `libdirs += path/to/libfoo/install/directory`\
- Adds the directory path to the libraries pathes list. Archive file
- **libfoo.a** is expectd in this directory.
-
-* `libdeps += path/to/greatlib/libgreatlib.a`\
- Adds the static library binary to the TA build dependencies.
-
----
-# 3. Android Build Environment
-
-OP-TEE devkit supports building in Android build environment. One can
-implement an Android.mk script for its TA next to the Makefile script.
-
-The Android build will parse the TA Android make script which will parse a
-devkit Android make script to locate TA build resources. Then the Android
-build will execute a `make` command to built the TA through its generic
-Makefile script.
-
-A typical Android.mk script for a TA is:
-```make
-$ cat hello_world/ta/Android.mk
-# Define base path for the TA sources filetree
-LOCAL_PATH := $(call my-dir)
-# Define the module name as the signed TA binary filename.
-local_module := 8aaaf200-2450-11e4-abe2-0002a5d5c51b.ta
-# Include the devkit Android make script
-include $(OPTEE_OS_DIR)/mk/aosp_optee.mk
-```
-
----
-# 4. TA Entry Points Implementation Basics
-
-TA source code is expected to provide implementation for the following
-functions:
-
-```c
-TEE_Result TA_CreateEntryPoint(void)
-{
- /* Allocate some resources, init something, ... */
- ...
-
- /* Return with a status */
- return TEE_SUCCESS;
-}
-
-void TA_DestroyEntryPoint(void)
-{
- /* Release resources if required before TA destruction */
- ...
-}
-
-TEE_Result TA_OpenSessionEntryPoint(uint32_t ptype,
- TEE_Param param[4],
- void **session_id_ptr)
-{
- /* Check client identity, and alloc/init some session resources if any */
- ...
-
- /* Return with a status */
- return TEE_SUCCESS;
-}
-
-void TA_CloseSessionEntryPoint(void *sess_ptr)
-{
- /* check client and handle session resource release, if any */
- ...
-}
-
-TEE_Result TA_InvokeCommandEntryPoint(void *session_id,
- uint32_t command_id,
- uint32_t parameters_type,
- TEE_Param parameters[4])
-{
- /* Decode the command and process execution of the target service */
- ...
-
- /* Return with a status */
- return TEE_SUCCESS;
-}
-```
-
----
-# 5. TA Properties Basics
-
-Trusted Application properties shall be defined in a specific ANSI-C header
-file named **user_ta_header_defines.h**. The header file shall define the following macros:
-
-- `TA_UUID` defines the TA uuid value
-
-- `TA_FLAGS` define some of the TA properties
-
-- `TA_STACK_SIZE` defines the RAM size to be reserved for TA stack
-
-- `TA_DATA_SIZE` defines the RAM size to be reserved for TA heap (TEE_Malloc() pool)
-
-Refer to [TA properties] to configure these macros.
-
-**user_ta_header_defines.h** file may provide the following macro:
-
-- `TA_CURRENT_TA_EXT_PROPERTIES` may define extra properties of the TA.
-
-
-Example of **user_ta_header_defines.h**:
-
-```c
-#ifndef USER_TA_HEADER_DEFINES_H
-#define USER_TA_HEADER_DEFINES_H
-
-#define TA_UUID
- { 0x8aaaf200, 0x2450, 0x11e4, \
- { 0xab, 0xe2, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} }
-
-#define TA_FLAGS (TA_FLAG_EXEC_DDR | \
- TA_FLAG_SINGLE_INSTANCE | \
- TA_FLAG_MULTI_SESSION)
-#define TA_STACK_SIZE (2 * 1024)
-#define TA_DATA_SIZE (32 * 1024)
-
-#define TA_CURRENT_TA_EXT_PROPERTIES \
- { "gp.ta.description", USER_TA_PROP_TYPE_STRING, "Foo TA for some purpose." }, \
- { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0100 } }
-
-#endif /* USER_TA_HEADER_DEFINES_H */
-```
-
----
-# 6. Specific cares on TA invocation parameters
-
-GPD TEE Client APIs `TEEC_InvokeCommand()` and `TEE_OpenSession()` allow a client
-to invoke a TA with some invocation parameters: values or references to memory buffers.
-
-It is mandatory that TAs verify the parameters types before using the parameters
-themsleves.
-
-TA can rely on macro TEE_PARAM_TYPE_GET(param_type, param_index)` to get the
-type of a parameter and check its value according to the expected parameter.
-
-For example, if TA expect that command ID 0 comes with param#0 being a input
-value, param#2 being a output value, and param#3 being a in/out memory
-reference (buffer), TA should implemented the following sequence:
-
-```c
-TEE_Result handle_command_0(void *session, uint32_t cmd_id,
- uint32_t param_types, TEE_Param params[4])
-{
- if ((TEE_PARAM_TYPE_GET(param_types, 0) != TEE_PARAM_TYPE_VALUE_IN) ||
- (TEE_PARAM_TYPE_GET(param_types, 1) != TEE_PARAM_TYPE_VALUE_OUT) ||
- (TEE_PARAM_TYPE_GET(param_types, 2) != TEE_PARAM_TYPE_MEMREF_INOUT) ||
- (TEE_PARAM_TYPE_GET(param_types, 3) != TEE_PARAM_TYPE_NONE)) {
- return TEE_ERROR_BAD_PARAMETERS
- }
-
- /* process command */
- ...
-}
-
-TEE_Result TA_InvokeCommandEntryPoint(void *session, uint32_t command_id,
- uint32_t param_types, TEE_Param params[4])
-{
- switch (command_id) {
- case 0:
- return handle_command_0(session, param_types, params);
- default:
- return TEE_ERROR_NOT_SUPPORTED;
- }
-}
-```
-
-[TA properties]: ./TA_properties.md
diff --git a/docs/TA_properties.md b/docs/TA_properties.md
deleted file mode 100644
index 7a705b8..0000000
--- a/docs/TA_properties.md
+++ /dev/null
@@ -1,140 +0,0 @@
-Defining Properties of Trusted Applications
-===========================================
-
-This document is related to the trusted application examples documentation [TA basics].
-
-
-### Contents
-
-1. [TA properties defined by GPD TEE specifications](#1-ta-properties-defined-by-gpd-tee-specifications)
-2. [TA Property Flags from the OP-TEE Extensions](#2-ta-property-flags-from-the-op-tee-extensions)
-
-
-# 1. TA properties defined by GPD TEE specifications
-
-Standard TA properties must be defined through property flag in macro
-`TA_FLAGS` by **user_ta_header_defines.h**.
-
-## 1.1. Single Instance Property
-
-`"gpd.ta.singleInstance"` is a boolean property of the TA.
-
-This property defines if one instance of the TA must be created and will
-receive all open session request, or if a new specific TA instance must be
-created for each incoming open session request.
-
-OP-TEE TA flag `TA_FLAG_SINGLE_INSTANCE` sets to configuration of this
-property.
-
-The boolean property is set to `true` if `TA_FLAGS` sets bit
-`TA_FLAG_SINGLE_INSTANCE`, otherwise the boolean property is set to `false`.
-
-## 1.2. Multi-session Property
-
-`"gpd.ta.multiSession"` is a boolean property of the TA.
-
-This property defines if the TA instance can handle several sessions. If
-disabled, TA instance support only one session. In such case, if the TA
-already has a opened session, any open session request will return with a
-busy error status.
-
-This property is meaningless if TA is NOT SingleInstance.
-
-OP-TEE TA flag `TA_FLAG_MULTI_SESSION` sets to configuration of this
-property.
-
-The boolean property is set to `true` if `TA_FLAGS` sets bit
-`TA_FLAG_MULTI_SESSION`, otherwise the boolean property is set to `false`.
-
-## 1.3. Keep Alive Property
-
-`"gpd.ta.instanceKeepAlive"` is a boolean property of the TA.
-
-This property defines if the TA instance created must be destroyed or not when
-all sessions opened towards the TA are closed. If the property is enabled, TA
-instance, once created (at 1st open session request), is never removed unless
-the TEE itself is restarted (boot/reboot).
-
-This property is meaningless if TA is NOT SingleInstance.
-
-OP-TEE TA flag `TA_FLAG_INSTANCE_KEEP_ALIVE` sets to configuration of this
-property.
-
-The boolean property is set to `true` if `TA_FLAGS` sets bit
-`TA_FLAG_INSTANCE_KEEP_ALIVE`, otherwise the boolean property is set to `false`.
-
-## 1.4. Heap Size Property
-
-`"gpd.ta.dataSize"` is a 32bit integer property of the TA.
-
-This property defines the size in bytes of the TA allocation pool, in which
-`TEE_Malloc()` and friends allocate memory.
-
-The value of the property must be defined by the macro `TA_DATA_SIZE` from
-**user_ta_header_defines.h**.
-
-## 1.5. Stack Size Property
-
-`"gpd.ta.stackSize"` is a 32bit integer property of the TA.
-
-This property defines the size in bytes of the stack used for TA execution.
-
-The value of the property must be defined by the macro `TA_STACK_SIZE` from
-**user_ta_header_defines.h**.
-
-# 2. TA Property Flags from the OP-TEE Extensions
-
-## 2.1. User Mode Property Flag
-
-`TA_FLAG_USER_MODE` is a bit flag supported by `TA_FLAGS`.
-
-This property flag is currently meaningless in OP-TEE. It may be set or not
-without impact on TA execution. All OP-TEE TAs are executed in user mode/level.
-
-Because of this we do not recommend to use this flag.
-
-## 2.2. Exec-in-DDR Property Flag
-
-`TA_FLAG_EXEC_DDR` is a bit flag supported by `TA_FLAGS`.
-
-This property flag is currently meaningless in OP-TEE. Nevertheless it shall
-be set. It is a legacy property flag that aimed at targeting location for the TA
-execution, internal RAM or external DDR.
-
-Therefore all TAs must set `TA_FLAG_EXEC_DDR` in `TA_FLAGS` in their
-**user_ta_header_defines.h** header file.
-
-Note: this flag will soon be deprecated.
-
-## 2.3. Secure Data Path Support Property Flag
-
-`TA_FLAG_SECURE_DATA_PATH` is a bit flag supported by `TA_FLAGS`.
-
-This property flag claims the secure data support from the OP-TEE OS for the TA.
-Refer to the OP-TEE OS for secure data path support.
-
-TAs that do not set `TA_FLAG_SECURE_DATA_PATH` in the value of `TA_FLAGS` will
-not be able to handle memory reference invocation parameters that relate to
-secure data path buffers.
-
-## 2.4. Remap Support Property Flag
-
-`TA_FLAG_REMAP_SUPPORT` is a bit flag supported by `TA_FLAGS`.
-
-This property flag is currently meaningless in OP-TEE and therefore we
-recommend to not use this flag.
-
-Note: this flag will soon be deprecated.
-
-## 2.5. Cache maintenance Property Flag
-
-`TA_FLAG_CACHE_MAINTENANCE` is a bit flag supported by `TA_FLAGS`.
-
-This property flag claims access to the cache maintenance API for the TA:
-`TEE_CacheXxxx()`. Refer to the OP-TEE to check if cache API support is
-enabled.
-
-TAs that do not set `TA_FLAG_CACHE_MAINTENANCE` in the value of their `TA_FLAGS`
-will not be able to call the cache maintenance API.
-
-[TA basics]: ./TA_basics.md
diff --git a/hotp/README.md b/hotp/README.md
deleted file mode 100644
index 4e5398c..0000000
--- a/hotp/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# HMAC based One Time Password in OP-TEE
-[HMAC] based One Time Passwords or shortly just 'HOTP' has been around for many
-years and was initially defined in [RFC4226] back in 2005. Since then it has
-been a popular choice for doing [two factor authentication]. With the
-implementation here we are showing how one could leverage OP-TEE for generating
-such HMAC based One Time Passwords in a secure manner.
-
-## Client (OP-TEE) / Server solution
-The most common way of using HOTP is in a client/server setup, where the client
-needs to authenticate itself to be able to get access to some resources on the
-server. In those cases the server will ask for an One Time Password, the client
-will generate that and send it over to the server and if the server is OK with
-the password it will grant access to the client.
-
-Technically how it is working is that the server and the client needs to agree
-on shared key ('`K`') and also start from the same counter ('`C`'). How that is
-done in practice is another topic, but RFC4226 has some discussion about it. You
-should at least have a secure channel between the client and the server when
-sharing the key, but even better would be if you could establish a secure
-channel all the way down to the TEE (currently we have TCP/UDP support in
-OP-TEE, but not TLS).
-
-When both the server and the client knows about and use the same key and
-counter they can start doing client authentication using HOTP. In short what
-happens is that both the client and the server computes the same HOTP and the
-server compares the result of both computations (which should be the same to
-grant access). How that could work can be seen in the sequence diagram below.
-
-In the current implementation we have OP-TEE acting as a client and the server
-is a remote service running somewhere else. There is no server implemented, but
-that should be pretty easy to add in a real scenario. The important thing here
-is to be able to register the shared key in the TEE and to get HOTP values from
-the TEE on request.
-
-Since the current implementation works as a client we do not need to think about
-implementing the look-ahead synchronization window ('`s`') nor do we have to
-think about adding throttling (which prevents/slows down brute force attacks).
-
-#### Sequence diagram - Client / Server
-
-
-## Client / Server (OP-TEE)?
-Even though the current implementation works as a HOTP client, there is nothing
-saying that the implementation cannot be updated to also work as the validating
-server. One could for example have a simple device (a [security token] only
-generating one time passwords) and use the TEE as a validating service to open
-up other secure services.
-
-[HMAC]: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code
-<!--- The link below to mscgen.js.org should be updated when regenerating the image -->
-[link to sequence diagram]: https://mscgen.js.org/?lang=xu&msc=msc%20%7B%0A%20%20wordwraparcs%3Doff%2C%0A%20%20hscale%3D%220.95%22%2C%0A%20%20watermark%3D%22HOTP%20OP-TEE%20%22%3B%0A%0A%20%20tee%20%5Blabel%3D%22TEE%20%2F%20TA%22%2C%20linecolor%3D%22darkgreen%22%2C%20textcolor%3D%22white%22%2C%20textbgcolor%3D%22darkgreen%22%2C%20arclinecolor%3D%22darkgreen%22%2C%20arctextcolor%3D%22darkgreen%22%5D%2C%0A%20%20client%20%5Blabel%3D%22Client%22%2C%20linecolor%3D%22darkgreen%22%2C%20textcolor%3D%22white%22%2C%20textbgcolor%3D%22darkgreen%22%2C%20arclinecolor%3D%22darkgreen%22%2C%20arctextcolor%3D%22darkgreen%22%5D%2C%0A%20%20server%20%5Blabel%3D%22Server%22%2C%20linecolor%3D%22%233a5795%22%2C%20textcolor%3D%22white%22%2C%20textbgcolor%3D%22%233a5795%22%2C%20arclinecolor%3D%22%233a5795%22%2C%20arctextcolor%3D%22%233a5795%22%5D%3B%0A%20%20%0A%20%20client%20note%20client%20%5Blabel%3D%22Shared%20key%20needs%5Cnto%20be%20handled%5Cnusing%20secure%5Cnchannels%20(TLS%2FSSL)%22%5D%3B%0A%20%20client%20%3C%3D%3E%20server%20%5Blabel%3D%22Agree%20on%20shared%20key%22%5D%3B%0A%20%20client%20%3D%3E%20tee%20%5Blabel%3D%22Store%20shared%20key%22%5D%3B%0A%20%20client%20%3D%3E%20server%20%5Blabel%3D%22Login%22%5D%3B%0A%20%20server%20%3D%3E%20client%20%5Blabel%3D%22Request%20HOTP%22%5D%3B%0A%20%20client%20%3D%3E%20tee%20%5Blabel%3D%22Get%20HOTP%20from%20TEE%22%5D%3B%0A%20%20tee%20%3E%3E%20tee%20%5Blabel%3D%22Calulate%20HOTP%22%5D%3B%0A%20%20tee%20%3E%3E%20client%20%5Blabel%3D%22HOPT%20value%22%5D%3B%0A%20%20client%20%3E%3E%20server%20%5Blabel%3D%22Send%20HTOP%20value%22%5D%3B%0A%20%20server%20%3E%3E%20server%20%5Blabel%3D%22Calulate%20HOTP%20locally%22%5D%3B%0A%20%20client%20alt%20server%20%5Blabel%3D%22Client%20HOTP%20%3D%3D%20Server%20HOTP%3F%22%2C%20linecolor%3D%22grey%22%2C%20textbgcolor%3D%22white%22%5D%20%7B%0A%20%20%09%0A%20%20%20%20---%20%5Blabel%3D%22Yes%22%2C%20linecolor%3Dgrey%2C%20textbgcolor%3Dwhite%5D%3B%0A%20%20%20%20server%20%3E%3E%20client%20%5Blabel%3D%22Grant%20access%22%5D%3B%0A%20%20%20%20%0A%20%20%20%20---%20%5Blabel%3D%22No%22%2C%20linecolor%3Dgrey%2C%20textbgcolor%3Dwhite%5D%3B%0A%20%20%20%20server%20%3E%3E%20client%20%5Blabel%3D%22Access%20denied%22%5D%3B%0A%20%20%7D%3B%0A%7D
-[RFC4226]: https://www.ietf.org/rfc/rfc4226.txt
-[security token]: https://en.wikipedia.org/wiki/Security_token
-[two factor authentication]: https://en.wikipedia.org/wiki/Multi-factor_authentication