Skip to content

Commit

Permalink
Version 0.2.2
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 46fc412c7ac4dc92a4cacbe7170d3d24306c45bc
  • Loading branch information
Terra Quantum AG committed Aug 28, 2024
1 parent 99c2923 commit c0ffeef
Show file tree
Hide file tree
Showing 56 changed files with 135,342 additions and 942 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,18 @@ jobs:
t = f.read().splitlines()
e = r.stdout.splitlines()
m = difflib.SequenceMatcher(a=t, b=e)
rp = os.path.relpath(path)
for tag, i1, i2, j1, j2 in m.get_opcodes():
if tag == "insert":
expecting = "%0A".join(["```"] + e[j1:j2] + ["```"])
print(f"::error file={os.path.relpath(path)},line={i1 or 1}::Please insert at line {i1+1}:%0A{expecting}")
print(f"::error file={rp},line={i1 or 1}::{rp}:{i1 or 1} Please insert at line {i1+1}:%0A{expecting}")
errors += 1
elif tag == "replace":
expecting = "%0A".join(["```"] + e[j1:j2] + ["```"])
print(f"::error file={os.path.relpath(path)},line={i1+1},endLine={i2}::Please replace line(s) {i1+1}-{i2} with:%0A{expecting}")
print(f"::error file={rp},line={i1+1},endLine={i2}::{rp}:{i1+1} Please replace line(s) {i1+1}-{i2} with:%0A{expecting}")
errors += 1
elif tag == "delete":
print(f"::error file={os.path.relpath(path)},line={i1+1},endLine={i2}::Please remove line(s) {i1+1}-{i2}")
print(f"::error file={rp},line={i1+1},endLine={i2}::{rp}:{i1+1} Please remove line(s) {i1+1}-{i2}")
errors += 1
sys.exit(int(bool(errors)))
Expand Down
3 changes: 3 additions & 0 deletions docs/api_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ Below you may find the reference to the all API methods or examples that exist i
- [`PQC_set_iv`](classic_quantum_resistant_algs/aes.html#pqc_set_iv)
- [`PQC_encrypt`](classic_quantum_resistant_algs/aes.html#pqc_encrypt)
- [`PQC_decrypt`](classic_quantum_resistant_algs/aes.html#pqc_decrypt)
- [`PQC_aead_encrypt`](classic_quantum_resistant_algs/aes.html#pqc_aead_encrypt)
- [`PQC_aead_check`](classic_quantum_resistant_algs/aes.html#pqc_aead_check)
- [`PQC_aead_decrypt`](classic_quantum_resistant_algs/aes.html#pqc_aead_decrypt)
- [`PQC_close_context`](classic_quantum_resistant_algs/aes.html#pqc_close_context)
- [AES Examples](classic_quantum_resistant_algs/aes.html#examples)

Expand Down
151 changes: 146 additions & 5 deletions docs/classic_quantum_resistant_algs/aes.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ The encryption modes are methods that describe how to repeatedly apply the ciphe
* **Output Feedback (OFB)**: OFB converts a block cipher into a synchronous stream cipher. It generates keystream blocks, which are then XORed with the plaintext blocks to produce ciphertext. The same keystream blocks are used to decrypt ciphertext back to plaintext. OFB ensures that the same plaintext inputs will result in different ciphertext outputs.

* **Counter (CTR)**: Like OFB, CTR turns a block cipher into a stream cipher. It encrypts a set of counter values and then XORs the resulting output with the plaintext to generate the ciphertext. The counter is increased by one for every subsequent block and must be unique for each encryption operation. CTR mode is known for its ability to allow random access to the encrypted data blocks.


* **Galois/Counter (GCM)**: The GCM algorithm provides both data authenticity (integrity) and confidentiality and belongs to the class of authenticated encryption with associated data (AEAD) methods. This means that as input it takes a key K, some plaintext P, and some associated data AD; it then encrypts the plaintext using the key to produce ciphertext C, and computes an authentication tag T from the ciphertext and the associated data (which remains unencrypted). A recipient with knowledge of K, upon reception of AD, C and T, can decrypt the ciphertext to recover the plaintext P and can check the tag T to ensure that neither ciphertext nor associated data were tampered with.

Each of these modes has a specific use case where it excels and others where it may be susceptible. Modern practices typically favor modes like CTR over ECB and CBC due to their stronger security properties and performance benefits, particularly in settings susceptible to parallel processing.

Expand Down Expand Up @@ -112,7 +113,7 @@ For both functions, the return values are specified as follows:
**Function signature**

```cpp
int PQC_set_iv(CIPHER_HANDLE ctx, const uint8_t* iv, size_t iv_length);
size_t PQC_set_iv(CIPHER_HANDLE ctx, const uint8_t* iv, size_t iv_length);
```
**Purpose**: This function is used to set the initialization vector for an initialized encryption context if it was not provided during the initialization with `PQC_init_context_iv()`.
Expand Down Expand Up @@ -144,7 +145,7 @@ The provided code snippet describes a function for encrypting data using an init
**Function signature:**
```cpp
int PQC_encrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length);
size_t PQC_encrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length);
```

**Purpose**: This function is used to encrypt data using the specified encryption context and encryption mode.
Expand Down Expand Up @@ -180,7 +181,7 @@ The function returns the following values:
**Function signature:**

```cpp
int PQC_decrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length);
size_t PQC_decrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length);
```
**Purpose**: This function is used to decrypt data using the specified encryption context and encryption mode.
Expand Down Expand Up @@ -211,12 +212,146 @@ The function returns the following values:
* `PQC_BAD_CIPHER`: Indicates that the selected cipher does not support symmetric encryption.
### `PQC_aead_encrypt`
**Function signature:**
```cpp
size_t PQC_aead_encrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length, const uint8_t * aad, size_t aad_length, uint8_t * auth_tag, size_t auth_tag_len);
```

**Purpose**: This function is used to encrypt data and create authentication tag using the specified encryption context and encryption mode.

**Parameters**:

* `ctx`: Handle of the initialized encryption context.

* `mode`: Constant to select the encryption mode. The possible values depend on the selected cipher. For PQC\_CIPHER\_AES, the available mode is PQC\_AES\_M\_GCM.

* `buffer` (in/out): Pointer to the data array. The data is encrypted in place within the same buffer.

* `length`: Length of the data buffer.

* `aad` (in): Pointer to the additional authenticated data array. This data is authenticated, but not encrypted.

* `aad_length`: Length of the aad data buffer.

* `tag` (out): Pointer to the authentication tag array. Size of tag should equal PQC\_AES\_IVLEN.

* `tag length`: Length of the tag buffer.

The function returns the following values:

* `PQC_OK`: Indicates that the operation was successful, and the data was encrypted.

* `PQC_BAD_CONTEXT`: Indicates that the context was not properly initialized, suggesting an issue with the encryption context handle.

* `PQC_BAD_LEN`: Indicates that the length of the data does not match the requirements for the selected cipher/mode.

* `PQC_NO_IV`: Indicates that an initialization vector is required for the selected cipher/mode, but it was not set.

* `PQC_BAD_MODE`: Indicates that the mode parameter provided is invalid.

* `PQC_BAD_CIPHER`: Indicates that the selected cipher does not support symmetric encryption.


### `PQC_aead_check`

**Function signature:**

```cpp
size_t PQC_aead_check(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length);
```
**Purpose**: This function is used to check authentity of data without decrypting it using the specified encryption context and encryption mode.
**Parameters**:
* `ctx`: Handle of the initialized encryption context.
* `mode`: Constant to select the encryption mode. The possible values depend on the selected cipher. For PQC\_CIPHER\_AES, the available mode is PQC\_AES\_M\_GCM.
* `buffer` (in/out): Pointer to the data array. The data is decrypted in place within the same buffer.
* `length`: Length of the data buffer.
* `aad` (in): Pointer to the additional authenticated data array. This data is authenticated, but not decrypted.
* `aad_length`: Length of the aad data buffer.
* `tag` (in): Pointer to the authentication tag array. Size of tag should equal PQC\_AES\_IVLEN.
* `tag length`: Length of the tag buffer.
The function returns the following values:
* `PQC_OK`: Indicates that the input data is authentic.
* `PQC_AUTHENTICATION_FAILURE`: Input is not authentic.
* `P_BAD_CONTEXT`: Indicates that the context was not properly initialized, suggesting an issue with the encryption context handle.
* `PQC_BAD_LEN`: Indicates that the length of the data does not match the requirements for the selected cipher/mode.
* `PQC_NO_IV`: Indicates that an initialization vector is required for the selected cipher/mode, but it was not set.
* `PQC_BAD_MODE`: Indicates that the mode parameter provided is invalid.
* `PQC_BAD_CIPHER`: Indicates that the selected cipher does not support symmetric encryption.
*** Note *** `PQC_aead_check` do not change initialization vector, so it can be used several times before `PQC_aead_decrypt` without affecting decryption context state. Otherwise, initialization vector is changed by `PQC_aead_decrypt`, so `PQC_aead_check` can not be used after the data is decrypted.
### `PQC_aead_decrypt`
**Function signature:**
```cpp
size_t PQC_aead_decrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t* buffer, size_t length);
```

**Purpose**: This function is used to decrypt and check authentity of data using the specified encryption context and encryption mode.

**Parameters**:

* `ctx`: Handle of the initialized encryption context.

* `mode`: Constant to select the encryption mode. The possible values depend on the selected cipher. For PQC\_CIPHER\_AES, the available mode is PQC\_AES\_M\_GCM.

* `buffer` (in/out): Pointer to the data array. The data is decrypted in place within the same buffer.

* `length`: Length of the data buffer.

* `aad` (in): Pointer to the additional authenticated data array. This data is authenticated, but not decrypted.

* `aad_length`: Length of the aad data buffer.

* `tag` (in): Pointer to the authentication tag array. Size of tag should equal PQC\_AES\_IVLEN.

* `tag length`: Length of the tag buffer.

The function returns the following values:

* `PQC_OK`: Indicates that the operation was successful, and the data was decrypted.

* `PQC_AUTHENTICATION_FAILURE`: Input is not authentic.

* `P_BAD_CONTEXT`: Indicates that the context was not properly initialized, suggesting an issue with the encryption context handle.

* `PQC_BAD_LEN`: Indicates that the length of the data does not match the requirements for the selected cipher/mode.

* `PQC_NO_IV`: Indicates that an initialization vector is required for the selected cipher/mode, but it was not set.

* `PQC_BAD_MODE`: Indicates that the mode parameter provided is invalid.

* `PQC_BAD_CIPHER`: Indicates that the selected cipher does not support symmetric encryption.


### `PQC_close_context`

**Function signature:**

```cpp
int PQC_close_context(CIPHER_HANDLE ctx);
size_t PQC_close_context(CIPHER_HANDLE ctx);
```
**Purpose**: This function is used to release resources associated with an initialized encryption context when it is no longer needed.
Expand Down Expand Up @@ -257,3 +392,9 @@ Examples
```cpp
{% include examples/aes/aes_ofb_example.cpp %}
```
### AES GCM
```cpp
{% include examples/aes/aes_gcm_example.cpp %}
```
2 changes: 1 addition & 1 deletion docs/index.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Hash Function:

Symmetric Encryption:

- [AES-256](classic_quantum_resistant_algs/aes.html) (modes: ECB, CBC, OFB, CTR)
- [AES-256](classic_quantum_resistant_algs/aes.html) (modes: ECB, CBC, OFB, CTR, GCM)

### Post-Quantum Algorithms

Expand Down
1 change: 1 addition & 0 deletions docs/keys/keys_container.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ int PQC_symmetric_container_get_key(PQC_CONTAINER_HANDLE container,
PQC_AES_M_CBC = 2
PQC_AES_M_ECB = 3
PQC_AES_M_OFB = 4
PQC_AES_M_GCM = 5
PQC_AES_M_CTR = 6
```

Expand Down
10 changes: 10 additions & 0 deletions examples/aes/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,13 @@ target_link_libraries(
aes_ofb_example
pqc
)

add_executable(
aes_gcm_example
aes_gcm_example.cpp
)

target_link_libraries(
aes_gcm_example
pqc
)
73 changes: 73 additions & 0 deletions examples/aes/aes_gcm_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <cstring>
#include <iostream>
#include <vector>

#include <pqc/aes.h>

// parties can obtain a common key through asymmetric key exchange

// Party A encrypts its plaintext using a key. Then data, its length, and key must be
// transmitted to party B

void gcm_encrypt(
const std::vector<uint8_t> & key, std::vector<uint8_t> & data, const std::vector<uint8_t> & aad,
std::vector<uint8_t> & tag
)
{
CIPHER_HANDLE context;

context = PQC_init_context(PQC_CIPHER_AES, key.data(), PQC_AES_KEYLEN);
PQC_aead_encrypt(
context, PQC_AES_M_CTR, data.data(), data.size(), aad.data(), aad.size(), tag.data(), PQC_AES_IVLEN
);
}


// Party B decrypts the ciphertext using the same key.

void gcm_decrypt(
const std::vector<uint8_t> & key, std::vector<uint8_t> data, std::vector<uint8_t> aad,
const std::vector<uint8_t> tag
)
{
CIPHER_HANDLE context;

context = PQC_init_context(PQC_CIPHER_AES, key.data(), PQC_AES_KEYLEN);
PQC_aead_decrypt(
context, PQC_AES_M_CTR, data.data(), data.size(), aad.data(), aad.size(), tag.data(), PQC_AES_IVLEN
);

PQC_close_context(context);
}


int main()
{
// CTR
std::vector<uint8_t> key = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'K', 'L'};

const int data_len = PQC_AES_BLOCKLEN;
std::vector<uint8_t> data_a = {89, 234, 87, 91, 40, 83, 179, 255, 80, 66, 19, 45, 89, 0, 64, 123};
std::vector<uint8_t> data_original(data_a);
std::vector<uint8_t> data_b(data_len);
std::vector<uint8_t> aad = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20};
std::vector<uint8_t> tag(PQC_AES_IVLEN);

gcm_encrypt(key, data_a, aad, tag); // This happens at party A

data_b = data_a; // Emulate transfer of encrypted message to party B

gcm_decrypt(key, data_b, aad, tag); // This happens at party B

if (data_b == data_original) // Vrification
{
std::cout << "Verification successful." << std::endl;
}
else
{
std::cout << "Verification failed." << std::endl;
}

return 0;
}
1 change: 1 addition & 0 deletions include/pqc/aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#define PQC_AES_M_CBC 2
#define PQC_AES_M_ECB 3
#define PQC_AES_M_OFB 4
#define PQC_AES_M_GCM 5
#define PQC_AES_M_CTR 6

// Fixed for all modes
Expand Down
17 changes: 16 additions & 1 deletion include/pqc/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ typedef size_t CIPHER_HANDLE;
#define PQC_BAD_SIGNATURE 6
#define PQC_IO_ERROR 8
#define PQC_BAD_CIPHER ((CIPHER_HANDLE)~0)
#define PQC_NO_AUT_TAG 9
#define PQC_AUTHENTICATION_FAILURE 9

#if defined(_WIN32) || defined(WIN32)
#define PQC_CALLBACK __stdcall
Expand Down Expand Up @@ -59,6 +59,21 @@ extern "C"

size_t PQC_API PQC_decrypt(CIPHER_HANDLE ctx, uint32_t mode, uint8_t * buffer, size_t length);

size_t PQC_API PQC_aead_encrypt(
CIPHER_HANDLE ctx, uint32_t mode, uint8_t * buffer, size_t length, const uint8_t * aad, size_t aad_length,
uint8_t * auth_tag, size_t auth_tag_len
);

size_t PQC_API PQC_aead_decrypt(
CIPHER_HANDLE ctx, uint32_t mode, uint8_t * buffer, size_t length, const uint8_t * aad, size_t aad_length,
const uint8_t * auth_tag, size_t auth_tag_len
);

size_t PQC_API PQC_aead_check(
CIPHER_HANDLE ctx, uint32_t mode, uint8_t * buffer, size_t length, const uint8_t * aad, size_t aad_length,
const uint8_t * auth_tag, size_t auth_tag_len
);

size_t PQC_API PQC_kem_encode_secret(
uint32_t cipher, uint8_t * message, size_t message_length, const uint8_t * public_key, size_t key_length,
uint8_t * shared_secret, size_t shared_secret_length
Expand Down
Loading

0 comments on commit c0ffeef

Please sign in to comment.