From 766f3af83f2c658e92051460e519ad02fc9215c4 Mon Sep 17 00:00:00 2001 From: wardmart Date: Sat, 2 Dec 2023 17:28:29 +0000 Subject: [PATCH 1/3] Update README.md --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index 1715e68..1648080 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,6 @@ V1.1.1 did not include an OpenAPI description. **IMPORTANT: These [OpenAPI](https://www.openapis.org/) specifications are under development in branch [edition2](https://forge.etsi.org/rep/qkd/gs014-key-deliv/-/tree/edition2) of this repository and are subject to change** -## Visualise - -View draft API in -[Swagger Editor](https://forge.etsi.org/swagger/editor-versions/v3.8.0/?url=https://forge.etsi.org/rep/qkd/gs014-key-deliv/raw/edition2/key-deliv.yaml). - ## Related ISG QKD Repositories - [Draft OpenAPI](https://forge.etsi.org/rep/qkd/gs020-interop-kms) for -- GitLab From c9069d1549e600303264f31598d8d40de9b038f9 Mon Sep 17 00:00:00 2001 From: wardmart Date: Sat, 2 Dec 2023 17:29:36 +0000 Subject: [PATCH 2/3] Revert "Update README.md" This reverts commit 766f3af83f2c658e92051460e519ad02fc9215c4 --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 1648080..1715e68 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,11 @@ V1.1.1 did not include an OpenAPI description. **IMPORTANT: These [OpenAPI](https://www.openapis.org/) specifications are under development in branch [edition2](https://forge.etsi.org/rep/qkd/gs014-key-deliv/-/tree/edition2) of this repository and are subject to change** +## Visualise + +View draft API in +[Swagger Editor](https://forge.etsi.org/swagger/editor-versions/v3.8.0/?url=https://forge.etsi.org/rep/qkd/gs014-key-deliv/raw/edition2/key-deliv.yaml). + ## Related ISG QKD Repositories - [Draft OpenAPI](https://forge.etsi.org/rep/qkd/gs020-interop-kms) for -- GitLab From 5e4c7e26c1030071a59bd9af7712fd4488eb295a Mon Sep 17 00:00:00 2001 From: wardmart Date: Sat, 2 Dec 2023 17:40:38 +0000 Subject: [PATCH 3/3] Initial ideas for discussion --- README.md | 2 +- key-deliv.yaml | 525 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 key-deliv.yaml diff --git a/README.md b/README.md index 1715e68..ce189ce 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ V1.1.1 did not include an OpenAPI description. ## Visualise View draft API in -[Swagger Editor](https://forge.etsi.org/swagger/editor-versions/v3.8.0/?url=https://forge.etsi.org/rep/qkd/gs014-key-deliv/raw/edition2/key-deliv.yaml). +[Swagger Editor](https://forge.etsi.org/swagger/editor-versions/v3.8.0/?url=https://forge.etsi.org/rep/qkd/gs014-key-deliv/raw/wrk-initial-openapi/key-deliv.yaml). ## Related ISG QKD Repositories diff --git a/key-deliv.yaml b/key-deliv.yaml new file mode 100644 index 0000000..1f8d174 --- /dev/null +++ b/key-deliv.yaml @@ -0,0 +1,525 @@ +# Copyright 2023 ETSI +# Licensed under the BSD-3 Clause (https://forge.etsi.org/legal-matters) +openapi: '3.0.3' +info: + title: Draft ETSI GS QKD 014 - Protocol and data format of REST-based key delivery for QKD + description: | + The present document describes a communication protocol and data format for a quantum key distribution (QKD) network to supply cryptographic keys to an application. It is intended to allow interoperability of equipment from different vendors. A REST (REpresentational State Transfer) API is specified as a simple, scalable, widely deployed approach that is familiar to a large developer community. The REST-based API specifies the format of the URIs, the communication protocols (HTTPS), and the JSON (JavaScript Object Notation) data format encoding of posted parameters and responses, including key material. + contact: + name: ETSI ISG QKD + email: 'isgsupport@etsi.org' + version: '1.2.1' + license: + name: BSD 3-Clause + url: https://opensource.org/licenses/BSD-3-Clause +servers: +- url: http://{kme_hostname} + description: Local KME server + variables: + kme_hostname: + default: '127.0.0.1:443' +externalDocs: + description: 'Work Item description' + url: 'https://portal.etsi.org/webapp/WorkProgram/Report_WorkItem.asp?WKI_ID=69542' + +tags: + - name: Introduction + description: | + Quantum key distribution (QKD) networks connect nodes using QKD links for the generation of cryptographic keys. + Applications need to be able to request key material from QKD Systems and their associated Key Management Systems (KMSs). + This document defines a key delivery specification to ensure interoperability between QKD networks, equipment, and applications offered by different vendors. + + The Application Programming Interface (API) defined in this document utilizes a REST-based approach. + This API operates over the HTTPS protocol and encodes data in the JSON format, allowing the secure delivery of block keys with key IDs to applications. + + REST-based APIs are popular across various application domains as a result of their simplicity. + Indeed, various software libraries are available off-the-shelf to implement REST-based API interactions, and for parsing JSON data. + + - name: Connection Specification + description: | + The common specifications for the Key Delivery API are as follows: + + | Name | Description | + |---------------------|--------------------------------------------------| + | Communication Protocol | HTTPS | + | Character code | UTF-8 | + | HTTP Content-type | application/json | + + SAEs shall connect to KMEs using HTTPS protocols with Transport Layer Security (TLS) version 1.3 (or higher). + At the connection establishment, mutual authentication between the SAE and KME shall be performed. + + The SAE shall verify the validity of the certificate possessed by the KME and confirm the KME ID based on the certificate. + If the KME certificate is not valid, the SAE will not proceed to use the API with the KME. + + Similarly, the KME shall verify the validity of the certificate possessed by the SAE and confirm its SAE ID based on the certificate. + Practically, X.509 certificates should be used where the identifying information is specified as a Distinguished Name (DN). + Specifically, the SAE's ID should be included as the UID field of the DN or if that is not possible, as the Common Name (CN). + If the certificate is invalid, or if the SAE ID in the certificate does not match the SAE ID for which the API call refers to, the KME will reject the API call. + + - name: Protocol Specification + description: | + The list of available API methods shall be as follows. + +paths: + + /kdapi/versions: + get: + summary: 'Get supported API versions' + operationId: get-versions + tags: + - 'Protocol Specification' + description: | + Returns list of supported ETSI GS QKD 014 API versions. + + When an SAE makes a request to a KME, it should always use the most recent version of the API that the KME and SAE support. + The SAE can use this end-point to determine which API versions the KME supports. + Note that this endpoint was introduced in v2 (ADD ETSI VERSION NUMBER HERE ONCE FINALISED). + Thus, if an SAE does not receive a response from a KME using this call, it should use v1 (i.e. ETSI GS QKD 014 V1.1.1). + responses: + '200': + description: Supported versions + content: + application/json: + schema: + $ref: '#/components/schemas/version_container' + '401': + $ref: '#/components/responses/401' + '503': + $ref: '#/components/responses/503' + + /kdapi/v2/status: + post: + summary: 'Get status of KME' + operationId: post-v2-status + tags: + - 'Protocol Specification' + description: 'Returns KME status. Status contains information about the KME.' + responses: + '200': + description: KME status + content: + application/json: + schema: + $ref: '#/components/schemas/kme_status' + '401': + $ref: '#/components/responses/401' + '503': + $ref: '#/components/responses/503' + + /kdapi/v2/status/link: + post: + summary: 'Get link status' + operationId: post-v2-status-link + tags: + - 'Protocol Specification' + description: | + Returns status for one or more QKD links. + + If both `initiator_sae_id` and `target_sae_id` are specified in the request body, a single status container is returned containing information on keys available to be requested by the initiator SAE for the specified target SAE. + + If only `initiator_sae_id` is specified in the request body, a status container will be returned for each link where the calling SAE is the specified initiator SAE. + + If only `target_sae_id` is specified in the request body, a status container will be returned for each link where the target SAE is the specified target SAE. + + If neither `initiator_sae_id` nor `target_sae_id` are specified, an Error Code 400 is returned. + requestBody: + description: Link status request. + content: + application/json: + schema: + $ref: '#/components/schemas/link_status_request' + responses: + '200': + description: Array of link statuses + content: + application/json: + schema: + $ref: '#/components/schemas/array_link_status' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '503': + $ref: '#/components/responses/503' + + /kdapi/v2/keys: + post: + summary: 'Get key' + operationId: post-v2-keys + tags: + - 'Protocol Specification' + description: | + Returns Key container data from the KME to the calling initiator SAE. + + Key container data contains one or more keys. The calling initiator SAE may supply Key request data to specify the requirement on Key container data. The target SAE specified by the target_sae_id parameter may subsequently request matching keys from a remote KME using key_id identifiers from the returned Key container. + requestBody: + description: Key request. + content: + application/json: + schema: + $ref: '#/components/schemas/key_request' + responses: + '200': + $ref: '#/components/responses/200-getkey' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '503': + $ref: '#/components/responses/503' + + /kdapi/v2/keys_with_id: + post: + summary: 'Get key with key ID' + operationId: post-v2-keys_with_id + tags: + - 'Protocol Specification' + description: | + Returns 'Key container' from the KME to the calling target SAE. + + Key container contains keys matching those previously delivered to a remote initiator SAE based on the Key IDs supplied from the remote initiator SAE in response to its call to Get key. The KME shall reject the request with a 401 HTTP status code if the SAE ID of the requestor was not an SAE ID supplied to the "Get key" method each time it was called resulting in the return of any of the Key IDs being requested. + requestBody: + description: Key ID request. + content: + application/json: + schema: + $ref: '#/components/schemas/key_id_container' + responses: + '200': + $ref: '#/components/responses/200-getkey' + '400': + $ref: '#/components/responses/400' + '401': + $ref: '#/components/responses/401' + '503': + $ref: '#/components/responses/503' + +components: + responses: + 200-getkey: + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/key_container' + 400: + description: Bad request format response + content: + application/json: + schema: + $ref: '#/components/schemas/message_data' + examples: + missing_parameters: + value: + message: 'missing parameters' + details: + - 'missing_parameters': 'required parameters are missing from the API call' + 401: + description: Unauthorized response + content: + application/json: + schema: + $ref: '#/components/schemas/message_data' + example: + message: 'unauthorized' + details: + - 'unauthorized': 'User-supplied certificate is invalid.' + 503: + description: Error of server side response + content: + application/json: + schema: + $ref: '#/components/schemas/message_data' + example: + message: 'server side general error' + details: + - 'server_side_general_error': 'The server encountered a general failure and cannot respond.' + + schemas: + # NOTE: the descriptions here don't get used for parameters in Swagger (but do in redocly) + kme_id: + type: string + example: kme1 + description: KME ID of the KME + initiator_kme_id: + type: string + example: kme1 + description: KME ID of the KME + target_kme_id: + type: string + example: kme2 + description: KME ID of the target KME + initiator_sae_id: + type: string + description: ID of the SAE that initiated the request to share the key(s) relevant to the request. + example: encryptor1 + target_sae_id: + type: string + description: ID of target SAE that the initiator SAE wishes to share keys with. + example: encryptor2 + target_sae_ids: + type: array + description: Array of IDs of target SAEs that the initiator SAE wishes to share keys with. A single target or multiple targets can be specified (where each target gets an identical key). The maximum number of IDs is defined as `max_sae_id_count` in Status data format. + items: + $ref: '#/components/schemas/target_sae_id' + key_size: + type: integer + description: 'Size of each key in bits (default value is defined as `key_size` in Status data format).' + example: 256 + number: + description: 'Number of keys requested (default value is 1).' + type: integer + default: 1 + example: 20 + key_size_default_status: + type: integer + description: 'Default size of key the KME can deliver to the SAE (in bits)' + example: 256 + stored_key_count: + type: integer + description: 'Number of stored keys KME can deliver to the SAE' + example: 25000 + max_key_count: + type: integer + description: 'Maximum number of stored_key_count' + example: 100000 + max_key_per_request: + type: integer + description: 'Maximum number of keys per request' + example: 128 + max_key_size: + type: integer + description: 'Maximum size of key the KME can deliver to the SAE (in bits)' + example: 1024 + min_key_size: + type: integer + description: 'Minimum size of key the KME can deliver to the SAE (in bits)' + example: 64 + max_sae_id_count: + type: integer + description: 'Maximum number of additional target_sae_ids the KME allows. "0" when the KME: not support key multicast' + example: 0 + delivered_key_count: + type: integer + description: 'Total number of keys delivered by KME to the calling initiator SAE' + example: 10 + delivered_key_bits: + type: integer + description: 'Total number of bits delivered by KME to the calling initiator SAE' + example: 2560 + uptime: + type: string + description: 'Uptime of KME (ISO8601 time duration format).' + example: 'P1Y2M10DT2H30M59S' + extension_mandatory: + type: array + description: 'Array of extension parameters specified as name/value pairs that KME shall handle or return an error. Parameter values may be of any type, including objects.' + items: + type: object + example: + - 'abc_route_type': 'direct' + - 'abc_transfer_method': 'qkd' + extension_optional: + type: array + description: 'Array of extension parameters specified as name/value pairs that KME may ignore. Parameter values may be of any type, including objects.' + items: + type: object + example: + - 'abc_max_age': 30000 + key_id: + description: 'ID of the key: UUID format.' + type: string + format: uuid + example: '550e8400-e29b-41d4-a716-446655440000' + value: + description: 'Key data encoded by base64. The key size is specified by the "size" parameter in "Get key". If not specified, the "key_size" value in Status data model is used as the default size.' + type: string + example: 'wHHVxRwDJs3/bXd38GHP3oe4svTuRpZS0yCC7x4Ly+s=' + extension: + type: object + description: 'Reserved for future use' + keys: + type: array + description: 'Array of keys. The number of keys is specified by the "number" parameter in "Get key". If not specified, the default number of keys is 1.' + items: + type: object + required: + - key_id + - value + properties: + key_id: + $ref: '#/components/schemas/key_id' + value: + $ref: '#/components/schemas/value' + extension: + $ref: '#/components/schemas/extension' + key_ids: + type: array + description: 'Array of key IDs.' + items: + $ref: '#/components/schemas/key_id' + + version: + type: string + description: 'Supported API version.' + example: 'v1' + versions: + type: array + description: 'Array of supported API versions.' + items: + $ref: '#/components/schemas/version' + example: ['v1', 'v2'] + version_container: + title: 'Version container' + type: object + required: + - versions + properties: + versions: + $ref: '#/components/schemas/versions' + extension: + $ref: '#/components/schemas/extension' + + link_status_request: + title: 'Link status request' + type: object + properties: + initiator_sae_id: + $ref: '#/components/schemas/initiator_sae_id' + target_sae_id: + $ref: '#/components/schemas/target_sae_id' + + link_status: + title: 'Link status' + type: object + required: + - initiator_kme_id + - target_kme_id + - initiator_sae_id + - target_sae_id + - key_size + - stored_key_count + - max_key_count + - max_key_per_request + - max_key_size + - min_key_size + - max_sae_id_count + properties: + initiator_kme_id: + $ref: '#/components/schemas/initiator_kme_id' + target_kme_id: + $ref: '#/components/schemas/target_kme_id' + initiator_sae_id: + $ref: '#/components/schemas/initiator_sae_id' + target_sae_id: + $ref: '#/components/schemas/target_sae_id' + key_size: + $ref: '#/components/schemas/key_size_default_status' + stored_key_count: + $ref: '#/components/schemas/stored_key_count' + max_key_count: + $ref: '#/components/schemas/max_key_count' + max_key_per_request: + $ref: '#/components/schemas/max_key_per_request' + max_key_size: + $ref: '#/components/schemas/max_key_size' + min_key_size: + $ref: '#/components/schemas/min_key_size' + max_sae_id_count: + $ref: '#/components/schemas/max_sae_id_count' + delivered_key_count: + $ref: '#/components/schemas/delivered_key_count' + delivered_key_bits: + $ref: '#/components/schemas/delivered_key_bits' + + array_link_status: + title: 'Array of link statuses' + type: array + items: + $ref: '#/components/schemas/link_status' + + kme_status: + title: 'KME status' + type: object + required: + - kme_id + - uptime + properties: + kme_id: + $ref: '#/components/schemas/kme_id' + uptime: + $ref: '#/components/schemas/uptime' + extension: + $ref: '#/components/schemas/extension' + + key_request: + title: 'Key request container' + type: object + required: + - initiator_sae_id + - target_sae_ids + properties: + initiator_sae_id: + $ref: '#/components/schemas/initiator_sae_id' + target_sae_ids: + $ref: '#/components/schemas/target_sae_ids' + number: + $ref: '#/components/schemas/number' + size: + $ref: '#/components/schemas/key_size' + extension_mandatory: + $ref: '#/components/schemas/extension_mandatory' + extension_optional: + $ref: '#/components/schemas/extension_optional' + + key_container: + title: 'Key container' + type: object + required: + - keys + properties: + keys: + $ref: '#/components/schemas/keys' + extension: + $ref: '#/components/schemas/extension' + + key_id_container: + title: 'Key IDs container' + type: object + required: + - initiator_sae_id + - target_sae_id + properties: + initiator_sae_id: + $ref: '#/components/schemas/initiator_sae_id' + target_sae_id: + $ref: '#/components/schemas/target_sae_id' + key_ids: + $ref: '#/components/schemas/key_ids' + extension: + $ref: '#/components/schemas/extension' + + message_data: + title: 'Message data format' + type: object + required: + - message + properties: + message: + description: 'Response message' + type: string + example: 'success' + details: + description: 'Array of objects containing details' + type: array + items: + type: object + + securitySchemes: + mutualTLS: + type: http + scheme: mutual + description: Mutual TLS authentication using certificates, TLSv1.3 (or later). NOTE - OpenAPI 3.1.0 introduces better support for describing mTLS. + +security: + - mutualTLS: [] -- GitLab