SET(API_FOLDER ${PROJECT_SOURCE_DIR}/api/yaca)
SET(EXAMPLES_FOLDER ${PROJECT_SOURCE_DIR}/examples)
SET(SRC_FOLDER ${PROJECT_SOURCE_DIR}/src)
+SET(PYTHON_FOLDER ${PROJECT_SOURCE_DIR}/python)
IF(NOT DEFINED LIB_INSTALL_DIR)
SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
ADD_SUBDIRECTORY(${SRC_FOLDER})
ADD_SUBDIRECTORY(${EXAMPLES_FOLDER})
+IF(NOT WITHOUT_PYTHON)
+ ADD_SUBDIRECTORY(${PYTHON_FOLDER})
+ENDIF(NOT WITHOUT_PYTHON)
Group: Security/Other
Summary: Yet Another Crypto API
BuildRequires: cmake
+BuildRequires: python3 >= 3.4
BuildRequires: pkgconfig(capi-base-common)
BuildRequires: pkgconfig(openssl)
Requires(post): /sbin/ldconfig
%install
%make_install
+%py3_compile %{buildroot}/%{python3_sitelib}
%clean
rm -rf %{buildroot}
%files examples
%{_bindir}/yaca-example*
%{_datadir}/%{name}/examples
+
+## Python3 Package ############################################################
+%package -n python3-yaca
+Summary: Yet Another Crypto API Python3 bindings
+Group: Security/Other
+Requires: yaca = %{version}-%{release}
+
+%description -n python3-yaca
+The package provides Yet Another Crypto API bindings for Python3.
+
+%files -n python3-yaca
+%{python3_sitelib}/%{name}
--- /dev/null
+FIND_PACKAGE(PythonInterp 3.4 REQUIRED)
+
+EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} -c "from sys import stdout; from distutils import sysconfig; stdout.write(sysconfig.get_python_lib())" OUTPUT_VARIABLE PYTHON_INSTALL_DIR)
+MESSAGE(STATUS "Python install dir is ${PYTHON_INSTALL_DIR}")
+MESSAGE(STATUS "Python version is ${PYTHON_VERSION_STRING}")
+
+FILE(GLOB yaca_SRCS yaca/*.py)
+INSTALL (FILES ${yaca_SRCS} DESTINATION ${PYTHON_INSTALL_DIR}/${PROJECT_NAME})
--- /dev/null
+#!/usr/bin/env python3
+
+# Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Contact: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+
+import yaca
+import yaca.tests
+
+yaca.tests.run_all_tests()
--- /dev/null
+#!/usr/bin/env python3
+
+# Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Contact: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+
+"""
+Python3 bindings for YACA.
+
+Usage is almost the same as in the C API. All the functions that made
+sense in Python were implemented. Memory allocations and functions for
+getting length of the buffers were ommited as all those things are
+handled automatically for both input and output.
+
+All the parameters for strings/data expect python's bytes type. All
+the parameters are named the same as in the C API and their meaning is
+exactly the same.
+
+The major exception being encrypt/decrypt update where second
+parameter can have 2 meanings. This is only used for CCM_AAD. See
+examples.
+
+Some parameters now have default values for ease of use.
+
+For details please refer to the C API doxygen documentation.
+
+For examples see tests/examples in yaca.tests module.
+"""
+
+import enum as _enum
+import ctypes as _ctypes
+import yaca.library
+from yaca.error import *
+del yaca.error
+
+# Initialization
+
+_lib = yaca.library.get_yaca()
+del yaca.library
+
+
+# Helpers
+
+def _get_char_param_nullify_if_zero(param):
+ return None if len(param) == 0 else param
+
+
+def _context_get_output_length(ctx, input_length):
+ output_length = _ctypes.c_size_t()
+ _lib.yaca_context_get_output_length(ctx,
+ input_length,
+ _ctypes.byref(output_length))
+ return output_length.value
+
+
+# Types
+
+class Context():
+ def __init__(self, ptr):
+ if not isinstance(ptr, _ctypes.c_void_p):
+ raise TypeError('Invalid type')
+ self._as_parameter_ = ptr
+
+ def __del__(self):
+ _lib.yaca_context_destroy(self._as_parameter_)
+
+
+class Key():
+ def __init__(self, ptr):
+ if not isinstance(ptr, _ctypes.c_void_p):
+ raise TypeError('Invalid type')
+ self._as_parameter_ = ptr
+
+ def __del__(self):
+ _lib.yaca_key_destroy(self._as_parameter_)
+
+ def __repr__(self):
+ if self._as_parameter_.value is None:
+ return '<yaca.Key: KEY_NULL>'
+ return '<yaca.Key: ' + str(self.get_type()) + ', ' + \
+ str(self.get_bit_length()) + ' bits at ' + str(hex(id(self))) + '>'
+
+ def get_type(self):
+ return key_get_type(self)
+
+ def get_bit_length(self):
+ return key_get_bit_length(self)
+
+
+KEY_NULL = Key(_ctypes.c_void_p())
+
+
+# Enums
+
+@_enum.unique
+class KEY_FORMAT(_enum.Enum):
+ DEFAULT = 0
+ PKCS8 = 1
+
+
+@_enum.unique
+class KEY_FILE_FORMAT(_enum.Enum):
+ RAW = 0
+ BASE64 = 1
+ PEM = 2
+ DER = 3
+
+
+@_enum.unique
+class KEY_TYPE(_enum.Enum):
+ SYMMETRIC = 0
+ DES = 1
+ IV = 2
+ RSA_PUB = 3
+ RSA_PRIV = 4
+ DSA_PUB = 5
+ DSA_PRIV = 6
+ DH_PUB = 7
+ DH_PRIV = 8
+ EC_PUB = 9
+ EC_PRIV = 10
+ DSA_PARAMS = 11
+ DH_PARAMS = 12
+ EC_PARAMS = 13
+
+
+class KEY_BIT_LENGTH(_enum.IntEnum):
+ IV_64BIT = 64
+ IV_128BIT = 128
+ UNSAFE_8BIT = 8
+ UNSAFE_40BIT = 40
+ UNSAFE_64BIT = 64
+ UNSAFE_80BIT = 80
+ UNSAFE_128BIT = 128
+ L192BIT = 192
+ L256BIT = 256
+ L512BIT = 512
+ L1024BIT = 1024
+ L2048BIT = 2048
+ L3072BIT = 3072
+ L4096BIT = 4096
+
+
+@_enum.unique
+class KEY_BIT_LENGTH_EC(_enum.IntEnum):
+ PRIME192V1 = 0x300000C0
+ PRIME256V1 = 0x30000100
+ SECP256K1 = 0x31200100
+ SECP384R1 = 0x31100180
+ SECP521R1 = 0x31100209
+
+
+KEY_LENGTH_DH_GENERATOR_2 = 0x10000000
+KEY_LENGTH_DH_GENERATOR_5 = 0x11000000
+
+
+@_enum.unique
+class KEY_BIT_LENGTH_DH_RFC(_enum.IntEnum):
+ L1024_160 = 0x20000400
+ L2048_224 = 0x21000800
+ L2048_256 = 0x22000800
+
+
+@_enum.unique
+class DIGEST_ALGORITHM(_enum.Enum):
+ MD5 = 0
+ SHA1 = 1
+ SHA224 = 2
+ SHA256 = 3
+ SHA384 = 4
+ SHA512 = 5
+
+
+@_enum.unique
+class ENCRYPT_ALGORITHM(_enum.Enum):
+ AES = 0
+ UNSAFE_DES = 1
+ UNSAFE_TRIPPLE_DES_2TDEA = 2
+ TRIPPLE_DES_3TDEA = 3
+ UNSAFE_RC2 = 4
+ UNSAFE_RC4 = 5
+ CAST5 = 6
+
+
+@_enum.unique
+class BLOCK_CIPHER_MODE(_enum.Enum):
+ NONE = 0
+ ECB = 1
+ CTR = 2
+ CBC = 3
+ GCM = 4
+ CFB = 5
+ CFB1 = 6
+ CFB8 = 7
+ OFB = 8
+ CCM = 9
+ WRAP = 10
+
+
+@_enum.unique
+class PROPERTY(_enum.Enum):
+ PADDING = 0
+ GCM_AAD = 1
+ GCM_TAG = 2
+ GCM_TAG_LEN = 3
+ CCM_AAD = 4
+ CCM_TAG = 5
+ CCM_TAG_LEN = 6
+ RC2_EFFECTIVE_KEY_BITS = 7
+
+
+@_enum.unique
+class PADDING(_enum.Enum):
+ NONE = 0
+ X931 = 1
+ PKCS1 = 2
+ PKCS1_PSS = 3
+ PKCS1_OAEP = 4
+ PKCS1_SSLV23 = 5
+ PKCS7 = 6
+
+
+@_enum.unique
+class KDF(_enum.Enum):
+ X942 = 0
+ X962 = 1
+
+
+# Implementation crypto
+
+def initialize():
+ """Initializes the library. Must be called before any other crypto
+ function. Should be called once in each thread that uses yaca."""
+ _lib.yaca_initialize()
+
+
+def cleanup():
+ """Cleans up the library.
+ Must be called before exiting the thread that called yaca_initialize()."""
+ _lib.yaca_cleanup()
+
+
+def memcmp(first, second, length):
+ """Safely compares first length bytes of two buffers."""
+ l = _ctypes.c_size_t(length)
+ return _lib.yaca_memcmp(first, second, l)
+
+
+def random_bytes(length):
+ """Generates random data."""
+ data = _ctypes.create_string_buffer(length)
+ _lib.yaca_randomize_bytes(data, length)
+ return bytes(data)
+
+
+def context_set_property(ctx, prop, prop_val):
+ """Sets the non-standard context properties.
+ Can only be called on an initialized context."""
+ if prop == PROPERTY.PADDING:
+ value = _ctypes.c_int(prop_val.value)
+ value_length = _ctypes.sizeof(value)
+ _lib.yaca_context_set_property(ctx,
+ prop.value,
+ _ctypes.byref(value),
+ value_length)
+ elif (prop == PROPERTY.GCM_AAD) or (prop == PROPERTY.CCM_AAD) or \
+ (prop == PROPERTY.GCM_TAG) or (prop == PROPERTY.CCM_TAG):
+ value = prop_val
+ value_length = len(prop_val)
+ _lib.yaca_context_set_property(ctx, prop.value,
+ value, value_length)
+ elif (prop == PROPERTY.GCM_TAG_LEN) or (prop == PROPERTY.CCM_TAG_LEN) or \
+ (prop == PROPERTY.RC2_EFFECTIVE_KEY_BITS):
+ value = _ctypes.c_size_t(prop_val)
+ value_length = _ctypes.sizeof(value)
+ _lib.yaca_context_set_property(
+ ctx, prop.value, _ctypes.byref(value), value_length)
+ else:
+ raise InvalidParameterError('Wrong property passed')
+
+
+def context_get_property(ctx, prop):
+ """Returns the non-standard context properties.
+ Can only be called on an initialized context."""
+ value = _ctypes.c_void_p()
+ value_length = _ctypes.c_size_t()
+ _lib.yaca_context_get_property(ctx, prop.value, _ctypes.byref(value),
+ _ctypes.byref(value_length))
+ if prop == PROPERTY.PADDING:
+ value_cast = _ctypes.cast(value, _ctypes.POINTER(_ctypes.c_int))
+ value_proper = value_cast.contents.value
+ assert value_length.value == _ctypes.sizeof(value_cast.contents)
+ elif (prop == PROPERTY.GCM_AAD) or (prop == PROPERTY.CCM_AAD) or \
+ (prop == PROPERTY.GCM_TAG) or (prop == PROPERTY.CCM_TAG):
+ value_cast = _ctypes.cast(value, _ctypes.POINTER(_ctypes.c_char))
+ value_proper = value_cast[:value_length.value]
+ assert value_length.value == len(value_proper)
+ elif (prop == PROPERTY.GCM_TAG_LEN) or \
+ (prop == PROPERTY.CCM_TAG_LEN) or \
+ (prop == PROPERTY.RC2_EFFECTIVE_KEY_BITS):
+ value_cast = _ctypes.cast(value, _ctypes.POINTER(_ctypes.c_size_t))
+ value_proper = value_cast.contents.value
+ assert value_length.value == _ctypes.sizeof(value_cast.contents)
+ else:
+ raise InvalidParameterError('Wrong property passed')
+ _lib.yaca_free(value)
+ return value_proper
+
+
+# Implementation key
+
+def key_get_type(key):
+ """Gets key's type"""
+ key_type = _ctypes.c_int()
+ _lib.yaca_key_get_type(key, _ctypes.byref(key_type))
+ return KEY_TYPE(key_type.value)
+
+
+def key_get_bit_length(key):
+ """Gets key's length (in bits)."""
+ key_bit_length = _ctypes.c_size_t()
+ _lib.yaca_key_get_bit_length(key, _ctypes.byref(key_bit_length))
+ return key_bit_length.value
+
+
+def key_import(data, key_type=KEY_TYPE.SYMMETRIC, password=b''):
+ """Imports a key or key generation parameters."""
+ key = _ctypes.c_void_p()
+ _lib.yaca_key_import(key_type.value, _ctypes.c_char_p(password),
+ data, len(data), _ctypes.byref(key))
+ return Key(key)
+
+
+def key_export(key, key_file_fmt=KEY_FILE_FORMAT.BASE64,
+ key_fmt=KEY_FORMAT.DEFAULT, password=b''):
+ """Exports a key or key generation parameters to arbitrary format."""
+ data = _ctypes.POINTER(_ctypes.c_char)()
+ data_length = _ctypes.c_size_t()
+ _lib.yaca_key_export(key, key_fmt.value, key_file_fmt.value,
+ _ctypes.c_char_p(password), _ctypes.byref(data),
+ _ctypes.byref(data_length))
+ data_bytes = data[:data_length.value]
+ _lib.yaca_free(data)
+ return data_bytes
+
+
+def key_generate(key_type=KEY_TYPE.SYMMETRIC,
+ key_bit_length=KEY_BIT_LENGTH.L256BIT):
+ """Generates a secure key or key generation parameters
+ (or an Initialization Vector)."""
+ key = _ctypes.c_void_p()
+ _lib.yaca_key_generate(key_type.value, key_bit_length,
+ _ctypes.byref(key))
+ return Key(key)
+
+
+def key_generate_from_parameters(params):
+ """Generates a secure private asymmetric key from parameters."""
+ prv_key = _ctypes.c_void_p()
+ _lib.yaca_key_generate_from_parameters(params,
+ _ctypes.byref(prv_key))
+ return Key(prv_key)
+
+
+def key_extract_public(prv_key):
+ """Extracts public key from a private one."""
+ pub_key = _ctypes.c_void_p()
+ _lib.yaca_key_extract_public(prv_key, _ctypes.byref(pub_key))
+ return Key(pub_key)
+
+
+def key_extract_parameters(key):
+ """Extracts parameters from a private or a public key."""
+ params = _ctypes.c_void_p()
+ _lib.yaca_key_extract_parameters(key, _ctypes.byref(params))
+ return Key(params)
+
+
+def key_derive_dh(prv_key, pub_key):
+ """Derives a shared secret using Diffie-Helmann or EC Diffie-Helmann
+ key exchange protocol."""
+ secret = _ctypes.POINTER(_ctypes.c_char)()
+ secret_length = _ctypes.c_size_t()
+ _lib.yaca_key_derive_dh(prv_key, pub_key, _ctypes.byref(secret),
+ _ctypes.byref(secret_length))
+ secret_bytes = secret[:secret_length.value]
+ _lib.yaca_free(secret)
+ return secret_bytes
+
+
+def key_derive_kdf(secret, key_material_length, info=b'',
+ kdf=KDF.X942, digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Derives a key material from shared secret."""
+ info_param = _get_char_param_nullify_if_zero(info)
+ key_material = _ctypes.POINTER(_ctypes.c_char)()
+ _lib.yaca_key_derive_kdf(kdf.value, digest_algo.value,
+ secret, len(secret),
+ info_param, len(info), key_material_length,
+ _ctypes.byref(key_material))
+ key_material_bytes = key_material[:key_material_length]
+ _lib.yaca_free(key_material)
+ return key_material_bytes
+
+
+def key_derive_pbkdf2(password, key_bit_length=KEY_BIT_LENGTH.L256BIT,
+ salt=b'', digest_algo=DIGEST_ALGORITHM.SHA256,
+ iterations=50000):
+ """Derives a key from user password (PKCS #5 a.k.a. pbkdf2 algorithm)."""
+ salt_param = _get_char_param_nullify_if_zero(salt)
+ key = _ctypes.c_void_p()
+ _lib.yaca_key_derive_pbkdf2(_ctypes.c_char_p(password), salt_param,
+ len(salt), iterations, digest_algo.value,
+ key_bit_length, _ctypes.byref(key))
+ return Key(key)
+
+
+# Implementation simple
+
+def simple_encrypt(sym_key, plaintext, encrypt_algo=ENCRYPT_ALGORITHM.AES,
+ bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
+ """Encrypts data using a symmetric cipher."""
+ plaintext_param = _get_char_param_nullify_if_zero(plaintext)
+ ciphertext = _ctypes.POINTER(_ctypes.c_char)()
+ ciphertext_length = _ctypes.c_size_t()
+ _lib.yaca_simple_encrypt(encrypt_algo.value, bcm.value, sym_key, iv,
+ plaintext_param, len(plaintext),
+ _ctypes.byref(ciphertext),
+ _ctypes.byref(ciphertext_length))
+ ciphertext_bytes = ciphertext[:ciphertext_length.value]
+ _lib.yaca_free(ciphertext)
+ return ciphertext_bytes
+
+
+def simple_decrypt(sym_key, ciphertext, encrypt_algo=ENCRYPT_ALGORITHM.AES,
+ bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
+ """Decrypts data using a symmetric cipher."""
+ ciphertext_param = _get_char_param_nullify_if_zero(ciphertext)
+ plaintext = _ctypes.POINTER(_ctypes.c_char)()
+ plaintext_length = _ctypes.c_size_t()
+ _lib.yaca_simple_decrypt(encrypt_algo.value, bcm.value, sym_key, iv,
+ ciphertext_param, len(ciphertext),
+ _ctypes.byref(plaintext),
+ _ctypes.byref(plaintext_length))
+ plaintext_bytes = plaintext[:plaintext_length.value]
+ _lib.yaca_free(plaintext)
+ return plaintext_bytes
+
+
+def simple_calculate_digest(message, digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Calculates a digest of a message."""
+ message_param = _get_char_param_nullify_if_zero(message)
+ digest = _ctypes.POINTER(_ctypes.c_char)()
+ digest_length = _ctypes.c_size_t()
+ _lib.yaca_simple_calculate_digest(digest_algo.value, message_param,
+ len(message),
+ _ctypes.byref(digest),
+ _ctypes.byref(digest_length))
+ digest_bytes = digest[:digest_length.value]
+ _lib.yaca_free(digest)
+ return digest_bytes
+
+
+def simple_calculate_signature(prv_key, message,
+ digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Creates a signature using asymmetric private key."""
+ message_param = _get_char_param_nullify_if_zero(message)
+ signature = _ctypes.POINTER(_ctypes.c_char)()
+ signature_length = _ctypes.c_size_t()
+ _lib.yaca_simple_calculate_signature(digest_algo.value, prv_key,
+ message_param, len(message),
+ _ctypes.byref(signature),
+ _ctypes.byref(signature_length))
+ signature_bytes = signature[:signature_length.value]
+ _lib.yaca_free(signature)
+ return signature_bytes
+
+
+def simple_verify_signature(pub_key, message, signature,
+ digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Verifies a signature using asymmetric public key."""
+ return _lib.yaca_simple_verify_signature(digest_algo.value, pub_key,
+ message, len(message),
+ signature, len(signature))
+
+
+def simple_calculate_hmac(sym_key, message,
+ digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Calculates a HMAC of given message using symmetric key."""
+ message_param = _get_char_param_nullify_if_zero(message)
+ mac = _ctypes.POINTER(_ctypes.c_char)()
+ mac_length = _ctypes.c_size_t()
+ _lib.yaca_simple_calculate_hmac(digest_algo.value, sym_key,
+ message_param, len(message),
+ _ctypes.byref(mac),
+ _ctypes.byref(mac_length))
+ mac_bytes = mac[:mac_length.value]
+ _lib.yaca_free(mac)
+ return mac_bytes
+
+
+def simple_calculate_cmac(sym_key, message,
+ encrypt_algo=ENCRYPT_ALGORITHM.AES):
+ """Calculates a CMAC of given message using symmetric key."""
+ message_param = _get_char_param_nullify_if_zero(message)
+ mac = _ctypes.POINTER(_ctypes.c_char)()
+ mac_length = _ctypes.c_size_t()
+ _lib.yaca_simple_calculate_cmac(encrypt_algo.value, sym_key,
+ message_param, len(message),
+ _ctypes.byref(mac),
+ _ctypes.byref(mac_length))
+ mac_bytes = mac[:mac_length.value]
+ _lib.yaca_free(mac)
+ return mac_bytes
+
+
+# Implementation digest
+
+def digest_initialize(digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Initializes a digest context."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_digest_initialize(_ctypes.byref(ctx), digest_algo.value)
+ return Context(ctx)
+
+
+def digest_update(ctx, message):
+ """Feeds the message into the message digest algorithm."""
+ _lib.yaca_digest_update(ctx, message, len(message))
+
+
+def digest_finalize(ctx):
+ """Calculates the final digest."""
+ output_length = _context_get_output_length(ctx, 0)
+ digest = _ctypes.create_string_buffer(output_length)
+ digest_length = _ctypes.c_size_t()
+ _lib.yaca_digest_finalize(ctx, digest, _ctypes.byref(digest_length))
+ return bytes(digest[:digest_length.value])
+
+
+# Implementation encrypt
+
+def encrypt_get_iv_bit_length(encrypt_algo, bcm, key_bin_length):
+ """Returns the recommended/default length of the Initialization Vector
+ for a given encryption configuration."""
+ iv_bit_length = _ctypes.c_size_t()
+ _lib.yaca_encrypt_get_iv_bit_length(encrypt_algo.value, bcm.value,
+ key_bin_length,
+ _ctypes.byref(iv_bit_length))
+ return iv_bit_length.value
+
+
+def encrypt_initialize(sym_key, encrypt_algo=ENCRYPT_ALGORITHM.AES,
+ bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
+ """Initializes an encryption context."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_encrypt_initialize(_ctypes.byref(ctx), encrypt_algo.value,
+ bcm.value, sym_key, iv)
+ return Context(ctx)
+
+
+def encrypt_update(ctx, plaintext):
+ """Encrypts chunk of the data.
+ Alternatively plaintext can be the total length of the input (int).
+ This is used for CCM_AAD."""
+ if isinstance(plaintext, int): # the case of using AAD in CCM
+ _lib.yaca_encrypt_update(ctx, None, plaintext, None,
+ _ctypes.byref(_ctypes.c_size_t()))
+ return
+
+ output_length = _context_get_output_length(ctx, len(plaintext))
+ ciphertext = _ctypes.create_string_buffer(output_length)
+ ciphertext_length = _ctypes.c_size_t()
+ _lib.yaca_encrypt_update(ctx, plaintext, len(plaintext),
+ ciphertext, _ctypes.byref(ciphertext_length))
+ return bytes(ciphertext[:ciphertext_length.value])
+
+
+def encrypt_finalize(ctx):
+ """Encrypts the final chunk of the data."""
+ output_length = _context_get_output_length(ctx, 0)
+ ciphertext = _ctypes.create_string_buffer(output_length)
+ ciphertext_length = _ctypes.c_size_t()
+ _lib.yaca_encrypt_finalize(ctx, ciphertext,
+ _ctypes.byref(ciphertext_length))
+ return bytes(ciphertext[:ciphertext_length.value])
+
+
+def decrypt_initialize(sym_key, encrypt_algo=ENCRYPT_ALGORITHM.AES,
+ bcm=BLOCK_CIPHER_MODE.ECB, iv=KEY_NULL):
+ """Initializes an decryption context."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_decrypt_initialize(_ctypes.byref(ctx), encrypt_algo.value,
+ bcm.value, sym_key, iv)
+ return Context(ctx)
+
+
+def decrypt_update(ctx, ciphertext):
+ """Decrypts chunk of the data.
+ Alternatively ciphertext can be the total length of the input (int).
+ This is used for CCM_AAD."""
+ if isinstance(ciphertext, int): # the case of using AAD in CCM
+ _lib.yaca_decrypt_update(ctx, None, ciphertext, None,
+ _ctypes.byref(_ctypes.c_size_t()))
+ return
+
+ output_length = _context_get_output_length(ctx, len(ciphertext))
+ plaintext = _ctypes.create_string_buffer(output_length)
+ plaintext_length = _ctypes.c_size_t()
+ _lib.yaca_decrypt_update(ctx, ciphertext, len(ciphertext),
+ plaintext, _ctypes.byref(plaintext_length))
+ return bytes(plaintext[:plaintext_length.value])
+
+
+def decrypt_finalize(ctx):
+ """Encrypts the final chunk of the data."""
+ output_length = _context_get_output_length(ctx, 0)
+ plaintext = _ctypes.create_string_buffer(output_length)
+ plaintext_length = _ctypes.c_size_t()
+ _lib.yaca_decrypt_finalize(ctx, plaintext,
+ _ctypes.byref(plaintext_length))
+ return bytes(plaintext[:plaintext_length.value])
+
+
+# Implementation sign
+
+def sign_initialize(prv_key, digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Initializes a signature context for asymmetric signatures."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_sign_initialize(_ctypes.byref(ctx), digest_algo.value,
+ prv_key)
+ return Context(ctx)
+
+
+def sign_initialize_hmac(sym_key, digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Initializes a signature context for HMAC."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_sign_initialize_hmac(_ctypes.byref(ctx),
+ digest_algo.value, sym_key)
+ return Context(ctx)
+
+
+def sign_initialize_cmac(sym_key, encrypt_algo=ENCRYPT_ALGORITHM.AES):
+ """Initializes a signature context for CMAC."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_sign_initialize_cmac(_ctypes.byref(ctx),
+ encrypt_algo.value, sym_key)
+ return Context(ctx)
+
+
+def sign_update(ctx, message):
+ """Feeds the message into the digital signature or MAC algorithm."""
+ _lib.yaca_sign_update(ctx, message, len(message))
+
+
+def sign_finalize(ctx):
+ """Calculates the final signature or MAC."""
+ output_length = _context_get_output_length(ctx, 0)
+ signature = _ctypes.create_string_buffer(output_length)
+ signature_len = _ctypes.c_size_t()
+ _lib.yaca_sign_finalize(ctx, signature, _ctypes.byref(signature_len))
+ return bytes(signature[:signature_len.value])
+
+
+def verify_initialize(pub_key, digest_algo=DIGEST_ALGORITHM.SHA256):
+ """Initializes a signature verification context for asymmetric signatures.
+ """
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_verify_initialize(_ctypes.byref(ctx), digest_algo.value,
+ pub_key)
+ return Context(ctx)
+
+
+def verify_update(ctx, message):
+ """Feeds the message into the digital signature verification algorithm."""
+ _lib.yaca_verify_update(ctx, message, len(message))
+
+
+def verify_finalize(ctx, signature):
+ """Performs the verification."""
+ return _lib.yaca_verify_finalize(ctx, signature, len(signature))
+
+
+# Implementation seal
+
+def seal_initialize(pub_key, sym_key_bit_length=KEY_BIT_LENGTH.L256BIT,
+ encrypt_algo=ENCRYPT_ALGORITHM.AES,
+ bcm=BLOCK_CIPHER_MODE.ECB):
+ ctx = _ctypes.c_void_p()
+ sym_key = _ctypes.c_void_p()
+ iv = _ctypes.c_void_p()
+ _lib.yaca_seal_initialize(_ctypes.byref(ctx), pub_key,
+ encrypt_algo.value, bcm.value,
+ sym_key_bit_length, _ctypes.byref(sym_key),
+ _ctypes.byref(iv))
+ return Context(ctx), Key(sym_key), Key(iv)
+
+
+def seal_update(ctx, plaintext):
+ """Encrypts piece of the data."""
+ output_length = _context_get_output_length(ctx, len(plaintext))
+ ciphertext = _ctypes.create_string_buffer(output_length)
+ ciphertext_length = _ctypes.c_size_t()
+ _lib.yaca_seal_update(ctx, plaintext, len(plaintext),
+ ciphertext, _ctypes.byref(ciphertext_length))
+ return bytes(ciphertext[:ciphertext_length.value])
+
+
+def seal_finalize(ctx):
+ """Encrypts the final piece of the data."""
+ output_length = _context_get_output_length(ctx, 0)
+ ciphertext = _ctypes.create_string_buffer(output_length)
+ ciphertext_length = _ctypes.c_size_t()
+ _lib.yaca_seal_finalize(ctx, ciphertext,
+ _ctypes.byref(ciphertext_length))
+ return bytes(ciphertext[:ciphertext_length.value])
+
+
+def open_initialize(prv_key, sym_key, iv=KEY_NULL,
+ sym_key_bit_length=KEY_BIT_LENGTH.L256BIT,
+ encrypt_algo=ENCRYPT_ALGORITHM.AES,
+ bcm=BLOCK_CIPHER_MODE.ECB):
+ """Initializes an asymmetric decryption context."""
+ ctx = _ctypes.c_void_p()
+ _lib.yaca_open_initialize(_ctypes.byref(ctx), prv_key,
+ encrypt_algo.value, bcm.value,
+ sym_key_bit_length, sym_key, iv)
+ return Context(ctx)
+
+
+def open_update(ctx, ciphertext):
+ """Decrypts piece of the data."""
+ output_length = _context_get_output_length(ctx, len(ciphertext))
+ plaintext = _ctypes.create_string_buffer(output_length)
+ plaintext_length = _ctypes.c_size_t()
+ _lib.yaca_open_update(ctx, ciphertext, len(ciphertext),
+ plaintext, _ctypes.byref(plaintext_length))
+ return bytes(plaintext[:plaintext_length.value])
+
+
+def open_finalize(ctx):
+ """Decrypts last chunk of sealed message."""
+ output_length = _context_get_output_length(ctx, 0)
+ plaintext = _ctypes.create_string_buffer(output_length)
+ plaintext_length = _ctypes.c_size_t()
+ _lib.yaca_open_finalize(ctx, plaintext,
+ _ctypes.byref(plaintext_length))
+ return bytes(plaintext[:plaintext_length.value])
+
+
+# Implementation rsa
+
+def rsa_public_encrypt(pub_key, plaintext, padding=PADDING.PKCS1):
+ """Encrypts data using a RSA public key (low-level encrypt equivalent)."""
+ ciphertext = _ctypes.POINTER(_ctypes.c_char)()
+ ciphertext_length = _ctypes.c_size_t()
+ plaintext_param = _get_char_param_nullify_if_zero(plaintext)
+ _lib.yaca_rsa_public_encrypt(padding.value, pub_key, plaintext_param,
+ len(plaintext),
+ _ctypes.byref(ciphertext),
+ _ctypes.byref(ciphertext_length))
+ ciphertext_bytes = ciphertext[:ciphertext_length.value]
+ _lib.yaca_free(ciphertext)
+ return ciphertext_bytes
+
+
+def rsa_private_decrypt(prv_key, ciphertext, padding=PADDING.PKCS1):
+ """Decrypts data using a RSA private key (low-level decrypt equivalent)."""
+ plaintext = _ctypes.POINTER(_ctypes.c_char)()
+ plaintext_length = _ctypes.c_size_t()
+ ciphertext_param = _get_char_param_nullify_if_zero(ciphertext)
+ _lib.yaca_rsa_private_decrypt(padding.value, prv_key,
+ ciphertext_param, len(ciphertext),
+ _ctypes.byref(plaintext),
+ _ctypes.byref(plaintext_length))
+ plaintext_bytes = plaintext[:plaintext_length.value]
+ _lib.yaca_free(plaintext)
+ return plaintext_bytes
+
+
+def rsa_private_encrypt(prv_key, plaintext, padding=PADDING.PKCS1):
+ """Encrypts data using a RSA private key (low-level sign equivalent)."""
+ ciphertext = _ctypes.POINTER(_ctypes.c_char)()
+ ciphertext_length = _ctypes.c_size_t()
+ plaintext_param = _get_char_param_nullify_if_zero(plaintext)
+ _lib.yaca_rsa_private_encrypt(padding.value, prv_key,
+ plaintext_param, len(plaintext),
+ _ctypes.byref(ciphertext),
+ _ctypes.byref(ciphertext_length))
+ ciphertext_bytes = ciphertext[:ciphertext_length.value]
+ _lib.yaca_free(ciphertext)
+ return ciphertext_bytes
+
+
+def rsa_public_decrypt(pub_key, ciphertext, padding=PADDING.PKCS1):
+ """Decrypts data using a RSA public key (low-level verify equivalent)."""
+ plaintext = _ctypes.POINTER(_ctypes.c_char)()
+ plaintext_length = _ctypes.c_size_t()
+ ciphertext_param = _get_char_param_nullify_if_zero(ciphertext)
+ _lib.yaca_rsa_public_decrypt(padding.value, pub_key,
+ ciphertext_param, len(ciphertext),
+ _ctypes.byref(plaintext),
+ _ctypes.byref(plaintext_length))
+ plaintext_bytes = plaintext[:plaintext_length.value]
+ _lib.yaca_free(plaintext)
+ return plaintext_bytes
--- /dev/null
+# Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+#
+# Contact: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+
+class YacaError(Exception):
+ """Base class for YACA exceptions."""
+ pass
+
+
+class InvalidParameterError(YacaError):
+ """Invalid parameter exception"""
+ def __init__(self, message):
+ YacaError.__init__(self, message)
+ self.message = message
+
+
+class OutOfMemoryError(YacaError):
+ """Out of memory exception"""
+ def __init__(self, message):
+ YacaError.__init__(self, message)
+ self.message = message
+
+
+class InternalError(YacaError):
+ """Internal exception"""
+ def __init__(self, message):
+ YacaError.__init__(self, message)
+ self.message = message
+
+
+class InvalidPasswordError(YacaError):
+ """Invalid password exception"""
+ def __init__(self, message):
+ YacaError.__init__(self, message)
+ self.message = message
--- /dev/null
+# Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+
+# Contact: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+
+import ctypes as _ctypes
+import enum as _enum
+import yaca.error as _err
+
+
+@_enum.unique
+class _Error(_enum.Enum):
+ __TIZEN_YACA_BASE = -0x01E30000
+ NONE = 0
+ INVALID_PARAMETER = -22
+ OUT_OF_MEMORY = -12
+ INTERNAL = __TIZEN_YACA_BASE | 0x01
+ DATA_MISMATCH = __TIZEN_YACA_BASE | 0x02
+ INVALID_PASSWORD = __TIZEN_YACA_BASE | 0x03
+
+
+def _errcheck(ret, func, arguments):
+ if ret == _Error.NONE.value:
+ return True
+ elif ret == _Error.DATA_MISMATCH.value:
+ return False
+ elif ret == _Error.INVALID_PARAMETER.value:
+ raise _err.InvalidParameterError(
+ 'Invalid Parameter error returned from YACA')
+ elif ret == _Error.OUT_OF_MEMORY.value:
+ raise _err.OutOfMemoryError('Out Of Memory error returned from YACA')
+ elif ret == _Error.INTERNAL.value:
+ raise _err.InternalError('Internal error returned from YACA')
+ elif ret == _Error.INVALID_PASSWORD.value:
+ raise _err.InvalidPasswordError(
+ 'Invalid Password error returned from YACA')
+ else:
+ raise RuntimeError('Unknown error returned from YACA')
+
+
+def get_yaca():
+ """Get C library and set argtypes"""
+
+ lib = _ctypes.CDLL("libyaca.so.0")
+
+ # crypto
+ lib.yaca_initialize.argtypes = []
+ lib.yaca_initialize.errcheck = _errcheck
+ lib.yaca_cleanup.argtypes = []
+ lib.yaca_cleanup.restype = None
+ lib.yaca_malloc.argtypes = \
+ [_ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_malloc.errcheck = _errcheck
+ lib.yaca_zalloc.argtypes = \
+ [_ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_zalloc.errcheck = _errcheck
+ lib.yaca_realloc.argtypes = \
+ [_ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_realloc.errcheck = _errcheck
+ lib.yaca_free.argtypes = [_ctypes.c_void_p]
+ lib.yaca_free.restype = None
+ lib.yaca_memcmp.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_char),
+ _ctypes.c_size_t]
+ lib.yaca_memcmp.errcheck = _errcheck
+ lib.yaca_randomize_bytes.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t]
+ lib.yaca_randomize_bytes.errcheck = _errcheck
+ lib.yaca_context_set_property.argtypes = \
+ [_ctypes.c_void_p, _ctypes.c_int, _ctypes.c_void_p, _ctypes.c_size_t]
+ lib.yaca_context_set_property.errcheck = _errcheck
+ lib.yaca_context_get_property.argtypes = \
+ [_ctypes.c_void_p, _ctypes.c_int, _ctypes.POINTER(_ctypes.c_void_p),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_context_get_property.errcheck = _errcheck
+ lib.yaca_context_get_output_length.argtypes = \
+ [_ctypes.c_void_p, _ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_context_get_output_length.errcheck = _errcheck
+ lib.yaca_context_destroy.argtypes = [_ctypes.c_void_p]
+ lib.yaca_context_destroy.restype = None
+
+ # simple
+ lib.yaca_simple_encrypt.argtypes = \
+ [_ctypes.c_int, _ctypes.c_int, _ctypes.c_void_p, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_simple_encrypt.errcheck = _errcheck
+ lib.yaca_simple_decrypt.argtypes = \
+ [_ctypes.c_int, _ctypes.c_int, _ctypes.c_void_p, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_simple_decrypt.errcheck = _errcheck
+ lib.yaca_simple_calculate_digest.argtypes = \
+ [_ctypes.c_int, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_simple_calculate_digest.errcheck = _errcheck
+ lib.yaca_simple_calculate_signature.argtypes = \
+ [_ctypes.c_int, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_simple_calculate_signature.errcheck = _errcheck
+ lib.yaca_simple_verify_signature.argtypes = \
+ [_ctypes.c_int, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t]
+ lib.yaca_simple_verify_signature.errcheck = _errcheck
+ lib.yaca_simple_calculate_hmac.argtypes = \
+ [_ctypes.c_int, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_simple_calculate_hmac.errcheck = _errcheck
+ lib.yaca_simple_calculate_cmac.argtypes = \
+ [_ctypes.c_int, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_simple_calculate_cmac.errcheck = _errcheck
+
+ # key
+ lib.yaca_key_get_type.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_int)]
+ lib.yaca_key_get_type.errcheck = _errcheck
+ lib.yaca_key_get_bit_length.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_key_get_bit_length.errcheck = _errcheck
+ lib.yaca_key_import.argtypes = \
+ [_ctypes.c_int, _ctypes.c_char_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_key_import.errcheck = _errcheck
+ lib.yaca_key_export.argtypes = \
+ [_ctypes.c_void_p, _ctypes.c_int, _ctypes.c_int, _ctypes.c_char_p,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_key_export.errcheck = _errcheck
+ lib.yaca_key_generate.argtypes = \
+ [_ctypes.c_void_p, _ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_key_generate.errcheck = _errcheck
+ lib.yaca_key_generate_from_parameters.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_key_generate_from_parameters.errcheck = _errcheck
+ lib.yaca_key_extract_public.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_key_extract_public.errcheck = _errcheck
+ lib.yaca_key_extract_parameters.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_key_extract_parameters.errcheck = _errcheck
+ lib.yaca_key_derive_dh.argtypes = \
+ [_ctypes.c_void_p, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_key_derive_dh.errcheck = _errcheck
+ lib.yaca_key_derive_kdf.argtypes = \
+ [_ctypes.c_int, _ctypes.c_int,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.c_size_t, _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char))]
+ lib.yaca_key_derive_kdf.errcheck = _errcheck
+ lib.yaca_key_derive_pbkdf2.argtypes = \
+ [_ctypes.c_char_p, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.c_size_t, _ctypes.c_int,
+ _ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_key_derive_pbkdf2.errcheck = _errcheck
+ lib.yaca_key_destroy.argtypes = [_ctypes.c_void_p]
+ lib.yaca_key_destroy.restype = None
+
+ # digest
+ lib.yaca_digest_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int]
+ lib.yaca_digest_initialize.errcheck = _errcheck
+ lib.yaca_digest_update.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t]
+ lib.yaca_digest_update.errcheck = _errcheck
+ lib.yaca_digest_finalize.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_digest_finalize.errcheck = _errcheck
+
+ # encrypt
+ lib.yaca_encrypt_get_iv_bit_length.argtypes = \
+ [_ctypes.c_int, _ctypes.c_int, _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_encrypt_get_iv_bit_length.errcheck = _errcheck
+ lib.yaca_encrypt_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int, _ctypes.c_int,
+ _ctypes.c_void_p, _ctypes.c_void_p]
+ lib.yaca_encrypt_initialize.errcheck = _errcheck
+ lib.yaca_encrypt_update.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_encrypt_update.errcheck = _errcheck
+ lib.yaca_encrypt_finalize.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_encrypt_finalize.errcheck = _errcheck
+ lib.yaca_decrypt_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int, _ctypes.c_int,
+ _ctypes.c_void_p, _ctypes.c_void_p]
+ lib.yaca_decrypt_initialize.errcheck = _errcheck
+ lib.yaca_decrypt_update.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_decrypt_update.errcheck = _errcheck
+ lib.yaca_decrypt_finalize.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_decrypt_finalize.errcheck = _errcheck
+
+ # sign
+ lib.yaca_sign_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int, _ctypes.c_void_p]
+ lib.yaca_sign_initialize.errcheck = _errcheck
+ lib.yaca_sign_initialize_hmac.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int, _ctypes.c_void_p]
+ lib.yaca_sign_initialize_hmac.errcheck = _errcheck
+ lib.yaca_sign_initialize_cmac.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int, _ctypes.c_void_p]
+ lib.yaca_sign_initialize_cmac.errcheck = _errcheck
+ lib.yaca_sign_update.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t]
+ lib.yaca_sign_update.errcheck = _errcheck
+ lib.yaca_sign_finalize.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_sign_finalize.errcheck = _errcheck
+ lib.yaca_verify_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_int, _ctypes.c_void_p]
+ lib.yaca_verify_initialize.errcheck = _errcheck
+ lib.yaca_verify_update.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t]
+ lib.yaca_verify_update.errcheck = _errcheck
+ lib.yaca_verify_finalize.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t]
+ lib.yaca_verify_finalize.errcheck = _errcheck
+
+ # seal
+ lib.yaca_seal_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_void_p, _ctypes.c_int,
+ _ctypes.c_int, _ctypes.c_size_t, _ctypes.POINTER(_ctypes.c_void_p),
+ _ctypes.POINTER(_ctypes.c_void_p)]
+ lib.yaca_seal_initialize.errcheck = _errcheck
+ lib.yaca_seal_update.argtypes = \
+ [_ctypes.c_void_p, _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_seal_update.errcheck = _errcheck
+ lib.yaca_seal_finalize.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_seal_finalize.errcheck = _errcheck
+ lib.yaca_open_initialize.argtypes = \
+ [_ctypes.POINTER(_ctypes.c_void_p), _ctypes.c_void_p, _ctypes.c_int,
+ _ctypes.c_int, _ctypes.c_size_t, _ctypes.c_void_p, _ctypes.c_void_p]
+ lib.yaca_open_initialize.errcheck = _errcheck
+ lib.yaca_open_update.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_open_update.errcheck = _errcheck
+ lib.yaca_open_finalize.argtypes = \
+ [_ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_open_finalize.errcheck = _errcheck
+
+ # rsa
+ rsa_argtypes = \
+ [_ctypes.c_int, _ctypes.c_void_p,
+ _ctypes.POINTER(_ctypes.c_char), _ctypes.c_size_t,
+ _ctypes.POINTER(_ctypes.POINTER(_ctypes.c_char)),
+ _ctypes.POINTER(_ctypes.c_size_t)]
+ lib.yaca_rsa_public_encrypt.argtypes = rsa_argtypes
+ lib.yaca_rsa_public_encrypt.errcheck = _errcheck
+ lib.yaca_rsa_private_decrypt.argtypes = rsa_argtypes
+ lib.yaca_rsa_private_decrypt.errcheck = _errcheck
+ lib.yaca_rsa_private_encrypt.argtypes = rsa_argtypes
+ lib.yaca_rsa_private_encrypt.errcheck = _errcheck
+ lib.yaca_rsa_public_decrypt.argtypes = rsa_argtypes
+ lib.yaca_rsa_public_decrypt.errcheck = _errcheck
+
+ return lib
--- /dev/null
+# Copyright (c) 2017-2018 Samsung Electronics Co., Ltd All Rights Reserved
+
+# Contact: Lukasz Pawelczyk <l.pawelczyk@samsung.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License
+
+
+"""
+These tests are not to test yaca itself. They are more of a
+syntax test to see that no stupid mistakes has been made in the
+python binding. To check whether the code runs properly and
+returns expected things.
+
+They can also be used as examples.
+"""
+
+import yaca
+
+
+def split_into_parts(data, l):
+ return [data[i:i + l] for i in range(0, len(data), l)]
+
+
+msg = b'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. \
+Donec hendrerit tempor tellus. Donec pretium posuere tellus. Proin \
+quam nisl, tincidunt et, mattis eget, convallis nec, purus. Cum \
+sociis natoque penatibus et magnis dis parturient montes, nascetur \
+ridiculus mus. Nulla posuere. Donec vitae dolor. Nullam tristique \
+diam non turpis. Cras placerat accumsan nulla. Nullam rutrum. Nam \
+vestibulum accumsan nisl.'
+
+msg_parts = split_into_parts(msg, 5)
+
+
+def run_all_tests():
+ """Runs all YACA tests/examples. No exceptions means success."""
+
+ yaca.initialize()
+
+ crypto()
+ key_gen()
+ key_exp_imp()
+ key_derive()
+ simple()
+ digest()
+ encrypt_basic()
+ encrypt_rc2_property()
+ encrypt_gcm_property()
+ encrypt_ccm_property()
+ sign()
+ seal()
+ rsa()
+
+ yaca.cleanup()
+
+
+def crypto():
+
+ msg_whole = b''
+ for part in msg_parts:
+ msg_whole += part
+
+ assert yaca.memcmp(msg, msg_whole, len(msg))
+
+ rand_bytes = yaca.random_bytes(50)
+ assert len(rand_bytes) == 50
+
+
+def key_gen():
+
+ key_iv_64 = yaca.key_generate(yaca.KEY_TYPE.IV,
+ yaca.KEY_BIT_LENGTH.IV_64BIT)
+ assert key_iv_64.get_type() == yaca.KEY_TYPE.IV
+ assert key_iv_64.get_bit_length() == yaca.KEY_BIT_LENGTH.IV_64BIT
+
+ key_iv_128 = yaca.key_generate(yaca.KEY_TYPE.IV,
+ yaca.KEY_BIT_LENGTH.IV_128BIT)
+ assert key_iv_128.get_type() == yaca.KEY_TYPE.IV
+ assert key_iv_128.get_bit_length() == yaca.KEY_BIT_LENGTH.IV_128BIT
+
+ key_sym = yaca.key_generate()
+ assert key_sym.get_type() == yaca.KEY_TYPE.SYMMETRIC
+ assert key_sym.get_bit_length() == yaca.KEY_BIT_LENGTH.L256BIT
+
+ key_rsa_prv = yaca.key_generate(yaca.KEY_TYPE.RSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ assert key_rsa_prv.get_type() == yaca.KEY_TYPE.RSA_PRIV
+ assert key_rsa_prv.get_bit_length() == yaca.KEY_BIT_LENGTH.L2048BIT
+
+ key_rsa_pub = yaca.key_extract_public(key_rsa_prv)
+ assert key_rsa_pub.get_type() == yaca.KEY_TYPE.RSA_PUB
+ assert key_rsa_pub.get_bit_length() == yaca.KEY_BIT_LENGTH.L2048BIT
+
+ key_dsa_prv = yaca.key_generate(yaca.KEY_TYPE.DSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ assert key_dsa_prv.get_type() == yaca.KEY_TYPE.DSA_PRIV
+ assert key_dsa_prv.get_bit_length() == yaca.KEY_BIT_LENGTH.L2048BIT
+
+ key_dsa_pub = yaca.key_extract_public(key_dsa_prv)
+ assert key_dsa_pub.get_type() == yaca.KEY_TYPE.DSA_PUB
+ assert key_dsa_pub.get_bit_length() == yaca.KEY_BIT_LENGTH.L2048BIT
+
+ key_dh_prv = yaca.key_generate(yaca.KEY_TYPE.DH_PRIV,
+ yaca.KEY_BIT_LENGTH_DH_RFC.L2048_256)
+ assert key_dh_prv.get_type() == yaca.KEY_TYPE.DH_PRIV
+ assert key_dh_prv.get_bit_length() == 2048
+
+ key_dh_pub = yaca.key_extract_public(key_dh_prv)
+ assert key_dh_pub.get_type() == yaca.KEY_TYPE.DH_PUB
+ assert key_dh_pub.get_bit_length() == 2048
+
+ key_dh_params = yaca.key_extract_parameters(key_dh_prv)
+ key_dh_prv_2 = yaca.key_generate_from_parameters(key_dh_params)
+ assert key_dh_prv_2.get_type() == key_dh_prv.get_type()
+ assert key_dh_prv_2.get_bit_length() == key_dh_prv.get_bit_length()
+
+ key_dh_prv_3 = yaca.key_generate(yaca.KEY_TYPE.DH_PRIV,
+ yaca.KEY_LENGTH_DH_GENERATOR_5 | 256)
+ assert key_dh_prv_3.get_type() == yaca.KEY_TYPE.DH_PRIV
+ assert key_dh_prv_3.get_bit_length() == 256
+
+ key_ec_prv = yaca.key_generate(yaca.KEY_TYPE.EC_PRIV,
+ yaca.KEY_BIT_LENGTH_EC.PRIME256V1)
+ assert key_ec_prv.get_type() == yaca.KEY_TYPE.EC_PRIV
+ assert key_ec_prv.get_bit_length() == yaca.KEY_BIT_LENGTH_EC.PRIME256V1
+
+ key_ec_pub = yaca.key_extract_public(key_ec_prv)
+ assert key_ec_pub.get_type() == yaca.KEY_TYPE.EC_PUB
+ assert key_ec_pub.get_bit_length() == yaca.KEY_BIT_LENGTH_EC.PRIME256V1
+
+
+def key_exp_imp():
+ # prepare:
+ key_sym = yaca.key_generate()
+ key_rsa_prv = yaca.key_generate(yaca.KEY_TYPE.RSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ # end prepare
+
+ key_sym_exp = yaca.key_export(key_sym)
+ key_sym_imp = yaca.key_import(key_sym_exp)
+ assert key_sym.get_type() == key_sym_imp.get_type()
+ assert key_sym.get_bit_length() == key_sym_imp.get_bit_length()
+
+ key_rsa_prv_exp = yaca.key_export(key_rsa_prv, yaca.KEY_FILE_FORMAT.PEM)
+ key_rsa_prv_imp = yaca.key_import(key_rsa_prv_exp, yaca.KEY_TYPE.RSA_PRIV)
+ assert key_rsa_prv.get_type() == key_rsa_prv_imp.get_type()
+ assert key_rsa_prv.get_bit_length() == key_rsa_prv_imp.get_bit_length()
+
+ key_rsa_prv_exp = yaca.key_export(key_rsa_prv, yaca.KEY_FILE_FORMAT.PEM,
+ yaca.KEY_FORMAT.PKCS8, b"password")
+ key_rsa_prv_imp = yaca.key_import(key_rsa_prv_exp, yaca.KEY_TYPE.RSA_PRIV,
+ b"password")
+ assert key_rsa_prv.get_type() == key_rsa_prv_imp.get_type()
+ assert key_rsa_prv.get_bit_length() == key_rsa_prv_imp.get_bit_length()
+
+
+def key_derive():
+ # prepare:
+ key_dh_prv = yaca.key_generate(yaca.KEY_TYPE.DH_PRIV,
+ yaca.KEY_BIT_LENGTH_DH_RFC.L2048_256)
+ key_dh_pub = yaca.key_extract_public(key_dh_prv)
+ key_dh_params = yaca.key_extract_parameters(key_dh_prv)
+ key_dh_prv_2 = yaca.key_generate_from_parameters(key_dh_params)
+ key_dh_pub_2 = yaca.key_extract_public(key_dh_prv_2)
+ # end prepare
+
+ secret = yaca.key_derive_dh(key_dh_prv_2, key_dh_pub)
+ assert len(secret) == 256
+
+ secret_2 = yaca.key_derive_dh(key_dh_prv, key_dh_pub_2)
+ assert secret == secret_2
+
+ key_material = yaca.key_derive_kdf(secret, 128)
+ assert len(key_material) == 128
+
+ key_derived = yaca.key_derive_pbkdf2(b'password')
+ assert key_derived.get_type() == yaca.KEY_TYPE.SYMMETRIC
+ assert key_derived.get_bit_length() == yaca.KEY_BIT_LENGTH.L256BIT
+
+
+def simple():
+ # prepare:
+ key_sym = yaca.key_generate()
+ key_iv_128 = yaca.key_generate(yaca.KEY_TYPE.IV,
+ yaca.KEY_BIT_LENGTH.IV_128BIT)
+ key_rsa_prv = yaca.key_generate(yaca.KEY_TYPE.RSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ key_rsa_pub = yaca.key_extract_public(key_rsa_prv)
+ # end prepare
+
+ enc_simple = yaca.simple_encrypt(key_sym, msg,
+ yaca.ENCRYPT_ALGORITHM.AES,
+ yaca.BLOCK_CIPHER_MODE.CBC, key_iv_128)
+ dec_simple = yaca.simple_decrypt(key_sym, enc_simple,
+ yaca.ENCRYPT_ALGORITHM.AES,
+ yaca.BLOCK_CIPHER_MODE.CBC, key_iv_128)
+ assert msg == dec_simple
+
+ dgst_simple = yaca.simple_calculate_digest(msg,
+ yaca.DIGEST_ALGORITHM.SHA512)
+ assert len(dgst_simple) == 64
+
+ hmac_simple = yaca.simple_calculate_hmac(key_sym, msg,
+ yaca.DIGEST_ALGORITHM.SHA512)
+ assert len(hmac_simple) == 64
+
+ cmac_simple = yaca.simple_calculate_cmac(key_sym, msg,
+ yaca.ENCRYPT_ALGORITHM.AES)
+ assert len(cmac_simple) == 16
+
+ sig_simple = yaca.simple_calculate_signature(key_rsa_prv, msg,
+ yaca.DIGEST_ALGORITHM.SHA512)
+ assert yaca.simple_verify_signature(key_rsa_pub, msg, sig_simple,
+ yaca.DIGEST_ALGORITHM.SHA512)
+
+
+def digest():
+ # prepare:
+ dgst_simple = yaca.simple_calculate_digest(msg,
+ yaca.DIGEST_ALGORITHM.SHA512)
+ # end prepare
+
+ ctx = yaca.digest_initialize(yaca.DIGEST_ALGORITHM.SHA512)
+ for part in msg_parts:
+ yaca.digest_update(ctx, part)
+ dgst = yaca.digest_finalize(ctx)
+
+ assert dgst == dgst_simple
+
+
+def encrypt_basic():
+ # prepare:
+ key_sym = yaca.key_generate()
+ key_iv_128 = yaca.key_generate(yaca.KEY_TYPE.IV,
+ yaca.KEY_BIT_LENGTH.IV_128BIT)
+ enc_simple = yaca.simple_encrypt(key_sym, msg,
+ yaca.ENCRYPT_ALGORITHM.AES,
+ yaca.BLOCK_CIPHER_MODE.CBC, key_iv_128)
+ # end prepare
+
+ len_iv = yaca.encrypt_get_iv_bit_length(yaca.ENCRYPT_ALGORITHM.AES,
+ yaca.BLOCK_CIPHER_MODE.CBC,
+ yaca.KEY_BIT_LENGTH.L256BIT)
+ assert len_iv == 128
+
+ ctx = yaca.encrypt_initialize(key_sym, bcm=yaca.BLOCK_CIPHER_MODE.CBC,
+ iv=key_iv_128)
+ enc = b''
+ for part in msg_parts:
+ enc += yaca.encrypt_update(ctx, part)
+ enc += yaca.encrypt_finalize(ctx)
+
+ assert enc == enc_simple
+
+ enc_parts = split_into_parts(enc, 5)
+
+ ctx = yaca.decrypt_initialize(key_sym, bcm=yaca.BLOCK_CIPHER_MODE.CBC,
+ iv=key_iv_128)
+ dec = b''
+ for part in enc_parts:
+ dec += yaca.decrypt_update(ctx, part)
+ dec += yaca.decrypt_finalize(ctx)
+
+ assert msg == dec
+
+
+def encrypt_rc2_property():
+ # prepare:
+ key_sym = yaca.key_generate()
+ # end prepare
+
+ len_iv = yaca.encrypt_get_iv_bit_length(yaca.ENCRYPT_ALGORITHM.UNSAFE_RC2,
+ yaca.BLOCK_CIPHER_MODE.ECB,
+ yaca.KEY_BIT_LENGTH.L256BIT)
+ assert len_iv == 0
+
+ ctx = yaca.encrypt_initialize(key_sym, yaca.ENCRYPT_ALGORITHM.UNSAFE_RC2,
+ yaca.BLOCK_CIPHER_MODE.ECB)
+ yaca.context_set_property(ctx, yaca.PROPERTY.RC2_EFFECTIVE_KEY_BITS, 192)
+ enc = b''
+ for part in msg_parts:
+ enc += yaca.encrypt_update(ctx, part)
+ enc += yaca.encrypt_finalize(ctx)
+
+ enc_parts = split_into_parts(enc, 5)
+
+ ctx = yaca.decrypt_initialize(key_sym, yaca.ENCRYPT_ALGORITHM.UNSAFE_RC2,
+ yaca.BLOCK_CIPHER_MODE.ECB)
+ yaca.context_set_property(ctx, yaca.PROPERTY.RC2_EFFECTIVE_KEY_BITS, 192)
+ dec = b''
+ for part in enc_parts:
+ dec += yaca.decrypt_update(ctx, part)
+ dec += yaca.decrypt_finalize(ctx)
+
+ assert msg == dec
+
+
+def encrypt_gcm_property():
+ # prepare:
+ key_sym = yaca.key_generate()
+ key_iv_128 = yaca.key_generate(yaca.KEY_TYPE.IV,
+ yaca.KEY_BIT_LENGTH.IV_128BIT)
+ # end prepare
+
+ tag_len = 16
+ aad = yaca.random_bytes(16)
+ ctx = yaca.encrypt_initialize(key_sym, bcm=yaca.BLOCK_CIPHER_MODE.GCM,
+ iv=key_iv_128)
+ yaca.context_set_property(ctx, yaca.PROPERTY.GCM_AAD, aad)
+ enc = b''
+ for part in msg_parts:
+ enc += yaca.encrypt_update(ctx, part)
+ enc += yaca.encrypt_finalize(ctx)
+ yaca.context_set_property(ctx, yaca.PROPERTY.GCM_TAG_LEN, tag_len)
+ tag = yaca.context_get_property(ctx, yaca.PROPERTY.GCM_TAG)
+ assert len(tag) == tag_len
+
+ enc_parts = split_into_parts(enc, 5)
+
+ ctx = yaca.decrypt_initialize(key_sym, bcm=yaca.BLOCK_CIPHER_MODE.GCM,
+ iv=key_iv_128)
+ yaca.context_set_property(ctx, yaca.PROPERTY.GCM_AAD, aad)
+ dec = b''
+ for part in enc_parts:
+ dec += yaca.decrypt_update(ctx, part)
+ yaca.context_set_property(ctx, yaca.PROPERTY.GCM_TAG, tag)
+ dec += yaca.decrypt_finalize(ctx)
+
+ assert msg == dec
+
+
+def encrypt_ccm_property():
+ # prepare:
+ key_sym = yaca.key_generate()
+ key_iv_64 = yaca.key_generate(yaca.KEY_TYPE.IV,
+ yaca.KEY_BIT_LENGTH.IV_64BIT)
+ # end prepare
+
+ tag_len = 12
+ aad = yaca.random_bytes(16)
+ ctx = yaca.encrypt_initialize(key_sym, bcm=yaca.BLOCK_CIPHER_MODE.CCM,
+ iv=key_iv_64)
+ yaca.context_set_property(ctx, yaca.PROPERTY.CCM_TAG_LEN, tag_len)
+ yaca.encrypt_update(ctx, len(msg)) # encrypt_update second type of usage
+ yaca.context_set_property(ctx, yaca.PROPERTY.CCM_AAD, aad)
+ enc = yaca.encrypt_update(ctx, msg)
+ enc += yaca.encrypt_finalize(ctx)
+ tag = yaca.context_get_property(ctx, yaca.PROPERTY.CCM_TAG)
+ assert len(tag) == tag_len
+
+ ctx = yaca.decrypt_initialize(key_sym, bcm=yaca.BLOCK_CIPHER_MODE.CCM,
+ iv=key_iv_64)
+ yaca.context_set_property(ctx, yaca.PROPERTY.CCM_TAG, tag)
+ yaca.decrypt_update(ctx, len(enc)) # decrypt_update second type of usage
+ yaca.context_set_property(ctx, yaca.PROPERTY.CCM_AAD, aad)
+ dec = yaca.decrypt_update(ctx, enc)
+ dec += yaca.decrypt_finalize(ctx)
+
+ assert msg == dec
+
+
+def sign():
+ # prepare:
+ key_sym = yaca.key_generate()
+ key_rsa_prv = yaca.key_generate(yaca.KEY_TYPE.RSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ key_rsa_pub = yaca.key_extract_public(key_rsa_prv)
+ hmac_simple = yaca.simple_calculate_hmac(key_sym, msg,
+ yaca.DIGEST_ALGORITHM.SHA512)
+ cmac_simple = yaca.simple_calculate_cmac(key_sym, msg,
+ yaca.ENCRYPT_ALGORITHM.AES)
+ sign_simple = yaca.simple_calculate_signature(key_rsa_prv, msg,
+ yaca.DIGEST_ALGORITHM.SHA512)
+ # end prepare
+
+ ctx = yaca.sign_initialize_hmac(key_sym, yaca.DIGEST_ALGORITHM.SHA512)
+ for part in msg_parts:
+ yaca.sign_update(ctx, part)
+ hmac = yaca.sign_finalize(ctx)
+
+ assert hmac == hmac_simple
+
+ ctx = yaca.sign_initialize_cmac(key_sym, yaca.ENCRYPT_ALGORITHM.AES)
+ for part in msg_parts:
+ yaca.sign_update(ctx, part)
+ cmac = yaca.sign_finalize(ctx)
+
+ assert cmac == cmac_simple
+
+ ctx = yaca.sign_initialize(key_rsa_prv, yaca.DIGEST_ALGORITHM.SHA512)
+ for part in msg_parts:
+ yaca.sign_update(ctx, part)
+ sig = yaca.sign_finalize(ctx)
+
+ assert sig == sign_simple # won't work for DSA
+
+ ctx = yaca.verify_initialize(key_rsa_pub, yaca.DIGEST_ALGORITHM.SHA512)
+ for part in msg_parts:
+ yaca.verify_update(ctx, part)
+ assert yaca.verify_finalize(ctx, sig)
+
+ # SIGN + SET PADDING
+
+ ctx = yaca.sign_initialize(key_rsa_prv)
+ for part in msg_parts:
+ yaca.sign_update(ctx, part)
+ yaca.context_set_property(ctx, yaca.PROPERTY.PADDING,
+ yaca.PADDING.PKCS1_PSS)
+ sig = yaca.sign_finalize(ctx)
+
+ ctx = yaca.verify_initialize(key_rsa_pub)
+ for part in msg_parts:
+ yaca.verify_update(ctx, part)
+ yaca.context_set_property(ctx, yaca.PROPERTY.PADDING,
+ yaca.PADDING.PKCS1_PSS)
+ assert yaca.verify_finalize(ctx, sig)
+
+
+def seal():
+ # prepare:
+ key_rsa_prv = yaca.key_generate(yaca.KEY_TYPE.RSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ key_rsa_pub = yaca.key_extract_public(key_rsa_prv)
+ # end prepare
+
+ ctx, key_seal, iv = yaca.seal_initialize(key_rsa_pub,
+ bcm=yaca.BLOCK_CIPHER_MODE.CBC)
+ sealed = b''
+ for part in msg_parts:
+ sealed += yaca.seal_update(ctx, part)
+ sealed += yaca.seal_finalize(ctx)
+
+ sealed_parts = split_into_parts(sealed, 5)
+
+ ctx = yaca.open_initialize(key_rsa_prv, key_seal, iv,
+ bcm=yaca.BLOCK_CIPHER_MODE.CBC)
+ opened = b''
+ for part in sealed_parts:
+ opened += yaca.open_update(ctx, part)
+ opened += yaca.open_finalize(ctx)
+
+ assert opened == msg
+
+
+def rsa():
+ # prepare:
+ key_rsa_prv = yaca.key_generate(yaca.KEY_TYPE.RSA_PRIV,
+ yaca.KEY_BIT_LENGTH.L2048BIT)
+ key_rsa_pub = yaca.key_extract_public(key_rsa_prv)
+ # end prepare
+
+ msg_short_max = int(2048 / 8 - 11)
+ msg_short = msg[:msg_short_max]
+
+ enc_rsa = yaca.rsa_public_encrypt(key_rsa_pub, msg_short)
+ dec_rsa = yaca.rsa_private_decrypt(key_rsa_prv, enc_rsa)
+
+ assert dec_rsa == msg_short
+
+ enc_rsa = yaca.rsa_private_encrypt(key_rsa_prv, msg_short)
+ dec_rsa = yaca.rsa_public_decrypt(key_rsa_pub, enc_rsa)
+
+ assert dec_rsa == msg_short