CARVIEW |
Select Language
HTTP/2 302
date: Wed, 23 Jul 2025 07:33:50 GMT
content-type: text/html; charset=utf-8
content-length: 0
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
location: https://release-assets.githubusercontent.com/github-production-release-asset/949716401/e1f66f1e-5f6e-46a7-a9ff-66dd072e7230?sp=r&sv=2018-11-09&sr=b&spr=https&se=2025-07-23T08%3A10%3A31Z&rscd=attachment%3B+filename%3DRagCraft.c&rsct=application%2Foctet-stream&skoid=96c2d410-5711-43a1-aedd-ab1947aa7ab0&sktid=398a6654-997b-47e9-b12b-9515b896b4de&skt=2025-07-23T07%3A10%3A18Z&ske=2025-07-23T08%3A10%3A31Z&sks=b&skv=2018-11-09&sig=8Yt%2FIeabbS8aewTNcS1wWRQpZPE9dvpqIwrnBZCYXj4%3D&jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmVsZWFzZS1hc3NldHMuZ2l0aHVidXNlcmNvbnRlbnQuY29tIiwia2V5Ijoia2V5MSIsImV4cCI6MTc1MzI1NjMzMCwibmJmIjoxNzUzMjU2MDMwLCJwYXRoIjoicmVsZWFzZWFzc2V0cHJvZHVjdGlvbi5ibG9iLmNvcmUud2luZG93cy5uZXQifQ.iaMXEfIXYAS2Omll2y3Vk-pWCw6I9tS3vH1ShMSuJEs&response-content-disposition=attachment%3B%20filename%3DRagCraft.c&response-content-type=application%2Foctet-stream
cache-control: no-cache
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
x-github-request-id: C226:1C6D98:64A45F:7E7C87:6880905E
HTTP/2 200
last-modified: Thu, 27 Mar 2025 00:41:27 GMT
etag: "0x8DD6CC81BCD4272"
server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
x-ms-request-id: 4707d6a1-401e-003b-43a4-fba4f1000000
x-ms-version: 2018-11-09
x-ms-creation-time: Thu, 27 Mar 2025 00:41:27 GMT
x-ms-blob-content-md5: 6fs9sawPCSjX6xPQq0vO5g==
x-ms-lease-status: unlocked
x-ms-lease-state: available
x-ms-blob-type: BlockBlob
x-ms-server-encrypted: true
via: 1.1 varnish, 1.1 varnish
accept-ranges: bytes
age: 0
date: Wed, 23 Jul 2025 07:33:51 GMT
x-served-by: cache-iad-kcgs7200132-IAD, cache-bom-vanm7210064-BOM
x-cache: MISS, MISS
x-cache-hits: 0, 0
x-timer: S1753256031.849554,VS0,VE388
content-disposition: attachment; filename=RagCraft.c
content-type: application/octet-stream
content-length: 4403565
#define DEFINE_DEPENDENCIES
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
#ifndef PROJECT_NAME_dep_declare
#define PROJECT_NAME_dep_declare
/* MIT License
Copyright (c) 2025 OUI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef LuaSilverChain_dep_declare
#define LuaSilverChain_dep_declare
#include
#include
#include
#include
#include
#ifndef BearsslHttps_allocate
#define BearsslHttps_allocate malloc
#endif
#ifndef BearsslHttps_reallocate
#define BearsslHttps_reallocate realloc
#endif
#ifndef BearsslHttps_free
#define BearsslHttps_free free
#endif
#if defined(_MSC_VER)
#include
#include
typedef SSIZE_T ssize_t;
typedef __m128i __m128i_u;
#define __src_inner_hbyteswap_ulong _byteswap_ulong
#endif
#if !defined(UniversalSocket_dep)
/* MIT License
Copyright (c) 2024 Samuel Henrique
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef UniversalSocket_dep
#define UniversalSocket_dep
#include
#include
#include
#include
#include
//#define _GET_ADDR_INFO_DEFAULT_
#if defined(__linux__)
#include
#include
#include
#include
#include
#include
#include
#endif
#if defined(_WIN32)
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
#endif
#endif
#ifndef UniversalSocket_mac
#define UniversalSocket_mac
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define UNI_AF_INET AF_INET
#define UNI_INADDR_ANY INADDR_ANY
#define UNI_FD_SET FD_SET
#define UNI_FD_CLR FD_CLR
#define UNI_FD_ISSET FD_ISSET
#define UNI_FD_ZERO FD_ZERO
#define UNI_SOCK_STREAM SOCK_STREAM
#define UNI_SOCK_DGRAM SOCK_DGRAM
#define UNI_SOCK_RAW SOCK_RAW
#define UNI_MSG_PEEK MSG_PEEK
#define UNI_SO_RCVTIMEO SO_RCVTIMEO
#define UNI_SO_SNDTIMEO SO_SNDTIMEO
#define UNI_SO_KEEPALIVE SO_KEEPALIVE
#define UNI_SO_BROADCAST SO_BROADCAST
#define UNI_SO_LINGER SO_LINGER
#define UNI_AF_UNSPEC AF_UNSPEC
#define UNI_IPPROTO_TCP IPPROTO_TCP
#define UNI_IPPROTO_UDP IPPROTO_UDP
#define UNI_MSG_OOB MSG_OOB
#define UNI_AF_INET6 AF_INET6
#define UNI_SHUT_RD SHUT_RD
#define UNI_SHUT_WR SHUT_WR
#define UNI_SHUT_RDWR SHUT_RDWR
#define UNI_SO_REUSEADDR SO_REUSEADDR
#define UNI_SO_RCVBUF SO_RCVBUF
#define UNI_SOL_SOCKET SOL_SOCKET
#define UNI_AF_INET6 AF_INET6
#define UNI_INET6_ADDRSTRLEN INET6_ADDRSTRLEN
#define UNI_EAI_MEMORY EAI_MEMORY
#define UNI_INET_ADDRSTRLEN INET_ADDRSTRLEN
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
#define UNI_INVALID_SOCKET -1
#define UNI_SOCKET_ERROR -1
#define UNI_EAGAIN EAGAIN
#define UNI_EWOULDBLOCK EWOULDBLOCK
#define UNI_ECONNREFUSED ECONNREFUSED
#define UNI_ETIMEDOUT ETIMEDOUT
#define UNI_EINPROGRESS EINPROGRESS
#define UNI_EADDRNOTAVAIL EADDRNOTAVAIL
#define UNI_ENETUNREACH ENETUNREACH
#define UNI_MSG_WAITALL MSG_WAITALL
#define UNI_EAI_NONAME EAI_NONAME
#define UNI_EAI_AGAIN EAI_AGAIN
#define UNI_EAI_FAIL EAI_FAIL
#define UNI_EAI_NODATA EAI_NONAME
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
#define UNI_INVALID_SOCKET INVALID_SOCKET
#define UNI_SOCKET_ERROR SOCKET_ERROR
#define UNI_EAGAIN WSAEWOULDBLOCK
#define UNI_EWOULDBLOCK WSAEWOULDBLOCK
#define UNI_MSG_WAITALL 0
#define UNI_ECONNREFUSED WSAECONNREFUSED
#define UNI_ETIMEDOUT WSAETIMEDOUT
#define UNI_EINPROGRESS WSAEINPROGRESS
#define UNI_EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define UNI_ENETUNREACH WSAENETUNREACH
#define UNI_EAI_NONAME WSAHOST_NOT_FOUND
#define UNI_EAI_AGAIN WSATRY_AGAIN
#define UNI_EAI_FAIL WSANO_RECOVERY
#define UNI_EAI_NODATA WSANO_DATA
#endif
#endif
#ifndef UniversalSocket_types
#define UniversalSocket_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct sockaddr Universal_sockaddr;
typedef struct sockaddr_in Universal_sockaddr_in;
typedef struct sockaddr_in6 Universal_sockaddr_in6;
typedef struct sockaddr_storage Universal_sockaddr_storage;
typedef struct addrinfo Universal_addrinfo;
typedef struct in_addr Universal_in_addr;
typedef struct in6_addr Universal_in6_addr;
typedef struct hostent Universal_hostent;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
typedef int Universal_socket_int;
typedef socklen_t Universal_socket_len;
typedef unsigned int Universal_DWORD;
typedef ssize_t Universal_ssize_t;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
typedef SOCKET Universal_socket_int;
typedef int Universal_socket_len;
typedef DWORD Universal_DWORD;
typedef unsigned long in_addr_t;
typedef long Universal_ssize_t;
#endif
#endif
#ifndef UniversalSocket_dec
#define UniversalSocket_dec
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern const char* Universal_inet_ntoa(Universal_in_addr addr);
extern ssize_t Universal_recv (int fd, void *buf, size_t n, int flags);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern ssize_t Universal_send (int fd, const void *buf, size_t n, int flags);
extern const char *Universal_inet_ntop(int af, const void *src, char *dst, Universal_socket_len size);
extern int Universal_inet_pton(int af, const char *src, void *dst);
uint32_t Universal_ntohl(uint32_t netlong);
uint16_t Universal_htons(uint16_t value);
uint16_t Universal_ntohs(uint16_t value);
extern in_addr_t Universal_inet_addr(const char *ip);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern int Universal_bind (int fd,Universal_sockaddr_in *addrin , Universal_socket_len len);
extern int Universal_accept (int fd, Universal_sockaddr_in *addrin,
Universal_socket_len *adrr_len);
extern int Universal_listen (int fd, int n);
extern int Universal_connect(int sockfd, const Universal_sockaddr *addr, socklen_t addrlen);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int Universal_getaddrinfo(const char *node, const char *service, const Universal_addrinfo *hints, Universal_addrinfo **res);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern char *Universal_GetLastError();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern int Universal_start_all ();
extern int Universal_close (int fd);
extern int Universal_end ();
//#if defined(_GET_ADDR_INFO_DEFAULT_)
int Universal_getaddrinfo(const char *node, const char *service, const Universal_addrinfo *hints, Universal_addrinfo **res);
void Universal_freeaddrinfo(Universal_addrinfo *addrinfo_ptr);
//#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int Universal_socket (int domain, int type, int protocol);
int Universal_ZeroMemory(void *ptr, size_t num);
int Universal_setsockopt(
Universal_socket_int sockfd,
int level,
int optname,
const void *optval,
Universal_socket_len optlen
);
int Universal_getsockopt(
Universal_socket_int sockfd,
int level,
int optname,
void *optval,
Universal_socket_len *optlen
);
Universal_hostent *Universal_gethostbyname(const char *hostname);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
ssize_t private_Universal_recv_all(int fd, void *buf, size_t n);
#endif
#endif
#define BEARSSL_HTTPS_UNIVERSAL_SOCKET_DECLARATED
#endif
#if !defined(BR_BEARSSL_H__)
#define BR_ENABLE_INTRINSICS 1
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef INNER_H__
#define INNER_H__
#include
#include
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef CONFIG_H__
#define CONFIG_H__
/*
* This file contains compile-time flags that can override the
* autodetection performed in relevant files. Each flag is a macro; it
* deactivates the feature if defined to 0, activates it if defined to a
* non-zero integer (normally 1). If the macro is not defined, then
* autodetection applies.
*/
/*
* When BR_64 is enabled, 64-bit integer types are assumed to be
* efficient (i.e. the architecture has 64-bit registers and can
* do 64-bit operations as fast as 32-bit operations).
*
#define BR_64 1
*/
/*
* When BR_LOMUL is enabled, then multiplications of 32-bit values whose
* result are truncated to the low 32 bits are assumed to be
* substantially more efficient than 32-bit multiplications that yield
* 64-bit results. This is typically the case on low-end ARM Cortex M
* systems (M0, M0+, M1, and arguably M3 and M4 as well).
*
#define BR_LOMUL 1
*/
/*
* When BR_SLOW_MUL is enabled, multiplications are assumed to be
* substantially slow with regards to other integer operations, thus
* making it worth to make more operations for a given task if it allows
* using less multiplications.
*
#define BR_SLOW_MUL 1
*/
/*
* When BR_SLOW_MUL15 is enabled, short multplications (on 15-bit words)
* are assumed to be substantially slow with regards to other integer
* operations, thus making it worth to make more integer operations if
* it allows using less multiplications.
*
#define BR_SLOW_MUL15 1
*/
/*
* When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used
* in the "i31" big integer implementation) use an alternate implementation
* which is slower and larger than the normal multiplication, but should
* ensure constant-time multiplications even on architectures where the
* multiplication opcode takes a variable number of cycles to complete.
*
#define BR_CT_MUL31 1
*/
/*
* When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held
* in 32-bit words) use an alternate implementation which is slower and
* larger than the normal multiplication, but should ensure
* constant-time multiplications on most/all architectures where the
* basic multiplication is not constant-time.
#define BR_CT_MUL15 1
*/
/*
* When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign
* extension) are performed with a sequence of operations which is bigger
* and slower than a simple right shift on a signed value. This avoids
* relying on an implementation-defined behaviour. However, most if not
* all C compilers use sign extension for right shifts on signed values,
* so this alternate macro is disabled by default.
#define BR_NO_ARITH_SHIFT 1
*/
/*
* When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode
* to automatically obtain quality randomness for seeding its internal
* PRNG. Since that opcode is present only in recent x86 CPU, its
* support is dynamically tested; if the current CPU does not support
* it, then another random source will be used, such as /dev/urandom or
* CryptGenRandom().
*
#define BR_RDRAND 1
*/
/*
* When BR_USE_GETENTROPY is enabled, the SSL engine will use the
* getentropy() function to obtain quality randomness for seeding its
* internal PRNG. On Linux and FreeBSD, getentropy() is implemented by
* the standard library with the system call getrandom(); on OpenBSD,
* getentropy() is the system call, and there is no getrandom() wrapper,
* hence the use of the getentropy() function for maximum portability.
*
* If the getentropy() call fails, and BR_USE_URANDOM is not explicitly
* disabled, then /dev/urandom will be used as a fallback mechanism. On
* FreeBSD and OpenBSD, this does not change much, since /dev/urandom
* will block if not enough entropy has been obtained since last boot.
* On Linux, /dev/urandom might not block, which can be troublesome in
* early boot stages, which is why getentropy() is preferred.
*
#define BR_USE_GETENTROPY 1
*/
/*
* When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom
* to automatically obtain quality randomness for seeding its internal
* PRNG.
*
#define BR_USE_URANDOM 1
*/
/*
* When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32
* (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to
* automatically obtain quality randomness for seeding its internal PRNG.
*
* Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the
* former takes precedence.
*
#define BR_USE_WIN32_RAND 1
*/
/*
* When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains
* the current time from the OS by calling time(), and assuming that the
* returned value (a 'time_t') is an integer that counts time in seconds
* since the Unix Epoch (Jan 1st, 1970, 00:00 UTC).
*
#define BR_USE_UNIX_TIME 1
*/
/*
* When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains
* the current time from the OS by calling the Win32 function
* GetSystemTimeAsFileTime().
*
* Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the
* former takes precedence.
*
#define BR_USE_WIN32_TIME 1
*/
/*
* When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with
* inline assembly which is shorter and/or faster. This should be used
* only when all of the following are true:
* - target architecture is ARM in Thumb mode
* - target endianness is little-endian
* - compiler is GCC (or GCC-compatible for inline assembly syntax)
*
* This is meant for the low-end cores (Cortex M0, M0+, M1, M3).
* Note: if BR_LOMUL is not explicitly enabled or disabled, then
* enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL.
*
#define BR_ARMEL_CORTEXM_GCC 1
*/
/*
* When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI"
* instructions (dedicated AES opcodes) will be compiled. If this is not
* enabled explicitly, then that AES implementation will be compiled only
* if a compatible compiler is detected. If set explicitly to 0, the
* implementation will not be compiled at all.
*
#define BR_AES_X86NI 1
*/
/*
* When BR_SSE2 is enabled, SSE2 intrinsics will be used for some
* algorithm implementations that use them (e.g. chacha20_sse2). If this
* is not enabled explicitly, then support for SSE2 intrinsics will be
* automatically detected. If set explicitly to 0, then SSE2 code will
* not be compiled at all.
*
#define BR_SSE2 1
*/
/*
* When BR_POWER8 is enabled, the AES implementation using the POWER ISA
* 2.07 opcodes (available on POWER8 processors and later) is compiled.
* If this is not enabled explicitly, then that implementation will be
* compiled only if a compatible compiler is detected, _and_ the target
* architecture is POWER8 or later.
*
#define BR_POWER8 1
*/
/*
* When BR_INT128 is enabled, then code using the 'unsigned __int64'
* and 'unsigned __int128' types will be used to leverage 64x64->128
* unsigned multiplications. This should work with GCC and compatible
* compilers on 64-bit architectures.
*
#define BR_INT128 1
*/
/*
* When BR_UMUL128 is enabled, then code using the '_umul128()' and
* '_addcarry_u64()' intrinsics will be used to implement 64x64->128
* unsigned multiplications. This should work on Visual C on x64 systems.
*
#define BR_UMUL128 1
*/
/*
* When BR_LE_UNALIGNED is enabled, then the current architecture is
* assumed to use little-endian encoding for integers, and to tolerate
* unaligned accesses with no or minimal time penalty.
*
#define BR_LE_UNALIGNED 1
*/
/*
* When BR_BE_UNALIGNED is enabled, then the current architecture is
* assumed to use big-endian encoding for integers, and to tolerate
* unaligned accesses with no or minimal time penalty.
*
#define BR_BE_UNALIGNED 1
*/
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_H__
#define BR_BEARSSL_H__
#include
#include
/** \mainpage BearSSL API
*
* # API Layout
*
* The functions and structures defined by the BearSSL API are located
* in various header files:
*
* | Header file | Elements |
* | :-------------- | :------------------------------------------------ |
* | bearssl_hash.h | Hash functions |
* | bearssl_hmac.h | HMAC |
* | bearssl_kdf.h | Key Derivation Functions |
* | bearssl_rand.h | Pseudorandom byte generators |
* | bearssl_prf.h | PRF implementations (for SSL/TLS) |
* | bearssl_block.h | Symmetric encryption |
* | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) |
* | bearssl_rsa.h | RSA encryption and signatures |
* | bearssl_ec.h | Elliptic curves support (including ECDSA) |
* | bearssl_ssl.h | SSL/TLS engine interface |
* | bearssl_x509.h | X.509 certificate decoding and validation |
* | bearssl_pem.h | Base64/PEM decoding support functions |
*
* Applications using BearSSL are supposed to simply include `bearssl.h`
* as follows:
*
* #include
*
* The `bearssl.h` file itself includes all the other header files. It is
* possible to include specific header files, but it has no practical
* advantage for the application. The API is separated into separate
* header files only for documentation convenience.
*
*
* # Conventions
*
* ## MUST and SHALL
*
* In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology
* is used. Failure to meet requirements expressed with a "MUST" or
* "SHALL" implies undefined behaviour, which means that segmentation
* faults, buffer overflows, and other similar adverse events, may occur.
*
* In general, BearSSL is not very forgiving of programming errors, and
* does not include much failsafes or error reporting when the problem
* does not arise from external transient conditions, and can be fixed
* only in the application code. This is done so in order to make the
* total code footprint lighter.
*
*
* ## `NULL` values
*
* Function parameters with a pointer type shall not be `NULL` unless
* explicitly authorised by the documentation. As an exception, when
* the pointer aims at a sequence of bytes and is accompanied with
* a length parameter, and the length is zero (meaning that there is
* no byte at all to retrieve), then the pointer may be `NULL` even if
* not explicitly allowed.
*
*
* ## Memory Allocation
*
* BearSSL does not perform dynamic memory allocation. This implies that
* for any functionality that requires a non-transient state, the caller
* is responsible for allocating the relevant context structure. Such
* allocation can be done in any appropriate area, including static data
* segments, the heap, and the stack, provided that proper alignment is
* respected. The header files define these context structures
* (including size and contents), so the C compiler should handle
* alignment automatically.
*
* Since there is no dynamic resource allocation, there is also nothing to
* release. When the calling code is done with a BearSSL feature, it
* may simple release the context structures it allocated itself, with
* no "close function" to call. If the context structures were allocated
* on the stack (as local variables), then even that release operation is
* implicit.
*
*
* ## Structure Contents
*
* Except when explicitly indicated, structure contents are opaque: they
* are included in the header files so that calling code may know the
* structure sizes and alignment requirements, but callers SHALL NOT
* access individual fields directly. For fields that are supposed to
* be read from or written to, the API defines accessor functions (the
* simplest of these accessor functions are defined as `static inline`
* functions, and the C compiler will optimise them away).
*
*
* # API Usage
*
* BearSSL usage for running a SSL/TLS client or server is described
* on the [BearSSL Web site](https://www.bearssl.org/api1.html). The
* BearSSL source archive also comes with sample code.
*/
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_HASH_H__
#define BR_BEARSSL_HASH_H__
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_hash.h
*
* # Hash Functions
*
* This file documents the API for hash functions.
*
*
* ## Procedural API
*
* For each implemented hash function, of name "`xxx`", the following
* elements are defined:
*
* - `br_xxx_vtable`
*
* An externally defined instance of `br_hash_class`.
*
* - `br_xxx_SIZE`
*
* A macro that evaluates to the output size (in bytes) of the
* hash function.
*
* - `br_xxx_ID`
*
* A macro that evaluates to a symbolic identifier for the hash
* function. Such identifiers are used with HMAC and signature
* algorithm implementations.
*
* NOTE: for the "standard" hash functions defined in [the TLS
* standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1),
* the symbolic identifiers match the constants used in TLS, i.e.
* 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512,
* respectively.
*
* - `br_xxx_context`
*
* Context for an ongoing computation. It is allocated by the
* caller, and a pointer to it is passed to all functions. A
* context contains no interior pointer, so it can be moved around
* and cloned (with a simple `memcpy()` or equivalent) in order to
* capture the function state at some point. Computations that use
* distinct context structures are independent of each other. The
* first field of `br_xxx_context` is always a pointer to the
* `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer.
*
* - `br_xxx_init(br_xxx_context *ctx)`
*
* Initialise the provided context. Previous contents of the structure
* are ignored. This calls resets the context to the start of a new
* hash computation; it also sets the first field of the context
* structure (called `vtable`) to a pointer to the statically
* allocated constant `br_xxx_vtable` structure.
*
* - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)`
*
* Add some more bytes to the hash computation represented by the
* provided context.
*
* - `br_xxx_out(const br_xxx_context *ctx, void *out)`
*
* Complete the hash computation and write the result in the provided
* buffer. The output buffer MUST be large enough to accommodate the
* result. The context is NOT modified by this operation, so this
* function can be used to get a "partial hash" while still keeping
* the possibility of adding more bytes to the input.
*
* - `br_xxx_state(const br_xxx_context *ctx, void *out)`
*
* Get a copy of the "current state" for the computation so far. For
* MD functions (MD5, SHA-1, SHA-2 family), this is the running state
* resulting from the processing of the last complete input block.
* Returned value is the current input length (in bytes).
*
* - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)`
*
* Set the internal state to the provided values. The 'stb' and
* 'count' values shall match that which was obtained from
* `br_xxx_state()`. This restores the hash state only if the state
* values were at an appropriate block boundary. This does NOT set
* the `vtable` pointer in the context.
*
* Context structures can be discarded without any explicit deallocation.
* Hash function implementations are purely software and don't reserve
* any resources outside of the context structure itself.
*
*
* ## Object-Oriented API
*
* For each hash function that follows the procedural API described
* above, an object-oriented API is also provided. In that API, function
* pointers from the vtable (`br_xxx_vtable`) are used. The vtable
* incarnates object-oriented programming. An introduction on the OOP
* concept used here can be read on the BearSSL Web site:
* [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) * * The vtable offers functions called `init()`, `update()`, `out()`, * `set()` and `set_state()`, which are in fact the functions from * the procedural API. That vtable also contains two informative fields: * * - `context_size` * * The size of the context structure (`br_xxx_context`), in bytes. * This can be used by generic implementations to perform dynamic * context allocation. * * - `desc` * * A "descriptor" field that encodes some information on the hash * function: symbolic identifier, output size, state size, * internal block size, details on the padding. * * Users of this object-oriented API (in particular generic HMAC * implementations) may make the following assumptions: * * - Hash output size is no more than 64 bytes. * - Hash internal state size is no more than 64 bytes. * - Internal block size is a power of two, no less than 16 and no more * than 256. * * * ## Implemented Hash Functions * * Implemented hash functions are: * * | Function | Name | Output length | State length | * | :-------- | :------ | :-----------: | :----------: | * | MD5 | md5 | 16 | 16 | * | SHA-1 | sha1 | 20 | 20 | * | SHA-224 | sha224 | 28 | 32 | * | SHA-256 | sha256 | 32 | 32 | * | SHA-384 | sha384 | 48 | 64 | * | SHA-512 | sha512 | 64 | 64 | * | MD5+SHA-1 | md5sha1 | 36 | 36 | * * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the * same input; in the implementation, the internal data buffer is * shared, thus making it more memory-efficient than separate MD5 and * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS * 1.1.) * * * ## Multi-Hasher * * An aggregate hasher is provided, that can compute several standard * hash functions in parallel. It uses `br_multihash_context` and a * procedural API. It is configured with the implementations (the vtables) * that it should use; it will then compute all these hash functions in * parallel, on the same input. It is meant to be used in cases when the * hash of an object will be used, but the exact hash function is not * known yet (typically, streamed processing on X.509 certificates). * * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 * and SHA-512) are supported by the multi-hasher. * * * ## GHASH * * GHASH is not a generic hash function; it is a _universal_ hash function, * which, as the name does not say, means that it CANNOT be used in most * places where a hash function is needed. GHASH is used within the GCM * encryption mode, to provide the checked integrity functionality. * * A GHASH implementation is basically a function that uses the type defined * in this file under the name `br_ghash`: * * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); * * The `y` pointer refers to a 16-byte value which is used as input, and * receives the output of the GHASH invocation. `h` is a 16-byte secret * value (that serves as key). `data` and `len` define the input data. * * Three GHASH implementations are provided, all constant-time, based on * the use of integer multiplications with appropriate masking to cancel * carry propagation. */ /** * \brief Class type for hash function implementations. * * A `br_hash_class` instance references the methods implementing a hash * function. Constant instances of this structure are defined for each * implemented hash function. Such instances are also called "vtables". * * Vtables are used to support object-oriented programming, as * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). */ typedef struct br_hash_class_ br_hash_class; struct br_hash_class_ { /** * \brief Size (in bytes) of the context structure appropriate for * computing this hash function. */ size_t context_size; /** * \brief Descriptor word that contains information about the hash * function. * * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` * and `BR_HASHDESC_xxx_MASK` to access the specific value, as * follows: * * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK * * The defined elements are: * * - `ID`: the symbolic identifier for the function, as defined * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) * (MD5 = 1, SHA-1 = 2,...). * * - `OUT`: hash output size, in bytes. * * - `STATE`: internal running state size, in bytes. * * - `LBLEN`: base-2 logarithm for the internal block size, as * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 * and SHA-256, since these functions use 64-byte blocks; for * SHA-384 and SHA-512, this is 7, corresponding to their * 128-byte blocks). * * The descriptor may contain a few other flags. */ uint32_t desc; /** * \brief Initialisation method. * * This method takes as parameter a pointer to a context area, * that it initialises. The first field of the context is set * to this vtable; other elements are initialised for a new hash * computation. * * \param ctx pointer to (the first field of) the context. */ void (*init)(const br_hash_class **ctx); /** * \brief Data injection method. * * The `len` bytes starting at address `data` are injected into * the running hash computation incarnated by the specified * context. The context is updated accordingly. It is allowed * to have `len == 0`, in which case `data` is ignored (and could * be `NULL`), and nothing happens. * on the input data. * * \param ctx pointer to (the first field of) the context. * \param data pointer to the first data byte to inject. * \param len number of bytes to inject. */ void (*update)(const br_hash_class **ctx, const void *data, size_t len); /** * \brief Produce hash output. * * The hash output corresponding to all data bytes injected in the * context since the last `init()` call is computed, and written * in the buffer pointed to by `dst`. The hash output size depends * on the implemented hash function (e.g. 16 bytes for MD5). * The context is _not_ modified by this call, so further bytes * may be afterwards injected to continue the current computation. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the hash output. */ void (*out)(const br_hash_class *const *ctx, void *dst); /** * \brief Get running state. * * This method saves the current running state into the `dst` * buffer. What constitutes the "running state" depends on the * hash function; for Merkle-Damgård hash functions (like * MD5 or SHA-1), this is the output obtained after processing * each block. The number of bytes injected so far is returned. * The context is not modified by this call. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the state. * \return the injected total byte length. */ uint64_t (*state)(const br_hash_class *const *ctx, void *dst); /** * \brief Set running state. * * This methods replaces the running state for the function. * * \param ctx pointer to (the first field of) the context. * \param stb source buffer for the state. * \param count injected total byte length. */ void (*set_state)(const br_hash_class **ctx, const void *stb, uint64_t count); }; #ifndef BR_DOXYGEN_IGNORE #define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) #define BR_HASHDESC_ID_OFF 0 #define BR_HASHDESC_ID_MASK 0xFF #define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) #define BR_HASHDESC_OUT_OFF 8 #define BR_HASHDESC_OUT_MASK 0x7F #define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) #define BR_HASHDESC_STATE_OFF 15 #define BR_HASHDESC_STATE_MASK 0xFF #define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) #define BR_HASHDESC_LBLEN_OFF 23 #define BR_HASHDESC_LBLEN_MASK 0x0F #define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) #define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) #define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) #endif /* * Specific hash functions. * * Rules for contexts: * -- No interior pointer. * -- No pointer to external dynamically allocated resources. * -- First field is called 'vtable' and is a pointer to a * const-qualified br_hash_class instance (pointer is set by init()). * -- SHA-224 and SHA-256 contexts are identical. * -- SHA-384 and SHA-512 contexts are identical. * * Thus, contexts can be moved and cloned to capture the hash function * current state; and there is no need for any explicit "release" function. */ /** * \brief Symbolic identifier for MD5. */ #define br_md5_ID 1 /** * \brief MD5 output size (in bytes). */ #define br_md5_SIZE 16 /** * \brief Constant vtable for MD5. */ extern const br_hash_class br_md5_vtable; /** * \brief MD5 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[4]; #endif } br_md5_context; /** * \brief MD5 context initialisation. * * This function initialises or resets a context for a new MD5 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5_init(br_md5_context *ctx); /** * \brief Inject some data bytes in a running MD5 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5_update(br_md5_context *ctx, const void *data, size_t len); /** * \brief Compute MD5 output. * * The MD5 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5_out(const br_md5_context *ctx, void *out); /** * \brief Save MD5 running state. * * The running state for MD5 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5_state(const br_md5_context *ctx, void *out); /** * \brief Restore MD5 running state. * * The running state for MD5 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-1. */ #define br_sha1_ID 2 /** * \brief SHA-1 output size (in bytes). */ #define br_sha1_SIZE 20 /** * \brief Constant vtable for SHA-1. */ extern const br_hash_class br_sha1_vtable; /** * \brief SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[5]; #endif } br_sha1_context; /** * \brief SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-1 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha1_init(br_sha1_context *ctx); /** * \brief Inject some data bytes in a running SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-1 output. * * The SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha1_out(const br_sha1_context *ctx, void *out); /** * \brief Save SHA-1 running state. * * The running state for SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); /** * \brief Restore SHA-1 running state. * * The running state for SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-224. */ #define br_sha224_ID 3 /** * \brief SHA-224 output size (in bytes). */ #define br_sha224_SIZE 28 /** * \brief Constant vtable for SHA-224. */ extern const br_hash_class br_sha224_vtable; /** * \brief SHA-224 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[8]; #endif } br_sha224_context; /** * \brief SHA-224 context initialisation. * * This function initialises or resets a context for a new SHA-224 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha224_init(br_sha224_context *ctx); /** * \brief Inject some data bytes in a running SHA-224 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-224 output. * * The SHA-224 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha224_out(const br_sha224_context *ctx, void *out); /** * \brief Save SHA-224 running state. * * The running state for SHA-224 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); /** * \brief Restore SHA-224 running state. * * The running state for SHA-224 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha224_set_state(br_sha224_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-256. */ #define br_sha256_ID 4 /** * \brief SHA-256 output size (in bytes). */ #define br_sha256_SIZE 32 /** * \brief Constant vtable for SHA-256. */ extern const br_hash_class br_sha256_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-256 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha256_context; #else typedef br_sha224_context br_sha256_context; #endif /** * \brief SHA-256 context initialisation. * * This function initialises or resets a context for a new SHA-256 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha256_init(br_sha256_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-256 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); #else #define br_sha256_update br_sha224_update #endif /** * \brief Compute SHA-256 output. * * The SHA-256 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha256_out(const br_sha256_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-256 running state. * * The running state for SHA-256 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); #else #define br_sha256_state br_sha224_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-256 running state. * * The running state for SHA-256 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha256_set_state(br_sha256_context *ctx, const void *stb, uint64_t count); #else #define br_sha256_set_state br_sha224_set_state #endif /** * \brief Symbolic identifier for SHA-384. */ #define br_sha384_ID 5 /** * \brief SHA-384 output size (in bytes). */ #define br_sha384_SIZE 48 /** * \brief Constant vtable for SHA-384. */ extern const br_hash_class br_sha384_vtable; /** * \brief SHA-384 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint64_t val[8]; #endif } br_sha384_context; /** * \brief SHA-384 context initialisation. * * This function initialises or resets a context for a new SHA-384 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha384_init(br_sha384_context *ctx); /** * \brief Inject some data bytes in a running SHA-384 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-384 output. * * The SHA-384 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha384_out(const br_sha384_context *ctx, void *out); /** * \brief Save SHA-384 running state. * * The running state for SHA-384 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); /** * \brief Restore SHA-384 running state. * * The running state for SHA-384 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha384_set_state(br_sha384_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-512. */ #define br_sha512_ID 6 /** * \brief SHA-512 output size (in bytes). */ #define br_sha512_SIZE 64 /** * \brief Constant vtable for SHA-512. */ extern const br_hash_class br_sha512_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-512 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha512_context; #else typedef br_sha384_context br_sha512_context; #endif /** * \brief SHA-512 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha512_init(br_sha512_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-512 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); #else #define br_sha512_update br_sha384_update #endif /** * \brief Compute SHA-512 output. * * The SHA-512 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha512_out(const br_sha512_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-512 running state. * * The running state for SHA-512 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); #else #define br_sha512_state br_sha384_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-512 running state. * * The running state for SHA-512 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha512_set_state(br_sha512_context *ctx, const void *stb, uint64_t count); #else #define br_sha512_set_state br_sha384_set_state #endif /* * "md5sha1" is a special hash function that computes both MD5 and SHA-1 * on the same input, and produces a 36-byte output (MD5 and SHA-1 * concatenation, in that order). State size is also 36 bytes. */ /** * \brief Symbolic identifier for MD5+SHA-1. * * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the * same input. It is not one of the functions identified in TLS, so * we give it a symbolic identifier of value 0. */ #define br_md5sha1_ID 0 /** * \brief MD5+SHA-1 output size (in bytes). */ #define br_md5sha1_SIZE 36 /** * \brief Constant vtable for MD5+SHA-1. */ extern const br_hash_class br_md5sha1_vtable; /** * \brief MD5+SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val_md5[4]; uint32_t val_sha1[5]; #endif } br_md5sha1_context; /** * \brief MD5+SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5sha1_init(br_md5sha1_context *ctx); /** * \brief Inject some data bytes in a running MD5+SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); /** * \brief Compute MD5+SHA-1 output. * * The MD5+SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); /** * \brief Save MD5+SHA-1 running state. * * The running state for MD5+SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); /** * \brief Restore MD5+SHA-1 running state. * * The running state for MD5+SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5sha1_set_state(br_md5sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Aggregate context for configurable hash function support. * * The `br_hash_compat_context` type is a type which is large enough to * serve as context for all standard hash functions defined above. */ typedef union { const br_hash_class *vtable; br_md5_context md5; br_sha1_context sha1; br_sha224_context sha224; br_sha256_context sha256; br_sha384_context sha384; br_sha512_context sha512; br_md5sha1_context md5sha1; } br_hash_compat_context; /* * The multi-hasher is a construct that handles hashing of the same input * data with several hash functions, with a single shared input buffer. * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 * simultaneously, though which functions are activated depends on * the set implementation pointers. */ /** * \brief Multi-hasher context structure. * * The multi-hasher runs up to six hash functions in the standard TLS list * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over * the same input. * * The multi-hasher does _not_ follow the OOP structure with a vtable. * Instead, it is configured with the vtables of the hash functions it * should run. Structure fields are not supposed to be accessed directly. */ typedef struct { #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint32_t val_32[25]; uint64_t val_64[16]; const br_hash_class *impl[6]; #endif } br_multihash_context; /** * \brief Clear a multi-hasher context. * * This should always be called once on a given context, _before_ setting * the implementation pointers. * * \param ctx the multi-hasher context. */ void br_multihash_zero(br_multihash_context *ctx); /** * \brief Set a hash function implementation. * * Implementations shall be set _after_ clearing the context (with * `br_multihash_zero()`) but _before_ initialising the computation * (with `br_multihash_init()`). The hash function implementation * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove * an implementation from the multi-hasher. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \param impl the hash function vtable, or `NULL`. */ static inline void br_multihash_setimpl(br_multihash_context *ctx, int id, const br_hash_class *impl) { /* * This code relies on hash functions ID being values 1 to 6, * in the MD5 to SHA-512 order. */ ctx->impl[id - 1] = impl; } /** * \brief Get a hash function implementation. * * This function returns the currently configured vtable for a given * hash function (by symbolic ID). If no such function was configured in * the provided multi-hasher context, then this function returns `NULL`. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \return the hash function vtable, or `NULL`. */ static inline const br_hash_class * br_multihash_getimpl(const br_multihash_context *ctx, int id) { return ctx->impl[id - 1]; } /** * \brief Reset a multi-hasher context. * * This function prepares the context for a new hashing computation, * for all implementations configured at that point. * * \param ctx the multi-hasher context. */ void br_multihash_init(br_multihash_context *ctx); /** * \brief Inject some data bytes in a running multi-hashing computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_multihash_update(br_multihash_context *ctx, const void *data, size_t len); /** * \brief Compute a hash output from a multi-hasher. * * The hash output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `dst`. The hash * function to use is identified by `id` and must be one of the standard * hash functions. If that hash function was indeed configured in the * multi-hasher context, the corresponding hash value is written in * `dst` and its length (in bytes) is returned. If the hash function * was _not_ configured, then nothing is written in `dst` and 0 is * returned. * * The context itself is not modified, so extra bytes may be injected * afterwards to continue the hash computations. * * \param ctx pointer to the context structure. * \param id the hash function symbolic identifier. * \param dst destination buffer for the hash output. * \return the hash output length (in bytes), or 0. */ size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); /** * \brief Type for a GHASH implementation. * * GHASH is a sort of keyed hash meant to be used to implement GCM in * combination with a block cipher (with 16-byte blocks). * * The `y` array has length 16 bytes and is used for input and output; in * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte * value that serves as key (it is derived from the encryption key in GCM, * using the block cipher). The data length (`len`) is expressed in bytes. * The `y` array is updated. * * If the data length is not a multiple of 16, then the data is implicitly * padded with zeros up to the next multiple of 16. Thus, when using GHASH * in GCM, this method may be called twice, for the associated data and * for the ciphertext, respectively; the zero-padding implements exactly * the GCM rules. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (mixed 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (strict 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, * but it is expected to be faster on architectures for which the * 32-bit multiplication opcode does not yield the upper 32 bits of the * product. It is constant-time (if multiplications are constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (64-bit). * * This implementation uses multiplications of 64-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). It is substantially faster than `br_ghash_ctmul()` * and `br_ghash_ctmul32()` on most 64-bit architectures. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using the `pclmulqdq` opcode (part of the * AES-NI instructions). * * This implementation is available only on x86 platforms where the * compiler supports the relevant intrinsic functions. Even if the * compiler supports these functions, the local CPU might not support * the `pclmulqdq` opcode, meaning that a call will fail with an * illegal instruction exception. To safely obtain a pointer to this * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pclmul` GHASH implementation, if available. * * If the `pclmul` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pclmul()` function. Otherwise, it will return `0`. * * \return the `pclmul` GHASH implementation, or `0`. */ br_ghash br_ghash_pclmul_get(void); /** * \brief GHASH implementation using the POWER8 opcodes. * * This implementation is available only on POWER8 platforms (and later). * To safely obtain a pointer to this function when supported (or 0 * otherwise), use `br_ghash_pwr8_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pwr8` GHASH implementation, if available. * * If the `pwr8` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pwr8()` function. Otherwise, it will return `0`. * * \return the `pwr8` GHASH implementation, or `0`. */ br_ghash br_ghash_pwr8_get(void); #ifdef __cplusplus } #endif #endif /* * Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_HMAC_H__
#define BR_BEARSSL_HMAC_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_hmac.h
*
* # HMAC
*
* HMAC is initialized with a key and an underlying hash function; it
* then fills a "key context". That context contains the processed
* key.
*
* With the key context, a HMAC context can be initialized to process
* the input bytes and obtain the MAC output. The key context is not
* modified during that process, and can be reused.
*
* IMPORTANT: HMAC shall be used only with functions that have the
* following properties:
*
* - hash output size does not exceed 64 bytes;
* - hash internal state size does not exceed 64 bytes;
* - internal block length is a power of 2 between 16 and 256 bytes.
*/
/**
* \brief HMAC key context.
*
* The HMAC key context is initialised with a hash function implementation
* and a secret key. Contents are opaque (callers should not access them
* directly). The caller is responsible for allocating the context where
* appropriate. Context initialisation and usage incurs no dynamic
* allocation, so there is no release function.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
const br_hash_class *dig_vtable;
unsigned char ksi[64], kso[64];
#endif
} br_hmac_key_context;
/**
* \brief HMAC key context initialisation.
*
* Initialise the key context with the provided key, using the hash function
* identified by `digest_vtable`. This supports arbitrary key lengths.
*
* \param kc HMAC key context to initialise.
* \param digest_vtable pointer to the hash function implementation vtable.
* \param key pointer to the HMAC secret key.
* \param key_len HMAC secret key length (in bytes).
*/
void br_hmac_key_init(br_hmac_key_context *kc,
const br_hash_class *digest_vtable, const void *key, size_t key_len);
/*
* \brief Get the underlying hash function.
*
* This function returns a pointer to the implementation vtable of the
* hash function used for this HMAC key context.
*
* \param kc HMAC key context.
* \return the hash function implementation.
*/
static inline const br_hash_class *br_hmac_key_get_digest(
const br_hmac_key_context *kc)
{
return kc->dig_vtable;
}
/**
* \brief HMAC computation context.
*
* The HMAC computation context maintains the state for a single HMAC
* computation. It is modified as input bytes are injected. The context
* is caller-allocated and has no release function since it does not
* dynamically allocate external resources. Its contents are opaque.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
br_hash_compat_context dig;
unsigned char kso[64];
size_t out_len;
#endif
} br_hmac_context;
/**
* \brief HMAC computation initialisation.
*
* Initialise a HMAC context with a key context. The key context is
* unmodified. Relevant data from the key context is immediately copied;
* the key context can thus be independently reused, modified or released
* without impacting this HMAC computation.
*
* An explicit output length can be specified; the actual output length
* will be the minimum of that value and the natural HMAC output length.
* If `out_len` is 0, then the natural HMAC output length is selected. The
* "natural output length" is the output length of the underlying hash
* function.
*
* \param ctx HMAC context to initialise.
* \param kc HMAC key context (already initialised with the key).
* \param out_len HMAC output length (0 to select "natural length").
*/
void br_hmac_init(br_hmac_context *ctx,
const br_hmac_key_context *kc, size_t out_len);
/**
* \brief Get the HMAC output size.
*
* The HMAC output size is the number of bytes that will actually be
* produced with `br_hmac_out()` with the provided context. This function
* MUST NOT be called on a non-initialised HMAC computation context.
* The returned value is the minimum of the HMAC natural length (output
* size of the underlying hash function) and the `out_len` parameter which
* was used with the last `br_hmac_init()` call on that context (if the
* initialisation `out_len` parameter was 0, then this function will
* return the HMAC natural length).
*
* \param ctx the (already initialised) HMAC computation context.
* \return the HMAC actual output size.
*/
static inline size_t
br_hmac_size(br_hmac_context *ctx)
{
return ctx->out_len;
}
/*
* \brief Get the underlying hash function.
*
* This function returns a pointer to the implementation vtable of the
* hash function used for this HMAC context.
*
* \param hc HMAC context.
* \return the hash function implementation.
*/
static inline const br_hash_class *br_hmac_get_digest(
const br_hmac_context *hc)
{
return hc->dig.vtable;
}
/**
* \brief Inject some bytes in HMAC.
*
* The provided `len` bytes are injected as extra input in the HMAC
* computation incarnated by the `ctx` HMAC context. It is acceptable
* that `len` is zero, in which case `data` is ignored (and may be
* `NULL`) and this function does nothing.
*/
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
/**
* \brief Compute the HMAC output.
*
* The destination buffer MUST be large enough to accommodate the result;
* its length is at most the "natural length" of HMAC (i.e. the output
* length of the underlying hash function). The context is NOT modified;
* further bytes may be processed. Thus, "partial HMAC" values can be
* efficiently obtained.
*
* Returned value is the output length (in bytes).
*
* \param ctx HMAC computation context.
* \param out destination buffer for the HMAC output.
* \return the produced value length (in bytes).
*/
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
/**
* \brief Constant-time HMAC computation.
*
* This function compute the HMAC output in constant time. Some extra
* input bytes are processed, then the output is computed. The extra
* input consists in the `len` bytes pointed to by `data`. The `len`
* parameter must lie between `min_len` and `max_len` (inclusive);
* `max_len` bytes are actually read from `data`. Computing time (and
* memory access pattern) will not depend upon the data byte contents or
* the value of `len`.
*
* The output is written in the `out` buffer, that MUST be large enough
* to receive it.
*
* The difference `max_len - min_len` MUST be less than 230
* (i.e. about one gigabyte).
*
* This function computes the output properly only if the underlying
* hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256,
* SHA-384 or SHA-512).
*
* The provided context is NOT modified.
*
* \param ctx the (already initialised) HMAC computation context.
* \param data the extra input bytes.
* \param len the extra input length (in bytes).
* \param min_len minimum extra input length (in bytes).
* \param max_len maximum extra input length (in bytes).
* \param out destination buffer for the HMAC output.
* \return the produced value length (in bytes).
*/
size_t br_hmac_outCT(const br_hmac_context *ctx,
const void *data, size_t len, size_t min_len, size_t max_len,
void *out);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_KDF_H__
#define BR_BEARSSL_KDF_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_kdf.h
*
* # Key Derivation Functions
*
* KDF are functions that takes a variable length input, and provide a
* variable length output, meant to be used to derive subkeys from a
* master key.
*
* ## HKDF
*
* HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869).
* It is based on HMAC, itself using an underlying hash function. Any
* hash function can be used, as long as it is compatible with the rules
* for the HMAC implementation (i.e. output size is 64 bytes or less, hash
* internal state size is 64 bytes or less, and the internal block length is
* a power of 2 between 16 and 256 bytes). HKDF has two phases:
*
* - HKDF-Extract: the input data in ingested, along with a "salt" value.
*
* - HKDF-Expand: the output is produced, from the result of processing
* the input and salt, and using an extra non-secret parameter called
* "info".
*
* The "salt" and "info" strings are non-secret and can be empty. Their role
* is normally to bind the input and output, respectively, to conventional
* identifiers that qualifu them within the used protocol or application.
*
* The implementation defined in this file uses the following functions:
*
* - `br_hkdf_init()`: initialize an HKDF context, with a hash function,
* and the salt. This starts the HKDF-Extract process.
*
* - `br_hkdf_inject()`: inject more input bytes. This function may be
* called repeatedly if the input data is provided by chunks.
*
* - `br_hkdf_flip()`: end the HKDF-Extract process, and start the
* HKDF-Expand process.
*
* - `br_hkdf_produce()`: get the next bytes of output. This function
* may be called several times to obtain the full output by chunks.
* For correct HKDF processing, the same "info" string must be
* provided for each call.
*
* Note that the HKDF total output size (the number of bytes that
* HKDF-Expand is willing to produce) is limited: if the hash output size
* is _n_ bytes, then the maximum output size is _255*n_.
*
* ## SHAKE
*
* SHAKE is defined in
* [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final)
* under two versions: SHAKE128 and SHAKE256, offering an alleged
* "security level" of 128 and 256 bits, respectively (SHAKE128 is
* about 20 to 25% faster than SHAKE256). SHAKE internally relies on
* the Keccak family of sponge functions, not on any externally provided
* hash function. Contrary to HKDF, SHAKE does not have a concept of
* either a "salt" or an "info" string. The API consists in four
* functions:
*
* - `br_shake_init()`: initialize a SHAKE context for a given
* security level.
*
* - `br_shake_inject()`: inject more input bytes. This function may be
* called repeatedly if the input data is provided by chunks.
*
* - `br_shake_flip()`: end the data injection process, and start the
* data production process.
*
* - `br_shake_produce()`: get the next bytes of output. This function
* may be called several times to obtain the full output by chunks.
*/
/**
* \brief HKDF context.
*
* The HKDF context is initialized with a hash function implementation
* and a salt value. Contents are opaque (callers should not access them
* directly). The caller is responsible for allocating the context where
* appropriate. Context initialisation and usage incurs no dynamic
* allocation, so there is no release function.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
union {
br_hmac_context hmac_ctx;
br_hmac_key_context prk_ctx;
} u;
unsigned char buf[64];
size_t ptr;
size_t dig_len;
unsigned chunk_num;
#endif
} br_hkdf_context;
/**
* \brief HKDF context initialization.
*
* The underlying hash function and salt value are provided. Arbitrary
* salt lengths can be used.
*
* HKDF makes a difference between a salt of length zero, and an
* absent salt (the latter being equivalent to a salt consisting of
* bytes of value zero, of the same length as the hash function output).
* If `salt_len` is zero, then this function assumes that the salt is
* present but of length zero. To specify an _absent_ salt, use
* `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored).
*
* \param hc HKDF context to initialise.
* \param digest_vtable pointer to the hash function implementation vtable.
* \param salt HKDF-Extract salt.
* \param salt_len HKDF-Extract salt length (in bytes).
*/
void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
const void *salt, size_t salt_len);
/**
* \brief The special "absent salt" value for HKDF.
*/
#define BR_HKDF_NO_SALT (&br_hkdf_no_salt)
#ifndef BR_DOXYGEN_IGNORE
extern const unsigned char br_hkdf_no_salt;
#endif
/**
* \brief HKDF input injection (HKDF-Extract).
*
* This function injects some more input bytes ("key material") into
* HKDF. This function may be called several times, after `br_hkdf_init()`
* but before `br_hkdf_flip()`.
*
* \param hc HKDF context.
* \param ikm extra input bytes.
* \param ikm_len number of extra input bytes.
*/
void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len);
/**
* \brief HKDF switch to the HKDF-Expand phase.
*
* This call terminates the HKDF-Extract process (input injection), and
* starts the HKDF-Expand process (output production).
*
* \param hc HKDF context.
*/
void br_hkdf_flip(br_hkdf_context *hc);
/**
* \brief HKDF output production (HKDF-Expand).
*
* Produce more output bytes from the current state. This function may be
* called several times, but only after `br_hkdf_flip()`.
*
* Returned value is the number of actually produced bytes. The total
* output length is limited to 255 times the output length of the
* underlying hash function.
*
* \param hc HKDF context.
* \param info application specific information string.
* \param info_len application specific information string length (in bytes).
* \param out destination buffer for the HKDF output.
* \param out_len the length of the requested output (in bytes).
* \return the produced output length (in bytes).
*/
size_t br_hkdf_produce(br_hkdf_context *hc,
const void *info, size_t info_len, void *out, size_t out_len);
/**
* \brief SHAKE context.
*
* The HKDF context is initialized with a "security level". The internal
* notion is called "capacity"; the capacity is twice the security level
* (for instance, SHAKE128 has capacity 256).
*
* The caller is responsible for allocating the context where
* appropriate. Context initialisation and usage incurs no dynamic
* allocation, so there is no release function.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
unsigned char dbuf[200];
size_t dptr;
size_t rate;
uint64_t A[25];
#endif
} br_shake_context;
/**
* \brief SHAKE context initialization.
*
* The context is initialized for the provided "security level".
* Internally, this sets the "capacity" to twice the security level;
* thus, for SHAKE128, the `security_level` parameter should be 128,
* which corresponds to a 256-bit capacity.
*
* Allowed security levels are all multiples of 32, from 32 to 768,
* inclusive. Larger security levels imply lower performance; levels
* beyond 256 bits don't make much sense. Standard levels are 128
* and 256 bits (for SHAKE128 and SHAKE256, respectively).
*
* \param sc SHAKE context to initialise.
* \param security_level security level (in bits).
*/
void br_shake_init(br_shake_context *sc, int security_level);
/**
* \brief SHAKE input injection.
*
* This function injects some more input bytes ("key material") into
* SHAKE. This function may be called several times, after `br_shake_init()`
* but before `br_shake_flip()`.
*
* \param sc SHAKE context.
* \param data extra input bytes.
* \param len number of extra input bytes.
*/
void br_shake_inject(br_shake_context *sc, const void *data, size_t len);
/**
* \brief SHAKE switch to production phase.
*
* This call terminates the input injection process, and starts the
* output production process.
*
* \param sc SHAKE context.
*/
void br_shake_flip(br_shake_context *hc);
/**
* \brief SHAKE output production.
*
* Produce more output bytes from the current state. This function may be
* called several times, but only after `br_shake_flip()`.
*
* There is no practical limit to the number of bytes that may be produced.
*
* \param sc SHAKE context.
* \param out destination buffer for the SHAKE output.
* \param len the length of the requested output (in bytes).
*/
void br_shake_produce(br_shake_context *sc, void *out, size_t len);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_RAND_H__
#define BR_BEARSSL_RAND_H__
#include
#include
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_BLOCK_H__
#define BR_BEARSSL_BLOCK_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_block.h
*
* # Block Ciphers and Symmetric Ciphers
*
* This file documents the API for block ciphers and other symmetric
* ciphers.
*
*
* ## Procedural API
*
* For a block cipher implementation, up to three separate sets of
* functions are provided, for CBC encryption, CBC decryption, and CTR
* encryption/decryption. Each set has its own context structure,
* initialised with the encryption key.
*
* For CBC encryption and decryption, the data to encrypt or decrypt is
* referenced as a sequence of blocks. The implementations assume that
* there is no partial block; no padding is applied or removed. The
* caller is responsible for handling any kind of padding.
*
* Function for CTR encryption are defined only for block ciphers with
* blocks of 16 bytes or more (i.e. AES, but not DES/3DES).
*
* Each implemented block cipher is identified by an "internal name"
* from which are derived the names of structures and functions that
* implement the cipher. For the block cipher of internal name "`xxx`",
* the following are defined:
*
* - `br_xxx_BLOCK_SIZE`
*
* A macro that evaluates to the block size (in bytes) of the
* cipher. For all implemented block ciphers, this value is a
* power of two.
*
* - `br_xxx_cbcenc_keys`
*
* Context structure that contains the subkeys resulting from the key
* expansion. These subkeys are appropriate for CBC encryption. The
* structure first field is called `vtable` and points to the
* appropriate OOP structure.
*
* - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for CBC encryption are computed and
* written in the provided context structure. The key length MUST be
* adequate for the implemented block cipher. This function also sets
* the `vtable` field.
*
* - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)`
*
* Perform CBC encryption of `len` bytes, in place. The encrypted data
* replaces the cleartext. `len` MUST be a multiple of the block length
* (if it is not, the function may loop forever or overflow a buffer).
* The IV is provided with the `iv` pointer; it is also updated with
* a copy of the last encrypted block.
*
* - `br_xxx_cbcdec_keys`
*
* Context structure that contains the subkeys resulting from the key
* expansion. These subkeys are appropriate for CBC decryption. The
* structure first field is called `vtable` and points to the
* appropriate OOP structure.
*
* - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for CBC decryption are computed and
* written in the provided context structure. The key length MUST be
* adequate for the implemented block cipher. This function also sets
* the `vtable` field.
*
* - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)`
*
* Perform CBC decryption of `len` bytes, in place. The decrypted data
* replaces the ciphertext. `len` MUST be a multiple of the block length
* (if it is not, the function may loop forever or overflow a buffer).
* The IV is provided with the `iv` pointer; it is also updated with
* a copy of the last _encrypted_ block.
*
* - `br_xxx_ctr_keys`
*
* Context structure that contains the subkeys resulting from the key
* expansion. These subkeys are appropriate for CTR encryption and
* decryption. The structure first field is called `vtable` and
* points to the appropriate OOP structure.
*
* - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for CTR encryption and decryption
* are computed and written in the provided context structure. The
* key length MUST be adequate for the implemented block cipher. This
* function also sets the `vtable` field.
*
* - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`)
*
* Perform CTR encryption/decryption of some data. Processing is done
* "in place" (the output data replaces the input data). This function
* implements the "standard incrementing function" from NIST SP800-38A,
* annex B: the IV length shall be 4 bytes less than the block size
* (i.e. 12 bytes for AES) and the counter is the 32-bit value starting
* with `cc`. The data length (`len`) is not necessarily a multiple of
* the block size. The new counter value is returned, which supports
* chunked processing, provided that each chunk length (except possibly
* the last one) is a multiple of the block size.
*
* - `br_xxx_ctrcbc_keys`
*
* Context structure that contains the subkeys resulting from the
* key expansion. These subkeys are appropriate for doing combined
* CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX
* authenticated encryption modes. The structure first field is
* called `vtable` and points to the appropriate OOP structure.
*
* - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for combined CTR
* encryption/decryption and CBC-MAC are computed and written in the
* provided context structure. The key length MUST be adequate for
* the implemented block cipher. This function also sets the
* `vtable` field.
*
* - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)`
*
* Perform CTR encryption of some data, and CBC-MAC. Processing is
* done "in place" (the output data replaces the input data). This
* function applies CTR encryption on the data, using a full
* block-size counter (i.e. for 128-bit blocks, the counter is
* incremented as a 128-bit value). The 'ctr' array contains the
* initial value for the counter (used in the first block) and it is
* updated with the new value after data processing. The 'cbcmac'
* value shall point to a block-sized value which is used as IV for
* CBC-MAC, computed over the encrypted data (output of CTR
* encryption); the resulting CBC-MAC is written over 'cbcmac' on
* output.
*
* The data length MUST be a multiple of the block size.
*
* - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)`
*
* Perform CTR decryption of some data, and CBC-MAC. Processing is
* done "in place" (the output data replaces the input data). This
* function applies CTR decryption on the data, using a full
* block-size counter (i.e. for 128-bit blocks, the counter is
* incremented as a 128-bit value). The 'ctr' array contains the
* initial value for the counter (used in the first block) and it is
* updated with the new value after data processing. The 'cbcmac'
* value shall point to a block-sized value which is used as IV for
* CBC-MAC, computed over the encrypted data (input of CTR
* encryption); the resulting CBC-MAC is written over 'cbcmac' on
* output.
*
* The data length MUST be a multiple of the block size.
*
* - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)`
*
* Perform CTR encryption or decryption of the provided data. The
* data is processed "in place" (the output data replaces the input
* data). A full block-sized counter is applied (i.e. for 128-bit
* blocks, the counter is incremented as a 128-bit value). The 'ctr'
* array contains the initial value for the counter (used in the
* first block), and it is updated with the new value after data
* processing.
*
* The data length MUST be a multiple of the block size.
*
* - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)`
*
* Compute CBC-MAC over the provided data. The IV for CBC-MAC is
* provided as 'cbcmac'; the output is written over the same array.
* The data itself is untouched. The data length MUST be a multiple
* of the block size.
*
*
* It shall be noted that the key expansion functions return `void`. If
* the provided key length is not allowed, then there will be no error
* reporting; implementations need not validate the key length, thus an
* invalid key length may result in undefined behaviour (e.g. buffer
* overflow).
*
* Subkey structures contain no interior pointer, and no external
* resources are allocated upon key expansion. They can thus be
* discarded without any explicit deallocation.
*
*
* ## Object-Oriented API
*
* Each context structure begins with a field (called `vtable`) that
* points to an instance of a structure that references the relevant
* functions through pointers. Each such structure contains the
* following:
*
* - `context_size`
*
* The size (in bytes) of the context structure for subkeys.
*
* - `block_size`
*
* The cipher block size (in bytes).
*
* - `log_block_size`
*
* The base-2 logarithm of cipher block size (e.g. 4 for blocks
* of 16 bytes).
*
* - `init`
*
* Pointer to the key expansion function.
*
* - `run`
*
* Pointer to the encryption/decryption function.
*
* For combined CTR/CBC-MAC encryption, the `vtable` has a slightly
* different structure:
*
* - `context_size`
*
* The size (in bytes) of the context structure for subkeys.
*
* - `block_size`
*
* The cipher block size (in bytes).
*
* - `log_block_size`
*
* The base-2 logarithm of cipher block size (e.g. 4 for blocks
* of 16 bytes).
*
* - `init`
*
* Pointer to the key expansion function.
*
* - `encrypt`
*
* Pointer to the CTR encryption + CBC-MAC function.
*
* - `decrypt`
*
* Pointer to the CTR decryption + CBC-MAC function.
*
* - `ctr`
*
* Pointer to the CTR encryption/decryption function.
*
* - `mac`
*
* Pointer to the CBC-MAC function.
*
* For block cipher "`xxx`", static, constant instances of these
* structures are defined, under the names:
*
* - `br_xxx_cbcenc_vtable`
* - `br_xxx_cbcdec_vtable`
* - `br_xxx_ctr_vtable`
* - `br_xxx_ctrcbc_vtable`
*
*
* ## Implemented Block Ciphers
*
* Provided implementations are:
*
* | Name | Function | Block Size (bytes) | Key lengths (bytes) |
* | :-------- | :------- | :----------------: | :-----------------: |
* | aes_big | AES | 16 | 16, 24 and 32 |
* | aes_small | AES | 16 | 16, 24 and 32 |
* | aes_ct | AES | 16 | 16, 24 and 32 |
* | aes_ct64 | AES | 16 | 16, 24 and 32 |
* | aes_x86ni | AES | 16 | 16, 24 and 32 |
* | aes_pwr8 | AES | 16 | 16, 24 and 32 |
* | des_ct | DES/3DES | 8 | 8, 16 and 24 |
* | des_tab | DES/3DES | 8 | 8, 16 and 24 |
*
* **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8,
* 16 and 24 bytes), but some of the bits are ignored by the algorithm, so
* the _effective_ key lengths, from a security point of view, are 56,
* 112 and 168 bits, respectively.
*
* `aes_big` is a "classical" AES implementation, using tables. It
* is fast but not constant-time, since it makes data-dependent array
* accesses.
*
* `aes_small` is an AES implementation optimized for code size. It
* is substantially slower than `aes_big`; it is not constant-time
* either.
*
* `aes_ct` is a constant-time implementation of AES; its code is about
* as big as that of `aes_big`, while its performance is comparable to
* that of `aes_small`. However, it is constant-time. This
* implementation should thus be considered to be the "default" AES in
* BearSSL, to be used unless the operational context guarantees that a
* non-constant-time implementation is safe, or an architecture-specific
* constant-time implementation can be used (e.g. using dedicated
* hardware opcodes).
*
* `aes_ct64` is another constant-time implementation of AES. It is
* similar to `aes_ct` but uses 64-bit values. On 32-bit machines,
* `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has
* a larger footprint; however, on 64-bit architectures, `aes_ct64`
* is typically twice faster than `aes_ct` for modes that allow parallel
* operations (i.e. CTR, and CBC decryption, but not CBC encryption).
*
* `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It
* uses the AES-NI opcodes when available.
*
* `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and
* 64-bit, both little-endian and big-endian). It uses the AES opcodes
* present in POWER8 and later.
*
* `des_tab` is a classic, table-based implementation of DES/3DES. It
* is not constant-time.
*
* `des_ct` is an constant-time implementation of DES/3DES. It is
* substantially slower than `des_tab`.
*
* ## ChaCha20 and Poly1305
*
* ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They
* are described in [RFC 7539](https://tools.ietf.org/html/rfc7539).
*
* Two function pointer types are defined:
*
* - `br_chacha20_run` describes a function that implements ChaCha20
* only.
*
* - `br_poly1305_run` describes an implementation of Poly1305,
* in the AEAD combination with ChaCha20 specified in RFC 7539
* (the ChaCha20 implementation is provided as a function pointer).
*
* `chacha20_ct` is a straightforward implementation of ChaCha20 in
* plain C; it is constant-time, small, and reasonably fast.
*
* `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that
* support these opcodes). It is faster than `chacha20_ct`.
*
* `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD
* construction, where the Poly1305 part is performed with mixed 32-bit
* multiplications (operands are 32-bit, result is 64-bit).
*
* `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit
* multiplications (32-bit operands, 32-bit result). It is slower than
* `poly1305_ctmul`, except on some specific architectures such as
* the ARM Cortex M0+.
*
* `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit
* multiplications (operands are 64-bit, result is 128-bit) on 64-bit
* platforms that support such operations.
*
* `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15"
* big integer implementation. It is meant mostly for testing purposes,
* although it can help with saving a few hundred bytes of code footprint
* on systems where code size is scarce.
*/
/**
* \brief Class type for CBC encryption implementations.
*
* A `br_block_cbcenc_class` instance points to the functions implementing
* a specific block cipher, when used in CBC mode for encrypting data.
*/
typedef struct br_block_cbcenc_class_ br_block_cbcenc_class;
struct br_block_cbcenc_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_cbcenc_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CBC encryption.
*
* The `iv` parameter points to the IV for this run; it is
* updated with a copy of the last encrypted block. The data
* is encrypted "in place"; its length (`len`) MUST be a
* multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param iv IV for CBC encryption (updated).
* \param data data to encrypt.
* \param len data length (in bytes, multiple of block size).
*/
void (*run)(const br_block_cbcenc_class *const *ctx,
void *iv, void *data, size_t len);
};
/**
* \brief Class type for CBC decryption implementations.
*
* A `br_block_cbcdec_class` instance points to the functions implementing
* a specific block cipher, when used in CBC mode for decrypting data.
*/
typedef struct br_block_cbcdec_class_ br_block_cbcdec_class;
struct br_block_cbcdec_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_cbcdec_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CBC decryption.
*
* The `iv` parameter points to the IV for this run; it is
* updated with a copy of the last encrypted block. The data
* is decrypted "in place"; its length (`len`) MUST be a
* multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param iv IV for CBC decryption (updated).
* \param data data to decrypt.
* \param len data length (in bytes, multiple of block size).
*/
void (*run)(const br_block_cbcdec_class *const *ctx,
void *iv, void *data, size_t len);
};
/**
* \brief Class type for CTR encryption/decryption implementations.
*
* A `br_block_ctr_class` instance points to the functions implementing
* a specific block cipher, when used in CTR mode for encrypting or
* decrypting data.
*/
typedef struct br_block_ctr_class_ br_block_ctr_class;
struct br_block_ctr_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_ctr_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CTR encryption or decryption.
*
* The `iv` parameter points to the IV for this run; its
* length is exactly 4 bytes less than the block size (e.g.
* 12 bytes for AES/CTR). The IV is combined with a 32-bit
* block counter to produce the block value which is processed
* with the block cipher.
*
* The data to encrypt or decrypt is updated "in place". Its
* length (`len` bytes) is not required to be a multiple of
* the block size; if the final block is partial, then the
* corresponding key stream bits are dropped.
*
* The resulting counter value is returned.
*
* \param ctx context structure (already initialised).
* \param iv IV for CTR encryption/decryption.
* \param cc initial value for the block counter.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \return the new block counter value.
*/
uint32_t (*run)(const br_block_ctr_class *const *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
};
/**
* \brief Class type for combined CTR and CBC-MAC implementations.
*
* A `br_block_ctrcbc_class` instance points to the functions implementing
* a specific block cipher, when used in CTR mode for encrypting or
* decrypting data, along with CBC-MAC.
*/
typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class;
struct br_block_ctrcbc_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_ctrcbc_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CTR encryption + CBC-MAC.
*
* The `ctr` parameter points to the counter; its length shall
* be equal to the block size. It is updated by this function
* as encryption proceeds.
*
* The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
* is computed over the encrypted data (output of CTR
* encryption). Its length shall be equal to the block size. The
* computed CBC-MAC value is written over the `cbcmac` array.
*
* The data to encrypt is updated "in place". Its length (`len`
* bytes) MUST be a multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param ctr counter for CTR encryption (initial and final).
* \param cbcmac IV and output buffer for CBC-MAC.
* \param data data to encrypt.
* \param len data length (in bytes).
*/
void (*encrypt)(const br_block_ctrcbc_class *const *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief Run the CTR decryption + CBC-MAC.
*
* The `ctr` parameter points to the counter; its length shall
* be equal to the block size. It is updated by this function
* as decryption proceeds.
*
* The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
* is computed over the encrypted data (i.e. before CTR
* decryption). Its length shall be equal to the block size. The
* computed CBC-MAC value is written over the `cbcmac` array.
*
* The data to decrypt is updated "in place". Its length (`len`
* bytes) MUST be a multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param ctr counter for CTR encryption (initial and final).
* \param cbcmac IV and output buffer for CBC-MAC.
* \param data data to decrypt.
* \param len data length (in bytes).
*/
void (*decrypt)(const br_block_ctrcbc_class *const *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief Run the CTR encryption/decryption only.
*
* The `ctr` parameter points to the counter; its length shall
* be equal to the block size. It is updated by this function
* as decryption proceeds.
*
* The data to decrypt is updated "in place". Its length (`len`
* bytes) MUST be a multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param ctr counter for CTR encryption (initial and final).
* \param data data to decrypt.
* \param len data length (in bytes).
*/
void (*ctr)(const br_block_ctrcbc_class *const *ctx,
void *ctr, void *data, size_t len);
/**
* \brief Run the CBC-MAC only.
*
* The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
* is computed over the encrypted data (i.e. before CTR
* decryption). Its length shall be equal to the block size. The
* computed CBC-MAC value is written over the `cbcmac` array.
*
* The data is unmodified. Its length (`len` bytes) MUST be a
* multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param cbcmac IV and output buffer for CBC-MAC.
* \param data data to decrypt.
* \param len data length (in bytes).
*/
void (*mac)(const br_block_ctrcbc_class *const *ctx,
void *cbcmac, const void *data, size_t len);
};
/*
* Traditional, table-based AES implementation. It is fast, but uses
* internal tables (in particular a 1 kB table for encryption, another
* 1 kB table for decryption, and a 256-byte table for key schedule),
* and it is not constant-time. In contexts where cache-timing attacks
* apply, this implementation may leak the secret key.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_big_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_big` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_big` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_big` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_big` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_big` implementation).
*/
extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_big` implementation).
*/
extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_big` implementation).
*/
extern const br_block_ctr_class br_aes_big_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_big` implementation).
*/
extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to encrypt or decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* AES implementation optimized for size. It is slower than the
* traditional table-based AES implementation, but requires much less
* code. It still uses data-dependent table accesses (albeit within a
* much smaller 256-byte table), which makes it conceptually vulnerable
* to cache-timing attacks.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_small_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_small` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_small` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_small` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_small` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_small` implementation).
*/
extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_small` implementation).
*/
extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_small` implementation).
*/
extern const br_block_ctr_class br_aes_small_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_small` implementation).
*/
extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* Constant-time AES implementation. Its size is similar to that of
* 'aes_big', and its performance is similar to that of 'aes_small' (faster
* decryption, slower encryption). However, it is constant-time, i.e.
* immune to cache-timing and similar attacks.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_ct_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_ct` implementation).
*/
extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_ct` implementation).
*/
extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_ct` implementation).
*/
extern const br_block_ctr_class br_aes_ct_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_ct` implementation).
*/
extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* 64-bit constant-time AES implementation. It is similar to 'aes_ct'
* but uses 64-bit registers, making it about twice faster than 'aes_ct'
* on 64-bit platforms, while remaining constant-time and with a similar
* code size. (The doubling in performance is only for CBC decryption
* and CTR mode; CBC encryption is non-parallel and cannot benefit from
* the larger registers.)
*/
/** \brief AES block size (16 bytes). */
#define br_aes_ct64_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_ct64` implementation).
*/
extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_ct64` implementation).
*/
extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_ct64` implementation).
*/
extern const br_block_ctr_class br_aes_ct64_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_ct64` implementation).
*/
extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* AES implementation using AES-NI opcodes (x86 platform).
*/
/** \brief AES block size (16 bytes). */
#define br_aes_x86ni_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`.
*/
extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`.
*/
extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`.
*/
extern const br_block_ctr_class br_aes_x86ni_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`.
*/
extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/**
* \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`.
*/
const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void);
/**
* \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`.
*/
const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void);
/**
* \brief Obtain the `aes_x86ni` AES-CTR implementation, if available.
*
* This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CTR implementation, or `NULL`.
*/
const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void);
/**
* \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if
* available.
*
* This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CTR implementation, or `NULL`.
*/
const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void);
/*
* AES implementation using POWER8 opcodes.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_pwr8_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`.
*/
extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`.
*/
extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`.
*/
extern const br_block_ctr_class br_aes_pwr8_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`.
*/
extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/**
* \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if
* that implementation was compiled in the library _and_ the POWER8
* crypto opcodes are available on the currently running CPU. If either
* of these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`.
*/
const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void);
/**
* \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if
* that implementation was compiled in the library _and_ the POWER8
* crypto opcodes are available on the currently running CPU. If either
* of these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`.
*/
const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void);
/**
* \brief Obtain the `aes_pwr8` AES-CTR implementation, if available.
*
* This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that
* implementation was compiled in the library _and_ the POWER8 crypto
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CTR implementation, or `NULL`.
*/
const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void);
/**
* \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if
* available.
*
* This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if
* that implementation was compiled in the library _and_ the POWER8 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CTR implementation, or `NULL`.
*/
const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void);
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC encryption) for all AES implementations.
*/
typedef union {
const br_block_cbcenc_class *vtable;
br_aes_big_cbcenc_keys c_big;
br_aes_small_cbcenc_keys c_small;
br_aes_ct_cbcenc_keys c_ct;
br_aes_ct64_cbcenc_keys c_ct64;
br_aes_x86ni_cbcenc_keys c_x86ni;
br_aes_pwr8_cbcenc_keys c_pwr8;
} br_aes_gen_cbcenc_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC decryption) for all AES implementations.
*/
typedef union {
const br_block_cbcdec_class *vtable;
br_aes_big_cbcdec_keys c_big;
br_aes_small_cbcdec_keys c_small;
br_aes_ct_cbcdec_keys c_ct;
br_aes_ct64_cbcdec_keys c_ct64;
br_aes_x86ni_cbcdec_keys c_x86ni;
br_aes_pwr8_cbcdec_keys c_pwr8;
} br_aes_gen_cbcdec_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CTR encryption and decryption) for all AES implementations.
*/
typedef union {
const br_block_ctr_class *vtable;
br_aes_big_ctr_keys c_big;
br_aes_small_ctr_keys c_small;
br_aes_ct_ctr_keys c_ct;
br_aes_ct64_ctr_keys c_ct64;
br_aes_x86ni_ctr_keys c_x86ni;
br_aes_pwr8_ctr_keys c_pwr8;
} br_aes_gen_ctr_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations.
*/
typedef union {
const br_block_ctrcbc_class *vtable;
br_aes_big_ctrcbc_keys c_big;
br_aes_small_ctrcbc_keys c_small;
br_aes_ct_ctrcbc_keys c_ct;
br_aes_ct64_ctrcbc_keys c_ct64;
br_aes_x86ni_ctrcbc_keys c_x86ni;
br_aes_pwr8_ctrcbc_keys c_pwr8;
} br_aes_gen_ctrcbc_keys;
/*
* Traditional, table-based implementation for DES/3DES. Since tables are
* used, cache-timing attacks are conceptually possible.
*/
/** \brief DES/3DES block size (8 bytes). */
#define br_des_tab_BLOCK_SIZE 8
/**
* \brief Context for DES subkeys (`des_tab` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_tab_cbcenc_keys;
/**
* \brief Context for DES subkeys (`des_tab` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_tab_cbcdec_keys;
/**
* \brief Class instance for DES CBC encryption (`des_tab` implementation).
*/
extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable;
/**
* \brief Class instance for DES CBC decryption (`des_tab` implementation).
*/
extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable;
/**
* \brief Context initialisation (key schedule) for DES CBC encryption
* (`des_tab` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for DES CBC decryption
* (`des_tab` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with DES (`des_tab` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with DES (`des_tab` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/*
* Constant-time implementation for DES/3DES. It is substantially slower
* (by a factor of about 4x), but also immune to cache-timing attacks.
*/
/** \brief DES/3DES block size (8 bytes). */
#define br_des_ct_BLOCK_SIZE 8
/**
* \brief Context for DES subkeys (`des_ct` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_ct_cbcenc_keys;
/**
* \brief Context for DES subkeys (`des_ct` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_ct_cbcdec_keys;
/**
* \brief Class instance for DES CBC encryption (`des_ct` implementation).
*/
extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable;
/**
* \brief Class instance for DES CBC decryption (`des_ct` implementation).
*/
extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable;
/**
* \brief Context initialisation (key schedule) for DES CBC encryption
* (`des_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for DES CBC decryption
* (`des_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with DES (`des_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with DES (`des_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/*
* These structures are large enough to accommodate subkeys for all
* DES/3DES implementations.
*/
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC encryption) for all DES implementations.
*/
typedef union {
const br_block_cbcenc_class *vtable;
br_des_tab_cbcenc_keys tab;
br_des_ct_cbcenc_keys ct;
} br_des_gen_cbcenc_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC decryption) for all DES implementations.
*/
typedef union {
const br_block_cbcdec_class *vtable;
br_des_tab_cbcdec_keys c_tab;
br_des_ct_cbcdec_keys c_ct;
} br_des_gen_cbcdec_keys;
/**
* \brief Type for a ChaCha20 implementation.
*
* An implementation follows the description in RFC 7539:
*
* - Key is 256 bits (`key` points to exactly 32 bytes).
*
* - IV is 96 bits (`iv` points to exactly 12 bytes).
*
* - Block counter is over 32 bits and starts at value `cc`; the
* resulting value is returned.
*
* Data (pointed to by `data`, of length `len`) is encrypted/decrypted
* in place. If `len` is not a multiple of 64, then the excess bytes from
* the last block processing are dropped (therefore, "chunked" processing
* works only as long as each non-final chunk has a length multiple of 64).
*
* \param key secret key (32 bytes).
* \param iv IV (12 bytes).
* \param cc initial counter value.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
typedef uint32_t (*br_chacha20_run)(const void *key,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief ChaCha20 implementation (straightforward C code, constant-time).
*
* \see br_chacha20_run
*
* \param key secret key (32 bytes).
* \param iv IV (12 bytes).
* \param cc initial counter value.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
uint32_t br_chacha20_ct_run(const void *key,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief ChaCha20 implementation (SSE2 code, constant-time).
*
* This implementation is available only on x86 platforms, depending on
* compiler support. Moreover, in 32-bit mode, it might not actually run,
* if the underlying hardware does not implement the SSE2 opcode (in
* 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled
* at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain
* a pointer to that function.
*
* \see br_chacha20_run
*
* \param key secret key (32 bytes).
* \param iv IV (12 bytes).
* \param cc initial counter value.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
uint32_t br_chacha20_sse2_run(const void *key,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief Obtain the `sse2` ChaCha20 implementation, if available.
*
* This function returns a pointer to `br_chacha20_sse2_run`, if
* that implementation was compiled in the library _and_ the SSE2
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `0`.
*
* \return the `sse2` ChaCha20 implementation, or `0`.
*/
br_chacha20_run br_chacha20_sse2_get(void);
/**
* \brief Type for a ChaCha20+Poly1305 AEAD implementation.
*
* The provided data is encrypted or decrypted with ChaCha20. The
* authentication tag is computed on the concatenation of the
* additional data and the ciphertext, with the padding and lengths
* as described in RFC 7539 (section 2.8).
*
* After decryption, the caller is responsible for checking that the
* computed tag matches the expected value.
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
typedef void (*br_poly1305_run)(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications).
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_ctmul_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications).
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_ctmul32_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (i15).
*
* This implementation relies on the generic big integer code "i15"
* (which uses pure 32-bit multiplications). As such, it may save a
* little code footprint in a context where "i15" is already included
* (e.g. for elliptic curves or for RSA); however, it is also
* substantially slower than the ctmul and ctmul32 implementations.
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_i15_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (ctmulq).
*
* This implementation uses 64-bit multiplications (result over 128 bits).
* It is available only on platforms that offer such a primitive (in
* practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to
* dynamically obtain a pointer to that function, or 0 if not supported.
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_ctmulq_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available.
*
* This function returns a pointer to the `br_poly1305_ctmulq_run()`
* function if supported on the current platform; otherwise, it returns 0.
*
* \return the ctmulq ChaCha20+Poly1305 implementation, or 0.
*/
br_poly1305_run br_poly1305_ctmulq_get(void);
#ifdef __cplusplus
}
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_rand.h
*
* # Pseudo-Random Generators
*
* A PRNG is a state-based engine that outputs pseudo-random bytes on
* demand. It is initialized with an initial seed, and additional seed
* bytes can be added afterwards. Bytes produced depend on the seeds and
* also on the exact sequence of calls (including sizes requested for
* each call).
*
*
* ## Procedural and OOP API
*
* For the PRNG of name "`xxx`", two API are provided. The _procedural_
* API defined a context structure `br_xxx_context` and three functions:
*
* - `br_xxx_init()`
*
* Initialise the context with an initial seed.
*
* - `br_xxx_generate()`
*
* Produce some pseudo-random bytes.
*
* - `br_xxx_update()`
*
* Inject some additional seed.
*
* The initialisation function sets the first context field (`vtable`)
* to a pointer to the vtable that supports the OOP API. The OOP API
* provides access to the same functions through function pointers,
* named `init()`, `generate()` and `update()`.
*
* Note that the context initialisation method may accept additional
* parameters, provided as a 'const void *' pointer at API level. These
* additional parameters depend on the implemented PRNG.
*
*
* ## HMAC_DRBG
*
* HMAC_DRBG is defined in [NIST SP 800-90A Revision
* 1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
* It uses HMAC repeatedly, over some configurable underlying hash
* function. In BearSSL, it is implemented under the "`hmac_drbg`" name.
* The "extra parameters" pointer for context initialisation should be
* set to a pointer to the vtable for the underlying hash function (e.g.
* pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256).
*
* According to the NIST standard, each request shall produce up to
* 219 bits (i.e. 64 kB of data); moreover, the context shall
* be reseeded at least once every 248 requests. This
* implementation does not maintain the reseed counter (the threshold is
* too high to be reached in practice) and does not object to producing
* more than 64 kB in a single request; thus, the code cannot fail,
* which corresponds to the fact that the API has no room for error
* codes. However, this implies that requesting more than 64 kB in one
* `generate()` request, or making more than 248 requests
* without reseeding, is formally out of NIST specification. There is
* no currently known security penalty for exceeding the NIST limits,
* and, in any case, HMAC_DRBG usage in implementing SSL/TLS always
* stays much below these thresholds.
*
*
* ## AESCTR_DRBG
*
* AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is
* meant to be used only in situations where you are desperate for
* speed, and have an hardware-optimized AES/CTR implementation. Whether
* this will yield perceptible improvements depends on what you use the
* pseudorandom bytes for, and how many you want; for instance, RSA key
* pair generation uses a substantial amount of randomness, and using
* AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key
* generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz).
*
* Internally, it uses CTR mode with successive counter values, starting
* at zero (counter value expressed over 128 bits, big-endian convention).
* The counter is not allowed to reach 32768; thus, every 32768*16 bytes
* at most, the `update()` function is run (on an empty seed, if none is
* provided). The `update()` function computes the new AES-128 key by
* applying a custom hash function to the concatenation of a state-dependent
* word (encryption of an all-one block with the current key) and the new
* seed. The custom hash function uses Hirose's construction over AES-256;
* see the comments in `aesctr_drbg.c` for details.
*
* This DRBG does not follow an existing standard, and thus should be
* considered as inadequate for production use until it has been properly
* analysed.
*/
/**
* \brief Class type for PRNG implementations.
*
* A `br_prng_class` instance references the methods implementing a PRNG.
* Constant instances of this structure are defined for each implemented
* PRNG. Such instances are also called "vtables".
*/
typedef struct br_prng_class_ br_prng_class;
struct br_prng_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate for
* running this PRNG.
*/
size_t context_size;
/**
* \brief Initialisation method.
*
* The context to initialise is provided as a pointer to its
* first field (the vtable pointer); this function sets that
* first field to a pointer to the vtable.
*
* The extra parameters depend on the implementation; each
* implementation defines what kind of extra parameters it
* expects (if any).
*
* Requirements on the initial seed depend on the implemented
* PRNG.
*
* \param ctx PRNG context to initialise.
* \param params extra parameters for the PRNG.
* \param seed initial seed.
* \param seed_len initial seed length (in bytes).
*/
void (*init)(const br_prng_class **ctx, const void *params,
const void *seed, size_t seed_len);
/**
* \brief Random bytes generation.
*
* This method produces `len` pseudorandom bytes, in the `out`
* buffer. The context is updated accordingly.
*
* \param ctx PRNG context.
* \param out output buffer.
* \param len number of pseudorandom bytes to produce.
*/
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
/**
* \brief Inject additional seed bytes.
*
* The provided seed bytes are added into the PRNG internal
* entropy pool.
*
* \param ctx PRNG context.
* \param seed additional seed.
* \param seed_len additional seed length (in bytes).
*/
void (*update)(const br_prng_class **ctx,
const void *seed, size_t seed_len);
};
/**
* \brief Context for HMAC_DRBG.
*
* The context contents are opaque, except the first field, which
* supports OOP.
*/
typedef struct {
/**
* \brief Pointer to the vtable.
*
* This field is set with the initialisation method/function.
*/
const br_prng_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
unsigned char K[64];
unsigned char V[64];
const br_hash_class *digest_class;
#endif
} br_hmac_drbg_context;
/**
* \brief Statically allocated, constant vtable for HMAC_DRBG.
*/
extern const br_prng_class br_hmac_drbg_vtable;
/**
* \brief HMAC_DRBG initialisation.
*
* The context to initialise is provided as a pointer to its first field
* (the vtable pointer); this function sets that first field to a
* pointer to the vtable.
*
* The `seed` value is what is called, in NIST terminology, the
* concatenation of the "seed", "nonce" and "personalization string", in
* that order.
*
* The `digest_class` parameter defines the underlying hash function.
* Formally, the NIST standard specifies that the hash function shall
* be only SHA-1 or one of the SHA-2 functions. This implementation also
* works with any other implemented hash function (such as MD5), but
* this is non-standard and therefore not recommended.
*
* \param ctx HMAC_DRBG context to initialise.
* \param digest_class vtable for the underlying hash function.
* \param seed initial seed.
* \param seed_len initial seed length (in bytes).
*/
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
const br_hash_class *digest_class, const void *seed, size_t seed_len);
/**
* \brief Random bytes generation with HMAC_DRBG.
*
* This method produces `len` pseudorandom bytes, in the `out`
* buffer. The context is updated accordingly. Formally, requesting
* more than 65536 bytes in one request falls out of specification
* limits (but it won't fail).
*
* \param ctx HMAC_DRBG context.
* \param out output buffer.
* \param len number of pseudorandom bytes to produce.
*/
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
/**
* \brief Inject additional seed bytes in HMAC_DRBG.
*
* The provided seed bytes are added into the HMAC_DRBG internal
* entropy pool. The process does not _replace_ existing entropy,
* thus pushing non-random bytes (i.e. bytes which are known to the
* attackers) does not degrade the overall quality of generated bytes.
*
* \param ctx HMAC_DRBG context.
* \param seed additional seed.
* \param seed_len additional seed length (in bytes).
*/
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
const void *seed, size_t seed_len);
/**
* \brief Get the hash function implementation used by a given instance of
* HMAC_DRBG.
*
* This calls MUST NOT be performed on a context which was not
* previously initialised.
*
* \param ctx HMAC_DRBG context.
* \return the hash function vtable.
*/
static inline const br_hash_class *
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
{
return ctx->digest_class;
}
/**
* \brief Type for a provider of entropy seeds.
*
* A "seeder" is a function that is able to obtain random values from
* some source and inject them as entropy seed in a PRNG. A seeder
* shall guarantee that the total entropy of the injected seed is large
* enough to seed a PRNG for purposes of cryptographic key generation
* (i.e. at least 128 bits).
*
* A seeder may report a failure to obtain adequate entropy. Seeders
* shall endeavour to fix themselves transient errors by trying again;
* thus, callers may consider reported errors as permanent.
*
* \param ctx PRNG context to seed.
* \return 1 on success, 0 on error.
*/
typedef int (*br_prng_seeder)(const br_prng_class **ctx);
/**
* \brief Get a seeder backed by the operating system or hardware.
*
* Get a seeder that feeds on RNG facilities provided by the current
* operating system or hardware. If no such facility is known, then 0
* is returned.
*
* If `name` is not `NULL`, then `*name` is set to a symbolic string
* that identifies the seeder implementation. If no seeder is returned
* and `name` is not `NULL`, then `*name` is set to a pointer to the
* constant string `"none"`.
*
* \param name receiver for seeder name, or `NULL`.
* \return the system seeder, if available, or 0.
*/
br_prng_seeder br_prng_seeder_system(const char **name);
/**
* \brief Context for AESCTR_DRBG.
*
* The context contents are opaque, except the first field, which
* supports OOP.
*/
typedef struct {
/**
* \brief Pointer to the vtable.
*
* This field is set with the initialisation method/function.
*/
const br_prng_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
br_aes_gen_ctr_keys sk;
uint32_t cc;
#endif
} br_aesctr_drbg_context;
/**
* \brief Statically allocated, constant vtable for AESCTR_DRBG.
*/
extern const br_prng_class br_aesctr_drbg_vtable;
/**
* \brief AESCTR_DRBG initialisation.
*
* The context to initialise is provided as a pointer to its first field
* (the vtable pointer); this function sets that first field to a
* pointer to the vtable.
*
* The internal AES key is first set to the all-zero key; then, the
* `br_aesctr_drbg_update()` function is called with the provided `seed`.
* The call is performed even if the seed length (`seed_len`) is zero.
*
* The `aesctr` parameter defines the underlying AES/CTR implementation.
*
* \param ctx AESCTR_DRBG context to initialise.
* \param aesctr vtable for the AES/CTR implementation.
* \param seed initial seed (can be `NULL` if `seed_len` is zero).
* \param seed_len initial seed length (in bytes).
*/
void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
const br_block_ctr_class *aesctr, const void *seed, size_t seed_len);
/**
* \brief Random bytes generation with AESCTR_DRBG.
*
* This method produces `len` pseudorandom bytes, in the `out`
* buffer. The context is updated accordingly.
*
* \param ctx AESCTR_DRBG context.
* \param out output buffer.
* \param len number of pseudorandom bytes to produce.
*/
void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx,
void *out, size_t len);
/**
* \brief Inject additional seed bytes in AESCTR_DRBG.
*
* The provided seed bytes are added into the AESCTR_DRBG internal
* entropy pool. The process does not _replace_ existing entropy,
* thus pushing non-random bytes (i.e. bytes which are known to the
* attackers) does not degrade the overall quality of generated bytes.
*
* \param ctx AESCTR_DRBG context.
* \param seed additional seed.
* \param seed_len additional seed length (in bytes).
*/
void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx,
const void *seed, size_t seed_len);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_PRF_H__
#define BR_BEARSSL_PRF_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_prf.h
*
* # The TLS PRF
*
* The "PRF" is the pseudorandom function used internally during the
* SSL/TLS handshake, notably to expand negotiated shared secrets into
* the symmetric encryption keys that will be used to process the
* application data.
*
* TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This
* is implemented by the `br_tls10_prf()` function.
*
* TLS 1.2 redefines the PRF, using an explicit hash function. The
* `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that
* PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites
* rely on the SHA-256 based PRF, but some use SHA-384.
*
* The PRF always uses as input three parameters: a "secret" (some
* bytes), a "label" (ASCII string), and a "seed" (again some bytes). An
* arbitrary output length can be produced. The "seed" is provided as an
* arbitrary number of binary chunks, that gets internally concatenated.
*/
/**
* \brief Type for a seed chunk.
*
* Each chunk may have an arbitrary length, and may be empty (no byte at
* all). If the chunk length is zero, then the pointer to the chunk data
* may be `NULL`.
*/
typedef struct {
/**
* \brief Pointer to the chunk data.
*/
const void *data;
/**
* \brief Chunk length (in bytes).
*/
size_t len;
} br_tls_prf_seed_chunk;
/**
* \brief PRF implementation for TLS 1.0 and 1.1.
*
* This PRF is the one specified by TLS 1.0 and 1.1. It internally uses
* MD5 and SHA-1.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
void br_tls10_prf(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/**
* \brief PRF implementation for TLS 1.2, with SHA-256.
*
* This PRF is the one specified by TLS 1.2, when the underlying hash
* function is SHA-256.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
void br_tls12_sha256_prf(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/**
* \brief PRF implementation for TLS 1.2, with SHA-384.
*
* This PRF is the one specified by TLS 1.2, when the underlying hash
* function is SHA-384.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
void br_tls12_sha384_prf(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/**
* brief A convenient type name for a PRF implementation.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_AEAD_H__
#define BR_BEARSSL_AEAD_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_aead.h
*
* # Authenticated Encryption with Additional Data
*
* This file documents the API for AEAD encryption.
*
*
* ## Procedural API
*
* An AEAD algorithm processes messages and provides confidentiality
* (encryption) and checked integrity (MAC). It uses the following
* parameters:
*
* - A symmetric key. Exact size depends on the AEAD algorithm.
*
* - A nonce (IV). Size depends on the AEAD algorithm; for most
* algorithms, it is crucial for security that any given nonce
* value is never used twice for the same key and distinct
* messages.
*
* - Data to encrypt and protect.
*
* - Additional authenticated data, which is covered by the MAC but
* otherwise left untouched (i.e. not encrypted).
*
* The AEAD algorithm encrypts the data, and produces an authentication
* tag. It is assumed that the encrypted data, the tag, the additional
* authenticated data and the nonce are sent to the receiver; the
* additional data and the nonce may be implicit (e.g. using elements of
* the underlying transport protocol, such as record sequence numbers).
* The receiver will recompute the tag value and compare it with the one
* received; if they match, then the data is correct, and can be
* decrypted and used; otherwise, at least one of the elements was
* altered in transit, normally leading to wholesale rejection of the
* complete message.
*
* For each AEAD algorithm, identified by a symbolic name (hereafter
* denoted as "`xxx`"), the following functions are defined:
*
* - `br_xxx_init()`
*
* Initialise the AEAD algorithm, on a provided context structure.
* Exact parameters depend on the algorithm, and may include
* pointers to extra implementations and context structures. The
* secret key is provided at this point, either directly or
* indirectly.
*
* - `br_xxx_reset()`
*
* Start a new AEAD computation. The nonce value is provided as
* parameter to this function.
*
* - `br_xxx_aad_inject()`
*
* Inject some additional authenticated data. Additional data may
* be provided in several chunks of arbitrary length.
*
* - `br_xxx_flip()`
*
* This function MUST be called after injecting all additional
* authenticated data, and before beginning to encrypt the plaintext
* (or decrypt the ciphertext).
*
* - `br_xxx_run()`
*
* Process some plaintext (to encrypt) or ciphertext (to decrypt).
* Encryption/decryption is done in place. Data may be provided in
* several chunks of arbitrary length.
*
* - `br_xxx_get_tag()`
*
* Compute the authentication tag. All message data (encrypted or
* decrypted) must have been injected at that point. Also, this
* call may modify internal context elements, so it may be called
* only once for a given AEAD computation.
*
* - `br_xxx_check_tag()`
*
* An alternative to `br_xxx_get_tag()`, meant to be used by the
* receiver: the authentication tag is internally recomputed, and
* compared with the one provided as parameter.
*
* This API makes the following assumptions on the AEAD algorithm:
*
* - Encryption does not expand the size of the ciphertext; there is
* no padding. This is true of most modern AEAD modes such as GCM.
*
* - The additional authenticated data must be processed first,
* before the encrypted/decrypted data.
*
* - Nonce, plaintext and additional authenticated data all consist
* in an integral number of bytes. There is no provision to use
* elements whose length in bits is not a multiple of 8.
*
* Each AEAD algorithm has its own requirements and limits on the sizes
* of additional data and plaintext. This API does not provide any
* way to report invalid usage; it is up to the caller to ensure that
* the provided key, nonce, and data elements all fit the algorithm's
* requirements.
*
*
* ## Object-Oriented API
*
* Each context structure begins with a field (called `vtable`) that
* points to an instance of a structure that references the relevant
* functions through pointers. Each such structure contains the
* following:
*
* - `reset`
*
* Pointer to the reset function, that allows starting a new
* computation.
*
* - `aad_inject`
*
* Pointer to the additional authenticated data injection function.
*
* - `flip`
*
* Pointer to the function that transitions from additional data
* to main message data processing.
*
* - `get_tag`
*
* Pointer to the function that computes and returns the tag.
*
* - `check_tag`
*
* Pointer to the function that computes and verifies the tag against
* a received value.
*
* Note that there is no OOP method for context initialisation: the
* various AEAD algorithms have different requirements that would not
* map well to a single initialisation API.
*
* The OOP API is not provided for CCM, due to its specific requirements
* (length of plaintext must be known in advance).
*/
/**
* \brief Class type of an AEAD algorithm.
*/
typedef struct br_aead_class_ br_aead_class;
struct br_aead_class_ {
/**
* \brief Size (in bytes) of authentication tags created by
* this AEAD algorithm.
*/
size_t tag_size;
/**
* \brief Reset an AEAD context.
*
* This function resets an already initialised AEAD context for
* a new computation run. Implementations and keys are
* conserved. This function can be called at any time; it
* cancels any ongoing AEAD computation that uses the provided
* context structure.
* The provided IV is a _nonce_. Each AEAD algorithm has its
* own requirements on IV size and contents; for most of them,
* it is crucial to security that each nonce value is used
* only once for a given secret key.
*
* \param cc AEAD context structure.
* \param iv AEAD nonce to use.
* \param len AEAD nonce length (in bytes).
*/
void (*reset)(const br_aead_class **cc, const void *iv, size_t len);
/**
* \brief Inject additional authenticated data.
*
* The provided data is injected into a running AEAD
* computation. Additional data must be injected _before_ the
* call to `flip()`. Additional data can be injected in several
* chunks of arbitrary length.
*
* \param cc AEAD context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void (*aad_inject)(const br_aead_class **cc,
const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data.
*
* This function MUST be called before beginning the actual
* encryption or decryption (with `run()`), even if no
* additional authenticated data was injected. No additional
* authenticated data may be injected after this function call.
*
* \param cc AEAD context structure.
*/
void (*flip)(const br_aead_class **cc);
/**
* \brief Encrypt or decrypt some data.
*
* Data encryption or decryption can be done after `flip()` has
* been called on the context. If `encrypt` is non-zero, then
* the provided data shall be plaintext, and it is encrypted in
* place. Otherwise, the data shall be ciphertext, and it is
* decrypted in place.
*
* Data may be provided in several chunks of arbitrary length.
*
* \param cc AEAD context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void (*run)(const br_aead_class **cc, int encrypt,
void *data, size_t len);
/**
* \brief Compute authentication tag.
*
* Compute the AEAD authentication tag. The tag length depends
* on the AEAD algorithm; it is written in the provided `tag`
* buffer. This call terminates the AEAD run: no data may be
* processed with that AEAD context afterwards, until `reset()`
* is called to initiate a new AEAD run.
*
* The tag value must normally be sent along with the encrypted
* data. When decrypting, the tag value must be recomputed and
* compared with the received tag: if the two tag values differ,
* then either the tag or the encrypted data was altered in
* transit. As an alternative to this function, the
* `check_tag()` function may be used to compute and check the
* tag value.
*
* Tag length depends on the AEAD algorithm.
*
* \param cc AEAD context structure.
* \param tag destination buffer for the tag.
*/
void (*get_tag)(const br_aead_class **cc, void *tag);
/**
* \brief Compute and check authentication tag.
*
* This function is an alternative to `get_tag()`, and is
* normally used on the receiving end (i.e. when decrypting
* messages). The tag value is recomputed and compared with the
* provided tag value. If they match, 1 is returned; on
* mismatch, 0 is returned. A returned value of 0 means that the
* data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* Tag length depends on the AEAD algorithm.
*
* \param cc AEAD context structure.
* \param tag tag value to compare with.
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t (*check_tag)(const br_aead_class **cc, const void *tag);
/**
* \brief Compute authentication tag (with truncation).
*
* This function is similar to `get_tag()`, except that the tag
* length is provided. Some AEAD algorithms allow several tag
* lengths, usually by truncating the normal tag. Shorter tags
* mechanically increase success probability of forgeries.
* The range of allowed tag lengths depends on the algorithm.
*
* \param cc AEAD context structure.
* \param tag destination buffer for the tag.
* \param len tag length (in bytes).
*/
void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len);
/**
* \brief Compute and check authentication tag (with truncation).
*
* This function is similar to `check_tag()` except that it
* works over an explicit tag length. See `get_tag()` for a
* discussion of explicit tag lengths; the range of allowed tag
* lengths depends on the algorithm.
*
* \param cc AEAD context structure.
* \param tag tag value to compare with.
* \param len tag length (in bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t (*check_tag_trunc)(const br_aead_class **cc,
const void *tag, size_t len);
};
/**
* \brief Context structure for GCM.
*
* GCM is an AEAD mode that combines a block cipher in CTR mode with a
* MAC based on GHASH, to provide authenticated encryption:
*
* - Any block cipher with 16-byte blocks can be used with GCM.
*
* - The nonce can have any length, from 0 up to 2^64-1 bits; however,
* 96-bit nonces (12 bytes) are recommended (nonces with a length
* distinct from 12 bytes are internally hashed, which risks reusing
* nonce value with a small but not always negligible probability).
*
* - Additional authenticated data may have length up to 2^64-1 bits.
*
* - Message length may range up to 2^39-256 bits at most.
*
* - The authentication tag has length 16 bytes.
*
* The GCM initialisation function receives as parameter an
* _initialised_ block cipher implementation context, with the secret
* key already set. A pointer to that context will be kept within the
* GCM context structure. It is up to the caller to allocate and
* initialise that block cipher context.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_aead_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_block_ctr_class **bctx;
br_ghash gh;
unsigned char h[16];
unsigned char j0_1[12];
unsigned char buf[16];
unsigned char y[16];
uint32_t j0_2, jc;
uint64_t count_aad, count_ctr;
#endif
} br_gcm_context;
/**
* \brief Initialize a GCM context.
*
* A block cipher implementation, with its initialised context structure,
* is provided. The block cipher MUST use 16-byte blocks in CTR mode,
* and its secret key MUST have been already set in the provided context.
* A GHASH implementation must also be provided. The parameters are linked
* in the GCM context.
*
* After this function has been called, the `br_gcm_reset()` function must
* be called, to provide the IV for GCM computation.
*
* \param ctx GCM context structure.
* \param bctx block cipher context (already initialised with secret key).
* \param gh GHASH implementation.
*/
void br_gcm_init(br_gcm_context *ctx,
const br_block_ctr_class **bctx, br_ghash gh);
/**
* \brief Reset a GCM context.
*
* This function resets an already initialised GCM context for a new
* computation run. Implementations and keys are conserved. This function
* can be called at any time; it cancels any ongoing GCM computation that
* uses the provided context structure.
*
* The provided IV is a _nonce_. It is critical to GCM security that IV
* values are not repeated for the same encryption key. IV can have
* arbitrary length (up to 2^64-1 bits), but the "normal" length is
* 96 bits (12 bytes).
*
* \param ctx GCM context structure.
* \param iv GCM nonce to use.
* \param len GCM nonce length (in bytes).
*/
void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len);
/**
* \brief Inject additional authenticated data into GCM.
*
* The provided data is injected into a running GCM computation. Additional
* data must be injected _before_ the call to `br_gcm_flip()`.
* Additional data can be injected in several chunks of arbitrary length;
* the maximum total size of additional authenticated data is 2^64-1
* bits.
*
* \param ctx GCM context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data into GCM.
*
* This function MUST be called before beginning the actual encryption
* or decryption (with `br_gcm_run()`), even if no additional authenticated
* data was injected. No additional authenticated data may be injected
* after this function call.
*
* \param ctx GCM context structure.
*/
void br_gcm_flip(br_gcm_context *ctx);
/**
* \brief Encrypt or decrypt some data with GCM.
*
* Data encryption or decryption can be done after `br_gcm_flip()`
* has been called on the context. If `encrypt` is non-zero, then the
* provided data shall be plaintext, and it is encrypted in place.
* Otherwise, the data shall be ciphertext, and it is decrypted in place.
*
* Data may be provided in several chunks of arbitrary length. The maximum
* total length for data is 2^39-256 bits, i.e. about 65 gigabytes.
*
* \param ctx GCM context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len);
/**
* \brief Compute GCM authentication tag.
*
* Compute the GCM authentication tag. The tag is a 16-byte value which
* is written in the provided `tag` buffer. This call terminates the
* GCM run: no data may be processed with that GCM context afterwards,
* until `br_gcm_reset()` is called to initiate a new GCM run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_gcm_check_tag()` function can be used to
* compute and check the tag value.
*
* \param ctx GCM context structure.
* \param tag destination buffer for the tag (16 bytes).
*/
void br_gcm_get_tag(br_gcm_context *ctx, void *tag);
/**
* \brief Compute and check GCM authentication tag.
*
* This function is an alternative to `br_gcm_get_tag()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* \param ctx GCM context structure.
* \param tag tag value to compare with (16 bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag);
/**
* \brief Compute GCM authentication tag (with truncation).
*
* This function is similar to `br_gcm_get_tag()`, except that it allows
* the tag to be truncated to a smaller length. The intended tag length
* is provided as `len` (in bytes); it MUST be no more than 16, but
* it may be smaller. Note that decreasing tag length mechanically makes
* forgeries easier; NIST SP 800-38D specifies that the tag length shall
* lie between 12 and 16 bytes (inclusive), but may be truncated down to
* 4 or 8 bytes, for specific applications that can tolerate it. It must
* also be noted that successful forgeries leak information on the
* authentication key, making subsequent forgeries easier. Therefore,
* tag truncation, and in particular truncation to sizes lower than 12
* bytes, shall be envisioned only with great care.
*
* The tag is written in the provided `tag` buffer. This call terminates
* the GCM run: no data may be processed with that GCM context
* afterwards, until `br_gcm_reset()` is called to initiate a new GCM
* run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_gcm_check_tag_trunc()` function can be used to
* compute and check the tag value.
*
* \param ctx GCM context structure.
* \param tag destination buffer for the tag.
* \param len tag length (16 bytes or less).
*/
void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len);
/**
* \brief Compute and check GCM authentication tag (with truncation).
*
* This function is an alternative to `br_gcm_get_tag_trunc()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* Tag length MUST be 16 bytes or less. The normal GCM tag length is 16
* bytes. See `br_check_tag_trunc()` for some discussion on the potential
* perils of truncating authentication tags.
*
* \param ctx GCM context structure.
* \param tag tag value to compare with.
* \param len tag length (in bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx,
const void *tag, size_t len);
/**
* \brief Class instance for GCM.
*/
extern const br_aead_class br_gcm_vtable;
/**
* \brief Context structure for EAX.
*
* EAX is an AEAD mode that combines a block cipher in CTR mode with
* CBC-MAC using the same block cipher and the same key, to provide
* authenticated encryption:
*
* - Any block cipher with 16-byte blocks can be used with EAX
* (technically, other block sizes are defined as well, but this
* is not implemented by these functions; shorter blocks also
* imply numerous security issues).
*
* - The nonce can have any length, as long as nonce values are
* not reused (thus, if nonces are randomly selected, the nonce
* size should be such that reuse probability is negligible).
*
* - Additional authenticated data length is unlimited.
*
* - Message length is unlimited.
*
* - The authentication tag has length 16 bytes.
*
* The EAX initialisation function receives as parameter an
* _initialised_ block cipher implementation context, with the secret
* key already set. A pointer to that context will be kept within the
* EAX context structure. It is up to the caller to allocate and
* initialise that block cipher context.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_aead_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_block_ctrcbc_class **bctx;
unsigned char L2[16];
unsigned char L4[16];
unsigned char nonce[16];
unsigned char head[16];
unsigned char ctr[16];
unsigned char cbcmac[16];
unsigned char buf[16];
size_t ptr;
#endif
} br_eax_context;
/**
* \brief EAX captured state.
*
* Some internal values computed by EAX may be captured at various
* points, and reused for another EAX run with the same secret key,
* for lower per-message overhead. Captured values do not depend on
* the nonce.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
unsigned char st[3][16];
#endif
} br_eax_state;
/**
* \brief Initialize an EAX context.
*
* A block cipher implementation, with its initialised context
* structure, is provided. The block cipher MUST use 16-byte blocks in
* CTR + CBC-MAC mode, and its secret key MUST have been already set in
* the provided context. The parameters are linked in the EAX context.
*
* After this function has been called, the `br_eax_reset()` function must
* be called, to provide the nonce for EAX computation.
*
* \param ctx EAX context structure.
* \param bctx block cipher context (already initialised with secret key).
*/
void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx);
/**
* \brief Capture pre-AAD state.
*
* This function precomputes key-dependent data, and stores it in the
* provided `st` structure. This structure should then be used with
* `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()`
* and then used with `br_eax_reset_post_aad()`.
*
* The EAX context structure is unmodified by this call.
*
* \param ctx EAX context structure.
* \param st recipient for captured state.
*/
void br_eax_capture(const br_eax_context *ctx, br_eax_state *st);
/**
* \brief Reset an EAX context.
*
* This function resets an already initialised EAX context for a new
* computation run. Implementations and keys are conserved. This function
* can be called at any time; it cancels any ongoing EAX computation that
* uses the provided context structure.
*
* It is critical to EAX security that nonce values are not repeated for
* the same encryption key. Nonces can have arbitrary length. If nonces
* are randomly generated, then a nonce length of at least 128 bits (16
* bytes) is recommended, to make nonce reuse probability sufficiently
* low.
*
* \param ctx EAX context structure.
* \param nonce EAX nonce to use.
* \param len EAX nonce length (in bytes).
*/
void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len);
/**
* \brief Reset an EAX context with a pre-AAD captured state.
*
* This function is an alternative to `br_eax_reset()`, that reuses a
* previously captured state structure for lower per-message overhead.
* The state should have been populated with `br_eax_capture_state()`
* but not updated with `br_eax_get_aad_mac()`.
*
* After this function is called, additional authenticated data MUST
* be injected. At least one byte of additional authenticated data
* MUST be provided with `br_eax_aad_inject()`; computation result will
* be incorrect if `br_eax_flip()` is called right away.
*
* After injection of the AAD and call to `br_eax_flip()`, at least
* one message byte must be provided. Empty messages are not supported
* with this reset mode.
*
* \param ctx EAX context structure.
* \param st pre-AAD captured state.
* \param nonce EAX nonce to use.
* \param len EAX nonce length (in bytes).
*/
void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
const void *nonce, size_t len);
/**
* \brief Reset an EAX context with a post-AAD captured state.
*
* This function is an alternative to `br_eax_reset()`, that reuses a
* previously captured state structure for lower per-message overhead.
* The state should have been populated with `br_eax_capture_state()`
* and then updated with `br_eax_get_aad_mac()`.
*
* After this function is called, message data MUST be injected. The
* `br_eax_flip()` function MUST NOT be called. At least one byte of
* message data MUST be provided with `br_eax_run()`; empty messages
* are not supported with this reset mode.
*
* \param ctx EAX context structure.
* \param st post-AAD captured state.
* \param nonce EAX nonce to use.
* \param len EAX nonce length (in bytes).
*/
void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
const void *nonce, size_t len);
/**
* \brief Inject additional authenticated data into EAX.
*
* The provided data is injected into a running EAX computation. Additional
* data must be injected _before_ the call to `br_eax_flip()`.
* Additional data can be injected in several chunks of arbitrary length;
* the total amount of additional authenticated data is unlimited.
*
* \param ctx EAX context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data into EAX.
*
* This function MUST be called before beginning the actual encryption
* or decryption (with `br_eax_run()`), even if no additional authenticated
* data was injected. No additional authenticated data may be injected
* after this function call.
*
* \param ctx EAX context structure.
*/
void br_eax_flip(br_eax_context *ctx);
/**
* \brief Obtain a copy of the MAC on additional authenticated data.
*
* This function may be called only after `br_eax_flip()`; it copies the
* AAD-specific MAC value into the provided state. The MAC value depends
* on the secret key and the additional data itself, but not on the
* nonce. The updated state `st` is meant to be used as parameter for a
* further `br_eax_reset_post_aad()` call.
*
* \param ctx EAX context structure.
* \param st captured state to update.
*/
static inline void
br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st)
{
memcpy(st->st[1], ctx->head, sizeof ctx->head);
}
/**
* \brief Encrypt or decrypt some data with EAX.
*
* Data encryption or decryption can be done after `br_eax_flip()`
* has been called on the context. If `encrypt` is non-zero, then the
* provided data shall be plaintext, and it is encrypted in place.
* Otherwise, the data shall be ciphertext, and it is decrypted in place.
*
* Data may be provided in several chunks of arbitrary length.
*
* \param ctx EAX context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len);
/**
* \brief Compute EAX authentication tag.
*
* Compute the EAX authentication tag. The tag is a 16-byte value which
* is written in the provided `tag` buffer. This call terminates the
* EAX run: no data may be processed with that EAX context afterwards,
* until `br_eax_reset()` is called to initiate a new EAX run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_eax_check_tag()` function can be used to
* compute and check the tag value.
*
* \param ctx EAX context structure.
* \param tag destination buffer for the tag (16 bytes).
*/
void br_eax_get_tag(br_eax_context *ctx, void *tag);
/**
* \brief Compute and check EAX authentication tag.
*
* This function is an alternative to `br_eax_get_tag()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* \param ctx EAX context structure.
* \param tag tag value to compare with (16 bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag);
/**
* \brief Compute EAX authentication tag (with truncation).
*
* This function is similar to `br_eax_get_tag()`, except that it allows
* the tag to be truncated to a smaller length. The intended tag length
* is provided as `len` (in bytes); it MUST be no more than 16, but
* it may be smaller. Note that decreasing tag length mechanically makes
* forgeries easier; NIST SP 800-38D specifies that the tag length shall
* lie between 12 and 16 bytes (inclusive), but may be truncated down to
* 4 or 8 bytes, for specific applications that can tolerate it. It must
* also be noted that successful forgeries leak information on the
* authentication key, making subsequent forgeries easier. Therefore,
* tag truncation, and in particular truncation to sizes lower than 12
* bytes, shall be envisioned only with great care.
*
* The tag is written in the provided `tag` buffer. This call terminates
* the EAX run: no data may be processed with that EAX context
* afterwards, until `br_eax_reset()` is called to initiate a new EAX
* run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_eax_check_tag_trunc()` function can be used to
* compute and check the tag value.
*
* \param ctx EAX context structure.
* \param tag destination buffer for the tag.
* \param len tag length (16 bytes or less).
*/
void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len);
/**
* \brief Compute and check EAX authentication tag (with truncation).
*
* This function is an alternative to `br_eax_get_tag_trunc()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* Tag length MUST be 16 bytes or less. The normal EAX tag length is 16
* bytes. See `br_check_tag_trunc()` for some discussion on the potential
* perils of truncating authentication tags.
*
* \param ctx EAX context structure.
* \param tag tag value to compare with.
* \param len tag length (in bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_eax_check_tag_trunc(br_eax_context *ctx,
const void *tag, size_t len);
/**
* \brief Class instance for EAX.
*/
extern const br_aead_class br_eax_vtable;
/**
* \brief Context structure for CCM.
*
* CCM is an AEAD mode that combines a block cipher in CTR mode with
* CBC-MAC using the same block cipher and the same key, to provide
* authenticated encryption:
*
* - Any block cipher with 16-byte blocks can be used with CCM
* (technically, other block sizes are defined as well, but this
* is not implemented by these functions; shorter blocks also
* imply numerous security issues).
*
* - The authentication tag length, and plaintext length, MUST be
* known when starting processing data. Plaintext and ciphertext
* can still be provided by chunks, but the total size must match
* the value provided upon initialisation.
*
* - The nonce length is constrained between 7 and 13 bytes (inclusive).
* Furthermore, the plaintext length, when encoded, must fit over
* 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then
* the plaintext length cannot exceed 65535 bytes.
*
* - Additional authenticated data length is practically unlimited
* (formal limit is at 2^64 bytes).
*
* - The authentication tag has length 4 to 16 bytes (even values only).
*
* The CCM initialisation function receives as parameter an
* _initialised_ block cipher implementation context, with the secret
* key already set. A pointer to that context will be kept within the
* CCM context structure. It is up to the caller to allocate and
* initialise that block cipher context.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
const br_block_ctrcbc_class **bctx;
unsigned char ctr[16];
unsigned char cbcmac[16];
unsigned char tagmask[16];
unsigned char buf[16];
size_t ptr;
size_t tag_len;
#endif
} br_ccm_context;
/**
* \brief Initialize a CCM context.
*
* A block cipher implementation, with its initialised context
* structure, is provided. The block cipher MUST use 16-byte blocks in
* CTR + CBC-MAC mode, and its secret key MUST have been already set in
* the provided context. The parameters are linked in the CCM context.
*
* After this function has been called, the `br_ccm_reset()` function must
* be called, to provide the nonce for CCM computation.
*
* \param ctx CCM context structure.
* \param bctx block cipher context (already initialised with secret key).
*/
void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx);
/**
* \brief Reset a CCM context.
*
* This function resets an already initialised CCM context for a new
* computation run. Implementations and keys are conserved. This function
* can be called at any time; it cancels any ongoing CCM computation that
* uses the provided context structure.
*
* The `aad_len` parameter contains the total length, in bytes, of the
* additional authenticated data. It may be zero. That length MUST be
* exact.
*
* The `data_len` parameter contains the total length, in bytes, of the
* data that will be injected (plaintext or ciphertext). That length MUST
* be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)).
*
* The nonce length (`nonce_len`), in bytes, must be in the 7..13 range
* (inclusive).
*
* The tag length (`tag_len`), in bytes, must be in the 4..16 range, and
* be an even integer. Short tags mechanically allow for higher forgery
* probabilities; hence, tag sizes smaller than 12 bytes shall be used only
* with care.
*
* It is critical to CCM security that nonce values are not repeated for
* the same encryption key. Random generation of nonces is not generally
* recommended, due to the relatively small maximum nonce value.
*
* Returned value is 1 on success, 0 on error. An error is reported if
* the tag or nonce length is out of range, or if the
* plaintext/ciphertext length cannot be encoded with the specified
* nonce length.
*
* \param ctx CCM context structure.
* \param nonce CCM nonce to use.
* \param nonce_len CCM nonce length (in bytes, 7 to 13).
* \param aad_len additional authenticated data length (in bytes).
* \param data_len plaintext/ciphertext length (in bytes).
* \param tag_len tag length (in bytes).
* \return 1 on success, 0 on error.
*/
int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len,
uint64_t aad_len, uint64_t data_len, size_t tag_len);
/**
* \brief Inject additional authenticated data into CCM.
*
* The provided data is injected into a running CCM computation. Additional
* data must be injected _before_ the call to `br_ccm_flip()`.
* Additional data can be injected in several chunks of arbitrary length,
* but the total amount MUST exactly match the value which was provided
* to `br_ccm_reset()`.
*
* \param ctx CCM context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data into CCM.
*
* This function MUST be called before beginning the actual encryption
* or decryption (with `br_ccm_run()`), even if no additional authenticated
* data was injected. No additional authenticated data may be injected
* after this function call.
*
* \param ctx CCM context structure.
*/
void br_ccm_flip(br_ccm_context *ctx);
/**
* \brief Encrypt or decrypt some data with CCM.
*
* Data encryption or decryption can be done after `br_ccm_flip()`
* has been called on the context. If `encrypt` is non-zero, then the
* provided data shall be plaintext, and it is encrypted in place.
* Otherwise, the data shall be ciphertext, and it is decrypted in place.
*
* Data may be provided in several chunks of arbitrary length, provided
* that the total length exactly matches the length provided to the
* `br_ccm_reset()` call.
*
* \param ctx CCM context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len);
/**
* \brief Compute CCM authentication tag.
*
* Compute the CCM authentication tag. This call terminates the CCM
* run: all data must have been injected with `br_ccm_run()` (in zero,
* one or more successive calls). After this function has been called,
* no more data can br processed; a `br_ccm_reset()` call is required
* to start a new message.
*
* The tag length was provided upon context initialisation (last call
* to `br_ccm_reset()`); it is returned by this function.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_ccm_check_tag()` function can be used to
* compute and check the tag value.
*
* \param ctx CCM context structure.
* \param tag destination buffer for the tag (up to 16 bytes).
* \return the tag length (in bytes).
*/
size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag);
/**
* \brief Compute and check CCM authentication tag.
*
* This function is an alternative to `br_ccm_get_tag()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* \param ctx CCM context structure.
* \param tag tag value to compare with (up to 16 bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_RSA_H__
#define BR_BEARSSL_RSA_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_rsa.h
*
* # RSA
*
* This file documents the RSA implementations provided with BearSSL.
* Note that the SSL engine accesses these implementations through a
* configurable API, so it is possible to, for instance, run a SSL
* server which uses a RSA engine which is not based on this code.
*
* ## Key Elements
*
* RSA public and private keys consist in lists of big integers. All
* such integers are represented with big-endian unsigned notation:
* first byte is the most significant, and the value is positive (so
* there is no dedicated "sign bit"). Public and private key structures
* thus contain, for each such integer, a pointer to the first value byte
* (`unsigned char *`), and a length (`size_t`) which is the number of
* relevant bytes. As a general rule, minimal-length encoding is not
* enforced: values may have extra leading bytes of value 0.
*
* RSA public keys consist in two integers:
*
* - the modulus (`n`);
* - the public exponent (`e`).
*
* RSA private keys, as defined in
* [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers:
*
* - the modulus (`n`);
* - the public exponent (`e`);
* - the private exponent (`d`);
* - the first prime factor (`p`);
* - the second prime factor (`q`);
* - the first reduced exponent (`dp`, which is `d` modulo `p-1`);
* - the second reduced exponent (`dq`, which is `d` modulo `q-1`);
* - the CRT coefficient (`iq`, the inverse of `q` modulo `p`).
*
* However, the implementations defined in BearSSL use only five of
* these integers: `p`, `q`, `dp`, `dq` and `iq`.
*
* ## Security Features and Limitations
*
* The implementations contained in BearSSL have the following limitations
* and features:
*
* - They are constant-time. This means that the execution time and
* memory access pattern may depend on the _lengths_ of the private
* key components, but not on their value, nor on the value of
* the operand. Note that this property is not achieved through
* random masking, but "true" constant-time code.
*
* - They support only private keys with two prime factors. RSA private
* keys with three or more prime factors are nominally supported, but
* rarely used; they may offer faster operations, at the expense of
* more code and potentially a reduction in security if there are
* "too many" prime factors.
*
* - The public exponent may have arbitrary length. Of course, it is
* a good idea to keep public exponents small, so that public key
* operations are fast; but, contrary to some widely deployed
* implementations, BearSSL has no problem with public exponents
* longer than 32 bits.
*
* - The two prime factors of the modulus need not have the same length
* (but severely imbalanced factor lengths might reduce security).
* Similarly, there is no requirement that the first factor (`p`)
* be greater than the second factor (`q`).
*
* - Prime factors and modulus must be smaller than a compile-time limit.
* This is made necessary by the use of fixed-size stack buffers, and
* the limit has been adjusted to keep stack usage under 2 kB for the
* RSA operations. Currently, the maximum modulus size is 4096 bits,
* and the maximum prime factor size is 2080 bits.
*
* - The RSA functions themselves do not enforce lower size limits,
* except that which is absolutely necessary for the operation to
* mathematically make sense (e.g. a PKCS#1 v1.5 signature with
* SHA-1 requires a modulus of at least 361 bits). It is up to users
* of this code to enforce size limitations when appropriate (e.g.
* the X.509 validation engine, by default, rejects RSA keys of
* less than 1017 bits).
*
* - Within the size constraints expressed above, arbitrary bit lengths
* are supported. There is no requirement that prime factors or
* modulus have a size multiple of 8 or 16.
*
* - When verifying PKCS#1 v1.5 signatures, both variants of the hash
* function identifying header (with and without the ASN.1 NULL) are
* supported. When producing such signatures, the variant with the
* ASN.1 NULL is used.
*
* ## Implementations
*
* Three RSA implementations are included:
*
* - The **i32** implementation internally represents big integers
* as arrays of 32-bit integers. It is perfunctory and portable,
* but not very efficient.
*
* - The **i31** implementation uses 32-bit integers, each containing
* 31 bits worth of integer data. The i31 implementation is somewhat
* faster than the i32 implementation (the reduced integer size makes
* carry propagation easier) for a similar code footprint, but uses
* very slightly larger stack buffers (about 4% bigger).
*
* - The **i62** implementation is similar to the i31 implementation,
* except that it internally leverages the 64x64->128 multiplication
* opcode. This implementation is available only on architectures
* where such an opcode exists. It is much faster than i31.
*
* - The **i15** implementation uses 16-bit integers, each containing
* 15 bits worth of integer data. Multiplication results fit on
* 32 bits, so this won't use the "widening" multiplication routine
* on ARM Cortex M0/M0+, for much better performance and constant-time
* execution.
*/
/**
* \brief RSA public key.
*
* The structure references the modulus and the public exponent. Both
* integers use unsigned big-endian representation; extra leading bytes
* of value 0 are allowed.
*/
typedef struct {
/** \brief Modulus. */
unsigned char *n;
/** \brief Modulus length (in bytes). */
size_t nlen;
/** \brief Public exponent. */
unsigned char *e;
/** \brief Public exponent length (in bytes). */
size_t elen;
} br_rsa_public_key;
/**
* \brief RSA private key.
*
* The structure references the private factors, reduced private
* exponents, and CRT coefficient. It also contains the bit length of
* the modulus. The big integers use unsigned big-endian representation;
* extra leading bytes of value 0 are allowed. However, the modulus bit
* length (`n_bitlen`) MUST be exact.
*/
typedef struct {
/** \brief Modulus bit length (in bits, exact value). */
uint32_t n_bitlen;
/** \brief First prime factor. */
unsigned char *p;
/** \brief First prime factor length (in bytes). */
size_t plen;
/** \brief Second prime factor. */
unsigned char *q;
/** \brief Second prime factor length (in bytes). */
size_t qlen;
/** \brief First reduced private exponent. */
unsigned char *dp;
/** \brief First reduced private exponent length (in bytes). */
size_t dplen;
/** \brief Second reduced private exponent. */
unsigned char *dq;
/** \brief Second reduced private exponent length (in bytes). */
size_t dqlen;
/** \brief CRT coefficient. */
unsigned char *iq;
/** \brief CRT coefficient length (in bytes). */
size_t iqlen;
} br_rsa_private_key;
/**
* \brief Type for a RSA public key engine.
*
* The public key engine performs the modular exponentiation of the
* provided value with the public exponent. The value is modified in
* place.
*
* The value length (`xlen`) is verified to have _exactly_ the same
* length as the modulus (actual modulus length, without extra leading
* zeros in the modulus representation in memory). If the length does
* not match, then this function returns 0 and `x[]` is unmodified.
*
* It `xlen` is correct, then `x[]` is modified. Returned value is 1
* on success, 0 on error. Error conditions include an oversized `x[]`
* (the array has the same length as the modulus, but the numerical value
* is not lower than the modulus) and an invalid modulus (e.g. an even
* integer). If an error is reported, then the new contents of `x[]` are
* unspecified.
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief Type for a RSA signature verification engine (PKCS#1 v1.5).
*
* Parameters are:
*
* - The signature itself. The provided array is NOT modified.
*
* - The encoded OID for the hash function. The provided array must begin
* with a single byte that contains the length of the OID value (in
* bytes), followed by exactly that many bytes. This parameter may
* also be `NULL`, in which case the raw hash value should be used
* with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up
* to TLS-1.1, with a 36-byte hash value).
*
* - The hash output length, in bytes.
*
* - The public key.
*
* - An output buffer for the hash value. The caller must still compare
* it with the hash of the data over which the signature is computed.
*
* **Constraints:**
*
* - Hash length MUST be no more than 64 bytes.
*
* - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]`
* must have a value in the 0..32 range, inclusive).
*
* This function verifies that the signature length (`xlen`) matches the
* modulus length (this function returns 0 on mismatch). If the modulus
* size exceeds the maximum supported RSA size, then the function also
* returns 0.
*
* Returned value is 1 on success, 0 on error.
*
* Implementations of this type need not be constant-time.
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief Type for a RSA signature verification engine (PSS).
*
* Parameters are:
*
* - The signature itself. The provided array is NOT modified.
*
* - The hash function which was used to hash the message.
*
* - The hash function to use with MGF1 within the PSS padding. This
* is not necessarily the same hash function as the one which was
* used to hash the signed message.
*
* - The hashed message (as an array of bytes).
*
* - The PSS salt length (in bytes).
*
* - The public key.
*
* **Constraints:**
*
* - Hash message length MUST be no more than 64 bytes.
*
* Note that, contrary to PKCS#1 v1.5 signature, the hash value of the
* signed data cannot be extracted from the signature; it must be
* provided to the verification function.
*
* This function verifies that the signature length (`xlen`) matches the
* modulus length (this function returns 0 on mismatch). If the modulus
* size exceeds the maximum supported RSA size, then the function also
* returns 0.
*
* Returned value is 1 on success, 0 on error.
*
* Implementations of this type need not be constant-time.
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief Type for a RSA encryption engine (OAEP).
*
* Parameters are:
*
* - A source of random bytes. The source must be already initialized.
*
* - A hash function, used internally with the mask generation function
* (MGF1).
*
* - A label. The `label` pointer may be `NULL` if `label_len` is zero
* (an empty label, which is the default in PKCS#1 v2.2).
*
* - The public key.
*
* - The destination buffer. Its maximum length (in bytes) is provided;
* if that length is lower than the public key length, then an error
* is reported.
*
* - The source message.
*
* The encrypted message output has exactly the same length as the modulus
* (mathematical length, in bytes, not counting extra leading zeros in the
* modulus representation in the public key).
*
* The source message (`src`, length `src_len`) may overlap with the
* destination buffer (`dst`, length `dst_max_len`).
*
* This function returns the actual encrypted message length, in bytes;
* on error, zero is returned. An error is reported if the output buffer
* is not large enough, or the public is invalid, or the public key
* modulus exceeds the maximum supported RSA size.
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
typedef size_t (*br_rsa_oaep_encrypt)(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief Type for a RSA private key engine.
*
* The `x[]` buffer is modified in place, and its length is inferred from
* the modulus length (`x[]` is assumed to have a length of
* `(sk->n_bitlen+7)/8` bytes).
*
* Returned value is 1 on success, 0 on error.
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_private)(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief Type for a RSA signature generation engine (PKCS#1 v1.5).
*
* Parameters are:
*
* - The encoded OID for the hash function. The provided array must begin
* with a single byte that contains the length of the OID value (in
* bytes), followed by exactly that many bytes. This parameter may
* also be `NULL`, in which case the raw hash value should be used
* with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up
* to TLS-1.1, with a 36-byte hash value).
*
* - The hash value computes over the data to sign (its length is
* expressed in bytes).
*
* - The RSA private key.
*
* - The output buffer, that receives the signature.
*
* Returned value is 1 on success, 0 on error. Error conditions include
* a too small modulus for the provided hash OID and value, or some
* invalid key parameters. The signature length is exactly
* `(sk->n_bitlen+7)/8` bytes.
*
* This function is expected to be constant-time with regards to the
* private key bytes (lengths of the modulus and the individual factors
* may leak, though) and to the hashed data.
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Type for a RSA signature generation engine (PSS).
*
* Parameters are:
*
* - An initialized PRNG for salt generation. If the salt length is
* zero (`salt_len` parameter), then the PRNG is optional (this is
* not the typical case, as the security proof of RSA/PSS is
* tighter when a non-empty salt is used).
*
* - The hash function which was used to hash the message.
*
* - The hash function to use with MGF1 within the PSS padding. This
* is not necessarily the same function as the one used to hash the
* message.
*
* - The hashed message.
*
* - The salt length, in bytes.
*
* - The RSA private key.
*
* - The output buffer, that receives the signature.
*
* Returned value is 1 on success, 0 on error. Error conditions include
* a too small modulus for the provided hash and salt lengths, or some
* invalid key parameters. The signature length is exactly
* `(sk->n_bitlen+7)/8` bytes.
*
* This function is expected to be constant-time with regards to the
* private key bytes (lengths of the modulus and the individual factors
* may leak, though) and to the hashed data.
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA1 \
((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A")
/**
* \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA224 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04")
/**
* \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA256 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
/**
* \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA384 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02")
/**
* \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA512 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
/**
* \brief Type for a RSA decryption engine (OAEP).
*
* Parameters are:
*
* - A hash function, used internally with the mask generation function
* (MGF1).
*
* - A label. The `label` pointer may be `NULL` if `label_len` is zero
* (an empty label, which is the default in PKCS#1 v2.2).
*
* - The private key.
*
* - The source and destination buffer. The buffer initially contains
* the encrypted message; the buffer contents are altered, and the
* decrypted message is written at the start of that buffer
* (decrypted message is always shorter than the encrypted message).
*
* If decryption fails in any way, then `*len` is unmodified, and the
* function returns 0. Otherwise, `*len` is set to the decrypted message
* length, and 1 is returned. The implementation is responsible for
* checking that the input message length matches the key modulus length,
* and that the padding is correct.
*
* Implementations MUST use constant-time check of the validity of the
* OAEP padding, at least until the leading byte and hash value have
* been checked. Whether overall decryption worked, and the length of
* the decrypted message, may leak.
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_oaep_decrypt)(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/*
* RSA "i32" engine. Integers are internally represented as arrays of
* 32-bit integers, and the core multiplication primitive is the
* 32x32->64 multiplication.
*/
/**
* \brief RSA public key engine "i32".
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i32" (PSS signatures).
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i32".
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i32" (PSS signatures).
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/*
* RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit
* word. This uses slightly more stack space (about 4% more) and code
* space, but it quite faster.
*/
/**
* \brief RSA public key engine "i31".
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i31" (PSS signatures).
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i31".
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i31" (PSS signatures).
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/*
* RSA "i62" engine. Similar to i31, but internal multiplication use
* 64x64->128 multiplications. This is available only on architecture
* that offer such an opcode.
*/
/**
* \brief RSA public key engine "i62".
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i62" (PSS signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i62".
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i62" (PSS signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Get the RSA "i62" implementation (public key operations),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_public br_rsa_i62_public_get(void);
/**
* \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void);
/**
* \brief Get the RSA "i62" implementation (PSS signature verification),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void);
/**
* \brief Get the RSA "i62" implementation (private key operations),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_private br_rsa_i62_private_get(void);
/**
* \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void);
/**
* \brief Get the RSA "i62" implementation (PSS signature generation),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pss_sign br_rsa_i62_pss_sign_get(void);
/**
* \brief Get the RSA "i62" implementation (OAEP encryption),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void);
/**
* \brief Get the RSA "i62" implementation (OAEP decryption),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void);
/*
* RSA "i15" engine. Integers are represented as 15-bit integers, so
* the code uses only 32-bit multiplication (no 64-bit result), which
* is vastly faster (and constant-time) on the ARM Cortex M0/M0+.
*/
/**
* \brief RSA public key engine "i15".
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i15" (PSS signatures).
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i15".
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i15" (PSS signatures).
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Get "default" RSA implementation (public-key operations).
*
* This returns the preferred implementation of RSA (public-key operations)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_public br_rsa_public_get_default(void);
/**
* \brief Get "default" RSA implementation (private-key operations).
*
* This returns the preferred implementation of RSA (private-key operations)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_private br_rsa_private_get_default(void);
/**
* \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification).
*
* This returns the preferred implementation of RSA (signature verification)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void);
/**
* \brief Get "default" RSA implementation (PSS signature verification).
*
* This returns the preferred implementation of RSA (signature verification)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void);
/**
* \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation).
*
* This returns the preferred implementation of RSA (signature generation)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void);
/**
* \brief Get "default" RSA implementation (PSS signature generation).
*
* This returns the preferred implementation of RSA (signature generation)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pss_sign br_rsa_pss_sign_get_default(void);
/**
* \brief Get "default" RSA implementation (OAEP encryption).
*
* This returns the preferred implementation of RSA (OAEP encryption)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void);
/**
* \brief Get "default" RSA implementation (OAEP decryption).
*
* This returns the preferred implementation of RSA (OAEP decryption)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void);
/**
* \brief RSA decryption helper, for SSL/TLS.
*
* This function performs the RSA decryption for a RSA-based key exchange
* in a SSL/TLS server. The provided RSA engine is used. The `data`
* parameter points to the value to decrypt, of length `len` bytes. On
* success, the 48-byte pre-master secret is copied into `data`, starting
* at the first byte of that buffer; on error, the contents of `data`
* become indeterminate.
*
* This function first checks that the provided value length (`len`) is
* not lower than 59 bytes, and matches the RSA modulus length; if neither
* of this property is met, then this function returns 0 and the buffer
* is unmodified.
*
* Otherwise, decryption and then padding verification are performed, both
* in constant-time. A decryption error, or a bad padding, or an
* incorrect decrypted value length are reported with a returned value of
* 0; on success, 1 is returned. The caller (SSL server engine) is supposed
* to proceed with a random pre-master secret in case of error.
*
* \param core RSA private key engine.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len length (in bytes) of the data to decrypt.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
unsigned char *data, size_t len);
/**
* \brief RSA encryption (OAEP) with the "i15" engine.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i15_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i15" engine.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief RSA encryption (OAEP) with the "i31" engine.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i31_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i31" engine.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief RSA encryption (OAEP) with the "i32" engine.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i32_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i32" engine.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief RSA encryption (OAEP) with the "i62" engine.
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i62_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i62" engine.
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief Get buffer size to hold RSA private key elements.
*
* This macro returns the length (in bytes) of the buffer needed to
* receive the elements of a RSA private key, as generated by one of
* the `br_rsa_*_keygen()` functions. If the provided size is a constant
* expression, then the whole macro evaluates to a constant expression.
*
* \param size target key size (modulus size, in bits)
* \return the length of the private key buffer, in bytes.
*/
#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4))
/**
* \brief Get buffer size to hold RSA public key elements.
*
* This macro returns the length (in bytes) of the buffer needed to
* receive the elements of a RSA public key, as generated by one of
* the `br_rsa_*_keygen()` functions. If the provided size is a constant
* expression, then the whole macro evaluates to a constant expression.
*
* \param size target key size (modulus size, in bits)
* \return the length of the public key buffer, in bytes.
*/
#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3))
/**
* \brief Type for RSA key pair generator implementation.
*
* This function generates a new RSA key pair whose modulus has bit
* length `size` bits. The private key elements are written in the
* `kbuf_priv` buffer, and pointer values and length fields to these
* elements are populated in the provided private key structure `sk`.
* Similarly, the public key elements are written in `kbuf_pub`, with
* pointers and lengths set in `pk`.
*
* If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the
* private key is set.
*
* If `pubexp` is not zero, then its value will be used as public
* exponent. Valid RSA public exponent values are odd integers
* greater than 1. If `pubexp` is zero, then the public exponent will
* have value 3.
*
* The provided PRNG (`rng_ctx`) must have already been initialized
* and seeded.
*
* Returned value is 1 on success, 0 on error. An error is reported
* if the requested range is outside of the supported key sizes, or
* if an invalid non-zero public exponent value is provided. Supported
* range starts at 512 bits, and up to an implementation-defined
* maximum (by default 4096 bits). Note that key sizes up to 768 bits
* have been broken in practice, and sizes lower than 2048 bits are
* usually considered to be weak and should not be used.
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
typedef uint32_t (*br_rsa_keygen)(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief RSA key pair generation with the "i15" engine.
*
* \see br_rsa_keygen
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
uint32_t br_rsa_i15_keygen(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief RSA key pair generation with the "i31" engine.
*
* \see br_rsa_keygen
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
uint32_t br_rsa_i31_keygen(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief RSA key pair generation with the "i62" engine.
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_keygen
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
uint32_t br_rsa_i62_keygen(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief Get the RSA "i62" implementation (key pair generation),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_keygen br_rsa_i62_keygen_get(void);
/**
* \brief Get "default" RSA implementation (key pair generation).
*
* This returns the preferred implementation of RSA (key pair generation)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_keygen br_rsa_keygen_get_default(void);
/**
* \brief Type for a modulus computing function.
*
* Such a function computes the public modulus from the private key. The
* encoded modulus (unsigned big-endian) is written on `n`, and the size
* (in bytes) is returned. If `n` is `NULL`, then the size is returned but
* the modulus itself is not computed.
*
* If the key size exceeds an internal limit, 0 is returned.
*
* \param n destination buffer (or `NULL`).
* \param sk RSA private key.
* \return the modulus length (in bytes), or 0.
*/
typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk);
/**
* \brief Recompute RSA modulus ("i15" engine).
*
* \see br_rsa_compute_modulus
*
* \param n destination buffer (or `NULL`).
* \param sk RSA private key.
* \return the modulus length (in bytes), or 0.
*/
size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk);
/**
* \brief Recompute RSA modulus ("i31" engine).
*
* \see br_rsa_compute_modulus
*
* \param n destination buffer (or `NULL`).
* \param sk RSA private key.
* \return the modulus length (in bytes), or 0.
*/
size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk);
/**
* \brief Get "default" RSA implementation (recompute modulus).
*
* This returns the preferred implementation of RSA (recompute modulus)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void);
/**
* \brief Type for a public exponent computing function.
*
* Such a function recomputes the public exponent from the private key.
* 0 is returned if any of the following occurs:
*
* - Either `p` or `q` is not equal to 3 modulo 4.
*
* - The public exponent does not fit on 32 bits.
*
* - An internal limit is exceeded.
*
* - The private key is invalid in some way.
*
* For all private keys produced by the key generator functions
* (`br_rsa_keygen` type), this function succeeds and returns the true
* public exponent. The public exponent is always an odd integer greater
* than 1.
*
* \return the public exponent, or 0.
*/
typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk);
/**
* \brief Recompute RSA public exponent ("i15" engine).
*
* \see br_rsa_compute_pubexp
*
* \return the public exponent, or 0.
*/
uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk);
/**
* \brief Recompute RSA public exponent ("i31" engine).
*
* \see br_rsa_compute_pubexp
*
* \return the public exponent, or 0.
*/
uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk);
/**
* \brief Get "default" RSA implementation (recompute public exponent).
*
* This returns the preferred implementation of RSA (recompute public
* exponent) on the current system.
*
* \return the default implementation.
*/
br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void);
/**
* \brief Type for a private exponent computing function.
*
* An RSA private key (`br_rsa_private_key`) contains two reduced
* private exponents, which are sufficient to perform private key
* operations. However, standard encoding formats for RSA private keys
* require also a copy of the complete private exponent (non-reduced),
* which this function recomputes.
*
* This function suceeds if all the following conditions hold:
*
* - Both private factors `p` and `q` are equal to 3 modulo 4.
*
* - The provided public exponent `pubexp` is correct, and, in particular,
* is odd, relatively prime to `p-1` and `q-1`, and greater than 1.
*
* - No internal storage limit is exceeded.
*
* For all private keys produced by the key generator functions
* (`br_rsa_keygen` type), this function succeeds. Note that the API
* restricts the public exponent to a maximum size of 32 bits.
*
* The encoded private exponent is written in `d` (unsigned big-endian
* convention), and the length (in bytes) is returned. If `d` is `NULL`,
* then the exponent is not written anywhere, but the length is still
* returned. On error, 0 is returned.
*
* Not all error conditions are detected when `d` is `NULL`; therefore, the
* returned value shall be checked also when actually producing the value.
*
* \param d destination buffer (or `NULL`).
* \param sk RSA private key.
* \param pubexp the public exponent.
* \return the private exponent length (in bytes), or 0.
*/
typedef size_t (*br_rsa_compute_privexp)(void *d,
const br_rsa_private_key *sk, uint32_t pubexp);
/**
* \brief Recompute RSA private exponent ("i15" engine).
*
* \see br_rsa_compute_privexp
*
* \param d destination buffer (or `NULL`).
* \param sk RSA private key.
* \param pubexp the public exponent.
* \return the private exponent length (in bytes), or 0.
*/
size_t br_rsa_i15_compute_privexp(void *d,
const br_rsa_private_key *sk, uint32_t pubexp);
/**
* \brief Recompute RSA private exponent ("i31" engine).
*
* \see br_rsa_compute_privexp
*
* \param d destination buffer (or `NULL`).
* \param sk RSA private key.
* \param pubexp the public exponent.
* \return the private exponent length (in bytes), or 0.
*/
size_t br_rsa_i31_compute_privexp(void *d,
const br_rsa_private_key *sk, uint32_t pubexp);
/**
* \brief Get "default" RSA implementation (recompute private exponent).
*
* This returns the preferred implementation of RSA (recompute private
* exponent) on the current system.
*
* \return the default implementation.
*/
br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_EC_H__
#define BR_BEARSSL_EC_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_ec.h
*
* # Elliptic Curves
*
* This file documents the EC implementations provided with BearSSL, and
* ECDSA.
*
* ## Elliptic Curve API
*
* Only "named curves" are supported. Each EC implementation supports
* one or several named curves, identified by symbolic identifiers.
* These identifiers are small integers, that correspond to the values
* registered by the
* [IANA](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
*
* Since all currently defined elliptic curve identifiers are in the 0..31
* range, it is convenient to encode support of some curves in a 32-bit
* word, such that bit x corresponds to curve of identifier x.
*
* An EC implementation is incarnated by a `br_ec_impl` instance, that
* offers the following fields:
*
* - `supported_curves`
*
* A 32-bit word that documents the identifiers of the curves supported
* by this implementation.
*
* - `generator()`
*
* Callback method that returns a pointer to the conventional generator
* point for that curve.
*
* - `order()`
*
* Callback method that returns a pointer to the subgroup order for
* that curve. That value uses unsigned big-endian encoding.
*
* - `xoff()`
*
* Callback method that returns the offset and length of the X
* coordinate in an encoded point.
*
* - `mul()`
*
* Multiply a curve point with an integer.
*
* - `mulgen()`
*
* Multiply the curve generator with an integer. This may be faster
* than the generic `mul()`.
*
* - `muladd()`
*
* Multiply two curve points by two integers, and return the sum of
* the two products.
*
* All curve points are represented in uncompressed format. The `mul()`
* and `muladd()` methods take care to validate that the provided points
* are really part of the relevant curve subgroup.
*
* For all point multiplication functions, the following holds:
*
* - Functions validate that the provided points are valid members
* of the relevant curve subgroup. An error is reported if that is
* not the case.
*
* - Processing is constant-time, even if the point operands are not
* valid. This holds for both the source and resulting points, and
* the multipliers (integers). Only the byte length of the provided
* multiplier arrays (not their actual value length in bits) may
* leak through timing-based side channels.
*
* - The multipliers (integers) MUST be lower than the subgroup order.
* If this property is not met, then the result is indeterminate,
* but an error value is not necessarily returned.
*
*
* ## ECDSA
*
* ECDSA signatures have two standard formats, called "raw" and "asn1".
* Internally, such a signature is a pair of modular integers `(r,s)`.
* The "raw" format is the concatenation of the unsigned big-endian
* encodings of these two integers, possibly left-padded with zeros so
* that they have the same encoded length. The "asn1" format is the
* DER encoding of an ASN.1 structure that contains the two integer
* values:
*
* ECDSASignature ::= SEQUENCE {
* r INTEGER,
* s INTEGER
* }
*
* In general, in all of X.509 and SSL/TLS, the "asn1" format is used.
* BearSSL offers ECDSA implementations for both formats; conversion
* functions between the two formats are also provided. Conversion of a
* "raw" format signature into "asn1" may enlarge a signature by no more
* than 9 bytes for all supported curves; conversely, conversion of an
* "asn1" signature to "raw" may expand the signature but the "raw"
* length will never be more than twice the length of the "asn1" length
* (and usually it will be shorter).
*
* Note that for a given signature, the "raw" format is not fully
* deterministic, in that it does not enforce a minimal common length.
*/
/*
* Standard curve ID. These ID are equal to the assigned numerical
* identifiers assigned to these curves for TLS:
* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
*/
/** \brief Identifier for named curve sect163k1. */
#define BR_EC_sect163k1 1
/** \brief Identifier for named curve sect163r1. */
#define BR_EC_sect163r1 2
/** \brief Identifier for named curve sect163r2. */
#define BR_EC_sect163r2 3
/** \brief Identifier for named curve sect193r1. */
#define BR_EC_sect193r1 4
/** \brief Identifier for named curve sect193r2. */
#define BR_EC_sect193r2 5
/** \brief Identifier for named curve sect233k1. */
#define BR_EC_sect233k1 6
/** \brief Identifier for named curve sect233r1. */
#define BR_EC_sect233r1 7
/** \brief Identifier for named curve sect239k1. */
#define BR_EC_sect239k1 8
/** \brief Identifier for named curve sect283k1. */
#define BR_EC_sect283k1 9
/** \brief Identifier for named curve sect283r1. */
#define BR_EC_sect283r1 10
/** \brief Identifier for named curve sect409k1. */
#define BR_EC_sect409k1 11
/** \brief Identifier for named curve sect409r1. */
#define BR_EC_sect409r1 12
/** \brief Identifier for named curve sect571k1. */
#define BR_EC_sect571k1 13
/** \brief Identifier for named curve sect571r1. */
#define BR_EC_sect571r1 14
/** \brief Identifier for named curve secp160k1. */
#define BR_EC_secp160k1 15
/** \brief Identifier for named curve secp160r1. */
#define BR_EC_secp160r1 16
/** \brief Identifier for named curve secp160r2. */
#define BR_EC_secp160r2 17
/** \brief Identifier for named curve secp192k1. */
#define BR_EC_secp192k1 18
/** \brief Identifier for named curve secp192r1. */
#define BR_EC_secp192r1 19
/** \brief Identifier for named curve secp224k1. */
#define BR_EC_secp224k1 20
/** \brief Identifier for named curve secp224r1. */
#define BR_EC_secp224r1 21
/** \brief Identifier for named curve secp256k1. */
#define BR_EC_secp256k1 22
/** \brief Identifier for named curve secp256r1. */
#define BR_EC_secp256r1 23
/** \brief Identifier for named curve secp384r1. */
#define BR_EC_secp384r1 24
/** \brief Identifier for named curve secp521r1. */
#define BR_EC_secp521r1 25
/** \brief Identifier for named curve brainpoolP256r1. */
#define BR_EC_brainpoolP256r1 26
/** \brief Identifier for named curve brainpoolP384r1. */
#define BR_EC_brainpoolP384r1 27
/** \brief Identifier for named curve brainpoolP512r1. */
#define BR_EC_brainpoolP512r1 28
/** \brief Identifier for named curve Curve25519. */
#define BR_EC_curve25519 29
/** \brief Identifier for named curve Curve448. */
#define BR_EC_curve448 30
/**
* \brief Structure for an EC public key.
*/
typedef struct {
/** \brief Identifier for the curve used by this key. */
int curve;
/** \brief Public curve point (uncompressed format). */
unsigned char *q;
/** \brief Length of public curve point (in bytes). */
size_t qlen;
} br_ec_public_key;
/**
* \brief Structure for an EC private key.
*
* The private key is an integer modulo the curve subgroup order. The
* encoding below tolerates extra leading zeros. In general, it is
* recommended that the private key has the same length as the curve
* subgroup order.
*/
typedef struct {
/** \brief Identifier for the curve used by this key. */
int curve;
/** \brief Private key (integer, unsigned big-endian encoding). */
unsigned char *x;
/** \brief Private key length (in bytes). */
size_t xlen;
} br_ec_private_key;
/**
* \brief Type for an EC implementation.
*/
typedef struct {
/**
* \brief Supported curves.
*
* This word is a bitfield: bit `x` is set if the curve of ID `x`
* is supported. E.g. an implementation supporting both NIST P-256
* (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have
* value `0x01800000` in this field.
*/
uint32_t supported_curves;
/**
* \brief Get the conventional generator.
*
* This function returns the conventional generator (encoded
* curve point) for the specified curve. This function MUST NOT
* be called if the curve is not supported.
*
* \param curve curve identifier.
* \param len receiver for the encoded generator length (in bytes).
* \return the encoded generator.
*/
const unsigned char *(*generator)(int curve, size_t *len);
/**
* \brief Get the subgroup order.
*
* This function returns the order of the subgroup generated by
* the conventional generator, for the specified curve. Unsigned
* big-endian encoding is used. This function MUST NOT be called
* if the curve is not supported.
*
* \param curve curve identifier.
* \param len receiver for the encoded order length (in bytes).
* \return the encoded order.
*/
const unsigned char *(*order)(int curve, size_t *len);
/**
* \brief Get the offset and length for the X coordinate.
*
* This function returns the offset and length (in bytes) of
* the X coordinate in an encoded non-zero point.
*
* \param curve curve identifier.
* \param len receiver for the X coordinate length (in bytes).
* \return the offset for the X coordinate (in bytes).
*/
size_t (*xoff)(int curve, size_t *len);
/**
* \brief Multiply a curve point by an integer.
*
* The source point is provided in array `G` (of size `Glen` bytes);
* the multiplication result is written over it. The multiplier
* `x` (of size `xlen` bytes) uses unsigned big-endian encoding.
*
* Rules:
*
* - The specified curve MUST be supported.
*
* - The source point must be a valid point on the relevant curve
* subgroup (and not the "point at infinity" either). If this is
* not the case, then this function returns an error (0).
*
* - The multiplier integer MUST be non-zero and less than the
* curve subgroup order. If this property does not hold, then
* the result is indeterminate and an error code is not
* guaranteed.
*
* Returned value is 1 on success, 0 on error. On error, the
* contents of `G` are indeterminate.
*
* \param G point to multiply.
* \param Glen length of the encoded point (in bytes).
* \param x multiplier (unsigned big-endian).
* \param xlen multiplier length (in bytes).
* \param curve curve identifier.
* \return 1 on success, 0 on error.
*/
uint32_t (*mul)(unsigned char *G, size_t Glen,
const unsigned char *x, size_t xlen, int curve);
/**
* \brief Multiply the generator by an integer.
*
* The multiplier MUST be non-zero and less than the curve
* subgroup order. Results are indeterminate if this property
* does not hold.
*
* \param R output buffer for the point.
* \param x multiplier (unsigned big-endian).
* \param xlen multiplier length (in bytes).
* \param curve curve identifier.
* \return encoded result point length (in bytes).
*/
size_t (*mulgen)(unsigned char *R,
const unsigned char *x, size_t xlen, int curve);
/**
* \brief Multiply two points by two integers and add the
* results.
*
* The point `x*A + y*B` is computed and written back in the `A`
* array.
*
* Rules:
*
* - The specified curve MUST be supported.
*
* - The source points (`A` and `B`) must be valid points on
* the relevant curve subgroup (and not the "point at
* infinity" either). If this is not the case, then this
* function returns an error (0).
*
* - If the `B` pointer is `NULL`, then the conventional
* subgroup generator is used. With some implementations,
* this may be faster than providing a pointer to the
* generator.
*
* - The multiplier integers (`x` and `y`) MUST be non-zero
* and less than the curve subgroup order. If either integer
* is zero, then an error is reported, but if one of them is
* not lower than the subgroup order, then the result is
* indeterminate and an error code is not guaranteed.
*
* - If the final result is the point at infinity, then an
* error is returned.
*
* Returned value is 1 on success, 0 on error. On error, the
* contents of `A` are indeterminate.
*
* \param A first point to multiply.
* \param B second point to multiply (`NULL` for the generator).
* \param len common length of the encoded points (in bytes).
* \param x multiplier for `A` (unsigned big-endian).
* \param xlen length of multiplier for `A` (in bytes).
* \param y multiplier for `A` (unsigned big-endian).
* \param ylen length of multiplier for `A` (in bytes).
* \param curve curve identifier.
* \return 1 on success, 0 on error.
*/
uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve);
} br_ec_impl;
/**
* \brief EC implementation "i31".
*
* This implementation internally uses generic code for modular integers,
* with a representation as sequences of 31-bit words. It supports secp256r1,
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
*/
extern const br_ec_impl br_ec_prime_i31;
/**
* \brief EC implementation "i15".
*
* This implementation internally uses generic code for modular integers,
* with a representation as sequences of 15-bit words. It supports secp256r1,
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
*/
extern const br_ec_impl br_ec_prime_i15;
/**
* \brief EC implementation "m15" for P-256.
*
* This implementation uses specialised code for curve secp256r1 (also
* known as NIST P-256), with optional Karatsuba decomposition, and fast
* modular reduction thanks to the field modulus special format. Only
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
*/
extern const br_ec_impl br_ec_p256_m15;
/**
* \brief EC implementation "m31" for P-256.
*
* This implementation uses specialised code for curve secp256r1 (also
* known as NIST P-256), relying on multiplications of 31-bit values
* (MUL31).
*/
extern const br_ec_impl br_ec_p256_m31;
/**
* \brief EC implementation "m62" (specialised code) for P-256.
*
* This implementation uses custom code relying on multiplication of
* integers up to 64 bits, with a 128-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer
* to that implementation.
*/
extern const br_ec_impl br_ec_p256_m62;
/**
* \brief Get the "m62" implementation of P-256, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_p256_m62_get(void);
/**
* \brief EC implementation "m64" (specialised code) for P-256.
*
* This implementation uses custom code relying on multiplication of
* integers up to 64 bits, with a 128-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer
* to that implementation.
*/
extern const br_ec_impl br_ec_p256_m64;
/**
* \brief Get the "m64" implementation of P-256, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_p256_m64_get(void);
/**
* \brief EC implementation "i15" (generic code) for Curve25519.
*
* This implementation uses the generic code for modular integers (with
* 15-bit words) to support Curve25519. Due to the specificities of the
* curve definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_i15;
/**
* \brief EC implementation "i31" (generic code) for Curve25519.
*
* This implementation uses the generic code for modular integers (with
* 31-bit words) to support Curve25519. Due to the specificities of the
* curve definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_i31;
/**
* \brief EC implementation "m15" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 15 bits. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m15;
/**
* \brief EC implementation "m31" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 31 bits. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m31;
/**
* \brief EC implementation "m62" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 62 bits, with a 124-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer
* to that implementation. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m62;
/**
* \brief Get the "m62" implementation of Curve25519, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_c25519_m62_get(void);
/**
* \brief EC implementation "m64" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 64 bits, with a 128-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer
* to that implementation. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m64;
/**
* \brief Get the "m64" implementation of Curve25519, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_c25519_m64_get(void);
/**
* \brief Aggregate EC implementation "m15".
*
* This implementation is a wrapper for:
*
* - `br_ec_c25519_m15` for Curve25519
* - `br_ec_p256_m15` for NIST P-256
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
*/
extern const br_ec_impl br_ec_all_m15;
/**
* \brief Aggregate EC implementation "m31".
*
* This implementation is a wrapper for:
*
* - `br_ec_c25519_m31` for Curve25519
* - `br_ec_p256_m31` for NIST P-256
* - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512)
*/
extern const br_ec_impl br_ec_all_m31;
/**
* \brief Get the "default" EC implementation for the current system.
*
* This returns a pointer to the preferred implementation on the
* current system.
*
* \return the default EC implementation.
*/
const br_ec_impl *br_ec_get_default(void);
/**
* \brief Convert a signature from "raw" to "asn1".
*
* Conversion is done "in place" and the new length is returned.
* Conversion may enlarge the signature, but by no more than 9 bytes at
* most. On error, 0 is returned (error conditions include an odd raw
* signature length, or an oversized integer).
*
* \param sig signature to convert.
* \param sig_len signature length (in bytes).
* \return the new signature length, or 0 on error.
*/
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
/**
* \brief Convert a signature from "asn1" to "raw".
*
* Conversion is done "in place" and the new length is returned.
* Conversion may enlarge the signature, but the new signature length
* will be less than twice the source length at most. On error, 0 is
* returned (error conditions include an invalid ASN.1 structure or an
* oversized integer).
*
* \param sig signature to convert.
* \param sig_len signature length (in bytes).
* \return the new signature length, or 0 on error.
*/
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
/**
* \brief Type for an ECDSA signer function.
*
* A pointer to the EC implementation is provided. The hash value is
* assumed to have the length inferred from the designated hash function
* class.
*
* Signature is written in the buffer pointed to by `sig`, and the length
* (in bytes) is returned. On error, nothing is written in the buffer,
* and 0 is returned. This function returns 0 if the specified curve is
* not supported by the provided EC implementation.
*
* The signature format is either "raw" or "asn1", depending on the
* implementation; maximum length is predictable from the implemented
* curve:
*
* | curve | raw | asn1 |
* | :--------- | --: | ---: |
* | NIST P-256 | 64 | 72 |
* | NIST P-384 | 96 | 104 |
* | NIST P-521 | 132 | 139 |
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief Type for an ECDSA signature verification function.
*
* A pointer to the EC implementation is provided. The hashed value,
* computed over the purportedly signed data, is also provided with
* its length.
*
* The signature format is either "raw" or "asn1", depending on the
* implementation.
*
* Returned value is 1 on success (valid signature), 0 on error. This
* function returns 0 if the specified curve is not supported by the
* provided EC implementation.
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature generator, "i31" implementation, "asn1" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature generator, "i31" implementation, "raw" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature verifier, "i31" implementation, "asn1" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature verifier, "i31" implementation, "raw" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief Get "default" ECDSA implementation (signer, asn1 format).
*
* This returns the preferred implementation of ECDSA signature generation
* ("asn1" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void);
/**
* \brief Get "default" ECDSA implementation (signer, raw format).
*
* This returns the preferred implementation of ECDSA signature generation
* ("raw" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_sign br_ecdsa_sign_raw_get_default(void);
/**
* \brief Get "default" ECDSA implementation (verifier, asn1 format).
*
* This returns the preferred implementation of ECDSA signature verification
* ("asn1" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void);
/**
* \brief Get "default" ECDSA implementation (verifier, raw format).
*
* This returns the preferred implementation of ECDSA signature verification
* ("raw" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void);
/**
* \brief Maximum size for EC private key element buffer.
*
* This is the largest number of bytes that `br_ec_keygen()` may need or
* ever return.
*/
#define BR_EC_KBUF_PRIV_MAX_SIZE 72
/**
* \brief Maximum size for EC public key element buffer.
*
* This is the largest number of bytes that `br_ec_compute_public()` may
* need or ever return.
*/
#define BR_EC_KBUF_PUB_MAX_SIZE 145
/**
* \brief Generate a new EC private key.
*
* If the specified `curve` is not supported by the elliptic curve
* implementation (`impl`), then this function returns zero.
*
* The `sk` structure fields are set to the new private key data. In
* particular, `sk.x` is made to point to the provided key buffer (`kbuf`),
* in which the actual private key data is written. That buffer is assumed
* to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum
* size for all supported curves.
*
* The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then
* the private key is not actually generated, and `sk` may also be `NULL`;
* the minimum length for `kbuf` is still computed and returned.
*
* If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is
* still generated and stored in `kbuf`.
*
* \param rng_ctx source PRNG context (already initialized).
* \param impl the elliptic curve implementation.
* \param sk the private key structure to fill, or `NULL`.
* \param kbuf the key element buffer, or `NULL`.
* \param curve the curve identifier.
* \return the key data length (in bytes), or zero.
*/
size_t br_ec_keygen(const br_prng_class **rng_ctx,
const br_ec_impl *impl, br_ec_private_key *sk,
void *kbuf, int curve);
/**
* \brief Compute EC public key from EC private key.
*
* This function uses the provided elliptic curve implementation (`impl`)
* to compute the public key corresponding to the private key held in `sk`.
* The public key point is written into `kbuf`, which is then linked from
* the `*pk` structure. The size of the public key point, i.e. the number
* of bytes used in `kbuf`, is returned.
*
* If `kbuf` is `NULL`, then the public key point is NOT computed, and
* the public key structure `*pk` is unmodified (`pk` may be `NULL` in
* that case). The size of the public key point is still returned.
*
* If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key
* point is computed and stored in `kbuf`, and its size is returned.
*
* If the curve used by the private key is not supported by the curve
* implementation, then this function returns zero.
*
* The private key MUST be valid. An off-range private key value is not
* necessarily detected, and leads to unpredictable results.
*
* \param impl the elliptic curve implementation.
* \param pk the public key structure to fill (or `NULL`).
* \param kbuf the public key point buffer (or `NULL`).
* \param sk the source private key.
* \return the public key point length (in bytes), or zero.
*/
size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
void *kbuf, const br_ec_private_key *sk);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_SSL_H__
#define BR_BEARSSL_SSL_H__
#include
#include
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_X509_H__
#define BR_BEARSSL_X509_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_x509.h
*
* # X.509 Certificate Chain Processing
*
* An X.509 processing engine receives an X.509 chain, chunk by chunk,
* as received from a SSL/TLS client or server (the client receives the
* server's certificate chain, and the server receives the client's
* certificate chain if it requested a client certificate). The chain
* is thus injected in the engine in SSL order (end-entity first).
*
* The engine's job is to return the public key to use for SSL/TLS.
* How exactly that key is obtained and verified is entirely up to the
* engine.
*
* **The "known key" engine** returns a public key which is already known
* from out-of-band information (e.g. the client _remembers_ the key from
* a previous connection, as in the usual SSH model). This is the simplest
* engine since it simply ignores the chain, thereby avoiding the need
* for any decoding logic.
*
* **The "minimal" engine** implements minimal X.509 decoding and chain
* validation:
*
* - The provided chain should validate "as is". There is no attempt
* at reordering, skipping or downloading extra certificates.
*
* - X.509 v1, v2 and v3 certificates are supported.
*
* - Trust anchors are a DN and a public key. Each anchor is either a
* "CA" anchor, or a non-CA.
*
* - If the end-entity certificate matches a non-CA anchor (subject DN
* is equal to the non-CA name, and public key is also identical to
* the anchor key), then this is a _direct trust_ case and the
* remaining certificates are ignored.
*
* - Unless direct trust is applied, the chain must be verifiable up to
* a certificate whose issuer DN matches the DN from a "CA" trust anchor,
* and whose signature is verifiable against that anchor's public key.
* Subsequent certificates in the chain are ignored.
*
* - The engine verifies subject/issuer DN matching, and enforces
* processing of Basic Constraints and Key Usage extensions. The
* Authority Key Identifier, Subject Key Identifier, Issuer Alt Name,
* Subject Directory Attribute, CRL Distribution Points, Freshest CRL,
* Authority Info Access and Subject Info Access extensions are
* ignored. The Subject Alt Name is decoded for the end-entity
* certificate under some conditions (see below). Other extensions
* are ignored if non-critical, or imply chain rejection if critical.
*
* - The Subject Alt Name extension is parsed for names of type `dNSName`
* when decoding the end-entity certificate, and only if there is a
* server name to match. If there is no SAN extension, then the
* Common Name from the subjectDN is used. That name matching is
* case-insensitive and honours a single starting wildcard (i.e. if
* the name in the certificate starts with "`*.`" then this matches
* any word as first element). Note: this name matching is performed
* also in the "direct trust" model.
*
* - DN matching is byte-to-byte equality (a future version might
* include some limited processing for case-insensitive matching and
* whitespace normalisation).
*
* - Successful validation produces a public key type but also a set
* of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
* The caller is responsible for checking that the key type and
* usages are compatible with the expected values (e.g. with the
* selected cipher suite, when the client validates the server's
* certificate).
*
* **Important caveats:**
*
* - The "minimal" engine does not check revocation status. The relevant
* extensions are ignored, and CRL or OCSP responses are not gathered
* or checked.
*
* - The "minimal" engine does not currently support Name Constraints
* (some basic functionality to handle sub-domains may be added in a
* later version).
*
* - The decoder is not "validating" in the sense that it won't reject
* some certificates with invalid field values when these fields are
* not actually processed.
*/
/*
* X.509 error codes are in the 32..63 range.
*/
/** \brief X.509 status: validation was successful; this is not actually
an error. */
#define BR_ERR_X509_OK 32
/** \brief X.509 status: invalid value in an ASN.1 structure. */
#define BR_ERR_X509_INVALID_VALUE 33
/** \brief X.509 status: truncated certificate. */
#define BR_ERR_X509_TRUNCATED 34
/** \brief X.509 status: empty certificate chain (no certificate at all). */
#define BR_ERR_X509_EMPTY_CHAIN 35
/** \brief X.509 status: decoding error: inner element extends beyond
outer element size. */
#define BR_ERR_X509_INNER_TRUNC 36
/** \brief X.509 status: decoding error: unsupported tag class (application
or private). */
#define BR_ERR_X509_BAD_TAG_CLASS 37
/** \brief X.509 status: decoding error: unsupported tag value. */
#define BR_ERR_X509_BAD_TAG_VALUE 38
/** \brief X.509 status: decoding error: indefinite length. */
#define BR_ERR_X509_INDEFINITE_LENGTH 39
/** \brief X.509 status: decoding error: extraneous element. */
#define BR_ERR_X509_EXTRA_ELEMENT 40
/** \brief X.509 status: decoding error: unexpected element. */
#define BR_ERR_X509_UNEXPECTED 41
/** \brief X.509 status: decoding error: expected constructed element, but
is primitive. */
#define BR_ERR_X509_NOT_CONSTRUCTED 42
/** \brief X.509 status: decoding error: expected primitive element, but
is constructed. */
#define BR_ERR_X509_NOT_PRIMITIVE 43
/** \brief X.509 status: decoding error: BIT STRING length is not multiple
of 8. */
#define BR_ERR_X509_PARTIAL_BYTE 44
/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */
#define BR_ERR_X509_BAD_BOOLEAN 45
/** \brief X.509 status: decoding error: value is off-limits. */
#define BR_ERR_X509_OVERFLOW 46
/** \brief X.509 status: invalid distinguished name. */
#define BR_ERR_X509_BAD_DN 47
/** \brief X.509 status: invalid date/time representation. */
#define BR_ERR_X509_BAD_TIME 48
/** \brief X.509 status: certificate contains unsupported features that
cannot be ignored. */
#define BR_ERR_X509_UNSUPPORTED 49
/** \brief X.509 status: key or signature size exceeds internal limits. */
#define BR_ERR_X509_LIMIT_EXCEEDED 50
/** \brief X.509 status: key type does not match that which was expected. */
#define BR_ERR_X509_WRONG_KEY_TYPE 51
/** \brief X.509 status: signature is invalid. */
#define BR_ERR_X509_BAD_SIGNATURE 52
/** \brief X.509 status: validation time is unknown. */
#define BR_ERR_X509_TIME_UNKNOWN 53
/** \brief X.509 status: certificate is expired or not yet valid. */
#define BR_ERR_X509_EXPIRED 54
/** \brief X.509 status: issuer/subject DN mismatch in the chain. */
#define BR_ERR_X509_DN_MISMATCH 55
/** \brief X.509 status: expected server name was not found in the chain. */
#define BR_ERR_X509_BAD_SERVER_NAME 56
/** \brief X.509 status: unknown critical extension in certificate. */
#define BR_ERR_X509_CRITICAL_EXTENSION 57
/** \brief X.509 status: not a CA, or path length constraint violation */
#define BR_ERR_X509_NOT_CA 58
/** \brief X.509 status: Key Usage extension prohibits intended usage. */
#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59
/** \brief X.509 status: public key found in certificate is too small. */
#define BR_ERR_X509_WEAK_PUBLIC_KEY 60
/** \brief X.509 status: chain could not be linked to a trust anchor. */
#define BR_ERR_X509_NOT_TRUSTED 62
/**
* \brief Aggregate structure for public keys.
*/
typedef struct {
/** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */
unsigned char key_type;
/** \brief Actual public key. */
union {
/** \brief RSA public key. */
br_rsa_public_key rsa;
/** \brief EC public key. */
br_ec_public_key ec;
} key;
} br_x509_pkey;
/**
* \brief Distinguished Name (X.500) structure.
*
* The DN is DER-encoded.
*/
typedef struct {
/** \brief Encoded DN data. */
unsigned char *data;
/** \brief Encoded DN length (in bytes). */
size_t len;
} br_x500_name;
/**
* \brief Trust anchor structure.
*/
typedef struct {
/** \brief Encoded DN (X.500 name). */
br_x500_name dn;
/** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */
unsigned flags;
/** \brief Anchor public key. */
br_x509_pkey pkey;
} br_x509_trust_anchor;
/**
* \brief Trust anchor flag: CA.
*
* A "CA" anchor is deemed fit to verify signatures on certificates.
* A "non-CA" anchor is accepted only for direct trust (server's
* certificate name and key match the anchor).
*/
#define BR_X509_TA_CA 0x0001
/*
* Key type: combination of a basic key type (low 4 bits) and some
* optional flags.
*
* For a public key, the basic key type only is set.
*
* For an expected key type, the flags indicate the intended purpose(s)
* for the key; the basic key type may be set to 0 to indicate that any
* key type compatible with the indicated purpose is acceptable.
*/
/** \brief Key type: algorithm is RSA. */
#define BR_KEYTYPE_RSA 1
/** \brief Key type: algorithm is EC. */
#define BR_KEYTYPE_EC 2
/**
* \brief Key type: usage is "key exchange".
*
* This value is combined (with bitwise OR) with the algorithm
* (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509
* validation engine that it should find a public key of that type,
* fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher
* suites).
*/
#define BR_KEYTYPE_KEYX 0x10
/**
* \brief Key type: usage is "signature".
*
* This value is combined (with bitwise OR) with the algorithm
* (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509
* validation engine that it should find a public key of that type,
* fit for signatures (e.g. `TLS_ECDHE_*` cipher suites).
*/
#define BR_KEYTYPE_SIGN 0x20
/*
* start_chain Called when a new chain is started. If 'server_name'
* is not NULL and non-empty, then it is a name that
* should be looked for in the EE certificate (in the
* SAN extension as dNSName, or in the subjectDN's CN
* if there is no SAN extension).
* The caller ensures that the provided 'server_name'
* pointer remains valid throughout validation.
*
* start_cert Begins a new certificate in the chain. The provided
* length is in bytes; this is the total certificate length.
*
* append Get some additional bytes for the current certificate.
*
* end_cert Ends the current certificate.
*
* end_chain Called at the end of the chain. Returned value is
* 0 on success, or a non-zero error code.
*
* get_pkey Returns the EE certificate public key.
*
* For a complete chain, start_chain() and end_chain() are always
* called. For each certificate, start_cert(), some append() calls, then
* end_cert() are called, in that order. There may be no append() call
* at all if the certificate is empty (which is not valid but may happen
* if the peer sends exactly that).
*
* get_pkey() shall return a pointer to a structure that is valid as
* long as a new chain is not started. This may be a sub-structure
* within the context for the engine. This function MAY return a valid
* pointer to a public key even in some cases of validation failure,
* depending on the validation engine.
*/
/**
* \brief Class type for an X.509 engine.
*
* A certificate chain validation uses a caller-allocated context, which
* contains the running state for that validation. Methods are called
* in due order:
*
* - `start_chain()` is called at the start of the validation.
* - Certificates are processed one by one, in SSL order (end-entity
* comes first). For each certificate, the following methods are
* called:
*
* - `start_cert()` at the beginning of the certificate.
* - `append()` is called zero, one or more times, to provide
* the certificate (possibly in chunks).
* - `end_cert()` at the end of the certificate.
*
* - `end_chain()` is called when the last certificate in the chain
* was processed.
* - `get_pkey()` is called after chain processing, if the chain
* validation was successful.
*
* A context structure may be reused; the `start_chain()` method shall
* ensure (re)initialisation.
*/
typedef struct br_x509_class_ br_x509_class;
struct br_x509_class_ {
/**
* \brief X.509 context size, in bytes.
*/
size_t context_size;
/**
* \brief Start a new chain.
*
* This method shall set the vtable (first field) of the context
* structure.
*
* The `server_name`, if not `NULL`, will be considered as a
* fully qualified domain name, to be matched against the `dNSName`
* elements of the end-entity certificate's SAN extension (if there
* is no SAN, then the Common Name from the subjectDN will be used).
* If `server_name` is `NULL` then no such matching is performed.
*
* \param ctx validation context.
* \param server_name server name to match (or `NULL`).
*/
void (*start_chain)(const br_x509_class **ctx,
const char *server_name);
/**
* \brief Start a new certificate.
*
* \param ctx validation context.
* \param length new certificate length (in bytes).
*/
void (*start_cert)(const br_x509_class **ctx, uint32_t length);
/**
* \brief Receive some bytes for the current certificate.
*
* This function may be called several times in succession for
* a given certificate. The caller guarantees that for each
* call, `len` is not zero, and the sum of all chunk lengths
* for a certificate matches the total certificate length which
* was provided in the previous `start_cert()` call.
*
* If the new certificate is empty (no byte at all) then this
* function won't be called at all.
*
* \param ctx validation context.
* \param buf certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void (*append)(const br_x509_class **ctx,
const unsigned char *buf, size_t len);
/**
* \brief Finish the current certificate.
*
* This function is called when the end of the current certificate
* is reached.
*
* \param ctx validation context.
*/
void (*end_cert)(const br_x509_class **ctx);
/**
* \brief Finish the chain.
*
* This function is called at the end of the chain. It shall
* return either 0 if the validation was successful, or a
* non-zero error code. The `BR_ERR_X509_*` constants are
* error codes, though other values may be possible.
*
* \param ctx validation context.
* \return 0 on success, or a non-zero error code.
*/
unsigned (*end_chain)(const br_x509_class **ctx);
/**
* \brief Get the resulting end-entity public key.
*
* The decoded public key is returned. The returned pointer
* may be valid only as long as the context structure is
* unmodified, i.e. it may cease to be valid if the context
* is released or reused.
*
* This function _may_ return `NULL` if the validation failed.
* However, returning a public key does not mean that the
* validation was wholly successful; some engines may return
* a decoded public key even if the chain did not end on a
* trusted anchor.
*
* If validation succeeded and `usage` is not `NULL`, then
* `*usage` is filled with a combination of `BR_KEYTYPE_SIGN`
* and/or `BR_KEYTYPE_KEYX` that specifies the validated key
* usage types. It is the caller's responsibility to check
* that value against the intended use of the public key.
*
* \param ctx validation context.
* \return the end-entity public key, or `NULL`.
*/
const br_x509_pkey *(*get_pkey)(
const br_x509_class *const *ctx, unsigned *usages);
};
/**
* \brief The "known key" X.509 engine structure.
*
* The structure contents are opaque (they shall not be accessed directly),
* except for the first field (the vtable).
*
* The "known key" engine returns an externally configured public key,
* and totally ignores the certificate contents.
*/
typedef struct {
/** \brief Reference to the context vtable. */
const br_x509_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
br_x509_pkey pkey;
unsigned usages;
#endif
} br_x509_knownkey_context;
/**
* \brief Class instance for the "known key" X.509 engine.
*/
extern const br_x509_class br_x509_knownkey_vtable;
/**
* \brief Initialize a "known key" X.509 engine with a known RSA public key.
*
* The `usages` parameter indicates the allowed key usages for that key
* (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
*
* The provided pointers are linked in, not copied, so they must remain
* valid while the public key may be in usage.
*
* \param ctx context to initialise.
* \param pk known public key.
* \param usages allowed key usages.
*/
void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
const br_rsa_public_key *pk, unsigned usages);
/**
* \brief Initialize a "known key" X.509 engine with a known EC public key.
*
* The `usages` parameter indicates the allowed key usages for that key
* (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
*
* The provided pointers are linked in, not copied, so they must remain
* valid while the public key may be in usage.
*
* \param ctx context to initialise.
* \param pk known public key.
* \param usages allowed key usages.
*/
void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
const br_ec_public_key *pk, unsigned usages);
#ifndef BR_DOXYGEN_IGNORE
/*
* The minimal X.509 engine has some state buffers which must be large
* enough to simultaneously accommodate:
* -- the public key extracted from the current certificate;
* -- the signature on the current certificate or on the previous
* certificate;
* -- the public key extracted from the EE certificate.
*
* We store public key elements in their raw unsigned big-endian
* encoding. We want to support up to RSA-4096 with a short (up to 64
* bits) public exponent, thus a buffer for a public key must have
* length at least 520 bytes. Similarly, a RSA-4096 signature has length
* 512 bytes.
*
* Though RSA public exponents can formally be as large as the modulus
* (mathematically, even larger exponents would work, but PKCS#1 forbids
* them), exponents that do not fit on 32 bits are extremely rare,
* notably because some widespread implementations (e.g. Microsoft's
* CryptoAPI) don't support them. Moreover, large public exponent do not
* seem to imply any tangible security benefit, and they increase the
* cost of public key operations. The X.509 "minimal" engine will tolerate
* public exponents of arbitrary size as long as the modulus and the
* exponent can fit together in the dedicated buffer.
*
* EC public keys are shorter than RSA public keys; even with curve
* NIST P-521 (the largest curve we care to support), a public key is
* encoded over 133 bytes only.
*/
#define BR_X509_BUFSIZE_KEY 520
#define BR_X509_BUFSIZE_SIG 512
#endif
/**
* \brief Type for receiving a name element.
*
* An array of such structures can be provided to the X.509 decoding
* engines. If the specified elements are found in the certificate
* subject DN or the SAN extension, then the name contents are copied
* as zero-terminated strings into the buffer.
*
* The decoder converts TeletexString and BMPString to UTF8String, and
* ensures that the resulting string is zero-terminated. If the string
* does not fit in the provided buffer, then the copy is aborted and an
* error is reported.
*/
typedef struct {
/**
* \brief Element OID.
*
* For X.500 name elements (to be extracted from the subject DN),
* this is the encoded OID for the requested name element; the
* first byte shall contain the length of the DER-encoded OID
* value, followed by the OID value (for instance, OID 2.5.4.3,
* for id-at-commonName, will be `03 55 04 03`). This is
* equivalent to full DER encoding with the length but without
* the tag.
*
* For SAN name elements, the first byte (`oid[0]`) has value 0,
* followed by another byte that matches the expected GeneralName
* tag. Allowed second byte values are then:
*
* - 1: `rfc822Name`
*
* - 2: `dNSName`
*
* - 6: `uniformResourceIdentifier`
*
* - 0: `otherName`
*
* If first and second byte are 0, then this is a SAN element of
* type `otherName`; the `oid[]` array should then contain, right
* after the two bytes of value 0, an encoded OID (with the same
* conventions as for X.500 name elements). If a match is found
* for that OID, then the corresponding name element will be
* extracted, as long as it is a supported string type.
*/
const unsigned char *oid;
/**
* \brief Destination buffer.
*/
char *buf;
/**
* \brief Length (in bytes) of the destination buffer.
*
* The buffer MUST NOT be smaller than 1 byte.
*/
size_t len;
/**
* \brief Decoding status.
*
* Status is 0 if the name element was not found, 1 if it was
* found and decoded, or -1 on error. Error conditions include
* an unrecognised encoding, an invalid encoding, or a string
* too large for the destination buffer.
*/
int status;
} br_name_element;
/**
* \brief Callback for validity date checks.
*
* The function receives as parameter an arbitrary user-provided context,
* and the notBefore and notAfter dates specified in an X.509 certificate,
* both expressed as a number of days and a number of seconds:
*
* - Days are counted in a proleptic Gregorian calendar since
* January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD";
* it is also traditionally known as "1 BC".
*
* - Seconds are counted since midnight, from 0 to 86400 (a count of
* 86400 is possible only if a leap second happened).
*
* Each date and time is understood in the UTC time zone. The "Unix
* Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and
* seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is
* days=584754, seconds=0.
*
* This function must return -1 if the current date is strictly before
* the "notBefore" time, or +1 if the current date is strictly after the
* "notAfter" time. If neither condition holds, then the function returns
* 0, which means that the current date falls within the validity range of
* the certificate. If the function returns a value distinct from -1, 0
* and +1, then this is interpreted as an unavailability of the current
* time, which normally ends the validation process with a
* `BR_ERR_X509_TIME_UNKNOWN` error.
*
* During path validation, this callback will be invoked for each
* considered X.509 certificate. Validation fails if any of the calls
* returns a non-zero value.
*
* The context value is an abritrary pointer set by the caller when
* configuring this callback.
*
* \param tctx context pointer.
* \param not_before_days notBefore date (days since Jan 1st, 0 AD).
* \param not_before_seconds notBefore time (seconds, at most 86400).
* \param not_after_days notAfter date (days since Jan 1st, 0 AD).
* \param not_after_seconds notAfter time (seconds, at most 86400).
* \return -1, 0 or +1.
*/
typedef int (*br_x509_time_check)(void *tctx,
uint32_t not_before_days, uint32_t not_before_seconds,
uint32_t not_after_days, uint32_t not_after_seconds);
/**
* \brief The "minimal" X.509 engine structure.
*
* The structure contents are opaque (they shall not be accessed directly),
* except for the first field (the vtable).
*
* The "minimal" engine performs a rudimentary but serviceable X.509 path
* validation.
*/
typedef struct {
const br_x509_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the EE public key. */
br_x509_pkey pkey;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[31];
uint32_t rp_stack[31];
int err;
/* Server name to match with the SAN / CN of the EE certificate. */
const char *server_name;
/* Validated key usages. */
unsigned char key_usages;
/* Explicitly set date and time. */
uint32_t days, seconds;
/* Current certificate length (in bytes). Set to 0 when the
certificate has been fully processed. */
uint32_t cert_length;
/* Number of certificates processed so far in the current chain.
It is incremented at the end of the processing of a certificate,
so it is 0 for the EE. */
uint32_t num_certs;
/* Certificate data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Buffer for EE public key data. */
unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY];
/* Buffer for currently decoded public key. */
unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
/* Signature type: signer key type, offset to the hash
function OID (in the T0 data block) and hash function
output length (TBS hash length). */
unsigned char cert_signer_key_type;
uint16_t cert_sig_hash_oid;
unsigned char cert_sig_hash_len;
/* Current/last certificate signature. */
unsigned char cert_sig[BR_X509_BUFSIZE_SIG];
uint16_t cert_sig_len;
/* Minimum RSA key length (difference in bytes from 128). */
int16_t min_rsa_size;
/* Configured trust anchors. */
const br_x509_trust_anchor *trust_anchors;
size_t trust_anchors_num;
/*
* Multi-hasher for the TBS.
*/
unsigned char do_mhash;
br_multihash_context mhash;
unsigned char tbs_hash[64];
/*
* Simple hasher for the subject/issuer DN.
*/
unsigned char do_dn_hash;
const br_hash_class *dn_hash_impl;
br_hash_compat_context dn_hash;
unsigned char current_dn_hash[64];
unsigned char next_dn_hash[64];
unsigned char saved_dn_hash[64];
/*
* Name elements to gather.
*/
br_name_element *name_elts;
size_t num_name_elts;
/*
* Callback function (and context) to get the current date.
*/
void *itime_ctx;
br_x509_time_check itime;
/*
* Public key cryptography implementations (signature verification).
*/
br_rsa_pkcs1_vrfy irsa;
br_ecdsa_vrfy iecdsa;
const br_ec_impl *iec;
#endif
} br_x509_minimal_context;
/**
* \brief Class instance for the "minimal" X.509 engine.
*/
extern const br_x509_class br_x509_minimal_vtable;
/**
* \brief Initialise a "minimal" X.509 engine.
*
* The `dn_hash_impl` parameter shall be a hash function internally used
* to match X.500 names (subject/issuer DN, and anchor names). Any standard
* hash function may be used, but a collision-resistant hash function is
* advised.
*
* After initialization, some implementations for signature verification
* (hash functions and signature algorithms) MUST be added.
*
* \param ctx context to initialise.
* \param dn_hash_impl hash function for DN comparisons.
* \param trust_anchors trust anchors.
* \param trust_anchors_num number of trust anchors.
*/
void br_x509_minimal_init(br_x509_minimal_context *ctx,
const br_hash_class *dn_hash_impl,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
/**
* \brief Set a supported hash function in an X.509 "minimal" engine.
*
* Hash functions are used with signature verification algorithms.
* Once initialised (with `br_x509_minimal_init()`), the context must
* be configured with the hash functions it shall support for that
* purpose. The hash function identifier MUST be one of the standard
* hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256,
* SHA-384 and SHA-512).
*
* If `impl` is `NULL`, this _removes_ support for the designated
* hash function.
*
* \param ctx validation context.
* \param id hash function identifier (from 1 to 6).
* \param impl hash function implementation (or `NULL`).
*/
static inline void
br_x509_minimal_set_hash(br_x509_minimal_context *ctx,
int id, const br_hash_class *impl)
{
br_multihash_setimpl(&ctx->mhash, id, impl);
}
/**
* \brief Set a RSA signature verification implementation in the X.509
* "minimal" engine.
*
* Once initialised (with `br_x509_minimal_init()`), the context must
* be configured with the signature verification implementations that
* it is supposed to support. If `irsa` is `0`, then the RSA support
* is disabled.
*
* \param ctx validation context.
* \param irsa RSA signature verification implementation (or `0`).
*/
static inline void
br_x509_minimal_set_rsa(br_x509_minimal_context *ctx,
br_rsa_pkcs1_vrfy irsa)
{
ctx->irsa = irsa;
}
/**
* \brief Set a ECDSA signature verification implementation in the X.509
* "minimal" engine.
*
* Once initialised (with `br_x509_minimal_init()`), the context must
* be configured with the signature verification implementations that
* it is supposed to support.
*
* If `iecdsa` is `0`, then this call disables ECDSA support; in that
* case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function
* that verifies ECDSA signatures with format "asn1", and it will use
* `iec` as underlying elliptic curve support.
*
* \param ctx validation context.
* \param iec elliptic curve implementation (or `NULL`).
* \param iecdsa ECDSA implementation (or `0`).
*/
static inline void
br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx,
const br_ec_impl *iec, br_ecdsa_vrfy iecdsa)
{
ctx->iecdsa = iecdsa;
ctx->iec = iec;
}
/**
* \brief Initialise a "minimal" X.509 engine with default algorithms.
*
* This function performs the same job as `br_x509_minimal_init()`, but
* also sets implementations for RSA, ECDSA, and the standard hash
* functions.
*
* \param ctx context to initialise.
* \param trust_anchors trust anchors.
* \param trust_anchors_num number of trust anchors.
*/
void br_x509_minimal_init_full(br_x509_minimal_context *ctx,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
/**
* \brief Set the validation time for the X.509 "minimal" engine.
*
* The validation time is set as two 32-bit integers, for days and
* seconds since a fixed epoch:
*
* - Days are counted in a proleptic Gregorian calendar since
* January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD";
* it is also traditionally known as "1 BC".
*
* - Seconds are counted since midnight, from 0 to 86400 (a count of
* 86400 is possible only if a leap second happened).
*
* The validation date and time is understood in the UTC time zone. The
* "Unix Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528
* and seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is
* days=584754, seconds=0.
*
* If the validation date and time are not explicitly set, but BearSSL
* was compiled with support for the system clock on the underlying
* platform, then the current time will automatically be used. Otherwise,
* not setting the validation date and time implies a validation
* failure (except in case of direct trust of the EE key).
*
* \param ctx validation context.
* \param days days since January 1st, 0 AD (Gregorian calendar).
* \param seconds seconds since midnight (0 to 86400).
*/
static inline void
br_x509_minimal_set_time(br_x509_minimal_context *ctx,
uint32_t days, uint32_t seconds)
{
ctx->days = days;
ctx->seconds = seconds;
ctx->itime = 0;
}
/**
* \brief Set the validity range callback function for the X.509
* "minimal" engine.
*
* The provided function will be invoked to check whether the validation
* date is within the validity range for a given X.509 certificate; a
* call will be issued for each considered certificate. The provided
* context pointer (itime_ctx) will be passed as first parameter to the
* callback.
*
* \param tctx context for callback invocation.
* \param cb callback function.
*/
static inline void
br_x509_minimal_set_time_callback(br_x509_minimal_context *ctx,
void *itime_ctx, br_x509_time_check itime)
{
ctx->itime_ctx = itime_ctx;
ctx->itime = itime;
}
/**
* \brief Set the minimal acceptable length for RSA keys (X.509 "minimal"
* engine).
*
* The RSA key length is expressed in bytes. The default minimum key
* length is 128 bytes, corresponding to 1017 bits. RSA keys shorter
* than the configured length will be rejected, implying validation
* failure. This setting applies to keys extracted from certificates
* (both end-entity, and intermediate CA) but not to "CA" trust anchors.
*
* \param ctx validation context.
* \param byte_length minimum RSA key length, **in bytes** (not bits).
*/
static inline void
br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length)
{
ctx->min_rsa_size = (int16_t)(byte_length - 128);
}
/**
* \brief Set the name elements to gather.
*
* The provided array is linked in the context. The elements are
* gathered from the EE certificate. If the same element type is
* requested several times, then the relevant structures will be filled
* in the order the matching values are encountered in the certificate.
*
* \param ctx validation context.
* \param elts array of name element structures to fill.
* \param num_elts number of name element structures to fill.
*/
static inline void
br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx,
br_name_element *elts, size_t num_elts)
{
ctx->name_elts = elts;
ctx->num_name_elts = num_elts;
}
/**
* \brief X.509 decoder context.
*
* This structure is _not_ for X.509 validation, but for extracting
* names and public keys from encoded certificates. Intended usage is
* to use (self-signed) certificates as trust anchors.
*
* Contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the public key. */
br_x509_pkey pkey;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Flag set when decoding succeeds. */
unsigned char decoded;
/* Validity dates. */
uint32_t notbefore_days, notbefore_seconds;
uint32_t notafter_days, notafter_seconds;
/* The "CA" flag. This is set to true if the certificate contains
a Basic Constraints extension that asserts CA status. */
unsigned char isCA;
/* DN processing: the subject DN is extracted and pushed to the
provided callback. */
unsigned char copy_dn;
void *append_dn_ctx;
void (*append_dn)(void *ctx, const void *buf, size_t len);
/* Certificate data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* Buffer for decoded public key. */
unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
/* Type of key and hash function used in the certificate signature. */
unsigned char signer_key_type;
unsigned char signer_hash_id;
#endif
} br_x509_decoder_context;
/**
* \brief Initialise an X.509 decoder context for processing a new
* certificate.
*
* The `append_dn()` callback (with opaque context `append_dn_ctx`)
* will be invoked to receive, chunk by chunk, the certificate's
* subject DN. If `append_dn` is `0` then the subject DN will be
* ignored.
*
* \param ctx X.509 decoder context to initialise.
* \param append_dn DN receiver callback (or `0`).
* \param append_dn_ctx context for the DN receiver callback.
*/
void br_x509_decoder_init(br_x509_decoder_context *ctx,
void (*append_dn)(void *ctx, const void *buf, size_t len),
void *append_dn_ctx);
/**
* \brief Push some certificate bytes into a decoder context.
*
* If `len` is non-zero, then that many bytes are pushed, from address
* `data`, into the provided decoder context.
*
* \param ctx X.509 decoder context.
* \param data certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void br_x509_decoder_push(br_x509_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Obtain the decoded public key.
*
* Returned value is a pointer to a structure internal to the decoder
* context; releasing or reusing the decoder context invalidates that
* structure.
*
* If decoding was not finished, or failed, then `NULL` is returned.
*
* \param ctx X.509 decoder context.
* \return the public key, or `NULL` on unfinished/error.
*/
static inline br_x509_pkey *
br_x509_decoder_get_pkey(br_x509_decoder_context *ctx)
{
if (ctx->decoded && ctx->err == 0) {
return &ctx->pkey;
} else {
return NULL;
}
}
/**
* \brief Get decoder error status.
*
* If no error was reported yet but the certificate decoding is not
* finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding
* was successful, then 0 is returned.
*
* \param ctx X.509 decoder context.
* \return 0 on successful decoding, or a non-zero error code.
*/
static inline int
br_x509_decoder_last_error(br_x509_decoder_context *ctx)
{
if (ctx->err != 0) {
return ctx->err;
}
if (!ctx->decoded) {
return BR_ERR_X509_TRUNCATED;
}
return 0;
}
/**
* \brief Get the "isCA" flag from an X.509 decoder context.
*
* This flag is set if the decoded certificate claims to be a CA through
* a Basic Constraints extension. This flag should not be read before
* decoding completed successfully.
*
* \param ctx X.509 decoder context.
* \return the "isCA" flag.
*/
static inline int
br_x509_decoder_isCA(br_x509_decoder_context *ctx)
{
return ctx->isCA;
}
/**
* \brief Get the issuing CA key type (type of algorithm used to sign the
* decoded certificate).
*
* This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned
* if the signature type was not recognised.
*
* \param ctx X.509 decoder context.
* \return the issuing CA key type.
*/
static inline int
br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx)
{
return ctx->signer_key_type;
}
/**
* \brief Get the identifier for the hash function used to sign the decoded
* certificate.
*
* This is 0 if the hash function was not recognised.
*
* \param ctx X.509 decoder context.
* \return the signature hash function identifier.
*/
static inline int
br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx)
{
return ctx->signer_hash_id;
}
/**
* \brief Type for an X.509 certificate (DER-encoded).
*/
typedef struct {
/** \brief The DER-encoded certificate data. */
unsigned char *data;
/** \brief The DER-encoded certificate length (in bytes). */
size_t data_len;
} br_x509_certificate;
/**
* \brief Private key decoder context.
*
* The private key decoder recognises RSA and EC private keys, either in
* their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8
* archive (again DER-encoded).
*
* Structure contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the private key. */
union {
br_rsa_private_key rsa;
br_ec_private_key ec;
} key;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
/* Private key data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Decoded key type; 0 until decoding is complete. */
unsigned char key_type;
/* Buffer for the private key elements. It shall be large enough
to accommodate all elements for a RSA-4096 private key (roughly
five 2048-bit integers, possibly a bit more). */
unsigned char key_data[3 * BR_X509_BUFSIZE_SIG];
#endif
} br_skey_decoder_context;
/**
* \brief Initialise a private key decoder context.
*
* \param ctx key decoder context to initialise.
*/
void br_skey_decoder_init(br_skey_decoder_context *ctx);
/**
* \brief Push some data bytes into a private key decoder context.
*
* If `len` is non-zero, then that many data bytes, starting at address
* `data`, are pushed into the decoder.
*
* \param ctx key decoder context.
* \param data private key data chunk.
* \param len private key data chunk length (in bytes).
*/
void br_skey_decoder_push(br_skey_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Get the decoding status for a private key.
*
* Decoding status is 0 on success, or a non-zero error code. If the
* decoding is unfinished when this function is called, then the
* status code `BR_ERR_X509_TRUNCATED` is returned.
*
* \param ctx key decoder context.
* \return 0 on successful decoding, or a non-zero error code.
*/
static inline int
br_skey_decoder_last_error(const br_skey_decoder_context *ctx)
{
if (ctx->err != 0) {
return ctx->err;
}
if (ctx->key_type == 0) {
return BR_ERR_X509_TRUNCATED;
}
return 0;
}
/**
* \brief Get the decoded private key type.
*
* Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is
* not finished or failed, then 0 is returned.
*
* \param ctx key decoder context.
* \return decoded private key type, or 0.
*/
static inline int
br_skey_decoder_key_type(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0) {
return ctx->key_type;
} else {
return 0;
}
}
/**
* \brief Get the decoded RSA private key.
*
* This function returns `NULL` if the decoding failed, or is not
* finished, or the key is not RSA. The returned pointer references
* structures within the context that can become invalid if the context
* is reused or released.
*
* \param ctx key decoder context.
* \return decoded RSA private key, or `NULL`.
*/
static inline const br_rsa_private_key *
br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) {
return &ctx->key.rsa;
} else {
return NULL;
}
}
/**
* \brief Get the decoded EC private key.
*
* This function returns `NULL` if the decoding failed, or is not
* finished, or the key is not EC. The returned pointer references
* structures within the context that can become invalid if the context
* is reused or released.
*
* \param ctx key decoder context.
* \return decoded EC private key, or `NULL`.
*/
static inline const br_ec_private_key *
br_skey_decoder_get_ec(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) {
return &ctx->key.ec;
} else {
return NULL;
}
}
/**
* \brief Encode an RSA private key (raw DER format).
*
* This function encodes the provided key into the "raw" format specified
* in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER
* encoding rules.
*
* The key elements are:
*
* - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`)
*
* - `pk`: the public key (`n` and `e`)
*
* - `d` (size: `dlen` bytes): the private exponent
*
* The public key elements, and the private exponent `d`, can be
* recomputed from the private key (see `br_rsa_compute_modulus()`,
* `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the RSA private key.
* \param pk the RSA public key.
* \param d the RSA private exponent.
* \param dlen the RSA private exponent length (in bytes).
* \return the encoded key length (in bytes).
*/
size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk,
const br_rsa_public_key *pk, const void *d, size_t dlen);
/**
* \brief Encode an RSA private key (PKCS#8 DER format).
*
* This function encodes the provided key into the PKCS#8 format
* (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER"
* format for the RSA key, as implemented by `br_encode_rsa_raw_der()`.
*
* The key elements are:
*
* - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`)
*
* - `pk`: the public key (`n` and `e`)
*
* - `d` (size: `dlen` bytes): the private exponent
*
* The public key elements, and the private exponent `d`, can be
* recomputed from the private key (see `br_rsa_compute_modulus()`,
* `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the RSA private key.
* \param pk the RSA public key.
* \param d the RSA private exponent.
* \param dlen the RSA private exponent length (in bytes).
* \return the encoded key length (in bytes).
*/
size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk,
const br_rsa_public_key *pk, const void *d, size_t dlen);
/**
* \brief Encode an EC private key (raw DER format).
*
* This function encodes the provided key into the "raw" format specified
* in RFC 5915 (type `ECPrivateKey`), with DER encoding rules.
*
* The private key is provided in `sk`, the public key being `pk`. If
* `pk` is `NULL`, then the encoded key will not include the public key
* in its `publicKey` field (which is nominally optional).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* If the key cannot be encoded (e.g. because there is no known OBJECT
* IDENTIFIER for the used curve), then 0 is returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the EC private key.
* \param pk the EC public key (or `NULL`).
* \return the encoded key length (in bytes), or 0.
*/
size_t br_encode_ec_raw_der(void *dest,
const br_ec_private_key *sk, const br_ec_public_key *pk);
/**
* \brief Encode an EC private key (PKCS#8 DER format).
*
* This function encodes the provided key into the PKCS#8 format
* (RFC 5958, type `OneAsymmetricKey`). The curve is identified
* by an OID provided as parameters to the `privateKeyAlgorithm`
* field. The private key value (contents of the `privateKey` field)
* contains the DER encoding of the `ECPrivateKey` type defined in
* RFC 5915, without the `parameters` field (since they would be
* redundant with the information in `privateKeyAlgorithm`).
*
* The private key is provided in `sk`, the public key being `pk`. If
* `pk` is not `NULL`, then the encoded public key is included in the
* `publicKey` field of the private key value (but not in the `publicKey`
* field of the PKCS#8 `OneAsymmetricKey` wrapper).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* If the key cannot be encoded (e.g. because there is no known OBJECT
* IDENTIFIER for the used curve), then 0 is returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the EC private key.
* \param pk the EC public key (or `NULL`).
* \return the encoded key length (in bytes), or 0.
*/
size_t br_encode_ec_pkcs8_der(void *dest,
const br_ec_private_key *sk, const br_ec_public_key *pk);
/**
* \brief PEM banner for RSA private key (raw).
*/
#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY"
/**
* \brief PEM banner for EC private key (raw).
*/
#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY"
/**
* \brief PEM banner for an RSA or EC private key in PKCS#8 format.
*/
#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY"
#ifdef __cplusplus
}
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_ssl.h
*
* # SSL
*
* For an overview of the SSL/TLS API, see [the BearSSL Web
* site](https://www.bearssl.org/api1.html).
*
* The `BR_TLS_*` constants correspond to the standard cipher suites and
* their values in the [IANA
* registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4).
*
* The `BR_ALERT_*` constants are for standard TLS alert messages. When
* a fatal alert message is sent of received, then the SSL engine context
* status is set to the sum of that alert value (an integer in the 0..255
* range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert,
* `BR_ERR_RECV_FATAL_ALERT` for a received alert).
*/
/** \brief Optimal input buffer size. */
#define BR_SSL_BUFSIZE_INPUT (16384 + 325)
/** \brief Optimal output buffer size. */
#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85)
/** \brief Optimal buffer size for monodirectional engine
(shared input/output buffer). */
#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT
/** \brief Optimal buffer size for bidirectional engine
(single buffer split into two separate input/output buffers). */
#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT)
/*
* Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1
* and TLS 1.2). Note that though there is a constant for SSL 3.0, that
* protocol version is not actually supported.
*/
/** \brief Protocol version: SSL 3.0 (unsupported). */
#define BR_SSL30 0x0300
/** \brief Protocol version: TLS 1.0. */
#define BR_TLS10 0x0301
/** \brief Protocol version: TLS 1.1. */
#define BR_TLS11 0x0302
/** \brief Protocol version: TLS 1.2. */
#define BR_TLS12 0x0303
/*
* Error constants. They are used to report the reason why a context has
* been marked as failed.
*
* Implementation note: SSL-level error codes should be in the 1..31
* range. The 32..63 range is for certificate decoding and validation
* errors. Received fatal alerts imply an error code in the 256..511 range.
*/
/** \brief SSL status: no error so far (0). */
#define BR_ERR_OK 0
/** \brief SSL status: caller-provided parameter is incorrect. */
#define BR_ERR_BAD_PARAM 1
/** \brief SSL status: operation requested by the caller cannot be applied
with the current context state (e.g. reading data while outgoing data
is waiting to be sent). */
#define BR_ERR_BAD_STATE 2
/** \brief SSL status: incoming protocol or record version is unsupported. */
#define BR_ERR_UNSUPPORTED_VERSION 3
/** \brief SSL status: incoming record version does not match the expected
version. */
#define BR_ERR_BAD_VERSION 4
/** \brief SSL status: incoming record length is invalid. */
#define BR_ERR_BAD_LENGTH 5
/** \brief SSL status: incoming record is too large to be processed, or
buffer is too small for the handshake message to send. */
#define BR_ERR_TOO_LARGE 6
/** \brief SSL status: decryption found an invalid padding, or the record
MAC is not correct. */
#define BR_ERR_BAD_MAC 7
/** \brief SSL status: no initial entropy was provided, and none can be
obtained from the OS. */
#define BR_ERR_NO_RANDOM 8
/** \brief SSL status: incoming record type is unknown. */
#define BR_ERR_UNKNOWN_TYPE 9
/** \brief SSL status: incoming record or message has wrong type with
regards to the current engine state. */
#define BR_ERR_UNEXPECTED 10
/** \brief SSL status: ChangeCipherSpec message from the peer has invalid
contents. */
#define BR_ERR_BAD_CCS 12
/** \brief SSL status: alert message from the peer has invalid contents
(odd length). */
#define BR_ERR_BAD_ALERT 13
/** \brief SSL status: incoming handshake message decoding failed. */
#define BR_ERR_BAD_HANDSHAKE 14
/** \brief SSL status: ServerHello contains a session ID which is larger
than 32 bytes. */
#define BR_ERR_OVERSIZED_ID 15
/** \brief SSL status: server wants to use a cipher suite that we did
not claim to support. This is also reported if we tried to advertise
a cipher suite that we do not support. */
#define BR_ERR_BAD_CIPHER_SUITE 16
/** \brief SSL status: server wants to use a compression that we did not
claim to support. */
#define BR_ERR_BAD_COMPRESSION 17
/** \brief SSL status: server's max fragment length does not match
client's. */
#define BR_ERR_BAD_FRAGLEN 18
/** \brief SSL status: secure renegotiation failed. */
#define BR_ERR_BAD_SECRENEG 19
/** \brief SSL status: server sent an extension type that we did not
announce, or used the same extension type several times in a single
ServerHello. */
#define BR_ERR_EXTRA_EXTENSION 20
/** \brief SSL status: invalid Server Name Indication contents (when
used by the server, this extension shall be empty). */
#define BR_ERR_BAD_SNI 21
/** \brief SSL status: invalid ServerHelloDone from the server (length
is not 0). */
#define BR_ERR_BAD_HELLO_DONE 22
/** \brief SSL status: internal limit exceeded (e.g. server's public key
is too large). */
#define BR_ERR_LIMIT_EXCEEDED 23
/** \brief SSL status: Finished message from peer does not match the
expected value. */
#define BR_ERR_BAD_FINISHED 24
/** \brief SSL status: session resumption attempt with distinct version
or cipher suite. */
#define BR_ERR_RESUME_MISMATCH 25
/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve,
signature algorithm, hash function). */
#define BR_ERR_INVALID_ALGORITHM 26
/** \brief SSL status: invalid signature (on ServerKeyExchange from
server, or in CertificateVerify from client). */
#define BR_ERR_BAD_SIGNATURE 27
/** \brief SSL status: peer's public key does not have the proper type
or is not allowed for requested operation. */
#define BR_ERR_WRONG_KEY_USAGE 28
/** \brief SSL status: client did not send a certificate upon request,
or the client certificate could not be validated. */
#define BR_ERR_NO_CLIENT_AUTH 29
/** \brief SSL status: I/O error or premature close on underlying
transport stream. This error code is set only by the simplified
I/O API ("br_sslio_*"). */
#define BR_ERR_IO 31
/** \brief SSL status: base value for a received fatal alert.
When a fatal alert is received from the peer, the alert value
is added to this constant. */
#define BR_ERR_RECV_FATAL_ALERT 256
/** \brief SSL status: base value for a sent fatal alert.
When a fatal alert is sent to the peer, the alert value is added
to this constant. */
#define BR_ERR_SEND_FATAL_ALERT 512
/* ===================================================================== */
/**
* \brief Decryption engine for SSL.
*
* When processing incoming records, the SSL engine will use a decryption
* engine that uses a specific context structure, and has a set of
* methods (a vtable) that follows this template.
*
* The decryption engine is responsible for applying decryption, verifying
* MAC, and keeping track of the record sequence number.
*/
typedef struct br_sslrec_in_class_ br_sslrec_in_class;
struct br_sslrec_in_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Test validity of the incoming record length.
*
* This function returns 1 if the announced length for an
* incoming record is valid, 0 otherwise,
*
* \param ctx decryption engine context.
* \param record_len incoming record length.
* \return 1 of a valid length, 0 otherwise.
*/
int (*check_length)(const br_sslrec_in_class *const *ctx,
size_t record_len);
/**
* \brief Decrypt the incoming record.
*
* This function may assume that the record length is valid
* (it has been previously tested with `check_length()`).
* Decryption is done in place; `*len` is updated with the
* cleartext length, and the address of the first plaintext
* byte is returned. If the record is correct but empty, then
* `*len` is set to 0 and a non-`NULL` pointer is returned.
*
* On decryption/MAC error, `NULL` is returned.
*
* \param ctx decryption engine context.
* \param record_type record type (23 for application data, etc).
* \param version record version.
* \param payload address of encrypted payload.
* \param len pointer to payload length (updated).
* \return pointer to plaintext, or `NULL` on error.
*/
unsigned char *(*decrypt)(const br_sslrec_in_class **ctx,
int record_type, unsigned version,
void *payload, size_t *len);
};
/**
* \brief Encryption engine for SSL.
*
* When building outgoing records, the SSL engine will use an encryption
* engine that uses a specific context structure, and has a set of
* methods (a vtable) that follows this template.
*
* The encryption engine is responsible for applying encryption and MAC,
* and keeping track of the record sequence number.
*/
typedef struct br_sslrec_out_class_ br_sslrec_out_class;
struct br_sslrec_out_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Compute maximum plaintext sizes and offsets.
*
* When this function is called, the `*start` and `*end`
* values contain offsets designating the free area in the
* outgoing buffer for plaintext data; that free area is
* preceded by a 5-byte space which will receive the record
* header.
*
* The `max_plaintext()` function is responsible for adjusting
* both `*start` and `*end` to make room for any record-specific
* header, MAC, padding, and possible split.
*
* \param ctx encryption engine context.
* \param start pointer to start of plaintext offset (updated).
* \param end pointer to start of plaintext offset (updated).
*/
void (*max_plaintext)(const br_sslrec_out_class *const *ctx,
size_t *start, size_t *end);
/**
* \brief Perform record encryption.
*
* This function encrypts the record. The plaintext address and
* length are provided. Returned value is the start of the
* encrypted record (or sequence of records, if a split was
* performed), _including_ the 5-byte header, and `*len` is
* adjusted to the total size of the record(s), there again
* including the header(s).
*
* \param ctx decryption engine context.
* \param record_type record type (23 for application data, etc).
* \param version record version.
* \param plaintext address of plaintext.
* \param len pointer to plaintext length (updated).
* \return pointer to start of built record.
*/
unsigned char *(*encrypt)(const br_sslrec_out_class **ctx,
int record_type, unsigned version,
void *plaintext, size_t *len);
};
/**
* \brief Context for a no-encryption engine.
*
* The no-encryption engine processes outgoing records during the initial
* handshake, before encryption is applied.
*/
typedef struct {
/** \brief No-encryption engine vtable. */
const br_sslrec_out_class *vtable;
} br_sslrec_out_clear_context;
/** \brief Static, constant vtable for the no-encryption engine. */
extern const br_sslrec_out_class br_sslrec_out_clear_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for CBC mode.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for CBC processing: block cipher implementation, block cipher key,
* HMAC parameters (hash function, key, MAC length), and IV. If the
* IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
*/
typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class;
struct br_sslrec_in_cbc_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CBC decryption).
* \param bc_key block cipher key.
* \param bc_key_len block cipher key length (in bytes).
* \param dig_impl hash function for HMAC.
* \param mac_key HMAC key.
* \param mac_key_len HMAC key length (in bytes).
* \param mac_out_len HMAC output length (in bytes).
* \param iv initial IV (or `NULL`).
*/
void (*init)(const br_sslrec_in_cbc_class **ctx,
const br_block_cbcdec_class *bc_impl,
const void *bc_key, size_t bc_key_len,
const br_hash_class *dig_impl,
const void *mac_key, size_t mac_key_len, size_t mac_out_len,
const void *iv);
};
/**
* \brief Record encryption engine class, for CBC mode.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for CBC processing: block cipher implementation, block cipher key,
* HMAC parameters (hash function, key, MAC length), and IV. If the
* IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
*/
typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class;
struct br_sslrec_out_cbc_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CBC encryption).
* \param bc_key block cipher key.
* \param bc_key_len block cipher key length (in bytes).
* \param dig_impl hash function for HMAC.
* \param mac_key HMAC key.
* \param mac_key_len HMAC key length (in bytes).
* \param mac_out_len HMAC output length (in bytes).
* \param iv initial IV (or `NULL`).
*/
void (*init)(const br_sslrec_out_cbc_class **ctx,
const br_block_cbcenc_class *bc_impl,
const void *bc_key, size_t bc_key_len,
const br_hash_class *dig_impl,
const void *mac_key, size_t mac_key_len, size_t mac_out_len,
const void *iv);
};
/**
* \brief Context structure for decrypting incoming records with
* CBC + HMAC.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_sslrec_in_cbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_cbcdec_class *vtable;
br_aes_gen_cbcdec_keys aes;
br_des_gen_cbcdec_keys des;
} bc;
br_hmac_key_context mac;
size_t mac_len;
unsigned char iv[16];
int explicit_IV;
#endif
} br_sslrec_in_cbc_context;
/**
* \brief Static, constant vtable for record decryption with CBC.
*/
extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable;
/**
* \brief Context structure for encrypting outgoing records with
* CBC + HMAC.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_sslrec_out_cbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_cbcenc_class *vtable;
br_aes_gen_cbcenc_keys aes;
br_des_gen_cbcenc_keys des;
} bc;
br_hmac_key_context mac;
size_t mac_len;
unsigned char iv[16];
int explicit_IV;
#endif
} br_sslrec_out_cbc_context;
/**
* \brief Static, constant vtable for record encryption with CBC.
*/
extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for GCM mode.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for GCM processing: block cipher implementation, block cipher key,
* GHASH implementation, and 4-byte IV.
*/
typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class;
struct br_sslrec_in_gcm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param gh_impl GHASH implementation.
* \param iv static IV (4 bytes).
*/
void (*init)(const br_sslrec_in_gcm_class **ctx,
const br_block_ctr_class *bc_impl,
const void *key, size_t key_len,
br_ghash gh_impl,
const void *iv);
};
/**
* \brief Record encryption engine class, for GCM mode.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for GCM processing: block cipher implementation, block cipher key,
* GHASH implementation, and 4-byte IV.
*/
typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class;
struct br_sslrec_out_gcm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param gh_impl GHASH implementation.
* \param iv static IV (4 bytes).
*/
void (*init)(const br_sslrec_out_gcm_class **ctx,
const br_block_ctr_class *bc_impl,
const void *key, size_t key_len,
br_ghash gh_impl,
const void *iv);
};
/**
* \brief Context structure for processing records with GCM.
*
* The same context structure is used for encrypting and decrypting.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
union {
const void *gen;
const br_sslrec_in_gcm_class *in;
const br_sslrec_out_gcm_class *out;
} vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_ctr_class *vtable;
br_aes_gen_ctr_keys aes;
} bc;
br_ghash gh;
unsigned char iv[4];
unsigned char h[16];
#endif
} br_sslrec_gcm_context;
/**
* \brief Static, constant vtable for record decryption with GCM.
*/
extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable;
/**
* \brief Static, constant vtable for record encryption with GCM.
*/
extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for ChaCha20+Poly1305.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for ChaCha20+Poly1305 processing: ChaCha20 implementation,
* Poly1305 implementation, key, and 12-byte IV.
*/
typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class;
struct br_sslrec_in_chapol_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param ichacha ChaCha20 implementation.
* \param ipoly Poly1305 implementation.
* \param key secret key (32 bytes).
* \param iv static IV (12 bytes).
*/
void (*init)(const br_sslrec_in_chapol_class **ctx,
br_chacha20_run ichacha,
br_poly1305_run ipoly,
const void *key, const void *iv);
};
/**
* \brief Record encryption engine class, for ChaCha20+Poly1305.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for ChaCha20+Poly1305 processing: ChaCha20 implementation,
* Poly1305 implementation, key, and 12-byte IV.
*/
typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class;
struct br_sslrec_out_chapol_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param ichacha ChaCha20 implementation.
* \param ipoly Poly1305 implementation.
* \param key secret key (32 bytes).
* \param iv static IV (12 bytes).
*/
void (*init)(const br_sslrec_out_chapol_class **ctx,
br_chacha20_run ichacha,
br_poly1305_run ipoly,
const void *key, const void *iv);
};
/**
* \brief Context structure for processing records with ChaCha20+Poly1305.
*
* The same context structure is used for encrypting and decrypting.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
union {
const void *gen;
const br_sslrec_in_chapol_class *in;
const br_sslrec_out_chapol_class *out;
} vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
unsigned char key[32];
unsigned char iv[12];
br_chacha20_run ichacha;
br_poly1305_run ipoly;
#endif
} br_sslrec_chapol_context;
/**
* \brief Static, constant vtable for record decryption with ChaCha20+Poly1305.
*/
extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable;
/**
* \brief Static, constant vtable for record encryption with ChaCha20+Poly1305.
*/
extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for CCM mode.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for CCM processing: block cipher implementation, block cipher key,
* and 4-byte IV.
*/
typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class;
struct br_sslrec_in_ccm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR+CBC).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param iv static IV (4 bytes).
* \param tag_len tag length (in bytes)
*/
void (*init)(const br_sslrec_in_ccm_class **ctx,
const br_block_ctrcbc_class *bc_impl,
const void *key, size_t key_len,
const void *iv, size_t tag_len);
};
/**
* \brief Record encryption engine class, for CCM mode.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for CCM processing: block cipher implementation, block cipher key,
* and 4-byte IV.
*/
typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class;
struct br_sslrec_out_ccm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR+CBC).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param iv static IV (4 bytes).
* \param tag_len tag length (in bytes)
*/
void (*init)(const br_sslrec_out_ccm_class **ctx,
const br_block_ctrcbc_class *bc_impl,
const void *key, size_t key_len,
const void *iv, size_t tag_len);
};
/**
* \brief Context structure for processing records with CCM.
*
* The same context structure is used for encrypting and decrypting.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
union {
const void *gen;
const br_sslrec_in_ccm_class *in;
const br_sslrec_out_ccm_class *out;
} vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_ctrcbc_class *vtable;
br_aes_gen_ctrcbc_keys aes;
} bc;
unsigned char iv[4];
size_t tag_len;
#endif
} br_sslrec_ccm_context;
/**
* \brief Static, constant vtable for record decryption with CCM.
*/
extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable;
/**
* \brief Static, constant vtable for record encryption with CCM.
*/
extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable;
/* ===================================================================== */
/**
* \brief Type for session parameters, to be saved for session resumption.
*/
typedef struct {
/** \brief Session ID buffer. */
unsigned char session_id[32];
/** \brief Session ID length (in bytes, at most 32). */
unsigned char session_id_len;
/** \brief Protocol version. */
uint16_t version;
/** \brief Cipher suite. */
uint16_t cipher_suite;
/** \brief Master secret. */
unsigned char master_secret[48];
} br_ssl_session_parameters;
#ifndef BR_DOXYGEN_IGNORE
/*
* Maximum number of cipher suites supported by a client or server.
*/
#define BR_MAX_CIPHER_SUITES 48
#endif
/**
* \brief Context structure for SSL engine.
*
* This strucuture is common to the client and server; both the client
* context (`br_ssl_client_context`) and the server context
* (`br_ssl_server_context`) include a `br_ssl_engine_context` as their
* first field.
*
* The engine context manages records, including alerts, closures, and
* transitions to new encryption/MAC algorithms. Processing of handshake
* records is delegated to externally provided code. This structure
* should not be used directly.
*
* Structure contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/*
* The error code. When non-zero, then the state is "failed" and
* no I/O may occur until reset.
*/
int err;
/*
* Configured I/O buffers. They are either disjoint, or identical.
*/
unsigned char *ibuf, *obuf;
size_t ibuf_len, obuf_len;
/*
* Maximum fragment length applies to outgoing records; incoming
* records can be processed as long as they fit in the input
* buffer. It is guaranteed that incoming records at least as big
* as max_frag_len can be processed.
*/
uint16_t max_frag_len;
unsigned char log_max_frag_len;
unsigned char peer_log_max_frag_len;
/*
* Buffering management registers.
*/
size_t ixa, ixb, ixc;
size_t oxa, oxb, oxc;
unsigned char iomode;
unsigned char incrypt;
/*
* Shutdown flag: when set to non-zero, incoming record bytes
* will not be accepted anymore. This is used after a close_notify
* has been received: afterwards, the engine no longer claims that
* it could receive bytes from the transport medium.
*/
unsigned char shutdown_recv;
/*
* 'record_type_in' is set to the incoming record type when the
* record header has been received.
* 'record_type_out' is used to make the next outgoing record
* header when it is ready to go.
*/
unsigned char record_type_in, record_type_out;
/*
* When a record is received, its version is extracted:
* -- if 'version_in' is 0, then it is set to the received version;
* -- otherwise, if the received version is not identical to
* the 'version_in' contents, then a failure is reported.
*
* This implements the SSL requirement that all records shall
* use the negotiated protocol version, once decided (in the
* ServerHello). It is up to the handshake handler to adjust this
* field when necessary.
*/
uint16_t version_in;
/*
* 'version_out' is used when the next outgoing record is ready
* to go.
*/
uint16_t version_out;
/*
* Record handler contexts.
*/
union {
const br_sslrec_in_class *vtable;
br_sslrec_in_cbc_context cbc;
br_sslrec_gcm_context gcm;
br_sslrec_chapol_context chapol;
br_sslrec_ccm_context ccm;
} in;
union {
const br_sslrec_out_class *vtable;
br_sslrec_out_clear_context clear;
br_sslrec_out_cbc_context cbc;
br_sslrec_gcm_context gcm;
br_sslrec_chapol_context chapol;
br_sslrec_ccm_context ccm;
} out;
/*
* The "application data" flag. Value:
* 0 handshake is in process, no application data acceptable
* 1 application data can be sent and received
* 2 closing, no application data can be sent, but some
* can still be received (and discarded)
*/
unsigned char application_data;
/*
* Context RNG.
*
* rng_init_done is initially 0. It is set to 1 when the
* basic structure of the RNG is set, and 2 when some
* entropy has been pushed in. The value 2 marks the RNG
* as "properly seeded".
*
* rng_os_rand_done is initially 0. It is set to 1 when
* some seeding from the OS or hardware has been attempted.
*/
br_hmac_drbg_context rng;
int rng_init_done;
int rng_os_rand_done;
/*
* Supported minimum and maximum versions, and cipher suites.
*/
uint16_t version_min;
uint16_t version_max;
uint16_t suites_buf[BR_MAX_CIPHER_SUITES];
unsigned char suites_num;
/*
* For clients, the server name to send as a SNI extension. For
* servers, the name received in the SNI extension (if any).
*/
char server_name[256];
/*
* "Security parameters". These are filled by the handshake
* handler, and used when switching encryption state.
*/
unsigned char client_random[32];
unsigned char server_random[32];
br_ssl_session_parameters session;
/*
* ECDHE elements: curve and point from the peer. The server also
* uses that buffer for the point to send to the client.
*/
unsigned char ecdhe_curve;
unsigned char ecdhe_point[133];
unsigned char ecdhe_point_len;
/*
* Secure renegotiation (RFC 5746): 'reneg' can be:
* 0 first handshake (server support is not known)
* 1 peer does not support secure renegotiation
* 2 peer supports secure renegotiation
*
* The saved_finished buffer contains the client and the
* server "Finished" values from the last handshake, in
* that order (12 bytes each).
*/
unsigned char reneg;
unsigned char saved_finished[24];
/*
* Behavioural flags.
*/
uint32_t flags;
/*
* Context variables for the handshake processor. The 'pad' must
* be large enough to accommodate an RSA-encrypted pre-master
* secret, or an RSA signature; since we want to support up to
* RSA-4096, this means at least 512 bytes. (Other pad usages
* require its length to be at least 256.)
*/
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
unsigned char pad[512];
unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out;
size_t hlen_in, hlen_out;
void (*hsrun)(void *ctx);
/*
* The 'action' value communicates OOB information between the
* engine and the handshake processor.
*
* From the engine:
* 0 invocation triggered by I/O
* 1 invocation triggered by explicit close
* 2 invocation triggered by explicit renegotiation
*/
unsigned char action;
/*
* State for alert messages. Value is either 0, or the value of
* the alert level byte (level is either 1 for warning, or 2 for
* fatal; we convert all other values to 'fatal').
*/
unsigned char alert;
/*
* Closure flags. This flag is set when a close_notify has been
* received from the peer.
*/
unsigned char close_received;
/*
* Multi-hasher for the handshake messages. The handshake handler
* is responsible for resetting it when appropriate.
*/
br_multihash_context mhash;
/*
* Pointer to the X.509 engine. The engine is supposed to be
* already initialized. It is used to validate the peer's
* certificate.
*/
const br_x509_class **x509ctx;
/*
* Certificate chain to send. This is used by both client and
* server, when they send their respective Certificate messages.
* If chain_len is 0, then chain may be NULL.
*/
const br_x509_certificate *chain;
size_t chain_len;
const unsigned char *cert_cur;
size_t cert_len;
/*
* List of supported protocol names (ALPN extension). If unset,
* (number of names is 0), then:
* - the client sends no ALPN extension;
* - the server ignores any incoming ALPN extension.
*
* Otherwise:
* - the client sends an ALPN extension with all the names;
* - the server selects the first protocol in its list that
* the client also supports, or fails (fatal alert 120)
* if the client sends an ALPN extension and there is no
* match.
*
* The 'selected_protocol' field contains 1+n if the matching
* name has index n in the list (the value is 0 if no match was
* performed, e.g. the peer did not send an ALPN extension).
*/
const char **protocol_names;
uint16_t protocol_names_num;
uint16_t selected_protocol;
/*
* Pointers to implementations; left to NULL for unsupported
* functions. For the raw hash functions, implementations are
* referenced from the multihasher (mhash field).
*/
br_tls_prf_impl prf10;
br_tls_prf_impl prf_sha256;
br_tls_prf_impl prf_sha384;
const br_block_cbcenc_class *iaes_cbcenc;
const br_block_cbcdec_class *iaes_cbcdec;
const br_block_ctr_class *iaes_ctr;
const br_block_ctrcbc_class *iaes_ctrcbc;
const br_block_cbcenc_class *ides_cbcenc;
const br_block_cbcdec_class *ides_cbcdec;
br_ghash ighash;
br_chacha20_run ichacha;
br_poly1305_run ipoly;
const br_sslrec_in_cbc_class *icbc_in;
const br_sslrec_out_cbc_class *icbc_out;
const br_sslrec_in_gcm_class *igcm_in;
const br_sslrec_out_gcm_class *igcm_out;
const br_sslrec_in_chapol_class *ichapol_in;
const br_sslrec_out_chapol_class *ichapol_out;
const br_sslrec_in_ccm_class *iccm_in;
const br_sslrec_out_ccm_class *iccm_out;
const br_ec_impl *iec;
br_rsa_pkcs1_vrfy irsavrfy;
br_ecdsa_vrfy iecdsa;
#endif
} br_ssl_engine_context;
/**
* \brief Get currently defined engine behavioural flags.
*
* \param cc SSL engine context.
* \return the flags.
*/
static inline uint32_t
br_ssl_engine_get_flags(br_ssl_engine_context *cc)
{
return cc->flags;
}
/**
* \brief Set all engine behavioural flags.
*
* \param cc SSL engine context.
* \param flags new value for all flags.
*/
static inline void
br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags = flags;
}
/**
* \brief Set some engine behavioural flags.
*
* The flags set in the `flags` parameter are set in the context; other
* flags are untouched.
*
* \param cc SSL engine context.
* \param flags additional set flags.
*/
static inline void
br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags |= flags;
}
/**
* \brief Clear some engine behavioural flags.
*
* The flags set in the `flags` parameter are cleared from the context; other
* flags are untouched.
*
* \param cc SSL engine context.
* \param flags flags to remove.
*/
static inline void
br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags &= ~flags;
}
/**
* \brief Behavioural flag: enforce server preferences.
*
* If this flag is set, then the server will enforce its own cipher suite
* preference order; otherwise, it follows the client preferences.
*/
#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0)
/**
* \brief Behavioural flag: disable renegotiation.
*
* If this flag is set, then renegotiations are rejected unconditionally:
* they won't be honoured if asked for programmatically, and requests from
* the peer are rejected.
*/
#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1)
/**
* \brief Behavioural flag: tolerate lack of client authentication.
*
* If this flag is set in a server and the server requests a client
* certificate, but the authentication fails (the client does not send
* a certificate, or the client's certificate chain cannot be validated),
* then the connection keeps on. Without this flag, a failed client
* authentication terminates the connection.
*
* Notes:
*
* - If the client's certificate can be validated and its public key is
* supported, then a wrong signature value terminates the connection
* regardless of that flag.
*
* - If using full-static ECDH, then a failure to validate the client's
* certificate prevents the handshake from succeeding.
*/
#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2)
/**
* \brief Behavioural flag: fail on application protocol mismatch.
*
* The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301))
* allows the client to send a list of application protocol names, and
* the server to select one. A mismatch is one of the following occurrences:
*
* - On the client: the client sends a list of names, the server
* responds with a protocol name which is _not_ part of the list of
* names sent by the client.
*
* - On the server: the client sends a list of names, and the server
* is also configured with a list of names, but there is no common
* protocol name between the two lists.
*
* Normal behaviour in case of mismatch is to report no matching name
* (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on.
* If the flag is set, then a mismatch implies a protocol failure (if
* the mismatch is detected by the server, it will send a fatal alert).
*
* Note: even with this flag, `br_ssl_engine_get_selected_protocol()`
* may still return `NULL` if the client or the server does not send an
* ALPN extension at all.
*/
#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3)
/**
* \brief Set the minimum and maximum supported protocol versions.
*
* The two provided versions MUST be supported by the implementation
* (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower
* than `version_min`.
*
* \param cc SSL engine context.
* \param version_min minimum supported TLS version.
* \param version_max maximum supported TLS version.
*/
static inline void
br_ssl_engine_set_versions(br_ssl_engine_context *cc,
unsigned version_min, unsigned version_max)
{
cc->version_min = (uint16_t)version_min;
cc->version_max = (uint16_t)version_max;
}
/**
* \brief Set the list of cipher suites advertised by this context.
*
* The provided array is copied into the context. It is the caller
* responsibility to ensure that all provided suites will be supported
* by the context. The engine context has enough room to receive _all_
* suites supported by the implementation. The provided array MUST NOT
* contain duplicates.
*
* If the engine is for a client, the "signaling" pseudo-cipher suite
* `TLS_FALLBACK_SCSV` can be added at the end of the list, if the
* calling application is performing a voluntary downgrade (voluntary
* downgrades are not recommended, but if such a downgrade is done, then
* adding the fallback pseudo-suite is a good idea).
*
* \param cc SSL engine context.
* \param suites cipher suites.
* \param suites_num number of cipher suites.
*/
void br_ssl_engine_set_suites(br_ssl_engine_context *cc,
const uint16_t *suites, size_t suites_num);
/**
* \brief Set the X.509 engine.
*
* The caller shall ensure that the X.509 engine is properly initialised.
*
* \param cc SSL engine context.
* \param x509ctx X.509 certificate validation context.
*/
static inline void
br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
{
cc->x509ctx = x509ctx;
}
/**
* \brief Set the supported protocol names.
*
* Protocol names are part of the ALPN extension ([RFC
* 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a
* character string, containing no more than 255 characters (256 with the
* terminating zero). When names are set, then:
*
* - The client will send an ALPN extension, containing the names. If
* the server responds with an ALPN extension, the client will verify
* that the response contains one of its name, and report that name
* through `br_ssl_engine_get_selected_protocol()`.
*
* - The server will parse incoming ALPN extension (from clients), and
* try to find a common protocol; if none is found, the connection
* is aborted with a fatal alert. On match, a response ALPN extension
* is sent, and name is reported through
* `br_ssl_engine_get_selected_protocol()`.
*
* The provided array is linked in, and must remain valid while the
* connection is live.
*
* Names MUST NOT be empty. Names MUST NOT be longer than 255 characters
* (excluding the terminating 0).
*
* \param ctx SSL engine context.
* \param names list of protocol names (zero-terminated).
* \param num number of protocol names (MUST be 1 or more).
*/
static inline void
br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx,
const char **names, size_t num)
{
ctx->protocol_names = names;
ctx->protocol_names_num = (uint16_t)num;
}
/**
* \brief Get the selected protocol.
*
* If this context was initialised with a non-empty list of protocol
* names, and both client and server sent ALPN extensions during the
* handshake, and a common name was found, then that name is returned.
* Otherwise, `NULL` is returned.
*
* The returned pointer is one of the pointers provided to the context
* with `br_ssl_engine_set_protocol_names()`.
*
* \return the selected protocol, or `NULL`.
*/
static inline const char *
br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx)
{
unsigned k;
k = ctx->selected_protocol;
return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1];
}
/**
* \brief Set a hash function implementation (by ID).
*
* Hash functions set with this call will be used for SSL/TLS specific
* usages, not X.509 certificate validation. Only "standard" hash functions
* may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl`
* is `NULL`, then the hash function support is removed, not added.
*
* \param ctx SSL engine context.
* \param id hash function identifier.
* \param impl hash function implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
int id, const br_hash_class *impl)
{
br_multihash_setimpl(&ctx->mhash, id, impl);
}
/**
* \brief Get a hash function implementation (by ID).
*
* This function retrieves a hash function implementation which was
* set with `br_ssl_engine_set_hash()`.
*
* \param ctx SSL engine context.
* \param id hash function identifier.
* \return the hash function implementation (or `NULL`).
*/
static inline const br_hash_class *
br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
{
return br_multihash_getimpl(&ctx->mhash, id);
}
/**
* \brief Set the PRF implementation (for TLS 1.0 and 1.1).
*
* This function sets (or removes, if `impl` is `NULL`) the implementation
* for the PRF used in TLS 1.0 and 1.1.
*
* \param cc SSL engine context.
* \param impl PRF implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf10 = impl;
}
/**
* \brief Set the PRF implementation with SHA-256 (for TLS 1.2).
*
* This function sets (or removes, if `impl` is `NULL`) the implementation
* for the SHA-256 variant of the PRF used in TLS 1.2.
*
* \param cc SSL engine context.
* \param impl PRF implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf_sha256 = impl;
}
/**
* \brief Set the PRF implementation with SHA-384 (for TLS 1.2).
*
* This function sets (or removes, if `impl` is `NULL`) the implementation
* for the SHA-384 variant of the PRF used in TLS 1.2.
*
* \param cc SSL engine context.
* \param impl PRF implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf_sha384 = impl;
}
/**
* \brief Set the AES/CBC implementations.
*
* \param cc SSL engine context.
* \param impl_enc AES/CBC encryption implementation (or `NULL`).
* \param impl_dec AES/CBC decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
const br_block_cbcenc_class *impl_enc,
const br_block_cbcdec_class *impl_dec)
{
cc->iaes_cbcenc = impl_enc;
cc->iaes_cbcdec = impl_dec;
}
/**
* \brief Set the "default" AES/CBC implementations.
*
* This function configures in the engine the AES implementations that
* should provide best runtime performance on the local system, while
* still being safe (in particular, constant-time). It also sets the
* handlers for CBC records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc);
/**
* \brief Set the AES/CTR implementation.
*
* \param cc SSL engine context.
* \param impl AES/CTR encryption/decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
const br_block_ctr_class *impl)
{
cc->iaes_ctr = impl;
}
/**
* \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH).
*
* This function configures in the engine the AES/CTR and GHASH
* implementation that should provide best runtime performance on the local
* system, while still being safe (in particular, constant-time). It also
* sets the handlers for GCM records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc);
/**
* \brief Set the DES/CBC implementations.
*
* \param cc SSL engine context.
* \param impl_enc DES/CBC encryption implementation (or `NULL`).
* \param impl_dec DES/CBC decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
const br_block_cbcenc_class *impl_enc,
const br_block_cbcdec_class *impl_dec)
{
cc->ides_cbcenc = impl_enc;
cc->ides_cbcdec = impl_dec;
}
/**
* \brief Set the "default" DES/CBC implementations.
*
* This function configures in the engine the DES implementations that
* should provide best runtime performance on the local system, while
* still being safe (in particular, constant-time). It also sets the
* handlers for CBC records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc);
/**
* \brief Set the GHASH implementation (used in GCM mode).
*
* \param cc SSL engine context.
* \param impl GHASH implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
{
cc->ighash = impl;
}
/**
* \brief Set the ChaCha20 implementation.
*
* \param cc SSL engine context.
* \param ichacha ChaCha20 implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_chacha20(br_ssl_engine_context *cc,
br_chacha20_run ichacha)
{
cc->ichacha = ichacha;
}
/**
* \brief Set the Poly1305 implementation.
*
* \param cc SSL engine context.
* \param ipoly Poly1305 implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_poly1305(br_ssl_engine_context *cc,
br_poly1305_run ipoly)
{
cc->ipoly = ipoly;
}
/**
* \brief Set the "default" ChaCha20 and Poly1305 implementations.
*
* This function configures in the engine the ChaCha20 and Poly1305
* implementations that should provide best runtime performance on the
* local system, while still being safe (in particular, constant-time).
* It also sets the handlers for ChaCha20+Poly1305 records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc);
/**
* \brief Set the AES/CTR+CBC implementation.
*
* \param cc SSL engine context.
* \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc,
const br_block_ctrcbc_class *impl)
{
cc->iaes_ctrcbc = impl;
}
/**
* \brief Set the "default" implementations for AES/CCM.
*
* This function configures in the engine the AES/CTR+CBC
* implementation that should provide best runtime performance on the local
* system, while still being safe (in particular, constant-time). It also
* sets the handlers for CCM records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc);
/**
* \brief Set the record encryption and decryption engines for CBC + HMAC.
*
* \param cc SSL engine context.
* \param impl_in record CBC decryption implementation (or `NULL`).
* \param impl_out record CBC encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
const br_sslrec_in_cbc_class *impl_in,
const br_sslrec_out_cbc_class *impl_out)
{
cc->icbc_in = impl_in;
cc->icbc_out = impl_out;
}
/**
* \brief Set the record encryption and decryption engines for GCM.
*
* \param cc SSL engine context.
* \param impl_in record GCM decryption implementation (or `NULL`).
* \param impl_out record GCM encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
const br_sslrec_in_gcm_class *impl_in,
const br_sslrec_out_gcm_class *impl_out)
{
cc->igcm_in = impl_in;
cc->igcm_out = impl_out;
}
/**
* \brief Set the record encryption and decryption engines for CCM.
*
* \param cc SSL engine context.
* \param impl_in record CCM decryption implementation (or `NULL`).
* \param impl_out record CCM encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_ccm(br_ssl_engine_context *cc,
const br_sslrec_in_ccm_class *impl_in,
const br_sslrec_out_ccm_class *impl_out)
{
cc->iccm_in = impl_in;
cc->iccm_out = impl_out;
}
/**
* \brief Set the record encryption and decryption engines for
* ChaCha20+Poly1305.
*
* \param cc SSL engine context.
* \param impl_in record ChaCha20 decryption implementation (or `NULL`).
* \param impl_out record ChaCha20 encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_chapol(br_ssl_engine_context *cc,
const br_sslrec_in_chapol_class *impl_in,
const br_sslrec_out_chapol_class *impl_out)
{
cc->ichapol_in = impl_in;
cc->ichapol_out = impl_out;
}
/**
* \brief Set the EC implementation.
*
* The elliptic curve implementation will be used for ECDH and ECDHE
* cipher suites, and for ECDSA support.
*
* \param cc SSL engine context.
* \param iec EC implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
{
cc->iec = iec;
}
/**
* \brief Set the "default" EC implementation.
*
* This function sets the elliptic curve implementation for ECDH and
* ECDHE cipher suites, and for ECDSA support. It selects the fastest
* implementation on the current system.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc);
/**
* \brief Get the EC implementation configured in the provided engine.
*
* \param cc SSL engine context.
* \return the EC implementation.
*/
static inline const br_ec_impl *
br_ssl_engine_get_ec(br_ssl_engine_context *cc)
{
return cc->iec;
}
/**
* \brief Set the RSA signature verification implementation.
*
* On the client, this is used to verify the server's signature on its
* ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server,
* this is used to verify the client's CertificateVerify message (if a
* client certificate is requested, and that certificate contains a RSA key).
*
* \param cc SSL engine context.
* \param irsavrfy RSA signature verification implementation.
*/
static inline void
br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
{
cc->irsavrfy = irsavrfy;
}
/**
* \brief Set the "default" RSA implementation (signature verification).
*
* This function sets the RSA implementation (signature verification)
* to the fastest implementation available on the current platform.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc);
/**
* \brief Get the RSA implementation (signature verification) configured
* in the provided engine.
*
* \param cc SSL engine context.
* \return the RSA signature verification implementation.
*/
static inline br_rsa_pkcs1_vrfy
br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc)
{
return cc->irsavrfy;
}
/*
* \brief Set the ECDSA implementation (signature verification).
*
* On the client, this is used to verify the server's signature on its
* ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server,
* this is used to verify the client's CertificateVerify message (if a
* client certificate is requested, that certificate contains an EC key,
* and full-static ECDH is not used).
*
* The ECDSA implementation will use the EC core implementation configured
* in the engine context.
*
* \param cc client context.
* \param iecdsa ECDSA verification implementation.
*/
static inline void
br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa)
{
cc->iecdsa = iecdsa;
}
/**
* \brief Set the "default" ECDSA implementation (signature verification).
*
* This function sets the ECDSA implementation (signature verification)
* to the fastest implementation available on the current platform. This
* call also sets the elliptic curve implementation itself, there again
* to the fastest EC implementation available.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc);
/**
* \brief Get the ECDSA implementation (signature verification) configured
* in the provided engine.
*
* \param cc SSL engine context.
* \return the ECDSA signature verification implementation.
*/
static inline br_ecdsa_vrfy
br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc)
{
return cc->iecdsa;
}
/**
* \brief Set the I/O buffer for the SSL engine.
*
* Once this call has been made, `br_ssl_client_reset()` or
* `br_ssl_server_reset()` MUST be called before using the context.
*
* The provided buffer will be used as long as the engine context is
* used. The caller is responsible for keeping it available.
*
* If `bidi` is 0, then the engine will operate in half-duplex mode
* (it won't be able to send data while there is unprocessed incoming
* data in the buffer, and it won't be able to receive data while there
* is unsent data in the buffer). The optimal buffer size in half-duplex
* mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra
* bytes are ignored. If the buffer is smaller, then this limits the
* capacity of the engine to support all allowed record sizes.
*
* If `bidi` is 1, then the engine will split the buffer into two
* parts, for separate handling of outgoing and incoming data. This
* enables full-duplex processing, but requires more RAM. The optimal
* buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the
* buffer is larger, then extra bytes are ignored. If the buffer is
* smaller, then the split will favour the incoming part, so that
* interoperability is maximised.
*
* \param cc SSL engine context
* \param iobuf I/O buffer.
* \param iobuf_len I/O buffer length (in bytes).
* \param bidi non-zero for full-duplex mode.
*/
void br_ssl_engine_set_buffer(br_ssl_engine_context *cc,
void *iobuf, size_t iobuf_len, int bidi);
/**
* \brief Set the I/O buffers for the SSL engine.
*
* Once this call has been made, `br_ssl_client_reset()` or
* `br_ssl_server_reset()` MUST be called before using the context.
*
* This function is similar to `br_ssl_engine_set_buffer()`, except
* that it enforces full-duplex mode, and the two I/O buffers are
* provided as separate chunks.
*
* The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT`
* evaluate to the optimal (maximum) sizes for the input and output
* buffer, respectively.
*
* \param cc SSL engine context
* \param ibuf input buffer.
* \param ibuf_len input buffer length (in bytes).
* \param obuf output buffer.
* \param obuf_len output buffer length (in bytes).
*/
void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc,
void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len);
/**
* \brief Inject some "initial entropy" in the context.
*
* This entropy will be added to what can be obtained from the
* underlying operating system, if that OS is supported.
*
* This function may be called several times; all injected entropy chunks
* are cumulatively mixed.
*
* If entropy gathering from the OS is supported and compiled in, then this
* step is optional. Otherwise, it is mandatory to inject randomness, and
* the caller MUST take care to push (as one or several successive calls)
* enough entropy to achieve cryptographic resistance (at least 80 bits,
* preferably 128 or more). The engine will report an error if no entropy
* was provided and none can be obtained from the OS.
*
* Take care that this function cannot assess the cryptographic quality of
* the provided bytes.
*
* In all generality, "entropy" must here be considered to mean "that
* which the attacker cannot predict". If your OS/architecture does not
* have a suitable source of randomness, then you can make do with the
* combination of a large enough secret value (possibly a copy of an
* asymmetric private key that you also store on the system) AND a
* non-repeating value (e.g. current time, provided that the local clock
* cannot be reset or altered by the attacker).
*
* \param cc SSL engine context.
* \param data extra entropy to inject.
* \param len length of the extra data (in bytes).
*/
void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc,
const void *data, size_t len);
/**
* \brief Get the "server name" in this engine.
*
* For clients, this is the name provided with `br_ssl_client_reset()`;
* for servers, this is the name received from the client as part of the
* ClientHello message. If there is no such name (e.g. the client did
* not send an SNI extension) then the returned string is empty
* (returned pointer points to a byte of value 0).
*
* The returned pointer refers to a buffer inside the context, which may
* be overwritten as part of normal SSL activity (even within the same
* connection, if a renegotiation occurs).
*
* \param cc SSL engine context.
* \return the server name (possibly empty).
*/
static inline const char *
br_ssl_engine_get_server_name(const br_ssl_engine_context *cc)
{
return cc->server_name;
}
/**
* \brief Get the protocol version.
*
* This function returns the protocol version that is used by the
* engine. That value is set after sending (for a server) or receiving
* (for a client) the ServerHello message.
*
* \param cc SSL engine context.
* \return the protocol version.
*/
static inline unsigned
br_ssl_engine_get_version(const br_ssl_engine_context *cc)
{
return cc->session.version;
}
/**
* \brief Get a copy of the session parameters.
*
* The session parameters are filled during the handshake, so this
* function shall not be called before completion of the handshake.
* The initial handshake is completed when the context first allows
* application data to be injected.
*
* This function copies the current session parameters into the provided
* structure. Beware that the session parameters include the master
* secret, which is sensitive data, to handle with great care.
*
* \param cc SSL engine context.
* \param pp destination structure for the session parameters.
*/
static inline void
br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc,
br_ssl_session_parameters *pp)
{
memcpy(pp, &cc->session, sizeof *pp);
}
/**
* \brief Set the session parameters to the provided values.
*
* This function is meant to be used in the client, before doing a new
* handshake; a session resumption will be attempted with these
* parameters. In the server, this function has no effect.
*
* \param cc SSL engine context.
* \param pp source structure for the session parameters.
*/
static inline void
br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc,
const br_ssl_session_parameters *pp)
{
memcpy(&cc->session, pp, sizeof *pp);
}
/**
* \brief Get identifier for the curve used for key exchange.
*
* If the cipher suite uses ECDHE, then this function returns the
* identifier for the curve used for transient parameters. This is
* defined during the course of the handshake, when the ServerKeyExchange
* is sent (on the server) or received (on the client). If the
* cipher suite does not use ECDHE (e.g. static ECDH, or RSA key
* exchange), then this value is indeterminate.
*
* @param cc SSL engine context.
* @return the ECDHE curve identifier.
*/
static inline int
br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc)
{
return cc->ecdhe_curve;
}
/**
* \brief Get the current engine state.
*
* An SSL engine (client or server) has, at any time, a state which is
* the combination of zero, one or more of these flags:
*
* - `BR_SSL_CLOSED`
*
* Engine is finished, no more I/O (until next reset).
*
* - `BR_SSL_SENDREC`
*
* Engine has some bytes to send to the peer.
*
* - `BR_SSL_RECVREC`
*
* Engine expects some bytes from the peer.
*
* - `BR_SSL_SENDAPP`
*
* Engine may receive application data to send (or flush).
*
* - `BR_SSL_RECVAPP`
*
* Engine has obtained some application data from the peer,
* that should be read by the caller.
*
* If no flag at all is set (state value is 0), then the engine is not
* fully initialised yet.
*
* The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag
* is set. To distinguish between a normal closure and an error, use
* `br_ssl_engine_last_error()`.
*
* Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually
* exclusive: the input buffer, at any point, either accumulates
* plaintext data, or contains an assembled record that is being sent.
* Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive.
* This may change in a future library version.
*
* \param cc SSL engine context.
* \return the current engine state.
*/
unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc);
/** \brief SSL engine state: closed or failed. */
#define BR_SSL_CLOSED 0x0001
/** \brief SSL engine state: record data is ready to be sent to the peer. */
#define BR_SSL_SENDREC 0x0002
/** \brief SSL engine state: engine may receive records from the peer. */
#define BR_SSL_RECVREC 0x0004
/** \brief SSL engine state: engine may accept application data to send. */
#define BR_SSL_SENDAPP 0x0008
/** \brief SSL engine state: engine has received application data. */
#define BR_SSL_RECVAPP 0x0010
/**
* \brief Get the engine error indicator.
*
* The error indicator is `BR_ERR_OK` (0) if no error was encountered
* since the last call to `br_ssl_client_reset()` or
* `br_ssl_server_reset()`. Other status values are "sticky": they
* remain set, and prevent all I/O activity, until cleared. Only the
* reset calls clear the error indicator.
*
* \param cc SSL engine context.
* \return 0, or a non-zero error code.
*/
static inline int
br_ssl_engine_last_error(const br_ssl_engine_context *cc)
{
return cc->err;
}
/*
* There are four I/O operations, each identified by a symbolic name:
*
* sendapp inject application data in the engine
* recvapp retrieving application data from the engine
* sendrec sending records on the transport medium
* recvrec receiving records from the transport medium
*
* Terminology works thus: in a layered model where the SSL engine sits
* between the application and the network, "send" designates operations
* where bytes flow from application to network, and "recv" for the
* reverse operation. Application data (the plaintext that is to be
* conveyed through SSL) is "app", while encrypted records are "rec".
* Note that from the SSL engine point of view, "sendapp" and "recvrec"
* designate bytes that enter the engine ("inject" operation), while
* "recvapp" and "sendrec" designate bytes that exit the engine
* ("extract" operation).
*
* For the operation 'xxx', two functions are defined:
*
* br_ssl_engine_xxx_buf
* Returns a pointer and length to the buffer to use for that
* operation. '*len' is set to the number of bytes that may be read
* from the buffer (extract operation) or written to the buffer
* (inject operation). If no byte may be exchanged for that operation
* at that point, then '*len' is set to zero, and NULL is returned.
* The engine state is unmodified by this call.
*
* br_ssl_engine_xxx_ack
* Informs the engine that 'len' bytes have been read from the buffer
* (extract operation) or written to the buffer (inject operation).
* The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed
* that which was obtained from a preceding br_ssl_engine_xxx_buf()
* call.
*/
/**
* \brief Get buffer for application data to send.
*
* If the engine is ready to accept application data to send to the
* peer, then this call returns a pointer to the buffer where such
* data shall be written, and its length is written in `*len`.
* Otherwise, `*len` is set to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the application data output buffer length, or 0.
* \return the application data output buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_sendapp_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Inform the engine of some new application data.
*
* After writing `len` bytes in the buffer returned by
* `br_ssl_engine_sendapp_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_sendapp_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes pushed (not zero).
*/
void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Get buffer for received application data.
*
* If the engine has received application data from the peer, then this
* call returns a pointer to the buffer from where such data shall be
* read, and its length is written in `*len`. Otherwise, `*len` is set
* to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the application data input buffer length, or 0.
* \return the application data input buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_recvapp_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Acknowledge some received application data.
*
* After reading `len` bytes from the buffer returned by
* `br_ssl_engine_recvapp_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_recvapp_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes read (not zero).
*/
void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Get buffer for record data to send.
*
* If the engine has prepared some records to send to the peer, then this
* call returns a pointer to the buffer from where such data shall be
* read, and its length is written in `*len`. Otherwise, `*len` is set
* to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the record data output buffer length, or 0.
* \return the record data output buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_sendrec_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Acknowledge some sent record data.
*
* After reading `len` bytes from the buffer returned by
* `br_ssl_engine_sendrec_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_sendrec_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes read (not zero).
*/
void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Get buffer for incoming records.
*
* If the engine is ready to accept records from the peer, then this
* call returns a pointer to the buffer where such data shall be
* written, and its length is written in `*len`. Otherwise, `*len` is
* set to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the record data input buffer length, or 0.
* \return the record data input buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_recvrec_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Inform the engine of some new record data.
*
* After writing `len` bytes in the buffer returned by
* `br_ssl_engine_recvrec_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_recvrec_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes pushed (not zero).
*/
void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Flush buffered application data.
*
* If some application data has been buffered in the engine, then wrap
* it into a record and mark it for sending. If no application data has
* been buffered but the engine would be ready to accept some, AND the
* `force` parameter is non-zero, then an empty record is assembled and
* marked for sending. In all other cases, this function does nothing.
*
* Empty records are technically legal, but not all existing SSL/TLS
* implementations support them. Empty records can be useful as a
* transparent "keep-alive" mechanism to maintain some low-level
* network activity.
*
* \param cc SSL engine context.
* \param force non-zero to force sending an empty record.
*/
void br_ssl_engine_flush(br_ssl_engine_context *cc, int force);
/**
* \brief Initiate a closure.
*
* If, at that point, the context is open and in ready state, then a
* `close_notify` alert is assembled and marked for sending; this
* triggers the closure protocol. Otherwise, no such alert is assembled.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_close(br_ssl_engine_context *cc);
/**
* \brief Initiate a renegotiation.
*
* If the engine is failed or closed, or if the peer is known not to
* support secure renegotiation (RFC 5746), or if renegotiations have
* been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there
* is buffered incoming application data, then this function returns 0
* and nothing else happens.
*
* Otherwise, this function returns 1, and a renegotiation attempt is
* triggered (if a handshake is already ongoing at that point, then
* no new handshake is triggered).
*
* \param cc SSL engine context.
* \return 1 on success, 0 on error.
*/
int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
/**
* \brief Export key material from a connected SSL engine (RFC 5705).
*
* This calls compute a secret key of arbitrary length from the master
* secret of a connected SSL engine. If the provided context is not
* currently in "application data" state (initial handshake is not
* finished, another handshake is ongoing, or the connection failed or
* was closed), then this function returns 0. Otherwise, a secret key of
* length `len` bytes is computed and written in the buffer pointed to
* by `dst`, and 1 is returned.
*
* The computed key follows the specification described in RFC 5705.
* That RFC includes two key computations, with and without a "context
* value". If `context` is `NULL`, then the variant without context is
* used; otherwise, the `context_len` bytes located at the address
* pointed to by `context` are used in the computation. Note that it
* is possible to have a "with context" key with a context length of
* zero bytes, by setting `context` to a non-`NULL` value but
* `context_len` to 0.
*
* When context bytes are used, the context length MUST NOT exceed
* 65535 bytes.
*
* \param cc SSL engine context.
* \param dst destination buffer for exported key.
* \param len exported key length (in bytes).
* \param label disambiguation label.
* \param context context value (or `NULL`).
* \param context_len context length (in bytes).
* \return 1 on success, 0 on error.
*/
int br_ssl_key_export(br_ssl_engine_context *cc,
void *dst, size_t len, const char *label,
const void *context, size_t context_len);
/*
* Pre-declaration for the SSL client context.
*/
typedef struct br_ssl_client_context_ br_ssl_client_context;
/**
* \brief Type for the client certificate, if requested by the server.
*/
typedef struct {
/**
* \brief Authentication type.
*
* This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA`
* (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange).
*/
int auth_type;
/**
* \brief Hash function for computing the CertificateVerify.
*
* This is the symbolic identifier for the hash function that
* will be used to produce the hash of handshake messages, to
* be signed into the CertificateVerify. For full static ECDH
* (client and server certificates are both EC in the same
* curve, and static ECDH is used), this value is set to -1.
*
* Take care that with TLS 1.0 and 1.1, that value MUST match
* the protocol requirements: value must be 0 (MD5+SHA-1) for
* a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only
* TLS 1.2 allows for other hash functions.
*/
int hash_id;
/**
* \brief Certificate chain to send to the server.
*
* This is an array of `br_x509_certificate` objects, each
* normally containing a DER-encoded certificate. The client
* code does not try to decode these elements. If there is no
* chain to send to the server, then this pointer shall be
* set to `NULL`.
*/
const br_x509_certificate *chain;
/**
* \brief Certificate chain length (number of certificates).
*
* If there is no chain to send to the server, then this value
* shall be set to 0.
*/
size_t chain_len;
} br_ssl_client_certificate;
/*
* Note: the constants below for signatures match the TLS constants.
*/
/** \brief Client authentication type: static ECDH. */
#define BR_AUTH_ECDH 0
/** \brief Client authentication type: RSA signature. */
#define BR_AUTH_RSA 1
/** \brief Client authentication type: ECDSA signature. */
#define BR_AUTH_ECDSA 3
/**
* \brief Class type for a certificate handler (client side).
*
* A certificate handler selects a client certificate chain to send to
* the server, upon explicit request from that server. It receives
* the list of trust anchor DN from the server, and supported types
* of certificates and signatures, and returns the chain to use. It
* is also invoked to perform the corresponding private key operation
* (a signature, or an ECDH computation).
*
* The SSL client engine will first push the trust anchor DN with
* `start_name_list()`, `start_name()`, `append_name()`, `end_name()`
* and `end_name_list()`. Then it will call `choose()`, to select the
* actual chain (and signature/hash algorithms). Finally, it will call
* either `do_sign()` or `do_keyx()`, depending on the algorithm choices.
*/
typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class;
struct br_ssl_client_certificate_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Begin reception of a list of trust anchor names. This
* is called while parsing the incoming CertificateRequest.
*
* \param pctx certificate handler context.
*/
void (*start_name_list)(const br_ssl_client_certificate_class **pctx);
/**
* \brief Begin reception of a new trust anchor name.
*
* The total encoded name length is provided; it is less than
* 65535 bytes.
*
* \param pctx certificate handler context.
* \param len encoded name length (in bytes).
*/
void (*start_name)(const br_ssl_client_certificate_class **pctx,
size_t len);
/**
* \brief Receive some more bytes for the current trust anchor name.
*
* The provided reference (`data`) points to a transient buffer
* they may be reused as soon as this function returns. The chunk
* length (`len`) is never zero.
*
* \param pctx certificate handler context.
* \param data anchor name chunk.
* \param len anchor name chunk length (in bytes).
*/
void (*append_name)(const br_ssl_client_certificate_class **pctx,
const unsigned char *data, size_t len);
/**
* \brief End current trust anchor name.
*
* This function is called when all the encoded anchor name data
* has been provided.
*
* \param pctx certificate handler context.
*/
void (*end_name)(const br_ssl_client_certificate_class **pctx);
/**
* \brief End list of trust anchor names.
*
* This function is called when all the anchor names in the
* CertificateRequest message have been obtained.
*
* \param pctx certificate handler context.
*/
void (*end_name_list)(const br_ssl_client_certificate_class **pctx);
/**
* \brief Select client certificate and algorithms.
*
* This callback function shall fill the provided `choices`
* structure with the selected algorithms and certificate chain.
* The `hash_id`, `chain` and `chain_len` fields must be set. If
* the client cannot or does not wish to send a certificate,
* then it shall set `chain` to `NULL` and `chain_len` to 0.
*
* The `auth_types` parameter describes the authentication types,
* signature algorithms and hash functions that are supported by
* both the client context and the server, and compatible with
* the current protocol version. This is a bit field with the
* following contents:
*
* - If RSA signatures with hash function x are supported, then
* bit x is set.
*
* - If ECDSA signatures with hash function x are supported,
* then bit 8+x is set.
*
* - If static ECDH is supported, with a RSA-signed certificate,
* then bit 16 is set.
*
* - If static ECDH is supported, with an ECDSA-signed certificate,
* then bit 17 is set.
*
* Notes:
*
* - When using TLS 1.0 or 1.1, the hash function for RSA
* signatures is always the special MD5+SHA-1 (id 0), and the
* hash function for ECDSA signatures is always SHA-1 (id 2).
*
* - When using TLS 1.2, the list of hash functions is trimmed
* down to include only hash functions that the client context
* can support. The actual server list can be obtained with
* `br_ssl_client_get_server_hashes()`; that list may be used
* to select the certificate chain to send to the server.
*
* \param pctx certificate handler context.
* \param cc SSL client context.
* \param auth_types supported authentication types and algorithms.
* \param choices destination structure for the policy choices.
*/
void (*choose)(const br_ssl_client_certificate_class **pctx,
const br_ssl_client_context *cc, uint32_t auth_types,
br_ssl_client_certificate *choices);
/**
* \brief Perform key exchange (client part).
*
* This callback is invoked in case of a full static ECDH key
* exchange:
*
* - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`;
*
* - the server requests a client certificate;
*
* - the client has, and sends, a client certificate that
* uses an EC key in the same curve as the server's key,
* and chooses static ECDH (the `hash_id` field in the choice
* structure was set to -1).
*
* In that situation, this callback is invoked to compute the
* client-side ECDH: the provided `data` (of length `*len` bytes)
* is the server's public key point (as decoded from its
* certificate), and the client shall multiply that point with
* its own private key, and write back the X coordinate of the
* resulting point in the same buffer, starting at offset 0.
* The `*len` value shall be modified to designate the actual
* length of the X coordinate.
*
* The callback must uphold the following:
*
* - If the input array does not have the proper length for
* an encoded curve point, then an error (0) shall be reported.
*
* - If the input array has the proper length, then processing
* MUST be constant-time, even if the data is not a valid
* encoded point.
*
* - This callback MUST check that the input point is valid.
*
* Returned value is 1 on success, 0 on error.
*
* \param pctx certificate handler context.
* \param data server public key point.
* \param len public key point length / X coordinate length.
* \return 1 on success, 0 on error.
*/
uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx,
unsigned char *data, size_t *len);
/**
* \brief Perform a signature (client authentication).
*
* This callback is invoked when a client certificate was sent,
* and static ECDH is not used. It shall compute a signature,
* using the client's private key, over the provided hash value
* (which is the hash of all previous handshake messages).
*
* On input, the hash value to sign is in `data`, of size
* `hv_len`; the involved hash function is identified by
* `hash_id`. The signature shall be computed and written
* back into `data`; the total size of that buffer is `len`
* bytes.
*
* This callback shall verify that the signature length does not
* exceed `len` bytes, and abstain from writing the signature if
* it does not fit.
*
* For RSA signatures, the `hash_id` may be 0, in which case
* this is the special header-less signature specified in TLS 1.0
* and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1
* v1.5 signatures shall be computed.
*
* For ECDSA signatures, the signature value shall use the ASN.1
* based encoding.
*
* Returned value is the signature length (in bytes), or 0 on error.
*
* \param pctx certificate handler context.
* \param hash_id hash function identifier.
* \param hv_len hash value length (in bytes).
* \param data input/output buffer (hash value, then signature).
* \param len total buffer length (in bytes).
* \return signature length (in bytes) on success, or 0 on error.
*/
size_t (*do_sign)(const br_ssl_client_certificate_class **pctx,
int hash_id, size_t hv_len, unsigned char *data, size_t len);
};
/**
* \brief A single-chain RSA client certificate handler.
*
* This handler uses a single certificate chain, with a RSA
* signature. The list of trust anchor DN is ignored.
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_client_certificate_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_rsa_private_key *sk;
br_rsa_pkcs1_sign irsasign;
#endif
} br_ssl_client_certificate_rsa_context;
/**
* \brief A single-chain EC client certificate handler.
*
* This handler uses a single certificate chain, with a RSA
* signature. The list of trust anchor DN is ignored.
*
* This handler may support both static ECDH, and ECDSA signatures
* (either usage may be selectively disabled).
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_client_certificate_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_ec_private_key *sk;
unsigned allowed_usages;
unsigned issuer_key_type;
const br_multihash_context *mhash;
const br_ec_impl *iec;
br_ecdsa_sign iecdsa;
#endif
} br_ssl_client_certificate_ec_context;
/**
* \brief Context structure for a SSL client.
*
* The first field (called `eng`) is the SSL engine; all functions that
* work on a `br_ssl_engine_context` structure shall take as parameter
* a pointer to that field. The other structure fields are opaque and
* must not be accessed directly.
*/
struct br_ssl_client_context_ {
/**
* \brief The encapsulated engine context.
*/
br_ssl_engine_context eng;
#ifndef BR_DOXYGEN_IGNORE
/*
* Minimum ClientHello length; padding with an extension (RFC
* 7685) is added if necessary to match at least that length.
* Such padding is nominally unnecessary, but it has been used
* to work around some server implementation bugs.
*/
uint16_t min_clienthello_len;
/*
* Bit field for algoithms (hash + signature) supported by the
* server when requesting a client certificate.
*/
uint32_t hashes;
/*
* Server's public key curve.
*/
int server_curve;
/*
* Context for certificate handler.
*/
const br_ssl_client_certificate_class **client_auth_vtable;
/*
* Client authentication type.
*/
unsigned char auth_type;
/*
* Hash function to use for the client signature. This is 0xFF
* if static ECDH is used.
*/
unsigned char hash_id;
/*
* For the core certificate handlers, thus avoiding (in most
* cases) the need for an externally provided policy context.
*/
union {
const br_ssl_client_certificate_class *vtable;
br_ssl_client_certificate_rsa_context single_rsa;
br_ssl_client_certificate_ec_context single_ec;
} client_auth;
/*
* Implementations.
*/
br_rsa_public irsapub;
#endif
};
/**
* \brief Get the hash functions and signature algorithms supported by
* the server.
*
* This value is a bit field:
*
* - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`,
* then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1,
* or 2 to 6 for the SHA family).
*
* - If ECDSA is supported with hash function of ID `x`, then bit `8+x`
* is set.
*
* - Newer algorithms are symbolic 16-bit identifiers that do not
* represent signature algorithm and hash function separately. If
* the TLS-level identifier is `0x0800+x` for a `x` in the 0..15
* range, then bit `16+x` is set.
*
* "New algorithms" are currently defined only in draft documents, so
* this support is subject to possible change. Right now (early 2017),
* this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA
* on Curve448) to bit 24. If the identifiers on the wire change in
* future document, then the decoding mechanism in BearSSL will be
* amended to keep mapping ed25519 and ed448 on bits 23 and 24,
* respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not
* guaranteed yet.
*
* \param cc client context.
* \return the server-supported hash functions and signature algorithms.
*/
static inline uint32_t
br_ssl_client_get_server_hashes(const br_ssl_client_context *cc)
{
return cc->hashes;
}
/**
* \brief Get the server key curve.
*
* This function returns the ID for the curve used by the server's public
* key. This is set when the server's certificate chain is processed;
* this value is 0 if the server's key is not an EC key.
*
* \return the server's public key curve ID, or 0.
*/
static inline int
br_ssl_client_get_server_curve(const br_ssl_client_context *cc)
{
return cc->server_curve;
}
/*
* Each br_ssl_client_init_xxx() function sets the list of supported
* cipher suites and used implementations, as specified by the profile
* name 'xxx'. Defined profile names are:
*
* full all supported versions and suites; constant-time implementations
* TODO: add other profiles
*/
/**
* \brief SSL client profile: full.
*
* This function initialises the provided SSL client context with
* all supported algorithms and cipher suites. It also initialises
* a companion X.509 validation engine with all supported algorithms,
* and the provided trust anchors; the X.509 engine will be used by
* the client context to validate the server's certificate.
*
* \param cc client context to initialise.
* \param xc X.509 validation context to initialise.
* \param trust_anchors trust anchors to use.
* \param trust_anchors_num number of trust anchors.
*/
void br_ssl_client_init_full(br_ssl_client_context *cc,
br_x509_minimal_context *xc,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
/**
* \brief Clear the complete contents of a SSL client context.
*
* Everything is cleared, including the reference to the configured buffer,
* implementations, cipher suites and state. This is a preparatory step
* to assembling a custom profile.
*
* \param cc client context to clear.
*/
void br_ssl_client_zero(br_ssl_client_context *cc);
/**
* \brief Set an externally provided client certificate handler context.
*
* The handler's methods are invoked when the server requests a client
* certificate.
*
* \param cc client context.
* \param pctx certificate handler context (pointer to its vtable field).
*/
static inline void
br_ssl_client_set_client_certificate(br_ssl_client_context *cc,
const br_ssl_client_certificate_class **pctx)
{
cc->client_auth_vtable = pctx;
}
/**
* \brief Set the RSA public-key operations implementation.
*
* This will be used to encrypt the pre-master secret with the server's
* RSA public key (RSA-encryption cipher suites only).
*
* \param cc client context.
* \param irsapub RSA public-key encryption implementation.
*/
static inline void
br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
{
cc->irsapub = irsapub;
}
/**
* \brief Set the "default" RSA implementation for public-key operations.
*
* This sets the RSA implementation in the client context (for encrypting
* the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest
* available on the current platform.
*
* \param cc client context.
*/
void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc);
/**
* \brief Set the minimum ClientHello length (RFC 7685 padding).
*
* If this value is set and the ClientHello would be shorter, then
* the Pad ClientHello extension will be added with enough padding bytes
* to reach the target size. Because of the extension header, the resulting
* size will sometimes be slightly more than `len` bytes if the target
* size cannot be exactly met.
*
* The target length relates to the _contents_ of the ClientHello, not
* counting its 4-byte header. For instance, if `len` is set to 512,
* then the padding will bring the ClientHello size to 516 bytes with its
* header, and 521 bytes when counting the 5-byte record header.
*
* \param cc client context.
* \param len minimum ClientHello length (in bytes).
*/
static inline void
br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
{
cc->min_clienthello_len = len;
}
/**
* \brief Prepare or reset a client context for a new connection.
*
* The `server_name` parameter is used to fill the SNI extension; the
* X.509 "minimal" engine will also match that name against the server
* names included in the server's certificate. If the parameter is
* `NULL` then no SNI extension will be sent, and the X.509 "minimal"
* engine (if used for server certificate validation) will not check
* presence of any specific name in the received certificate.
*
* Therefore, setting the `server_name` to `NULL` shall be reserved
* to cases where alternate or additional methods are used to ascertain
* that the right server public key is used (e.g. a "known key" model).
*
* If `resume_session` is non-zero and the context was previously used
* then the session parameters may be reused (depending on whether the
* server previously sent a non-empty session ID, and accepts the session
* resumption). The session parameters for session resumption can also
* be set explicitly with `br_ssl_engine_set_session_parameters()`.
*
* On failure, the context is marked as failed, and this function
* returns 0. A possible failure condition is when no initial entropy
* was injected, and none could be obtained from the OS (either OS
* randomness gathering is not supported, or it failed).
*
* \param cc client context.
* \param server_name target server name, or `NULL`.
* \param resume_session non-zero to try session resumption.
* \return 0 on failure, 1 on success.
*/
int br_ssl_client_reset(br_ssl_client_context *cc,
const char *server_name, int resume_session);
/**
* \brief Forget any session in the context.
*
* This means that the next handshake that uses this context will
* necessarily be a full handshake (this applies both to new connections
* and to renegotiations).
*
* \param cc client context.
*/
static inline void
br_ssl_client_forget_session(br_ssl_client_context *cc)
{
cc->eng.session.session_id_len = 0;
}
/**
* \brief Set client certificate chain and key (single RSA case).
*
* This function sets a client certificate chain, that the client will
* send to the server whenever a client certificate is requested. This
* certificate uses an RSA public key; the corresponding private key is
* invoked for authentication. Trust anchor names sent by the server are
* ignored.
*
* The provided chain and private key are linked in the client context;
* they must remain valid as long as they may be used, i.e. normally
* for the duration of the connection, since they might be invoked
* again upon renegotiations.
*
* \param cc SSL client context.
* \param chain client certificate chain (SSL order: EE comes first).
* \param chain_len client chain length (number of certificates).
* \param sk client private key.
* \param irsasign RSA signature implementation (PKCS#1 v1.5).
*/
void br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign);
/*
* \brief Set the client certificate chain and key (single EC case).
*
* This function sets a client certificate chain, that the client will
* send to the server whenever a client certificate is requested. This
* certificate uses an EC public key; the corresponding private key is
* invoked for authentication. Trust anchor names sent by the server are
* ignored.
*
* The provided chain and private key are linked in the client context;
* they must remain valid as long as they may be used, i.e. normally
* for the duration of the connection, since they might be invoked
* again upon renegotiations.
*
* The `allowed_usages` is a combination of usages, namely
* `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX`
* value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value
* allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA
* signature implementation must be provided; otherwise, the `iecdsa`
* parameter may be 0.
*
* The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or
* `BR_KEYTYPE_EC`; it is the type of the public key used the the CA
* that issued (signed) the client certificate. That value is used with
* full static ECDH: support of the certificate by the server depends
* on how the certificate was signed. (Note: when using TLS 1.2, this
* parameter is ignored; but its value matters for TLS 1.0 and 1.1.)
*
* \param cc server context.
* \param chain server certificate chain to send.
* \param chain_len chain length (number of certificates).
* \param sk server private key (EC).
* \param allowed_usages allowed private key usages.
* \param cert_issuer_key_type issuing CA's key type.
* \param iec EC core implementation.
* \param iecdsa ECDSA signature implementation ("asn1" format).
*/
void br_ssl_client_set_single_ec(br_ssl_client_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk, unsigned allowed_usages,
unsigned cert_issuer_key_type,
const br_ec_impl *iec, br_ecdsa_sign iecdsa);
/**
* \brief Type for a "translated cipher suite", as an array of two
* 16-bit integers.
*
* The first element is the cipher suite identifier (as used on the wire).
* The second element is the concatenation of four 4-bit elements which
* characterise the cipher suite contents. In most to least significant
* order, these 4-bit elements are:
*
* - Bits 12 to 15: key exchange + server key type
*
* | val | symbolic constant | suite type | details |
* | :-- | :----------------------- | :---------- | :----------------------------------------------- |
* | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) |
* | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) |
* | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) |
* | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA |
* | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA |
*
* - Bits 8 to 11: symmetric encryption algorithm
*
* | val | symbolic constant | symmetric encryption | key strength (bits) |
* | :-- | :--------------------- | :------------------- | :------------------ |
* | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 |
* | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 |
* | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 |
* | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 |
* | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 |
* | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 |
*
* - Bits 4 to 7: MAC algorithm
*
* | val | symbolic constant | MAC type | details |
* | :-- | :----------------- | :----------- | :------------------------------------ |
* | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) |
* | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` |
* | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` |
* | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` |
*
* - Bits 0 to 3: hash function for PRF when used with TLS-1.2
*
* | val | symbolic constant | hash function | details |
* | :-- | :----------------- | :------------ | :----------------------------------- |
* | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` |
* | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` |
*
* For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has
* standard identifier 0x009C, and is translated to 0x0304, for, in
* that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0),
* SHA-256 in the TLS PRF (4).
*/
typedef uint16_t br_suite_translated[2];
#ifndef BR_DOXYGEN_IGNORE
/*
* Constants are already documented in the br_suite_translated type.
*/
#define BR_SSLKEYX_RSA 0
#define BR_SSLKEYX_ECDHE_RSA 1
#define BR_SSLKEYX_ECDHE_ECDSA 2
#define BR_SSLKEYX_ECDH_RSA 3
#define BR_SSLKEYX_ECDH_ECDSA 4
#define BR_SSLENC_3DES_CBC 0
#define BR_SSLENC_AES128_CBC 1
#define BR_SSLENC_AES256_CBC 2
#define BR_SSLENC_AES128_GCM 3
#define BR_SSLENC_AES256_GCM 4
#define BR_SSLENC_CHACHA20 5
#define BR_SSLMAC_AEAD 0
#define BR_SSLMAC_SHA1 br_sha1_ID
#define BR_SSLMAC_SHA256 br_sha256_ID
#define BR_SSLMAC_SHA384 br_sha384_ID
#define BR_SSLPRF_SHA256 br_sha256_ID
#define BR_SSLPRF_SHA384 br_sha384_ID
#endif
/*
* Pre-declaration for the SSL server context.
*/
typedef struct br_ssl_server_context_ br_ssl_server_context;
/**
* \brief Type for the server policy choices, taken after analysis of
* the client message (ClientHello).
*/
typedef struct {
/**
* \brief Cipher suite to use with that client.
*/
uint16_t cipher_suite;
/**
* \brief Hash function or algorithm for signing the ServerKeyExchange.
*
* This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*`
* cipher suites; it is used only for `TLS_ECDHE_*` suites, in
* which the server _signs_ the ephemeral EC Diffie-Hellman
* parameters sent to the client.
*
* This identifier must be one of the following values:
*
* - `0xFF00 + id`, where `id` is a hash function identifier
* (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions);
*
* - a full 16-bit identifier, lower than `0xFF00`.
*
* If the first option is used, then the SSL engine will
* compute the hash of the data that is to be signed, with the
* designated hash function. The `do_sign()` method will be
* invoked with that hash value provided in the the `data`
* buffer.
*
* If the second option is used, then the SSL engine will NOT
* compute a hash on the data; instead, it will provide the
* to-be-signed data itself in `data`, i.e. the concatenation of
* the client random, server random, and encoded ECDH
* parameters. Furthermore, with TLS-1.2 and later, the 16-bit
* identifier will be used "as is" in the protocol, in the
* SignatureAndHashAlgorithm; for instance, `0x0401` stands for
* RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash
* function (the `04`).
*
* Take care that with TLS 1.0 and 1.1, the hash function is
* constrainted by the protocol: RSA signature must use
* MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1
* (`0xFF02`). Since TLS 1.0 and 1.1 don't include a
* SignatureAndHashAlgorithm field in their ServerKeyExchange
* messages, any value below `0xFF00` will be usable to send the
* raw ServerKeyExchange data to the `do_sign()` callback, but
* that callback must still follow the protocol requirements
* when generating the signature.
*/
unsigned algo_id;
/**
* \brief Certificate chain to send to the client.
*
* This is an array of `br_x509_certificate` objects, each
* normally containing a DER-encoded certificate. The server
* code does not try to decode these elements.
*/
const br_x509_certificate *chain;
/**
* \brief Certificate chain length (number of certificates).
*/
size_t chain_len;
} br_ssl_server_choices;
/**
* \brief Class type for a policy handler (server side).
*
* A policy handler selects the policy parameters for a connection
* (cipher suite and other algorithms, and certificate chain to send to
* the client); it also performs the server-side computations involving
* its permanent private key.
*
* The SSL server engine will invoke first `choose()`, once the
* ClientHello message has been received, then either `do_keyx()`
* `do_sign()`, depending on the cipher suite.
*/
typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class;
struct br_ssl_server_policy_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Select algorithms and certificates for this connection.
*
* This callback function shall fill the provided `choices`
* structure with the policy choices for this connection. This
* entails selecting the cipher suite, hash function for signing
* the ServerKeyExchange (applicable only to ECDHE cipher suites),
* and certificate chain to send.
*
* The callback receives a pointer to the server context that
* contains the relevant data. In particular, the functions
* `br_ssl_server_get_client_suites()`,
* `br_ssl_server_get_client_hashes()` and
* `br_ssl_server_get_client_curves()` can be used to obtain
* the cipher suites, hash functions and elliptic curves
* supported by both the client and server, respectively. The
* `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()`
* functions yield the protocol version and requested server name
* (SNI), respectively.
*
* This function may modify its context structure (`pctx`) in
* arbitrary ways to keep track of its own choices.
*
* This function shall return 1 if appropriate policy choices
* could be made, or 0 if this connection cannot be pursued.
*
* \param pctx policy context.
* \param cc SSL server context.
* \param choices destination structure for the policy choices.
* \return 1 on success, 0 on error.
*/
int (*choose)(const br_ssl_server_policy_class **pctx,
const br_ssl_server_context *cc,
br_ssl_server_choices *choices);
/**
* \brief Perform key exchange (server part).
*
* This callback is invoked to perform the server-side cryptographic
* operation for a key exchange that is not ECDHE. This callback
* uses the private key.
*
* **For RSA key exchange**, the provided `data` (of length `*len`
* bytes) shall be decrypted with the server's private key, and
* the 48-byte premaster secret copied back to the first 48 bytes
* of `data`.
*
* - The caller makes sure that `*len` is at least 59 bytes.
*
* - This callback MUST check that the provided length matches
* that of the key modulus; it shall report an error otherwise.
*
* - If the length matches that of the RSA key modulus, then
* processing MUST be constant-time, even if decryption fails,
* or the padding is incorrect, or the plaintext message length
* is not exactly 48 bytes.
*
* - This callback needs not check the two first bytes of the
* obtained pre-master secret (the caller will do that).
*
* - If an error is reported (0), then what the callback put
* in the first 48 bytes of `data` is unimportant (the caller
* will use random bytes instead).
*
* **For ECDH key exchange**, the provided `data` (of length `*len`
* bytes) is the elliptic curve point from the client. The
* callback shall multiply it with its private key, and store
* the resulting X coordinate in `data`, starting at offset 0,
* and set `*len` to the length of the X coordinate.
*
* - If the input array does not have the proper length for
* an encoded curve point, then an error (0) shall be reported.
*
* - If the input array has the proper length, then processing
* MUST be constant-time, even if the data is not a valid
* encoded point.
*
* - This callback MUST check that the input point is valid.
*
* Returned value is 1 on success, 0 on error.
*
* \param pctx policy context.
* \param data key exchange data from the client.
* \param len key exchange data length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx,
unsigned char *data, size_t *len);
/**
* \brief Perform a signature (for a ServerKeyExchange message).
*
* This callback function is invoked for ECDHE cipher suites. On
* input, the hash value or message to sign is in `data`, of
* size `hv_len`; the involved hash function or algorithm is
* identified by `algo_id`. The signature shall be computed and
* written back into `data`; the total size of that buffer is
* `len` bytes.
*
* This callback shall verify that the signature length does not
* exceed `len` bytes, and abstain from writing the signature if
* it does not fit.
*
* The `algo_id` value matches that which was written in the
* `choices` structures by the `choose()` callback. This will be
* one of the following:
*
* - `0xFF00 + id` for a hash function identifier `id`. In
* that case, the `data` buffer contains a hash value
* already computed over the data that is to be signed,
* of length `hv_len`. The `id` may be 0 to designate the
* special MD5+SHA-1 concatenation (old-style RSA signing).
*
* - Another value, lower than `0xFF00`. The `data` buffer
* then contains the raw, non-hashed data to be signed
* (concatenation of the client and server randoms and
* ECDH parameters). The callback is responsible to apply
* any relevant hashing as part of the signing process.
*
* Returned value is the signature length (in bytes), or 0 on error.
*
* \param pctx policy context.
* \param algo_id hash function / algorithm identifier.
* \param data input/output buffer (message/hash, then signature).
* \param hv_len hash value or message length (in bytes).
* \param len total buffer length (in bytes).
* \return signature length (in bytes) on success, or 0 on error.
*/
size_t (*do_sign)(const br_ssl_server_policy_class **pctx,
unsigned algo_id,
unsigned char *data, size_t hv_len, size_t len);
};
/**
* \brief A single-chain RSA policy handler.
*
* This policy context uses a single certificate chain, and a RSA
* private key. The context can be restricted to only signatures or
* only key exchange.
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_server_policy_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_rsa_private_key *sk;
unsigned allowed_usages;
br_rsa_private irsacore;
br_rsa_pkcs1_sign irsasign;
#endif
} br_ssl_server_policy_rsa_context;
/**
* \brief A single-chain EC policy handler.
*
* This policy context uses a single certificate chain, and an EC
* private key. The context can be restricted to only signatures or
* only key exchange.
*
* Due to how TLS is defined, this context must be made aware whether
* the server certificate was itself signed with RSA or ECDSA. The code
* does not try to decode the certificate to obtain that information.
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_server_policy_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_ec_private_key *sk;
unsigned allowed_usages;
unsigned cert_issuer_key_type;
const br_multihash_context *mhash;
const br_ec_impl *iec;
br_ecdsa_sign iecdsa;
#endif
} br_ssl_server_policy_ec_context;
/**
* \brief Class type for a session parameter cache.
*
* Session parameters are saved in the cache with `save()`, and
* retrieved with `load()`. The cache implementation can apply any
* storage and eviction strategy that it sees fit. The SSL server
* context that performs the request is provided, so that its
* functionalities may be used by the implementation (e.g. hash
* functions or random number generation).
*/
typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class;
struct br_ssl_session_cache_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Record a session.
*
* This callback should record the provided session parameters.
* The `params` structure is transient, so its contents shall
* be copied into the cache. The session ID has been randomly
* generated and always has length exactly 32 bytes.
*
* \param ctx session cache context.
* \param server_ctx SSL server context.
* \param params session parameters to save.
*/
void (*save)(const br_ssl_session_cache_class **ctx,
br_ssl_server_context *server_ctx,
const br_ssl_session_parameters *params);
/**
* \brief Lookup a session in the cache.
*
* The session ID to lookup is in `params` and always has length
* exactly 32 bytes. If the session parameters are found in the
* cache, then the parameters shall be copied into the `params`
* structure. Returned value is 1 on successful lookup, 0
* otherwise.
*
* \param ctx session cache context.
* \param server_ctx SSL server context.
* \param params destination for session parameters.
* \return 1 if found, 0 otherwise.
*/
int (*load)(const br_ssl_session_cache_class **ctx,
br_ssl_server_context *server_ctx,
br_ssl_session_parameters *params);
};
/**
* \brief Context for a basic cache system.
*
* The system stores session parameters in a buffer provided at
* initialisation time. Each entry uses exactly 100 bytes, and
* buffer sizes up to 4294967295 bytes are supported.
*
* Entries are evicted with a LRU (Least Recently Used) policy. A
* search tree is maintained to keep lookups fast even with large
* caches.
*
* Apart from the first field (vtable pointer), the structure
* contents are opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_session_cache_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
unsigned char *store;
size_t store_len, store_ptr;
unsigned char index_key[32];
const br_hash_class *hash;
int init_done;
uint32_t head, tail, root;
#endif
} br_ssl_session_cache_lru;
/**
* \brief Initialise a LRU session cache with the provided storage space.
*
* The provided storage space must remain valid as long as the cache
* is used. Arbitrary lengths are supported, up to 4294967295 bytes;
* each entry uses up exactly 100 bytes.
*
* \param cc session cache context.
* \param store storage space for cached entries.
* \param store_len storage space length (in bytes).
*/
void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
unsigned char *store, size_t store_len);
/**
* \brief Forget an entry in an LRU session cache.
*
* The session cache context must have been initialised. The entry
* with the provided session ID (of exactly 32 bytes) is looked for
* in the cache; if located, it is disabled.
*
* \param cc session cache context.
* \param id session ID to forget.
*/
void br_ssl_session_cache_lru_forget(
br_ssl_session_cache_lru *cc, const unsigned char *id);
/**
* \brief Context structure for a SSL server.
*
* The first field (called `eng`) is the SSL engine; all functions that
* work on a `br_ssl_engine_context` structure shall take as parameter
* a pointer to that field. The other structure fields are opaque and
* must not be accessed directly.
*/
struct br_ssl_server_context_ {
/**
* \brief The encapsulated engine context.
*/
br_ssl_engine_context eng;
#ifndef BR_DOXYGEN_IGNORE
/*
* Maximum version from the client.
*/
uint16_t client_max_version;
/*
* Session cache.
*/
const br_ssl_session_cache_class **cache_vtable;
/*
* Translated cipher suites supported by the client. The list
* is trimmed to include only the cipher suites that the
* server also supports; they are in the same order as in the
* client message.
*/
br_suite_translated client_suites[BR_MAX_CIPHER_SUITES];
unsigned char client_suites_num;
/*
* Hash functions supported by the client, with ECDSA and RSA
* (bit mask). For hash function with id 'x', set bit index is
* x for RSA, x+8 for ECDSA. For newer algorithms, with ID
* 0x08**, bit 16+k is set for algorithm 0x0800+k.
*/
uint32_t hashes;
/*
* Curves supported by the client (bit mask, for named curves).
*/
uint32_t curves;
/*
* Context for chain handler.
*/
const br_ssl_server_policy_class **policy_vtable;
uint16_t sign_hash_id;
/*
* For the core handlers, thus avoiding (in most cases) the
* need for an externally provided policy context.
*/
union {
const br_ssl_server_policy_class *vtable;
br_ssl_server_policy_rsa_context single_rsa;
br_ssl_server_policy_ec_context single_ec;
} chain_handler;
/*
* Buffer for the ECDHE private key.
*/
unsigned char ecdhe_key[70];
size_t ecdhe_key_len;
/*
* Trust anchor names for client authentication. "ta_names" and
* "tas" cannot be both non-NULL.
*/
const br_x500_name *ta_names;
const br_x509_trust_anchor *tas;
size_t num_tas;
size_t cur_dn_index;
const unsigned char *cur_dn;
size_t cur_dn_len;
/*
* Buffer for the hash value computed over all handshake messages
* prior to CertificateVerify, and identifier for the hash function.
*/
unsigned char hash_CV[64];
size_t hash_CV_len;
int hash_CV_id;
/*
* Server-specific implementations.
* (none for now)
*/
#endif
};
/*
* Each br_ssl_server_init_xxx() function sets the list of supported
* cipher suites and used implementations, as specified by the profile
* name 'xxx'. Defined profile names are:
*
* full_rsa all supported algorithm, server key type is RSA
* full_ec all supported algorithm, server key type is EC
* TODO: add other profiles
*
* Naming scheme for "minimal" profiles: min123
*
* -- character 1: key exchange
* r = RSA
* e = ECDHE_RSA
* f = ECDHE_ECDSA
* u = ECDH_RSA
* v = ECDH_ECDSA
* -- character 2: version / PRF
* 0 = TLS 1.0 / 1.1 with MD5+SHA-1
* 2 = TLS 1.2 with SHA-256
* 3 = TLS 1.2 with SHA-384
* -- character 3: encryption
* a = AES/CBC
* d = 3DES/CBC
* g = AES/GCM
* c = ChaCha20+Poly1305
*/
/**
* \brief SSL server profile: full_rsa.
*
* This function initialises the provided SSL server context with
* all supported algorithms and cipher suites that rely on a RSA
* key pair.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: full_ec.
*
* This function initialises the provided SSL server context with
* all supported algorithms and cipher suites that rely on an EC
* key pair.
*
* The key type of the CA that issued the server's certificate must
* be provided, since it matters for ECDH cipher suites (ECDH_RSA
* suites require a RSA-powered CA). The key type is either
* `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len chain length (number of certificates).
* \param cert_issuer_key_type certificate issuer's key type.
* \param sk EC private key.
*/
void br_ssl_server_init_full_ec(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
unsigned cert_issuer_key_type, const br_ec_private_key *sk);
/**
* \brief SSL server profile: minr2g.
*
* This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is
* RSA, and RSA key exchange is used (not forward secure, but uses little
* CPU in the client).
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_minr2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: mine2g.
*
* This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key
* is RSA, and ECDHE key exchange is used. This suite provides forward
* security, with a higher CPU expense on the client, and a somewhat
* larger code footprint (compared to "minr2g").
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_mine2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: minf2g.
*
* This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
* Server key is EC, and ECDHE key exchange is used. This suite provides
* forward security, with a higher CPU expense on the client and server
* (by a factor of about 3 to 4), and a somewhat larger code footprint
* (compared to "minu2g" and "minv2g").
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minf2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief SSL server profile: minu2g.
*
* This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256.
* Server key is EC, and ECDH key exchange is used; the issuing CA used
* a RSA key.
*
* The "minu2g" and "minv2g" profiles do not provide forward secrecy,
* but are the lightest on the server (for CPU usage), and are rather
* inexpensive on the client as well.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minu2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief SSL server profile: minv2g.
*
* This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256.
* Server key is EC, and ECDH key exchange is used; the issuing CA used
* an EC key.
*
* The "minu2g" and "minv2g" profiles do not provide forward secrecy,
* but are the lightest on the server (for CPU usage), and are rather
* inexpensive on the client as well.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minv2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief SSL server profile: mine2c.
*
* This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
* Server key is RSA, and ECDHE key exchange is used. This suite
* provides forward security.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_mine2c(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: minf2c.
*
* This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
* Server key is EC, and ECDHE key exchange is used. This suite provides
* forward security.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minf2c(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief Get the supported client suites.
*
* This function shall be called only after the ClientHello has been
* processed, typically from the policy engine. The returned array
* contains the cipher suites that are supported by both the client
* and the server; these suites are in client preference order, unless
* the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case
* they are in server preference order.
*
* The suites are _translated_, which means that each suite is given
* as two 16-bit integers: the standard suite identifier, and its
* translated version, broken down into its individual components,
* as explained with the `br_suite_translated` type.
*
* The returned array is allocated in the context and will be rewritten
* by each handshake.
*
* \param cc server context.
* \param num receives the array size (number of suites).
* \return the translated common cipher suites, in preference order.
*/
static inline const br_suite_translated *
br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
{
*num = cc->client_suites_num;
return cc->client_suites;
}
/**
* \brief Get the hash functions and signature algorithms supported by
* the client.
*
* This value is a bit field:
*
* - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`,
* then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1,
* or 2 to 6 for the SHA family).
*
* - If ECDSA is supported with hash function of ID `x`, then bit `8+x`
* is set.
*
* - Newer algorithms are symbolic 16-bit identifiers that do not
* represent signature algorithm and hash function separately. If
* the TLS-level identifier is `0x0800+x` for a `x` in the 0..15
* range, then bit `16+x` is set.
*
* "New algorithms" are currently defined only in draft documents, so
* this support is subject to possible change. Right now (early 2017),
* this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA
* on Curve448) to bit 24. If the identifiers on the wire change in
* future document, then the decoding mechanism in BearSSL will be
* amended to keep mapping ed25519 and ed448 on bits 23 and 24,
* respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not
* guaranteed yet.
*
* \param cc server context.
* \return the client-supported hash functions and signature algorithms.
*/
static inline uint32_t
br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
{
return cc->hashes;
}
/**
* \brief Get the elliptic curves supported by the client.
*
* This is a bit field (bit x is set if curve of ID x is supported).
*
* \param cc server context.
* \return the client-supported elliptic curves.
*/
static inline uint32_t
br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
{
return cc->curves;
}
/**
* \brief Clear the complete contents of a SSL server context.
*
* Everything is cleared, including the reference to the configured buffer,
* implementations, cipher suites and state. This is a preparatory step
* to assembling a custom profile.
*
* \param cc server context to clear.
*/
void br_ssl_server_zero(br_ssl_server_context *cc);
/**
* \brief Set an externally provided policy context.
*
* The policy context's methods are invoked to decide the cipher suite
* and certificate chain, and to perform operations involving the server's
* private key.
*
* \param cc server context.
* \param pctx policy context (pointer to its vtable field).
*/
static inline void
br_ssl_server_set_policy(br_ssl_server_context *cc,
const br_ssl_server_policy_class **pctx)
{
cc->policy_vtable = pctx;
}
/**
* \brief Set the server certificate chain and key (single RSA case).
*
* This function uses a policy context included in the server context.
* It configures use of a single server certificate chain with a RSA
* private key. The `allowed_usages` is a combination of usages, namely
* `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
* the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for
* key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures).
*
* \param cc server context.
* \param chain server certificate chain to send to the client.
* \param chain_len chain length (number of certificates).
* \param sk server private key (RSA).
* \param allowed_usages allowed private key usages.
* \param irsacore RSA core implementation.
* \param irsasign RSA signature implementation (PKCS#1 v1.5).
*/
void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk, unsigned allowed_usages,
br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);
/**
* \brief Set the server certificate chain and key (single EC case).
*
* This function uses a policy context included in the server context.
* It configures use of a single server certificate chain with an EC
* private key. The `allowed_usages` is a combination of usages, namely
* `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
* the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for
* key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures).
*
* In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH),
* the algorithm type of the key used by the issuing CA to sign the
* server's certificate must be provided, as `cert_issuer_key_type`
* parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`).
*
* \param cc server context.
* \param chain server certificate chain to send.
* \param chain_len chain length (number of certificates).
* \param sk server private key (EC).
* \param allowed_usages allowed private key usages.
* \param cert_issuer_key_type issuing CA's key type.
* \param iec EC core implementation.
* \param iecdsa ECDSA signature implementation ("asn1" format).
*/
void br_ssl_server_set_single_ec(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk, unsigned allowed_usages,
unsigned cert_issuer_key_type,
const br_ec_impl *iec, br_ecdsa_sign iecdsa);
/**
* \brief Activate client certificate authentication.
*
* The trust anchor encoded X.500 names (DN) to send to the client are
* provided. A client certificate will be requested and validated through
* the X.509 validator configured in the SSL engine. If `num` is 0, then
* client certificate authentication is disabled.
*
* If the client does not send a certificate, or on validation failure,
* the handshake aborts. Unauthenticated clients can be tolerated by
* setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag.
*
* The provided array is linked in, not copied, so that pointer must
* remain valid as long as anchor names may be used.
*
* \param cc server context.
* \param ta_names encoded trust anchor names.
* \param num number of encoded trust anchor names.
*/
static inline void
br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc,
const br_x500_name *ta_names, size_t num)
{
cc->ta_names = ta_names;
cc->tas = NULL;
cc->num_tas = num;
}
/**
* \brief Activate client certificate authentication.
*
* This is a variant for `br_ssl_server_set_trust_anchor_names()`: the
* trust anchor names are provided not as an array of stand-alone names
* (`br_x500_name` structures), but as an array of trust anchors
* (`br_x509_trust_anchor` structures). The server engine itself will
* only use the `dn` field of each trust anchor. This is meant to allow
* defining a single array of trust anchors, to be used here and in the
* X.509 validation engine itself.
*
* The provided array is linked in, not copied, so that pointer must
* remain valid as long as anchor names may be used.
*
* \param cc server context.
* \param tas trust anchors (only names are used).
* \param num number of trust anchors.
*/
static inline void
br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc,
const br_x509_trust_anchor *tas, size_t num)
{
cc->ta_names = NULL;
cc->tas = tas;
cc->num_tas = num;
}
/**
* \brief Configure the cache for session parameters.
*
* The cache context is provided as a pointer to its first field (vtable
* pointer).
*
* \param cc server context.
* \param vtable session cache context.
*/
static inline void
br_ssl_server_set_cache(br_ssl_server_context *cc,
const br_ssl_session_cache_class **vtable)
{
cc->cache_vtable = vtable;
}
/**
* \brief Prepare or reset a server context for handling an incoming client.
*
* \param cc server context.
* \return 1 on success, 0 on error.
*/
int br_ssl_server_reset(br_ssl_server_context *cc);
/* ===================================================================== */
/*
* Context for the simplified I/O context. The transport medium is accessed
* through the low_read() and low_write() callback functions, each with
* its own opaque context pointer.
*
* low_read() read some bytes, at most 'len' bytes, into data[]. The
* returned value is the number of read bytes, or -1 on error.
* The 'len' parameter is guaranteed never to exceed 20000,
* so the length always fits in an 'int' on all platforms.
*
* low_write() write up to 'len' bytes, to be read from data[]. The
* returned value is the number of written bytes, or -1 on
* error. The 'len' parameter is guaranteed never to exceed
* 20000, so the length always fits in an 'int' on all
* parameters.
*
* A socket closure (if the transport medium is a socket) should be reported
* as an error (-1). The callbacks shall endeavour to block until at least
* one byte can be read or written; a callback returning 0 at times is
* acceptable, but this normally leads to the callback being immediately
* called again, so the callback should at least always try to block for
* some time if no I/O can take place.
*
* The SSL engine naturally applies some buffering, so the callbacks need
* not apply buffers of their own.
*/
/**
* \brief Context structure for the simplified SSL I/O wrapper.
*
* This structure is initialised with `br_sslio_init()`. Its contents
* are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
br_ssl_engine_context *engine;
int (*low_read)(void *read_context,
unsigned char *data, size_t len);
void *read_context;
int (*low_write)(void *write_context,
const unsigned char *data, size_t len);
void *write_context;
#endif
} br_sslio_context;
/**
* \brief Initialise a simplified I/O wrapper context.
*
* The simplified I/O wrapper offers a simpler read/write API for a SSL
* engine (client or server), using the provided callback functions for
* reading data from, or writing data to, the transport medium.
*
* The callback functions have the following semantics:
*
* - Each callback receives an opaque context value (of type `void *`)
* that the callback may use arbitrarily (or possibly ignore).
*
* - `low_read()` reads at least one byte, at most `len` bytes, from
* the transport medium. Read bytes shall be written in `data`.
*
* - `low_write()` writes at least one byte, at most `len` bytes, unto
* the transport medium. The bytes to write are read from `data`.
*
* - The `len` parameter is never zero, and is always lower than 20000.
*
* - The number of processed bytes (read or written) is returned. Since
* that number is less than 20000, it always fits on an `int`.
*
* - On error, the callbacks return -1. Reaching end-of-stream is an
* error. Errors are permanent: the SSL connection is terminated.
*
* - Callbacks SHOULD NOT return 0. This is tolerated, as long as
* callbacks endeavour to block for some non-negligible amount of
* time until at least one byte can be sent or received (if a
* callback returns 0, then the wrapper invokes it again
* immediately).
*
* - Callbacks MAY return as soon as at least one byte is processed;
* they MAY also insist on reading or writing _all_ requested bytes.
* Since SSL is a self-terminated protocol (each record has a length
* header), this does not change semantics.
*
* - Callbacks need not apply any buffering (for performance) since SSL
* itself uses buffers.
*
* \param ctx wrapper context to initialise.
* \param engine SSL engine to wrap.
* \param low_read callback for reading data from the transport.
* \param read_context context pointer for `low_read()`.
* \param low_write callback for writing data on the transport.
* \param write_context context pointer for `low_write()`.
*/
void br_sslio_init(br_sslio_context *ctx,
br_ssl_engine_context *engine,
int (*low_read)(void *read_context,
unsigned char *data, size_t len),
void *read_context,
int (*low_write)(void *write_context,
const unsigned char *data, size_t len),
void *write_context);
/**
* \brief Read some application data from a SSL connection.
*
* If `len` is zero, then this function returns 0 immediately. In
* all other cases, it never returns 0.
*
* This call returns only when at least one byte has been obtained.
* Returned value is the number of bytes read, or -1 on error. The
* number of bytes always fits on an 'int' (data from a single SSL/TLS
* record is returned).
*
* On error or SSL closure, this function returns -1. The caller should
* inspect the error status on the SSL engine to distinguish between
* normal closure and error.
*
* \param cc SSL wrapper context.
* \param dst destination buffer for application data.
* \param len maximum number of bytes to obtain.
* \return number of bytes obtained, or -1 on error.
*/
int br_sslio_read(br_sslio_context *cc, void *dst, size_t len);
/**
* \brief Read application data from a SSL connection.
*
* This calls returns only when _all_ requested `len` bytes are read,
* or an error is reached. Returned value is 0 on success, -1 on error.
* A normal (verified) SSL closure before that many bytes are obtained
* is reported as an error by this function.
*
* \param cc SSL wrapper context.
* \param dst destination buffer for application data.
* \param len number of bytes to obtain.
* \return 0 on success, or -1 on error.
*/
int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len);
/**
* \brief Write some application data unto a SSL connection.
*
* If `len` is zero, then this function returns 0 immediately. In
* all other cases, it never returns 0.
*
* This call returns only when at least one byte has been written.
* Returned value is the number of bytes written, or -1 on error. The
* number of bytes always fits on an 'int' (less than 20000).
*
* On error or SSL closure, this function returns -1. The caller should
* inspect the error status on the SSL engine to distinguish between
* normal closure and error.
*
* **Important:** SSL is buffered; a "written" byte is a byte that was
* injected into the wrapped SSL engine, but this does not necessarily mean
* that it has been scheduled for sending. Use `br_sslio_flush()` to
* ensure that all pending data has been sent to the transport medium.
*
* \param cc SSL wrapper context.
* \param src source buffer for application data.
* \param len maximum number of bytes to write.
* \return number of bytes written, or -1 on error.
*/
int br_sslio_write(br_sslio_context *cc, const void *src, size_t len);
/**
* \brief Write application data unto a SSL connection.
*
* This calls returns only when _all_ requested `len` bytes have been
* written, or an error is reached. Returned value is 0 on success, -1
* on error. A normal (verified) SSL closure before that many bytes are
* written is reported as an error by this function.
*
* **Important:** SSL is buffered; a "written" byte is a byte that was
* injected into the wrapped SSL engine, but this does not necessarily mean
* that it has been scheduled for sending. Use `br_sslio_flush()` to
* ensure that all pending data has been sent to the transport medium.
*
* \param cc SSL wrapper context.
* \param src source buffer for application data.
* \param len number of bytes to write.
* \return 0 on success, or -1 on error.
*/
int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len);
/**
* \brief Flush pending data.
*
* This call makes sure that any buffered application data in the
* provided context (including the wrapped SSL engine) has been sent
* to the transport medium (i.e. accepted by the `low_write()` callback
* method). If there is no such pending data, then this function does
* nothing (and returns a success, i.e. 0).
*
* If the underlying transport medium has its own buffers, then it is
* up to the caller to ensure the corresponding flushing.
*
* Returned value is 0 on success, -1 on error.
*
* \param cc SSL wrapper context.
* \return 0 on success, or -1 on error.
*/
int br_sslio_flush(br_sslio_context *cc);
/**
* \brief Close the SSL connection.
*
* This call runs the SSL closure protocol (sending a `close_notify`,
* receiving the response `close_notify`). When it returns, the SSL
* connection is finished. It is still up to the caller to manage the
* possible transport-level termination, if applicable (alternatively,
* the underlying transport stream may be reused for non-SSL messages).
*
* Returned value is 0 on success, -1 on error. A failure by the peer
* to process the complete closure protocol (i.e. sending back the
* `close_notify`) is an error.
*
* \param cc SSL wrapper context.
* \return 0 on success, or -1 on error.
*/
int br_sslio_close(br_sslio_context *cc);
/* ===================================================================== */
/*
* Symbolic constants for cipher suites.
*/
/* From RFC 5246 */
#define BR_TLS_NULL_WITH_NULL_NULL 0x0000
#define BR_TLS_RSA_WITH_NULL_MD5 0x0001
#define BR_TLS_RSA_WITH_NULL_SHA 0x0002
#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B
#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004
#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005
#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A
#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D
#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E
#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F
#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040
#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068
#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069
#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A
#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018
#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B
#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C
#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D
/* From RFC 4492 */
#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001
#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002
#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005
#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006
#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007
#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A
#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B
#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C
#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D
#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E
#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F
#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010
#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011
#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012
#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013
#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014
#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015
#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016
#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017
#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018
#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019
/* From RFC 5288 */
#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D
#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F
#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0
#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1
#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3
#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4
#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5
#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6
#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7
/* From RFC 5289 */
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026
#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028
#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029
#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E
#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030
#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032
/* From RFC 6655 and 7251 */
#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C
#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D
#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0
#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF
/* From RFC 7905 */
#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8
#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA
#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB
#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC
#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD
#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE
/* From RFC 7507 */
#define BR_TLS_FALLBACK_SCSV 0x5600
/*
* Symbolic constants for alerts.
*/
#define BR_ALERT_CLOSE_NOTIFY 0
#define BR_ALERT_UNEXPECTED_MESSAGE 10
#define BR_ALERT_BAD_RECORD_MAC 20
#define BR_ALERT_RECORD_OVERFLOW 22
#define BR_ALERT_DECOMPRESSION_FAILURE 30
#define BR_ALERT_HANDSHAKE_FAILURE 40
#define BR_ALERT_BAD_CERTIFICATE 42
#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43
#define BR_ALERT_CERTIFICATE_REVOKED 44
#define BR_ALERT_CERTIFICATE_EXPIRED 45
#define BR_ALERT_CERTIFICATE_UNKNOWN 46
#define BR_ALERT_ILLEGAL_PARAMETER 47
#define BR_ALERT_UNKNOWN_CA 48
#define BR_ALERT_ACCESS_DENIED 49
#define BR_ALERT_DECODE_ERROR 50
#define BR_ALERT_DECRYPT_ERROR 51
#define BR_ALERT_PROTOCOL_VERSION 70
#define BR_ALERT_INSUFFICIENT_SECURITY 71
#define BR_ALERT_INTERNAL_ERROR 80
#define BR_ALERT_USER_CANCELED 90
#define BR_ALERT_NO_RENEGOTIATION 100
#define BR_ALERT_UNSUPPORTED_EXTENSION 110
#define BR_ALERT_NO_APPLICATION_PROTOCOL 120
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_PEM_H__
#define BR_BEARSSL_PEM_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_pem.h
*
* # PEM Support
*
* PEM is a traditional encoding layer use to store binary objects (in
* particular X.509 certificates, and private keys) in text files. While
* the acronym comes from an old, defunct standard ("Privacy Enhanced
* Mail"), the format has been reused, with some variations, by many
* systems, and is a _de facto_ standard, even though it is not, actually,
* specified in all clarity anywhere.
*
* ## Format Details
*
* BearSSL contains a generic, streamed PEM decoder, which handles the
* following format:
*
* - The input source (a sequence of bytes) is assumed to be the
* encoding of a text file in an ASCII-compatible charset. This
* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each
* line ends on a newline character (U+000A LINE FEED). The
* U+000D CARRIAGE RETURN characters are ignored, so the code
* accepts both Windows-style and Unix-style line endings.
*
* - Each object begins with a banner that occurs at the start of
* a line; the first banner characters are "`-----BEGIN `" (five
* dashes, the word "BEGIN", and a space). The banner matching is
* not case-sensitive.
*
* - The _object name_ consists in the characters that follow the
* banner start sequence, up to the end of the line, but without
* trailing dashes (in "normal" PEM, there are five trailing
* dashes, but this implementation is not picky about these dashes).
* The BearSSL decoder normalises the name characters to uppercase
* (for ASCII letters only) and accepts names up to 127 characters.
*
* - The object ends with a banner that again occurs at the start of
* a line, and starts with "`-----END `" (again case-insensitive).
*
* - Between that start and end banner, only Base64 data shall occur.
* Base64 converts each sequence of three bytes into four
* characters; the four characters are ASCII letters, digits, "`+`"
* or "`-`" signs, and one or two "`=`" signs may occur in the last
* quartet. Whitespace is ignored (whitespace is any ASCII character
* of code 32 or less, so control characters are whitespace) and
* lines may have arbitrary length; the only restriction is that the
* four characters of a quartet must appear on the same line (no
* line break inside a quartet).
*
* - A single file may contain more than one PEM object. Bytes that
* occur between objects are ignored.
*
*
* ## PEM Decoder API
*
* The PEM decoder offers a state-machine API. The caller allocates a
* decoder context, then injects source bytes. Source bytes are pushed
* with `br_pem_decoder_push()`. The decoder stops accepting bytes when
* it reaches an "event", which is either the start of an object, the
* end of an object, or a decoding error within an object.
*
* The `br_pem_decoder_event()` function is used to obtain the current
* event; it also clears it, thus allowing the decoder to accept more
* bytes. When a object start event is raised, the decoder context
* offers the found object name (normalised to ASCII uppercase).
*
* When an object is reached, the caller must set an appropriate callback
* function, which will receive (by chunks) the decoded object data.
*
* Since the decoder context makes no dynamic allocation, it requires
* no explicit deallocation.
*/
/**
* \brief PEM decoder context.
*
* Contents are opaque (they should not be accessed directly).
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
const unsigned char *hbuf;
size_t hlen;
void (*dest)(void *dest_ctx, const void *src, size_t len);
void *dest_ctx;
unsigned char event;
char name[128];
unsigned char buf[255];
size_t ptr;
#endif
} br_pem_decoder_context;
/**
* \brief Initialise a PEM decoder structure.
*
* \param ctx decoder context to initialise.
*/
void br_pem_decoder_init(br_pem_decoder_context *ctx);
/**
* \brief Push some bytes into the decoder.
*
* Returned value is the number of bytes actually consumed; this may be
* less than the number of provided bytes if an event is raised. When an
* event is raised, it must be read (with `br_pem_decoder_event()`);
* until the event is read, this function will return 0.
*
* \param ctx decoder context.
* \param data new data bytes.
* \param len number of new data bytes.
* \return the number of bytes actually received (may be less than `len`).
*/
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Set the receiver for decoded data.
*
* When an object is entered, the provided function (with opaque context
* pointer) will be called repeatedly with successive chunks of decoded
* data for that object. If `dest` is set to 0, then decoded data is
* simply ignored. The receiver can be set at any time, but, in practice,
* it should be called immediately after receiving a "start of object"
* event.
*
* \param ctx decoder context.
* \param dest callback for receiving decoded data.
* \param dest_ctx opaque context pointer for the `dest` callback.
*/
static inline void
br_pem_decoder_setdest(br_pem_decoder_context *ctx,
void (*dest)(void *dest_ctx, const void *src, size_t len),
void *dest_ctx)
{
ctx->dest = dest;
ctx->dest_ctx = dest_ctx;
}
/**
* \brief Get the last event.
*
* If an event was raised, then this function returns the event value, and
* also clears it, thereby allowing the decoder to proceed. If no event
* was raised since the last call to `br_pem_decoder_event()`, then this
* function returns 0.
*
* \param ctx decoder context.
* \return the raised event, or 0.
*/
int br_pem_decoder_event(br_pem_decoder_context *ctx);
/**
* \brief Event: start of object.
*
* This event is raised when the start of a new object has been detected.
* The object name (normalised to uppercase) can be accessed with
* `br_pem_decoder_name()`.
*/
#define BR_PEM_BEGIN_OBJ 1
/**
* \brief Event: end of object.
*
* This event is raised when the end of the current object is reached
* (normally, i.e. with no decoding error).
*/
#define BR_PEM_END_OBJ 2
/**
* \brief Event: decoding error.
*
* This event is raised when decoding fails within an object.
* This formally closes the current object and brings the decoder back
* to the "out of any object" state. The offending line in the source
* is consumed.
*/
#define BR_PEM_ERROR 3
/**
* \brief Get the name of the encountered object.
*
* The encountered object name is defined only when the "start of object"
* event is raised. That name is normalised to uppercase (for ASCII letters
* only) and does not include trailing dashes.
*
* \param ctx decoder context.
* \return the current object name.
*/
static inline const char *
br_pem_decoder_name(br_pem_decoder_context *ctx)
{
return ctx->name;
}
/**
* \brief Encode an object in PEM.
*
* This function encodes the provided binary object (`data`, of length `len`
* bytes) into PEM. The `banner` text will be included in the header and
* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).
*
* The length (in characters) of the PEM output is returned; that length
* does NOT include the terminating zero, that this function nevertheless
* adds. If using the returned value for allocation purposes, the allocated
* buffer size MUST be at least one byte larger than the returned size.
*
* If `dest` is `NULL`, then the encoding does not happen; however, the
* length of the encoded object is still computed and returned.
*
* The `data` pointer may be `NULL` only if `len` is zero (when encoding
* an object of length zero, which is not very useful), or when `dest`
* is `NULL` (in that case, source data bytes are ignored).
*
* Some `flags` can be specified to alter the encoding behaviour:
*
* - If `BR_PEM_LINE64` is set, then line-breaking will occur after
* every 64 characters of output, instead of the default of 76.
*
* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use
* CR+LF instead of a single LF.
*
* The `data` and `dest` buffers may overlap, in which case the source
* binary data is destroyed in the process. Note that the PEM-encoded output
* is always larger than the source binary.
*
* \param dest the destination buffer (or `NULL`).
* \param data the source buffer (can be `NULL` in some cases).
* \param len the source length (in bytes).
* \param banner the PEM banner expression.
* \param flags the behavioural flags.
* \return the PEM object length (in characters), EXCLUDING the final zero.
*/
size_t br_pem_encode(void *dest, const void *data, size_t len,
const char *banner, unsigned flags);
/**
* \brief PEM encoding flag: split lines at 64 characters.
*/
#define BR_PEM_LINE64 0x0001
/**
* \brief PEM encoding flag: use CR+LF line endings.
*/
#define BR_PEM_CRLF 0x0002
#ifdef __cplusplus
}
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \brief Type for a configuration option.
*
* A "configuration option" is a value that is selected when the BearSSL
* library itself is compiled. Most options are boolean; their value is
* then either 1 (option is enabled) or 0 (option is disabled). Some
* values have other integer values. Option names correspond to macro
* names. Some of the options can be explicitly set in the internal
* `"config.h"` file.
*/
typedef struct {
/** \brief Configurable option name. */
const char *name;
/** \brief Configurable option value. */
long value;
} br_config_option;
/** \brief Get configuration report.
*
* This function returns compiled configuration options, each as a
* 'long' value. Names match internal macro names, in particular those
* that can be set in the `"config.h"` inner file. For boolean options,
* the numerical value is 1 if enabled, 0 if disabled. For maximum
* key sizes, values are expressed in bits.
*
* The returned array is terminated by an entry whose `name` is `NULL`.
*
* \return the configuration report.
*/
const br_config_option *br_get_config(void);
/* ======================================================================= */
/** \brief Version feature: support for time callback. */
#define BR_FEATURE_X509_TIME_CALLBACK 1
#ifdef __cplusplus
}
#endif
#endif
/*
* On MSVC, disable the warning about applying unary minus on an
* unsigned type: it is standard, we do it all the time, and for
* good reasons.
*/
#if _MSC_VER
#pragma warning( disable : 4146 )
#endif
/*
* Maximum size for a RSA modulus (in bits). Allocated stack buffers
* depend on that size, so this value should be kept small. Currently,
* 2048-bit RSA keys offer adequate security, and should still do so for
* the next few decades; however, a number of widespread PKI have
* already set their root keys to RSA-4096, so we should be able to
* process such keys.
*
* This value MUST be a multiple of 64. This value MUST NOT exceed 47666
* (some computations in RSA key generation rely on the factor size being
* no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a
* lot of sense anyway.
*/
#define BR_MAX_RSA_SIZE 4096
/*
* Minimum size for a RSA modulus (in bits); this value is used only to
* filter out invalid parameters for key pair generation. Normally,
* applications should not use RSA keys smaller than 2048 bits; but some
* specific cases might need shorter keys, for legacy or research
* purposes.
*/
#define BR_MIN_RSA_SIZE 512
/*
* Maximum size for a RSA factor (in bits). This is for RSA private-key
* operations. Default is to support factors up to a bit more than half
* the maximum modulus size.
*
* This value MUST be a multiple of 32.
*/
#define BR_MAX_RSA_FACTOR ((BR_MAX_RSA_SIZE + 64) >> 1)
/*
* Maximum size for an EC curve (modulus or order), in bits. Size of
* stack buffers depends on that parameter. This size MUST be a multiple
* of 8 (so that decoding an integer with that many bytes does not
* overflow).
*/
#define BR_MAX_EC_SIZE 528
/*
* Some macros to recognize the current architecture. Right now, we are
* interested into automatically recognizing architecture with efficient
* 64-bit types so that we may automatically use implementations that
* use 64-bit registers in that case. Future versions may detect, e.g.,
* availability of SSE2 intrinsics.
*
* If 'unsigned long' is a 64-bit type, then we assume that 64-bit types
* are efficient. Otherwise, we rely on macros that depend on compiler,
* OS and architecture. In any case, failure to detect the architecture
* as 64-bit means that the 32-bit code will be used, and that code
* works also on 64-bit architectures (the 64-bit code may simply be
* more efficient).
*
* The test on 'unsigned long' should already catch most cases, the one
* notable exception being Windows code where 'unsigned long' is kept to
* 32-bit for compatibility with all the legacy code that liberally uses
* the 'DWORD' type for 32-bit values.
*
* Macro names are taken from: https://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
*/
#ifndef BR_64
#if ((ULONG_MAX >> 31) >> 31) == 3
#define BR_64 1
#elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64)
#define BR_64 1
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \
|| defined(__64BIT__) || defined(_LP64) || defined(__LP64__)
#define BR_64 1
#elif defined(__sparc64__)
#define BR_64 1
#elif defined(__x86_64__) || defined(_M_X64)
#define BR_64 1
#elif defined(__aarch64__) || defined(_M_ARM64)
#define BR_64 1
#elif defined(__mips64)
#define BR_64 1
#endif
#endif
/*
* Set BR_LOMUL on platforms where it makes sense.
*/
#ifndef BR_LOMUL
#if BR_ARMEL_CORTEXM_GCC
#define BR_LOMUL 1
#endif
#endif
/*
* Architecture detection.
*/
#ifndef BR_i386
#if __i386__ || _M_IX86
#define BR_i386 1
#endif
#endif
#ifndef BR_amd64
#if __x86_64__ || _M_X64
#define BR_amd64 1
#endif
#endif
/*
* Compiler brand and version.
*
* Implementations that use intrinsics need to detect the compiler type
* and version because some specific actions may be needed to activate
* the corresponding opcodes, both for header inclusion, and when using
* them in a function.
*
* BR_GCC, BR_CLANG and BR_MSC will be set to 1 for, respectively, GCC,
* Clang and MS Visual C. For each of them, sub-macros will be defined
* for versions; each sub-macro is set whenever the compiler version is
* at least as recent as the one corresponding to the macro.
*/
/*
* GCC thresholds are on versions 4.4 to 4.9 and 5.0.
*/
#ifndef BR_GCC
#if __GNUC__ && !__clang__
#define BR_GCC 1
#if __GNUC__ > 4
#define BR_GCC_5_0 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
#define BR_GCC_4_9 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8
#define BR_GCC_4_8 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7
#define BR_GCC_4_7 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6
#define BR_GCC_4_6 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 5
#define BR_GCC_4_5 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 4
#define BR_GCC_4_4 1
#endif
#if BR_GCC_5_0
#define BR_GCC_4_9 1
#endif
#if BR_GCC_4_9
#define BR_GCC_4_8 1
#endif
#if BR_GCC_4_8
#define BR_GCC_4_7 1
#endif
#if BR_GCC_4_7
#define BR_GCC_4_6 1
#endif
#if BR_GCC_4_6
#define BR_GCC_4_5 1
#endif
#if BR_GCC_4_5
#define BR_GCC_4_4 1
#endif
#endif
#endif
/*
* Clang thresholds are on versions 3.7.0 and 3.8.0.
*/
#ifndef BR_CLANG
#if __clang__
#define BR_CLANG 1
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8)
#define BR_CLANG_3_8 1
#elif __clang_major__ == 3 && __clang_minor__ >= 7
#define BR_CLANG_3_7 1
#endif
#if BR_CLANG_3_8
#define BR_CLANG_3_7 1
#endif
#endif
#endif
/*
* MS Visual C thresholds are on Visual Studio 2005 to 2015.
*/
#ifndef BR_MSC
#if _MSC_VER
#define BR_MSC 1
#if _MSC_VER >= 1900
#define BR_MSC_2015 1
#elif _MSC_VER >= 1800
#define BR_MSC_2013 1
#elif _MSC_VER >= 1700
#define BR_MSC_2012 1
#elif _MSC_VER >= 1600
#define BR_MSC_2010 1
#elif _MSC_VER >= 1500
#define BR_MSC_2008 1
#elif _MSC_VER >= 1400
#define BR_MSC_2005 1
#endif
#if BR_MSC_2015
#define BR_MSC_2013 1
#endif
#if BR_MSC_2013
#define BR_MSC_2012 1
#endif
#if BR_MSC_2012
#define BR_MSC_2010 1
#endif
#if BR_MSC_2010
#define BR_MSC_2008 1
#endif
#if BR_MSC_2008
#define BR_MSC_2005 1
#endif
#endif
#endif
/*
* GCC 4.4+ and Clang 3.7+ allow tagging specific functions with a
* 'target' attribute that activates support for specific opcodes.
*/
#if BR_GCC_4_4 || BR_CLANG_3_7
#define BR_TARGET(x) __attribute__((target(x)))
#else
#define BR_TARGET(x)
#endif
/*
* AES-NI intrinsics are available on x86 (32-bit and 64-bit) with
* GCC 4.8+, Clang 3.7+ and MSC 2012+.
*/
#ifndef BR_AES_X86NI
#if (BR_i386 || BR_amd64) && (BR_GCC_4_8 || BR_CLANG_3_7 || BR_MSC_2012)
#define BR_AES_X86NI 1
#endif
#endif
/*
* SSE2 intrinsics are available on x86 (32-bit and 64-bit) with
* GCC 4.4+, Clang 3.7+ and MSC 2005+.
*/
#ifndef BR_SSE2
#if (BR_i386 || BR_amd64) && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005)
#define BR_SSE2 1
#endif
#endif
/*
* RDRAND intrinsics are available on x86 (32-bit and 64-bit) with
* GCC 4.6+, Clang 3.7+ and MSC 2012+.
*/
#ifndef BR_RDRAND
#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012)
#define BR_RDRAND 1
#endif
#endif
/*
* Determine type of OS for random number generation. Macro names and
* values are documented on:
* https://sourceforge.net/p/predef/wiki/OperatingSystems/
*
* Win32's CryptGenRandom() should be available on Windows systems.
*
* /dev/urandom should work on all Unix-like systems (including macOS X).
*
* getentropy() is present on Linux (Glibc 2.25+), FreeBSD (12.0+) and
* OpenBSD (5.6+). For OpenBSD, there does not seem to be easy to use
* macros to test the minimum version, so we just assume that it is
* recent enough (last version without getentropy() has gone out of
* support in May 2015).
*
* Ideally we should use getentropy() on macOS (10.12+) too, but I don't
* know how to test the exact OS version with preprocessor macros.
*
* TODO: enrich the list of detected system.
*/
#ifndef BR_USE_URANDOM
#if defined _AIX \
|| defined __ANDROID__ \
|| defined __FreeBSD__ \
|| defined __NetBSD__ \
|| defined __OpenBSD__ \
|| defined __DragonFly__ \
|| defined __linux__ \
|| (defined __sun && (defined __SVR4 || defined __svr4__)) \
|| (defined __APPLE__ && defined __MACH__)
#define BR_USE_URANDOM 1
#endif
#endif
#ifndef BR_USE_GETENTROPY
#if (defined __linux__ \
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) \
|| (defined __FreeBSD__ && __FreeBSD__ >= 12) \
|| defined __OpenBSD__
#define BR_USE_GETENTROPY 1
#endif
#endif
#ifndef BR_USE_WIN32_RAND
#if defined _WIN32 || defined _WIN64
#define BR_USE_WIN32_RAND 1
#endif
#endif
/*
* POWER8 crypto support. We rely on compiler macros for the
* architecture, since we do not have a reliable, simple way to detect
* the required support at runtime (we could try running an opcode, and
* trapping the exception or signal on illegal instruction, but this
* induces some non-trivial OS dependencies that we would prefer to
* avoid if possible).
*/
#ifndef BR_POWER8
#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__)
#define BR_POWER8 1
#endif
#endif
/*
* Detect endinanness on POWER8.
*/
#if BR_POWER8
#if defined BR_POWER8_LE
#undef BR_POWER8_BE
#if BR_POWER8_LE
#define BR_POWER8_BE 0
#else
#define BR_POWER8_BE 1
#endif
#elif defined BR_POWER8_BE
#undef BR_POWER8_LE
#if BR_POWER8_BE
#define BR_POWER8_LE 0
#else
#define BR_POWER8_LE 1
#endif
#else
#if __LITTLE_ENDIAN__
#define BR_POWER8_LE 1
#define BR_POWER8_BE 0
#else
#define BR_POWER8_LE 0
#define BR_POWER8_BE 1
#endif
#endif
#endif
/*
* Detect support for 128-bit integers.
*/
#if !defined BR_INT128 && !defined BR_UMUL128
#ifdef __SIZEOF_INT128__
#define BR_INT128 1
#elif _M_X64
#define BR_UMUL128 1
#endif
#endif
/*
* Detect support for unaligned accesses with known endianness.
*
* x86 (both 32-bit and 64-bit) is little-endian and allows unaligned
* accesses.
*
* POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and
* later also allow unaligned accesses when little-endian.
*/
#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED
#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64
#define BR_LE_UNALIGNED 1
#elif BR_POWER8_BE
#define BR_BE_UNALIGNED 1
#elif BR_POWER8_LE
#define BR_LE_UNALIGNED 1
#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \
&& __BIG_ENDIAN__
#define BR_BE_UNALIGNED 1
#endif
#endif
/*
* Detect support for an OS-provided time source.
*/
#ifndef BR_USE_UNIX_TIME
#if defined __unix__ || defined __linux__ \
|| defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \
|| (defined __APPLE__ && defined __MACH__)
#define BR_USE_UNIX_TIME 1
#endif
#endif
#ifndef BR_USE_WIN32_TIME
#if defined _WIN32 || defined _WIN64
#define BR_USE_WIN32_TIME 1
#endif
#endif
/* ==================================================================== */
/*
* Encoding/decoding functions.
*
* 32-bit and 64-bit decoding, both little-endian and big-endian, is
* implemented with the inline functions below.
*
* When allowed by some compile-time options (autodetected or provided),
* optimised code is used, to perform direct memory access when the
* underlying architecture supports it, both for endianness and
* alignment. This, however, may trigger strict aliasing issues; the
* code below uses unions to perform (supposedly) safe type punning.
* Since the C aliasing rules are relatively complex and were amended,
* or at least re-explained with different phrasing, in all successive
* versions of the C standard, it is always a bit risky to bet that any
* specific version of a C compiler got it right, for some notion of
* "right".
*/
typedef union {
uint16_t u;
unsigned char b[sizeof(uint16_t)];
} br_union_u16;
typedef union {
uint32_t u;
unsigned char b[sizeof(uint32_t)];
} br_union_u32;
typedef union {
uint64_t u;
unsigned char b[sizeof(uint64_t)];
} br_union_u64;
static inline void
br_enc16le(void *dst, unsigned x)
{
#if BR_LE_UNALIGNED
((br_union_u16 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)x;
buf[1] = (unsigned char)(x >> 8);
#endif
}
static inline void
br_enc16be(void *dst, unsigned x)
{
#if BR_BE_UNALIGNED
((br_union_u16 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)(x >> 8);
buf[1] = (unsigned char)x;
#endif
}
static inline unsigned
br_dec16le(const void *src)
{
#if BR_LE_UNALIGNED
return ((const br_union_u16 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return (unsigned)buf[0] | ((unsigned)buf[1] << 8);
#endif
}
static inline unsigned
br_dec16be(const void *src)
{
#if BR_BE_UNALIGNED
return ((const br_union_u16 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return ((unsigned)buf[0] << 8) | (unsigned)buf[1];
#endif
}
static inline void
br_enc32le(void *dst, uint32_t x)
{
#if BR_LE_UNALIGNED
((br_union_u32 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)x;
buf[1] = (unsigned char)(x >> 8);
buf[2] = (unsigned char)(x >> 16);
buf[3] = (unsigned char)(x >> 24);
#endif
}
static inline void
br_enc32be(void *dst, uint32_t x)
{
#if BR_BE_UNALIGNED
((br_union_u32 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)(x >> 24);
buf[1] = (unsigned char)(x >> 16);
buf[2] = (unsigned char)(x >> 8);
buf[3] = (unsigned char)x;
#endif
}
static inline uint32_t
br_dec32le(const void *src)
{
#if BR_LE_UNALIGNED
return ((const br_union_u32 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return (uint32_t)buf[0]
| ((uint32_t)buf[1] << 8)
| ((uint32_t)buf[2] << 16)
| ((uint32_t)buf[3] << 24);
#endif
}
static inline uint32_t
br_dec32be(const void *src)
{
#if BR_BE_UNALIGNED
return ((const br_union_u32 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return ((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3];
#endif
}
static inline void
br_enc64le(void *dst, uint64_t x)
{
#if BR_LE_UNALIGNED
((br_union_u64 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
br_enc32le(buf, (uint32_t)x);
br_enc32le(buf + 4, (uint32_t)(x >> 32));
#endif
}
static inline void
br_enc64be(void *dst, uint64_t x)
{
#if BR_BE_UNALIGNED
((br_union_u64 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
br_enc32be(buf, (uint32_t)(x >> 32));
br_enc32be(buf + 4, (uint32_t)x);
#endif
}
static inline uint64_t
br_dec64le(const void *src)
{
#if BR_LE_UNALIGNED
return ((const br_union_u64 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return (uint64_t)br_dec32le(buf)
| ((uint64_t)br_dec32le(buf + 4) << 32);
#endif
}
static inline uint64_t
br_dec64be(const void *src)
{
#if BR_BE_UNALIGNED
return ((const br_union_u64 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return ((uint64_t)br_dec32be(buf) << 32)
| (uint64_t)br_dec32be(buf + 4);
#endif
}
/*
* Range decoding and encoding (for several successive values).
*/
void br_range_dec16le(uint16_t *v, size_t num, const void *src);
void br_range_dec16be(uint16_t *v, size_t num, const void *src);
void br_range_enc16le(void *dst, const uint16_t *v, size_t num);
void br_range_enc16be(void *dst, const uint16_t *v, size_t num);
void br_range_dec32le(uint32_t *v, size_t num, const void *src);
void br_range_dec32be(uint32_t *v, size_t num, const void *src);
void br_range_enc32le(void *dst, const uint32_t *v, size_t num);
void br_range_enc32be(void *dst, const uint32_t *v, size_t num);
void br_range_dec64le(uint64_t *v, size_t num, const void *src);
void br_range_dec64be(uint64_t *v, size_t num, const void *src);
void br_range_enc64le(void *dst, const uint64_t *v, size_t num);
void br_range_enc64be(void *dst, const uint64_t *v, size_t num);
/*
* Byte-swap a 32-bit integer.
*/
static inline uint32_t
br_swap32(uint32_t x)
{
x = ((x & (uint32_t)0x00FF00FF) << 8)
| ((x >> 8) & (uint32_t)0x00FF00FF);
return (x << 16) | (x >> 16);
}
/* ==================================================================== */
/*
* Support code for hash functions.
*/
/*
* IV for MD5, SHA-1, SHA-224 and SHA-256.
*/
extern const uint32_t br_md5_IV[];
extern const uint32_t br_sha1_IV[];
extern const uint32_t br_sha224_IV[];
extern const uint32_t br_sha256_IV[];
/*
* Round functions for MD5, SHA-1, SHA-224 and SHA-256 (SHA-224 and
* SHA-256 use the same round function).
*/
void br_md5_round(const unsigned char *buf, uint32_t *val);
void br_sha1_round(const unsigned char *buf, uint32_t *val);
void br_sha2small_round(const unsigned char *buf, uint32_t *val);
/*
* The core function for the TLS PRF. It computes
* P_hash(secret, label + seed), and XORs the result into the dst buffer.
*/
void br_tls_phash(void *dst, size_t len,
const br_hash_class *dig,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/*
* Copy all configured hash implementations from a multihash context
* to another.
*/
static inline void
br_multihash_copyimpl(br_multihash_context *dst,
const br_multihash_context *src)
{
memcpy((void *)dst->impl, src->impl, sizeof src->impl);
}
/* ==================================================================== */
/*
* Constant-time primitives. These functions manipulate 32-bit values in
* order to provide constant-time comparisons and multiplexers.
*
* Boolean values (the "ctl" bits) MUST have value 0 or 1.
*
* Implementation notes:
* =====================
*
* The uintN_t types are unsigned and with width exactly N bits; the C
* standard guarantees that computations are performed modulo 2^N, and
* there can be no overflow. Negation (unary '-') works on unsigned types
* as well.
*
* The intN_t types are guaranteed to have width exactly N bits, with no
* padding bit, and using two's complement representation. Casting
* intN_t to uintN_t really is conversion modulo 2^N. Beware that intN_t
* types, being signed, trigger implementation-defined behaviour on
* overflow (including raising some signal): with GCC, while modular
* arithmetics are usually applied, the optimizer may assume that
* overflows don't occur (unless the -fwrapv command-line option is
* added); Clang has the additional -ftrapv option to explicitly trap on
* integer overflow or underflow.
*/
/*
* Negate a boolean.
*/
static inline uint32_t
NOT(uint32_t ctl)
{
return ctl ^ 1;
}
/*
* Multiplexer: returns x if ctl == 1, y if ctl == 0.
*/
static inline uint32_t
MUX(uint32_t ctl, uint32_t x, uint32_t y)
{
return y ^ (-ctl & (x ^ y));
}
/*
* Equality check: returns 1 if x == y, 0 otherwise.
*/
static inline uint32_t
EQ(uint32_t x, uint32_t y)
{
uint32_t q;
q = x ^ y;
return NOT((q | -q) >> 31);
}
/*
* Inequality check: returns 1 if x != y, 0 otherwise.
*/
static inline uint32_t
NEQ(uint32_t x, uint32_t y)
{
uint32_t q;
q = x ^ y;
return (q | -q) >> 31;
}
/*
* Comparison: returns 1 if x > y, 0 otherwise.
*/
static inline uint32_t
GT(uint32_t x, uint32_t y)
{
/*
* If both x < 2^31 and x < 2^31, then y-x will have its high
* bit set if x > y, cleared otherwise.
*
* If either x >= 2^31 or y >= 2^31 (but not both), then the
* result is the high bit of x.
*
* If both x >= 2^31 and y >= 2^31, then we can virtually
* subtract 2^31 from both, and we are back to the first case.
* Since (y-2^31)-(x-2^31) = y-x, the subtraction is already
* fine.
*/
uint32_t z;
z = y - x;
return (z ^ ((x ^ y) & (x ^ z))) >> 31;
}
/*
* Other comparisons (greater-or-equal, lower-than, lower-or-equal).
*/
#define GE(x, y) NOT(GT(y, x))
#define LT(x, y) GT(y, x)
#define LE(x, y) NOT(GT(x, y))
/*
* General comparison: returned value is -1, 0 or 1, depending on
* whether x is lower than, equal to, or greater than y.
*/
static inline int32_t
CMP(uint32_t x, uint32_t y)
{
return (int32_t)GT(x, y) | -(int32_t)GT(y, x);
}
/*
* Returns 1 if x == 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
EQ0(int32_t x)
{
uint32_t q;
q = (uint32_t)x;
return ~(q | -q) >> 31;
}
/*
* Returns 1 if x > 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
GT0(int32_t x)
{
/*
* High bit of -x is 0 if x == 0, but 1 if x > 0.
*/
uint32_t q;
q = (uint32_t)x;
return (~q & -q) >> 31;
}
/*
* Returns 1 if x >= 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
GE0(int32_t x)
{
return ~(uint32_t)x >> 31;
}
/*
* Returns 1 if x < 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
LT0(int32_t x)
{
return (uint32_t)x >> 31;
}
/*
* Returns 1 if x <= 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
LE0(int32_t x)
{
uint32_t q;
/*
* ~-x has its high bit set if and only if -x is nonnegative (as
* a signed int), i.e. x is in the -(2^31-1) to 0 range. We must
* do an OR with x itself to account for x = -2^31.
*/
q = (uint32_t)x;
return (q | ~-q) >> 31;
}
/*
* Conditional copy: src[] is copied into dst[] if and only if ctl is 1.
* dst[] and src[] may overlap completely (but not partially).
*/
void br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len);
#define CCOPY br_ccopy
/*
* Compute the bit length of a 32-bit integer. Returned value is between 0
* and 32 (inclusive).
*/
static inline uint32_t
BIT_LENGTH(uint32_t x)
{
uint32_t k, c;
k = NEQ(x, 0);
c = GT(x, 0xFFFF); x = MUX(c, x >> 16, x); k += c << 4;
c = GT(x, 0x00FF); x = MUX(c, x >> 8, x); k += c << 3;
c = GT(x, 0x000F); x = MUX(c, x >> 4, x); k += c << 2;
c = GT(x, 0x0003); x = MUX(c, x >> 2, x); k += c << 1;
k += GT(x, 0x0001);
return k;
}
/*
* Compute the minimum of x and y.
*/
static inline uint32_t
MIN(uint32_t x, uint32_t y)
{
return MUX(GT(x, y), y, x);
}
/*
* Compute the maximum of x and y.
*/
static inline uint32_t
MAX(uint32_t x, uint32_t y)
{
return MUX(GT(x, y), x, y);
}
/*
* Multiply two 32-bit integers, with a 64-bit result. This default
* implementation assumes that the basic multiplication operator
* yields constant-time code.
*/
#define MUL(x, y) ((uint64_t)(x) * (uint64_t)(y))
#if BR_CT_MUL31
/*
* Alternate implementation of MUL31, that will be constant-time on some
* (old) platforms where the default MUL31 is not. Unfortunately, it is
* also substantially slower, and yields larger code, on more modern
* platforms, which is why it is deactivated by default.
*
* MUL31_lo() must do some extra work because on some platforms, the
* _signed_ multiplication may return early if the top bits are 1.
* Simply truncating (casting) the output of MUL31() would not be
* sufficient, because the compiler may notice that we keep only the low
* word, and then replace automatically the unsigned multiplication with
* a signed multiplication opcode.
*/
#define MUL31(x, y) ((uint64_t)((x) | (uint32_t)0x80000000) \
* (uint64_t)((y) | (uint32_t)0x80000000) \
- ((uint64_t)(x) << 31) - ((uint64_t)(y) << 31) \
- ((uint64_t)1 << 62))
static inline uint32_t
MUL31_lo(uint32_t x, uint32_t y)
{
uint32_t xl, xh;
uint32_t yl, yh;
xl = (x & 0xFFFF) | (uint32_t)0x80000000;
xh = (x >> 16) | (uint32_t)0x80000000;
yl = (y & 0xFFFF) | (uint32_t)0x80000000;
yh = (y >> 16) | (uint32_t)0x80000000;
return (xl * yl + ((xl * yh + xh * yl) << 16)) & (uint32_t)0x7FFFFFFF;
}
#else
/*
* Multiply two 31-bit integers, with a 62-bit result. This default
* implementation assumes that the basic multiplication operator
* yields constant-time code.
* The MUL31_lo() macro returns only the low 31 bits of the product.
*/
#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y))
#define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF)
#endif
/*
* Multiply two words together; the sum of the lengths of the two
* operands must not exceed 31 (for instance, one operand may use 16
* bits if the other fits on 15). If BR_CT_MUL15 is non-zero, then the
* macro will contain some extra operations that help in making the
* operation constant-time on some platforms, where the basic 32-bit
* multiplication is not constant-time.
*/
#if BR_CT_MUL15
#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \
* ((uint32_t)(y) | (uint32_t)0x80000000) \
& (uint32_t)0x7FFFFFFF)
#else
#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y))
#endif
/*
* Arithmetic right shift (sign bit is copied). What happens when
* right-shifting a negative value is _implementation-defined_, so it
* does not trigger undefined behaviour, but it is still up to each
* compiler to define (and document) what it does. Most/all compilers
* will do an arithmetic shift, the sign bit being used to fill the
* holes; this is a native operation on the underlying CPU, and it would
* make little sense for the compiler to do otherwise. GCC explicitly
* documents that it follows that convention.
*
* Still, if BR_NO_ARITH_SHIFT is defined (and non-zero), then an
* alternate version will be used, that does not rely on such
* implementation-defined behaviour. Unfortunately, it is also slower
* and yields bigger code, which is why it is deactivated by default.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#endif
/*
* Constant-time division. The dividend hi:lo is divided by the
* divisor d; the quotient is returned and the remainder is written
* in *r. If hi == d, then the quotient does not fit on 32 bits;
* returned value is thus truncated. If hi > d, returned values are
* indeterminate.
*/
uint32_t br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r);
/*
* Wrapper for br_divrem(); the remainder is returned, and the quotient
* is discarded.
*/
static inline uint32_t
br_rem(uint32_t hi, uint32_t lo, uint32_t d)
{
uint32_t r;
br_divrem(hi, lo, d, &r);
return r;
}
/*
* Wrapper for br_divrem(); the quotient is returned, and the remainder
* is discarded.
*/
static inline uint32_t
br_div(uint32_t hi, uint32_t lo, uint32_t d)
{
uint32_t r;
return br_divrem(hi, lo, d, &r);
}
/* ==================================================================== */
/*
* Integers 'i32'
* --------------
*
* The 'i32' functions implement computations on big integers using
* an internal representation as an array of 32-bit integers. For
* an array x[]:
* -- x[0] contains the "announced bit length" of the integer
* -- x[1], x[2]... contain the value in little-endian order (x[1]
* contains the least significant 32 bits)
*
* Multiplications rely on the elementary 32x32->64 multiplication.
*
* The announced bit length specifies the number of bits that are
* significant in the subsequent 32-bit words. Unused bits in the
* last (most significant) word are set to 0; subsequent words are
* uninitialized and need not exist at all.
*
* The execution time and memory access patterns of all computations
* depend on the announced bit length, but not on the actual word
* values. For modular integers, the announced bit length of any integer
* modulo n is equal to the actual bit length of n; thus, computations
* on modular integers are "constant-time" (only the modulus length may
* leak).
*/
/*
* Compute the actual bit length of an integer. The argument x should
* point to the first (least significant) value word of the integer.
* The len 'xlen' contains the number of 32-bit words to access.
*
* CT: value or length of x does not leak.
*/
uint32_t br_i32_bit_length(uint32_t *x, size_t xlen);
/*
* Decode an integer from its big-endian unsigned representation. The
* "true" bit length of the integer is computed, but all words of x[]
* corresponding to the full 'len' bytes of the source are set.
*
* CT: value or length of x does not leak.
*/
void br_i32_decode(uint32_t *x, const void *src, size_t len);
/*
* Decode an integer from its big-endian unsigned representation. The
* integer MUST be lower than m[]; the announced bit length written in
* x[] will be equal to that of m[]. All 'len' bytes from the source are
* read.
*
* Returned value is 1 if the decode value fits within the modulus, 0
* otherwise. In the latter case, the x[] buffer will be set to 0 (but
* still with the announced bit length of m[]).
*
* CT: value or length of x does not leak. Memory access pattern depends
* only of 'len' and the announced bit length of m. Whether x fits or
* not does not leak either.
*/
uint32_t br_i32_decode_mod(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Reduce an integer (a[]) modulo another (m[]). The result is written
* in x[] and its announced bit length is set to be equal to that of m[].
*
* x[] MUST be distinct from a[] and m[].
*
* CT: only announced bit lengths leak, not values of x, a or m.
*/
void br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m);
/*
* Decode an integer from its big-endian unsigned representation, and
* reduce it modulo the provided modulus m[]. The announced bit length
* of the result is set to be equal to that of the modulus.
*
* x[] MUST be distinct from m[].
*/
void br_i32_decode_reduce(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Encode an integer into its big-endian unsigned representation. The
* output length in bytes is provided (parameter 'len'); if the length
* is too short then the integer is appropriately truncated; if it is
* too long then the extra bytes are set to 0.
*/
void br_i32_encode(void *dst, size_t len, const uint32_t *x);
/*
* Multiply x[] by 2^32 and then add integer z, modulo m[]. This
* function assumes that x[] and m[] have the same announced bit
* length, and the announced bit length of m[] matches its true
* bit length.
*
* x[] and m[] MUST be distinct arrays.
*
* CT: only the common announced bit length of x and m leaks, not
* the values of x, z or m.
*/
void br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
/*
* Extract one word from an integer. The offset is counted in bits.
* The word MUST entirely fit within the word elements corresponding
* to the announced bit length of a[].
*/
static inline uint32_t
br_i32_word(const uint32_t *a, uint32_t off)
{
size_t u;
unsigned j;
u = (size_t)(off >> 5) + 1;
j = (unsigned)off & 31;
if (j == 0) {
return a[u];
} else {
return (a[u] >> j) | (a[u + 1] << (32 - j));
}
}
/*
* Test whether an integer is zero.
*/
uint32_t br_i32_iszero(const uint32_t *x);
/*
* Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
* is unmodified, but the carry is still computed and returned. The
* arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
* then a[] is unmodified, but the carry is still computed and returned.
* The arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Compute d+a*b, result in d. The initial announced bit length of d[]
* MUST match that of a[]. The d[] array MUST be large enough to
* accommodate the full result, plus (possibly) an extra word. The
* resulting announced bit length of d[] will be the sum of the announced
* bit lengths of a[] and b[] (therefore, it may be larger than the actual
* bit length of the numerical result).
*
* a[] and b[] may be the same array. d[] must be disjoint from both a[]
* and b[].
*/
void br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
/*
* Zeroize an integer. The announced bit length is set to the provided
* value, and the corresponding words are set to 0.
*/
static inline void
br_i32_zero(uint32_t *x, uint32_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
}
/*
* Compute -(1/x) mod 2^32. If x is even, then this function returns 0.
*/
uint32_t br_i32_ninv32(uint32_t x);
/*
* Convert a modular integer to Montgomery representation. The integer x[]
* MUST be lower than m[], but with the same announced bit length.
*/
void br_i32_to_monty(uint32_t *x, const uint32_t *m);
/*
* Convert a modular integer back from Montgomery representation. The
* integer x[] MUST be lower than m[], but with the same announced bit
* length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is
* the least significant value word of m[] (this works only if m[] is
* an odd integer).
*/
void br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
/*
* Compute a modular Montgomery multiplication. d[] is filled with the
* value of x*y/R modulo m[] (where R is the Montgomery factor). The
* array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be
* numerically lower than m[]. x[] and y[] MAY be the same array. The
* "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer).
*/
void br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
const uint32_t *m, uint32_t m0i);
/*
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
* (same announced bit length, lower value). m[] MUST be odd. The
* exponent is in big-endian unsigned notation, over 'elen' bytes. The
* "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer). The t1[] and t2[] parameters must be temporary arrays,
* each large enough to accommodate an integer with the same size as m[].
*/
void br_i32_modpow(uint32_t *x, const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
/* ==================================================================== */
/*
* Integers 'i31'
* --------------
*
* The 'i31' functions implement computations on big integers using
* an internal representation as an array of 32-bit integers. For
* an array x[]:
* -- x[0] encodes the array length and the "announced bit length"
* of the integer: namely, if the announced bit length is k,
* then x[0] = ((k / 31) << 5) + (k % 31).
* -- x[1], x[2]... contain the value in little-endian order, 31
* bits per word (x[1] contains the least significant 31 bits).
* The upper bit of each word is 0.
*
* Multiplications rely on the elementary 32x32->64 multiplication.
*
* The announced bit length specifies the number of bits that are
* significant in the subsequent 32-bit words. Unused bits in the
* last (most significant) word are set to 0; subsequent words are
* uninitialized and need not exist at all.
*
* The execution time and memory access patterns of all computations
* depend on the announced bit length, but not on the actual word
* values. For modular integers, the announced bit length of any integer
* modulo n is equal to the actual bit length of n; thus, computations
* on modular integers are "constant-time" (only the modulus length may
* leak).
*/
/*
* Test whether an integer is zero.
*/
uint32_t br_i31_iszero(const uint32_t *x);
/*
* Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
* is unmodified, but the carry is still computed and returned. The
* arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
* then a[] is unmodified, but the carry is still computed and returned.
* The arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Compute the ENCODED actual bit length of an integer. The argument x
* should point to the first (least significant) value word of the
* integer. The len 'xlen' contains the number of 32-bit words to
* access. The upper bit of each value word MUST be 0.
* Returned value is ((k / 31) << 5) + (k % 31) if the bit length is k.
*
* CT: value or length of x does not leak.
*/
uint32_t br_i31_bit_length(uint32_t *x, size_t xlen);
/*
* Decode an integer from its big-endian unsigned representation. The
* "true" bit length of the integer is computed and set in the encoded
* announced bit length (x[0]), but all words of x[] corresponding to
* the full 'len' bytes of the source are set.
*
* CT: value or length of x does not leak.
*/
void br_i31_decode(uint32_t *x, const void *src, size_t len);
/*
* Decode an integer from its big-endian unsigned representation. The
* integer MUST be lower than m[]; the (encoded) announced bit length
* written in x[] will be equal to that of m[]. All 'len' bytes from the
* source are read.
*
* Returned value is 1 if the decode value fits within the modulus, 0
* otherwise. In the latter case, the x[] buffer will be set to 0 (but
* still with the announced bit length of m[]).
*
* CT: value or length of x does not leak. Memory access pattern depends
* only of 'len' and the announced bit length of m. Whether x fits or
* not does not leak either.
*/
uint32_t br_i31_decode_mod(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Zeroize an integer. The announced bit length is set to the provided
* value, and the corresponding words are set to 0. The ENCODED bit length
* is expected here.
*/
static inline void
br_i31_zero(uint32_t *x, uint32_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
}
/*
* Right-shift an integer. The shift amount must be lower than 31
* bits.
*/
void br_i31_rshift(uint32_t *x, int count);
/*
* Reduce an integer (a[]) modulo another (m[]). The result is written
* in x[] and its announced bit length is set to be equal to that of m[].
*
* x[] MUST be distinct from a[] and m[].
*
* CT: only announced bit lengths leak, not values of x, a or m.
*/
void br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m);
/*
* Decode an integer from its big-endian unsigned representation, and
* reduce it modulo the provided modulus m[]. The announced bit length
* of the result is set to be equal to that of the modulus.
*
* x[] MUST be distinct from m[].
*/
void br_i31_decode_reduce(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Multiply x[] by 2^31 and then add integer z, modulo m[]. This
* function assumes that x[] and m[] have the same announced bit
* length, the announced bit length of m[] matches its true
* bit length.
*
* x[] and m[] MUST be distinct arrays. z MUST fit in 31 bits (upper
* bit set to 0).
*
* CT: only the common announced bit length of x and m leaks, not
* the values of x, z or m.
*/
void br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
/*
* Encode an integer into its big-endian unsigned representation. The
* output length in bytes is provided (parameter 'len'); if the length
* is too short then the integer is appropriately truncated; if it is
* too long then the extra bytes are set to 0.
*/
void br_i31_encode(void *dst, size_t len, const uint32_t *x);
/*
* Compute -(1/x) mod 2^31. If x is even, then this function returns 0.
*/
uint32_t br_i31_ninv31(uint32_t x);
/*
* Compute a modular Montgomery multiplication. d[] is filled with the
* value of x*y/R modulo m[] (where R is the Montgomery factor). The
* array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be
* numerically lower than m[]. x[] and y[] MAY be the same array. The
* "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer).
*/
void br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
const uint32_t *m, uint32_t m0i);
/*
* Convert a modular integer to Montgomery representation. The integer x[]
* MUST be lower than m[], but with the same announced bit length.
*/
void br_i31_to_monty(uint32_t *x, const uint32_t *m);
/*
* Convert a modular integer back from Montgomery representation. The
* integer x[] MUST be lower than m[], but with the same announced bit
* length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is
* the least significant value word of m[] (this works only if m[] is
* an odd integer).
*/
void br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
/*
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
* (same announced bit length, lower value). m[] MUST be odd. The
* exponent is in big-endian unsigned notation, over 'elen' bytes. The
* "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer). The t1[] and t2[] parameters must be temporary arrays,
* each large enough to accommodate an integer with the same size as m[].
*/
void br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
/*
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
* (same announced bit length, lower value). m[] MUST be odd. The
* exponent is in big-endian unsigned notation, over 'elen' bytes. The
* "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer). The tmp[] array is used for temporaries, and has size
* 'twlen' words; it must be large enough to accommodate at least two
* temporary values with the same size as m[] (including the leading
* "bit length" word). If there is room for more temporaries, then this
* function may use the extra room for window-based optimisation,
* resulting in faster computations.
*
* Returned value is 1 on success, 0 on error. An error is reported if
* the provided tmp[] array is too short.
*/
uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
/*
* Compute d+a*b, result in d. The initial announced bit length of d[]
* MUST match that of a[]. The d[] array MUST be large enough to
* accommodate the full result, plus (possibly) an extra word. The
* resulting announced bit length of d[] will be the sum of the announced
* bit lengths of a[] and b[] (therefore, it may be larger than the actual
* bit length of the numerical result).
*
* a[] and b[] may be the same array. d[] must be disjoint from both a[]
* and b[].
*/
void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
/*
* Compute x/y mod m, result in x. Values x and y must be between 0 and
* m-1, and have the same announced bit length as m. Modulus m must be
* odd. The "m0i" parameter is equal to -1/m mod 2^31. The array 't'
* must point to a temporary area that can hold at least three integers
* of the size of m.
*
* m may not overlap x and y. x and y may overlap each other (this can
* be useful to test whether a value is invertible modulo m). t must be
* disjoint from all other arrays.
*
* Returned value is 1 on success, 0 otherwise. Success is attained if
* y is invertible modulo m.
*/
uint32_t br_i31_moddiv(uint32_t *x, const uint32_t *y,
const uint32_t *m, uint32_t m0i, uint32_t *t);
/* ==================================================================== */
/*
* FIXME: document "i15" functions.
*/
static inline void
br_i15_zero(uint16_t *x, uint16_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x);
}
uint32_t br_i15_iszero(const uint16_t *x);
uint16_t br_i15_ninv15(uint16_t x);
uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl);
uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl);
void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m);
void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
const uint16_t *m, uint16_t m0i);
void br_i15_to_monty(uint16_t *x, const uint16_t *m);
void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen,
const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2);
uint32_t br_i15_modpow_opt(uint16_t *x, const unsigned char *e, size_t elen,
const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen);
void br_i15_encode(void *dst, size_t len, const uint16_t *x);
uint32_t br_i15_decode_mod(uint16_t *x,
const void *src, size_t len, const uint16_t *m);
void br_i15_rshift(uint16_t *x, int count);
uint32_t br_i15_bit_length(uint16_t *x, size_t xlen);
void br_i15_decode(uint16_t *x, const void *src, size_t len);
void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i);
void br_i15_decode_reduce(uint16_t *x,
const void *src, size_t len, const uint16_t *m);
void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m);
void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b);
uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y,
const uint16_t *m, uint16_t m0i, uint16_t *t);
/*
* Variant of br_i31_modpow_opt() that internally uses 64x64->128
* multiplications. It expects the same parameters as br_i31_modpow_opt(),
* except that the temporaries should be 64-bit integers, not 32-bit
* integers.
*/
uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen,
const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen);
/*
* Type for a function with the same API as br_i31_modpow_opt() (some
* implementations of this type may have stricter alignment requirements
* on the temporaries).
*/
typedef uint32_t (*br_i31_modpow_opt_type)(uint32_t *x,
const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
/*
* Wrapper for br_i62_modpow_opt() that uses the same type as
* br_i31_modpow_opt(); however, it requires its 'tmp' argument to the
* 64-bit aligned.
*/
uint32_t br_i62_modpow_opt_as_i31(uint32_t *x,
const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
/* ==================================================================== */
static inline size_t
br_digest_size(const br_hash_class *digest_class)
{
return (size_t)(digest_class->desc >> BR_HASHDESC_OUT_OFF)
& BR_HASHDESC_OUT_MASK;
}
/*
* Get the output size (in bytes) of a hash function.
*/
size_t br_digest_size_by_ID(int digest_id);
/*
* Get the OID (encoded OBJECT IDENTIFIER value, without tag and length)
* for a hash function. If digest_id is not a supported digest identifier
* (in particular if it is equal to 0, i.e. br_md5sha1_ID), then NULL is
* returned and *len is set to 0.
*/
const unsigned char *br_digest_OID(int digest_id, size_t *len);
/* ==================================================================== */
/*
* DES support functions.
*/
/*
* Apply DES Initial Permutation.
*/
void br_des_do_IP(uint32_t *xl, uint32_t *xr);
/*
* Apply DES Final Permutation (inverse of IP).
*/
void br_des_do_invIP(uint32_t *xl, uint32_t *xr);
/*
* Key schedule unit: for a DES key (8 bytes), compute 16 subkeys. Each
* subkey is two 28-bit words represented as two 32-bit words; the PC-2
* bit extration is NOT applied.
*/
void br_des_keysched_unit(uint32_t *skey, const void *key);
/*
* Reversal of 16 DES sub-keys (for decryption).
*/
void br_des_rev_skey(uint32_t *skey);
/*
* DES/3DES key schedule for 'des_tab' (encryption direction). Returned
* value is the number of rounds.
*/
unsigned br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len);
/*
* DES/3DES key schedule for 'des_ct' (encryption direction). Returned
* value is the number of rounds.
*/
unsigned br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len);
/*
* DES/3DES subkey decompression (from the compressed bitsliced subkeys).
*/
void br_des_ct_skey_expand(uint32_t *sk_exp,
unsigned num_rounds, const uint32_t *skey);
/*
* DES/3DES block encryption/decryption ('des_tab').
*/
void br_des_tab_process_block(unsigned num_rounds,
const uint32_t *skey, void *block);
/*
* DES/3DES block encryption/decryption ('des_ct').
*/
void br_des_ct_process_block(unsigned num_rounds,
const uint32_t *skey, void *block);
/* ==================================================================== */
/*
* AES support functions.
*/
/*
* The AES S-box (256-byte table).
*/
extern const unsigned char br_aes_S[];
/*
* AES key schedule. skey[] is filled with n+1 128-bit subkeys, where n
* is the number of rounds (10 to 14, depending on key size). The number
* of rounds is returned. If the key size is invalid (not 16, 24 or 32),
* then 0 is returned.
*
* This implementation uses a 256-byte table and is NOT constant-time.
*/
unsigned br_aes_keysched(uint32_t *skey, const void *key, size_t key_len);
/*
* AES key schedule for decryption ('aes_big' implementation).
*/
unsigned br_aes_big_keysched_inv(uint32_t *skey,
const void *key, size_t key_len);
/*
* AES block encryption with the 'aes_big' implementation (fast, but
* not constant-time). This function encrypts a single block "in place".
*/
void br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data);
/*
* AES block decryption with the 'aes_big' implementation (fast, but
* not constant-time). This function decrypts a single block "in place".
*/
void br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data);
/*
* AES block encryption with the 'aes_small' implementation (small, but
* slow and not constant-time). This function encrypts a single block
* "in place".
*/
void br_aes_small_encrypt(unsigned num_rounds,
const uint32_t *skey, void *data);
/*
* AES block decryption with the 'aes_small' implementation (small, but
* slow and not constant-time). This function decrypts a single block
* "in place".
*/
void br_aes_small_decrypt(unsigned num_rounds,
const uint32_t *skey, void *data);
/*
* The constant-time implementation is "bitsliced": the 128-bit state is
* split over eight 32-bit words q* in the following way:
*
* -- Input block consists in 16 bytes:
* a00 a10 a20 a30 a01 a11 a21 a31 a02 a12 a22 a32 a03 a13 a23 a33
* In the terminology of FIPS 197, this is a 4x4 matrix which is read
* column by column.
*
* -- Each byte is split into eight bits which are distributed over the
* eight words, at the same rank. Thus, for a byte x at rank k, bit 0
* (least significant) of x will be at rank k in q0 (if that bit is b,
* then it contributes "b << k" to the value of q0), bit 1 of x will be
* at rank k in q1, and so on.
*
* -- Ranks given to bits are in "row order" and are either all even, or
* all odd. Two independent AES states are thus interleaved, one using
* the even ranks, the other the odd ranks. Row order means:
* a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 a30 a31 a32 a33
*
* Converting input bytes from two AES blocks to bitslice representation
* is done in the following way:
* -- Decode first block into the four words q0 q2 q4 q6, in that order,
* using little-endian convention.
* -- Decode second block into the four words q1 q3 q5 q7, in that order,
* using little-endian convention.
* -- Call br_aes_ct_ortho().
*
* Converting back to bytes is done by using the reverse operations. Note
* that br_aes_ct_ortho() is its own inverse.
*/
/*
* Perform bytewise orthogonalization of eight 32-bit words. Bytes
* of q0..q7 are spread over all words: for a byte x that occurs
* at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit
* of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.
*
* This operation is an involution.
*/
void br_aes_ct_ortho(uint32_t *q);
/*
* The AES S-box, as a bitsliced constant-time version. The input array
* consists in eight 32-bit words; 32 S-box instances are computed in
* parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)
* are spread over the words 0 to 7, at the same rank.
*/
void br_aes_ct_bitslice_Sbox(uint32_t *q);
/*
* Like br_aes_bitslice_Sbox(), but for the inverse S-box.
*/
void br_aes_ct_bitslice_invSbox(uint32_t *q);
/*
* Compute AES encryption on bitsliced data. Since input is stored on
* eight 32-bit words, two block encryptions are actually performed
* in parallel.
*/
void br_aes_ct_bitslice_encrypt(unsigned num_rounds,
const uint32_t *skey, uint32_t *q);
/*
* Compute AES decryption on bitsliced data. Since input is stored on
* eight 32-bit words, two block decryptions are actually performed
* in parallel.
*/
void br_aes_ct_bitslice_decrypt(unsigned num_rounds,
const uint32_t *skey, uint32_t *q);
/*
* AES key schedule, constant-time version. skey[] is filled with n+1
* 128-bit subkeys, where n is the number of rounds (10 to 14, depending
* on key size). The number of rounds is returned. If the key size is
* invalid (not 16, 24 or 32), then 0 is returned.
*/
unsigned br_aes_ct_keysched(uint32_t *comp_skey,
const void *key, size_t key_len);
/*
* Expand AES subkeys as produced by br_aes_ct_keysched(), into
* a larger array suitable for br_aes_ct_bitslice_encrypt() and
* br_aes_ct_bitslice_decrypt().
*/
void br_aes_ct_skey_expand(uint32_t *skey,
unsigned num_rounds, const uint32_t *comp_skey);
/*
* For the ct64 implementation, the same bitslicing technique is used,
* but four instances are interleaved. First instance uses bits 0, 4,
* 8, 12,... of each word; second instance uses bits 1, 5, 9, 13,...
* and so on.
*/
/*
* Perform bytewise orthogonalization of eight 64-bit words. Bytes
* of q0..q7 are spread over all words: for a byte x that occurs
* at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit
* of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.
*
* This operation is an involution.
*/
void br_aes_ct64_ortho(uint64_t *q);
/*
* Interleave bytes for an AES input block. If input bytes are
* denoted 0123456789ABCDEF, and have been decoded with little-endian
* convention (w[0] contains 0123, with '3' being most significant;
* w[1] contains 4567, and so on), then output word q0 will be
* set to 08192A3B (again little-endian convention) and q1 will
* be set to 4C5D6E7F.
*/
void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w);
/*
* Perform the opposite of br_aes_ct64_interleave_in().
*/
void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1);
/*
* The AES S-box, as a bitsliced constant-time version. The input array
* consists in eight 64-bit words; 64 S-box instances are computed in
* parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)
* are spread over the words 0 to 7, at the same rank.
*/
void br_aes_ct64_bitslice_Sbox(uint64_t *q);
/*
* Like br_aes_bitslice_Sbox(), but for the inverse S-box.
*/
void br_aes_ct64_bitslice_invSbox(uint64_t *q);
/*
* Compute AES encryption on bitsliced data. Since input is stored on
* eight 64-bit words, four block encryptions are actually performed
* in parallel.
*/
void br_aes_ct64_bitslice_encrypt(unsigned num_rounds,
const uint64_t *skey, uint64_t *q);
/*
* Compute AES decryption on bitsliced data. Since input is stored on
* eight 64-bit words, four block decryptions are actually performed
* in parallel.
*/
void br_aes_ct64_bitslice_decrypt(unsigned num_rounds,
const uint64_t *skey, uint64_t *q);
/*
* AES key schedule, constant-time version. skey[] is filled with n+1
* 128-bit subkeys, where n is the number of rounds (10 to 14, depending
* on key size). The number of rounds is returned. If the key size is
* invalid (not 16, 24 or 32), then 0 is returned.
*/
unsigned br_aes_ct64_keysched(uint64_t *comp_skey,
const void *key, size_t key_len);
/*
* Expand AES subkeys as produced by br_aes_ct64_keysched(), into
* a larger array suitable for br_aes_ct64_bitslice_encrypt() and
* br_aes_ct64_bitslice_decrypt().
*/
void br_aes_ct64_skey_expand(uint64_t *skey,
unsigned num_rounds, const uint64_t *comp_skey);
/*
* Test support for AES-NI opcodes.
*/
int br_aes_x86ni_supported(void);
/*
* AES key schedule, using x86 AES-NI instructions. This yields the
* subkeys in the encryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_x86ni_keysched_enc(unsigned char *skni,
const void *key, size_t len);
/*
* AES key schedule, using x86 AES-NI instructions. This yields the
* subkeys in the decryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_x86ni_keysched_dec(unsigned char *skni,
const void *key, size_t len);
/*
* Test support for AES POWER8 opcodes.
*/
int br_aes_pwr8_supported(void);
/*
* AES key schedule, using POWER8 instructions. This yields the
* subkeys in the encryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_pwr8_keysched(unsigned char *skni,
const void *key, size_t len);
/* ==================================================================== */
/*
* RSA.
*/
/*
* Apply proper PKCS#1 v1.5 padding (for signatures). 'hash_oid' is
* the encoded hash function OID, or NULL.
*/
uint32_t br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
uint32_t n_bitlen, unsigned char *x);
/*
* Check PKCS#1 v1.5 padding (for signatures). 'hash_oid' is the encoded
* hash function OID, or NULL. The provided 'sig' value is _after_ the
* modular exponentiation, i.e. it should be the padded hash. On
* success, the hashed message is extracted.
*/
uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len,
const unsigned char *hash_oid, size_t hash_len,
unsigned char *hash_out);
/*
* Apply proper PSS padding. The 'x' buffer is output only: it
* receives the value that is to be exponentiated.
*/
uint32_t br_rsa_pss_sig_pad(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash, size_t salt_len,
uint32_t n_bitlen, unsigned char *x);
/*
* Check PSS padding. The provided value is the one _after_
* the modular exponentiation; it is modified by this function.
* This function infers the signature length from the public key
* size, i.e. it assumes that this has already been verified (as
* part of the exponentiation).
*/
uint32_t br_rsa_pss_sig_unpad(
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash, size_t salt_len,
const br_rsa_public_key *pk, unsigned char *x);
/*
* Apply OAEP padding. Returned value is the actual padded string length,
* or zero on error.
*/
size_t br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len, const br_rsa_public_key *pk,
void *dst, size_t dst_nax_len, const void *src, size_t src_len);
/*
* Unravel and check OAEP padding. If the padding is correct, then 1 is
* returned, '*len' is adjusted to the length of the message, and the
* data is moved to the start of the 'data' buffer. If the padding is
* incorrect, then 0 is returned and '*len' is untouched. Either way,
* the complete buffer contents are altered.
*/
uint32_t br_rsa_oaep_unpad(const br_hash_class *dig,
const void *label, size_t label_len, void *data, size_t *len);
/*
* Compute MGF1 for a given seed, and XOR the output into the provided
* buffer.
*/
void br_mgf1_xor(void *data, size_t len,
const br_hash_class *dig, const void *seed, size_t seed_len);
/*
* Inner function for RSA key generation; used by the "i31" and "i62"
* implementations.
*/
uint32_t br_rsa_i31_keygen_inner(const br_prng_class **rng,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31);
/* ==================================================================== */
/*
* Elliptic curves.
*/
/*
* Type for generic EC parameters: curve order (unsigned big-endian
* encoding) and encoded conventional generator.
*/
typedef struct {
int curve;
const unsigned char *order;
size_t order_len;
const unsigned char *generator;
size_t generator_len;
} br_ec_curve_def;
extern const br_ec_curve_def br_secp256r1;
extern const br_ec_curve_def br_secp384r1;
extern const br_ec_curve_def br_secp521r1;
/*
* For Curve25519, the advertised "order" really is 2^255-1, since the
* point multipliction function really works over arbitrary 255-bit
* scalars. This value is only meant as a hint for ECDH key generation;
* only ECDSA uses the exact curve order, and ECDSA is not used with
* that specific curve.
*/
extern const br_ec_curve_def br_curve25519;
/*
* Decode some bytes as an i31 integer, with truncation (corresponding
* to the 'bits2int' operation in RFC 6979). The target ENCODED bit
* length is provided as last parameter. The resulting value will have
* this declared bit length, and consists the big-endian unsigned decoding
* of exactly that many bits in the source (capped at the source length).
*/
void br_ecdsa_i31_bits2int(uint32_t *x,
const void *src, size_t len, uint32_t ebitlen);
/*
* Decode some bytes as an i15 integer, with truncation (corresponding
* to the 'bits2int' operation in RFC 6979). The target ENCODED bit
* length is provided as last parameter. The resulting value will have
* this declared bit length, and consists the big-endian unsigned decoding
* of exactly that many bits in the source (capped at the source length).
*/
void br_ecdsa_i15_bits2int(uint16_t *x,
const void *src, size_t len, uint32_t ebitlen);
/* ==================================================================== */
/*
* ASN.1 support functions.
*/
/*
* A br_asn1_uint structure contains encoding information about an
* INTEGER nonnegative value: pointer to the integer contents (unsigned
* big-endian representation), length of the integer contents,
* and length of the encoded value. The data shall have minimal length:
* - If the integer value is zero, then 'len' must be zero.
* - If the integer value is not zero, then data[0] must be non-zero.
*
* Under these conditions, 'asn1len' is necessarily equal to either len
* or len+1.
*/
typedef struct {
const unsigned char *data;
size_t len;
size_t asn1len;
} br_asn1_uint;
/*
* Given an encoded integer (unsigned big-endian, with possible leading
* bytes of value 0), returned the "prepared INTEGER" structure.
*/
br_asn1_uint br_asn1_uint_prepare(const void *xdata, size_t xlen);
/*
* Encode an ASN.1 length. The length of the encoded length is returned.
* If 'dest' is NULL, then no encoding is performed, but the length of
* the encoded length is still computed and returned.
*/
size_t br_asn1_encode_length(void *dest, size_t len);
/*
* Convenient macro for computing lengths of lengths.
*/
#define len_of_len(len) br_asn1_encode_length(NULL, len)
/*
* Encode a (prepared) ASN.1 INTEGER. The encoded length is returned.
* If 'dest' is NULL, then no encoding is performed, but the length of
* the encoded integer is still computed and returned.
*/
size_t br_asn1_encode_uint(void *dest, br_asn1_uint pp);
/*
* Get the OID that identifies an elliptic curve. Returned value is
* the DER-encoded OID, with the length (always one byte) but without
* the tag. Thus, the first byte of the returned buffer contains the
* number of subsequent bytes in the value. If the curve is not
* recognised, NULL is returned.
*/
const unsigned char *br_get_curve_OID(int curve);
/*
* Inner function for EC private key encoding. This is equivalent to
* the API function br_encode_ec_raw_der(), except for an extra
* parameter: if 'include_curve_oid' is zero, then the curve OID is
* _not_ included in the output blob (this is for PKCS#8 support).
*/
size_t br_encode_ec_raw_der_inner(void *dest,
const br_ec_private_key *sk, const br_ec_public_key *pk,
int include_curve_oid);
/* ==================================================================== */
/*
* SSL/TLS support functions.
*/
/*
* Record types.
*/
#define BR_SSL_CHANGE_CIPHER_SPEC 20
#define BR_SSL_ALERT 21
#define BR_SSL_HANDSHAKE 22
#define BR_SSL_APPLICATION_DATA 23
/*
* Handshake message types.
*/
#define BR_SSL_HELLO_REQUEST 0
#define BR_SSL_CLIENT_HELLO 1
#define BR_SSL_SERVER_HELLO 2
#define BR_SSL_CERTIFICATE 11
#define BR_SSL_SERVER_KEY_EXCHANGE 12
#define BR_SSL_CERTIFICATE_REQUEST 13
#define BR_SSL_SERVER_HELLO_DONE 14
#define BR_SSL_CERTIFICATE_VERIFY 15
#define BR_SSL_CLIENT_KEY_EXCHANGE 16
#define BR_SSL_FINISHED 20
/*
* Alert levels.
*/
#define BR_LEVEL_WARNING 1
#define BR_LEVEL_FATAL 2
/*
* Low-level I/O state.
*/
#define BR_IO_FAILED 0
#define BR_IO_IN 1
#define BR_IO_OUT 2
#define BR_IO_INOUT 3
/*
* Mark a SSL engine as failed. The provided error code is recorded if
* the engine was not already marked as failed. If 'err' is 0, then the
* engine is marked as closed (without error).
*/
void br_ssl_engine_fail(br_ssl_engine_context *cc, int err);
/*
* Test whether the engine is closed (normally or as a failure).
*/
static inline int
br_ssl_engine_closed(const br_ssl_engine_context *cc)
{
return cc->iomode == BR_IO_FAILED;
}
/*
* Configure a new maximum fragment length. If possible, the maximum
* length for outgoing records is immediately adjusted (if there are
* not already too many buffered bytes for that).
*/
void br_ssl_engine_new_max_frag_len(
br_ssl_engine_context *rc, unsigned max_frag_len);
/*
* Test whether the current incoming record has been fully received
* or not. This functions returns 0 only if a complete record header
* has been received, but some of the (possibly encrypted) payload
* has not yet been obtained.
*/
int br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc);
/*
* Flush the current record (if not empty). This is meant to be called
* from the handshake processor only.
*/
void br_ssl_engine_flush_record(br_ssl_engine_context *cc);
/*
* Test whether there is some accumulated payload to send.
*/
static inline int
br_ssl_engine_has_pld_to_send(const br_ssl_engine_context *rc)
{
return rc->oxa != rc->oxb && rc->oxa != rc->oxc;
}
/*
* Initialize RNG in engine. Returned value is 1 on success, 0 on error.
* This function will try to use the OS-provided RNG, if available. If
* there is no OS-provided RNG, or if it failed, and no entropy was
* injected by the caller, then a failure will be reported. On error,
* the context error code is set.
*/
int br_ssl_engine_init_rand(br_ssl_engine_context *cc);
/*
* Reset the handshake-related parts of the engine.
*/
void br_ssl_engine_hs_reset(br_ssl_engine_context *cc,
void (*hsinit)(void *), void (*hsrun)(void *));
/*
* Get the PRF to use for this context, for the provided PRF hash
* function ID.
*/
br_tls_prf_impl br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id);
/*
* Consume the provided pre-master secret and compute the corresponding
* master secret. The 'prf_id' is the ID of the hash function to use
* with the TLS 1.2 PRF (ignored if the version is TLS 1.0 or 1.1).
*/
void br_ssl_engine_compute_master(br_ssl_engine_context *cc,
int prf_id, const void *pms, size_t len);
/*
* Switch to CBC decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF (ignored if not TLS 1.2+)
* mac_id id of hash function for HMAC
* bc_impl block cipher implementation (CBC decryption)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc,
int is_client, int prf_id, int mac_id,
const br_block_cbcdec_class *bc_impl, size_t cipher_key_len);
/*
* Switch to CBC encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF (ignored if not TLS 1.2+)
* mac_id id of hash function for HMAC
* bc_impl block cipher implementation (CBC encryption)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc,
int is_client, int prf_id, int mac_id,
const br_block_cbcenc_class *bc_impl, size_t cipher_key_len);
/*
* Switch to GCM decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctr_class *bc_impl, size_t cipher_key_len);
/*
* Switch to GCM encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctr_class *bc_impl, size_t cipher_key_len);
/*
* Switch to ChaCha20+Poly1305 decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
*/
void br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
int is_client, int prf_id);
/*
* Switch to ChaCha20+Poly1305 encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
*/
void br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
int is_client, int prf_id);
/*
* Switch to CCM decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR+CBC)
* cipher_key_len block cipher key length (in bytes)
* tag_len tag length (in bytes)
*/
void br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctrcbc_class *bc_impl,
size_t cipher_key_len, size_t tag_len);
/*
* Switch to GCM encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR+CBC)
* cipher_key_len block cipher key length (in bytes)
* tag_len tag length (in bytes)
*/
void br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctrcbc_class *bc_impl,
size_t cipher_key_len, size_t tag_len);
/*
* Calls to T0-generated code.
*/
void br_ssl_hs_client_init_main(void *ctx);
void br_ssl_hs_client_run(void *ctx);
void br_ssl_hs_server_init_main(void *ctx);
void br_ssl_hs_server_run(void *ctx);
/*
* Get the hash function to use for signatures, given a bit mask of
* supported hash functions. This implements a strict choice order
* (namely SHA-256, SHA-384, SHA-512, SHA-224, SHA-1). If the mask
* does not document support of any of these hash functions, then this
* functions returns 0.
*/
int br_ssl_choose_hash(unsigned bf);
/* ==================================================================== */
/*
* PowerPC / POWER assembly stuff. The special BR_POWER_ASM_MACROS macro
* must be defined before including this file; this is done by source
* files that use some inline assembly for PowerPC / POWER machines.
*/
#if BR_POWER_ASM_MACROS
#define lxvw4x(xt, ra, rb) lxvw4x_(xt, ra, rb)
#define stxvw4x(xt, ra, rb) stxvw4x_(xt, ra, rb)
#define bdnz(foo) bdnz_(foo)
#define bdz(foo) bdz_(foo)
#define beq(foo) beq_(foo)
#define li(rx, value) li_(rx, value)
#define addi(rx, ra, imm) addi_(rx, ra, imm)
#define cmpldi(rx, imm) cmpldi_(rx, imm)
#define mtctr(rx) mtctr_(rx)
#define vspltb(vrt, vrb, uim) vspltb_(vrt, vrb, uim)
#define vspltw(vrt, vrb, uim) vspltw_(vrt, vrb, uim)
#define vspltisb(vrt, imm) vspltisb_(vrt, imm)
#define vspltisw(vrt, imm) vspltisw_(vrt, imm)
#define vrlw(vrt, vra, vrb) vrlw_(vrt, vra, vrb)
#define vsbox(vrt, vra) vsbox_(vrt, vra)
#define vxor(vrt, vra, vrb) vxor_(vrt, vra, vrb)
#define vand(vrt, vra, vrb) vand_(vrt, vra, vrb)
#define vsro(vrt, vra, vrb) vsro_(vrt, vra, vrb)
#define vsl(vrt, vra, vrb) vsl_(vrt, vra, vrb)
#define vsldoi(vt, va, vb, sh) vsldoi_(vt, va, vb, sh)
#define vsr(vrt, vra, vrb) vsr_(vrt, vra, vrb)
#define vaddcuw(vrt, vra, vrb) vaddcuw_(vrt, vra, vrb)
#define vadduwm(vrt, vra, vrb) vadduwm_(vrt, vra, vrb)
#define vsububm(vrt, vra, vrb) vsububm_(vrt, vra, vrb)
#define vsubuwm(vrt, vra, vrb) vsubuwm_(vrt, vra, vrb)
#define vsrw(vrt, vra, vrb) vsrw_(vrt, vra, vrb)
#define vcipher(vt, va, vb) vcipher_(vt, va, vb)
#define vcipherlast(vt, va, vb) vcipherlast_(vt, va, vb)
#define vncipher(vt, va, vb) vncipher_(vt, va, vb)
#define vncipherlast(vt, va, vb) vncipherlast_(vt, va, vb)
#define vperm(vt, va, vb, vc) vperm_(vt, va, vb, vc)
#define vpmsumd(vt, va, vb) vpmsumd_(vt, va, vb)
#define xxpermdi(vt, va, vb, d) xxpermdi_(vt, va, vb, d)
#define lxvw4x_(xt, ra, rb) "\tlxvw4x\t" #xt "," #ra "," #rb "\n"
#define stxvw4x_(xt, ra, rb) "\tstxvw4x\t" #xt "," #ra "," #rb "\n"
#define label(foo) #foo "%=:\n"
#define bdnz_(foo) "\tbdnz\t" #foo "%=\n"
#define bdz_(foo) "\tbdz\t" #foo "%=\n"
#define beq_(foo) "\tbeq\t" #foo "%=\n"
#define li_(rx, value) "\tli\t" #rx "," #value "\n"
#define addi_(rx, ra, imm) "\taddi\t" #rx "," #ra "," #imm "\n"
#define cmpldi_(rx, imm) "\tcmpldi\t" #rx "," #imm "\n"
#define mtctr_(rx) "\tmtctr\t" #rx "\n"
#define vspltb_(vrt, vrb, uim) "\tvspltb\t" #vrt "," #vrb "," #uim "\n"
#define vspltw_(vrt, vrb, uim) "\tvspltw\t" #vrt "," #vrb "," #uim "\n"
#define vspltisb_(vrt, imm) "\tvspltisb\t" #vrt "," #imm "\n"
#define vspltisw_(vrt, imm) "\tvspltisw\t" #vrt "," #imm "\n"
#define vrlw_(vrt, vra, vrb) "\tvrlw\t" #vrt "," #vra "," #vrb "\n"
#define vsbox_(vrt, vra) "\tvsbox\t" #vrt "," #vra "\n"
#define vxor_(vrt, vra, vrb) "\tvxor\t" #vrt "," #vra "," #vrb "\n"
#define vand_(vrt, vra, vrb) "\tvand\t" #vrt "," #vra "," #vrb "\n"
#define vsro_(vrt, vra, vrb) "\tvsro\t" #vrt "," #vra "," #vrb "\n"
#define vsl_(vrt, vra, vrb) "\tvsl\t" #vrt "," #vra "," #vrb "\n"
#define vsldoi_(vt, va, vb, sh) "\tvsldoi\t" #vt "," #va "," #vb "," #sh "\n"
#define vsr_(vrt, vra, vrb) "\tvsr\t" #vrt "," #vra "," #vrb "\n"
#define vaddcuw_(vrt, vra, vrb) "\tvaddcuw\t" #vrt "," #vra "," #vrb "\n"
#define vadduwm_(vrt, vra, vrb) "\tvadduwm\t" #vrt "," #vra "," #vrb "\n"
#define vsububm_(vrt, vra, vrb) "\tvsububm\t" #vrt "," #vra "," #vrb "\n"
#define vsubuwm_(vrt, vra, vrb) "\tvsubuwm\t" #vrt "," #vra "," #vrb "\n"
#define vsrw_(vrt, vra, vrb) "\tvsrw\t" #vrt "," #vra "," #vrb "\n"
#define vcipher_(vt, va, vb) "\tvcipher\t" #vt "," #va "," #vb "\n"
#define vcipherlast_(vt, va, vb) "\tvcipherlast\t" #vt "," #va "," #vb "\n"
#define vncipher_(vt, va, vb) "\tvncipher\t" #vt "," #va "," #vb "\n"
#define vncipherlast_(vt, va, vb) "\tvncipherlast\t" #vt "," #va "," #vb "\n"
#define vperm_(vt, va, vb, vc) "\tvperm\t" #vt "," #va "," #vb "," #vc "\n"
#define vpmsumd_(vt, va, vb) "\tvpmsumd\t" #vt "," #va "," #vb "\n"
#define xxpermdi_(vt, va, vb, d) "\txxpermdi\t" #vt "," #va "," #vb "," #d "\n"
#endif
/* ==================================================================== */
/*
* Special "activate intrinsics" code, needed for some compiler versions.
* This is defined at the end of this file, so that it won't impact any
* of the inline functions defined previously; and it is controlled by
* a specific macro defined in the caller code.
*
* Calling code conventions:
*
* - Caller must define BR_ENABLE_INTRINSICS before including "inner.h".
* - Functions that use intrinsics must be enclosed in an "enabled"
* region (between BR_TARGETS_X86_UP and BR_TARGETS_X86_DOWN).
* - Functions that use intrinsics must be tagged with the appropriate
* BR_TARGET().
*/
#if BR_ENABLE_INTRINSICS && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005)
/*
* x86 intrinsics (both 32-bit and 64-bit).
*/
#if BR_i386 || BR_amd64
/*
* On GCC before version 5.0, we need to use the pragma to enable the
* target options globally, because the 'target' function attribute
* appears to be unreliable. Before 4.6 we must also avoid the
* push_options / pop_options mechanism, because it tends to trigger
* some internal compiler errors.
*/
#if BR_GCC && !BR_GCC_5_0
#if BR_GCC_4_6
#define BR_TARGETS_X86_UP \
_Pragma("GCC push_options") \
_Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul,rdrnd\")")
#define BR_TARGETS_X86_DOWN \
_Pragma("GCC pop_options")
#else
#define BR_TARGETS_X86_UP \
_Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")")
#define BR_TARGETS_X86_DOWN
#endif
#pragma GCC diagnostic ignored "-Wpsabi"
#endif
#if BR_CLANG && !BR_CLANG_3_8
#undef __SSE2__
#undef __SSE3__
#undef __SSSE3__
#undef __SSE4_1__
#undef __AES__
#undef __PCLMUL__
#undef __RDRND__
#define __SSE2__ 1
#define __SSE3__ 1
#define __SSSE3__ 1
#define __SSE4_1__ 1
#define __AES__ 1
#define __PCLMUL__ 1
#define __RDRND__ 1
#endif
#ifndef BR_TARGETS_X86_UP
#define BR_TARGETS_X86_UP
#endif
#ifndef BR_TARGETS_X86_DOWN
#define BR_TARGETS_X86_DOWN
#endif
#if BR_GCC || BR_CLANG
BR_TARGETS_X86_UP
#include
#include
#define br_bswap32 __builtin_bswap32
BR_TARGETS_X86_DOWN
#endif
#if BR_MSC
#include
#include
#include
#define br_bswap32 __src_inner_hbyteswap_ulong
#endif
static inline int
br_cpuid(uint32_t mask_eax, uint32_t mask_ebx,
uint32_t mask_ecx, uint32_t mask_edx)
{
#if BR_GCC || BR_CLANG
unsigned eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
if ((eax & mask_eax) == mask_eax
&& (ebx & mask_ebx) == mask_ebx
&& (ecx & mask_ecx) == mask_ecx
&& (edx & mask_edx) == mask_edx)
{
return 1;
}
}
#elif BR_MSC
int info[4];
__cpuid(info, 1);
if (((uint32_t)info[0] & mask_eax) == mask_eax
&& ((uint32_t)info[1] & mask_ebx) == mask_ebx
&& ((uint32_t)info[2] & mask_ecx) == mask_ecx
&& ((uint32_t)info[3] & mask_edx) == mask_edx)
{
return 1;
}
#endif
return 0;
}
#endif
#endif
/* ==================================================================== */
#endif
#define BEARSSL_HTTPS_BEARSSL_DECLARATED
#endif
#if !defined(cJSON__h) && !defined(BEARSSL_HTTPS_MOCK_CJSON)
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#include
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif
#define BEARSSL_HTTPS_CJSON_DECLARATED
#endif
#endif
#ifndef LuaSilverChain_macros
#define LuaSilverChain_macros
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define PRIVATE_BEARSSL_NO_BODY 0
#define PRIVATE_BEARSSL_BODY_RAW 1
#define PRIVATE_BEARSSL_BODY_FILE 2
#define PRIVATE_BEARSSL_BODY_JSON 3
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define BEARSSL_HTTPS_FAILT_TO_START_UNISOCKET 1
#define BEARSSL_HTTPS_INVALID_URL 2
#define BEARSSL_HTTPS_IMPOSSIBLE_TO_OPEN_FILE 3
#define BEARSSL_HTTPS_MUST_BE_IPV4 4
#define BEARSSL_HTTPS_BODY_ITS_BINARY 5
#define BEARSSL_HTTPS_IMPOSSIBLE_TO_READ_BODY 6
#define BEARSSL_HTTPS_BODY_SIZE_ITS_BIGGER_THAN_LIMIT 7
#define BEARSSL_HTTPS_ALOCATION_FAILED 8
#define BEARSSL_HTTPS_BODY_ITS_NOT_A_VALID_JSON 9
#define BEARSSL_HTTPS_FAILT_TO_CREATE_DNS_REQUEST 10
#define BEARSSL_HTTPS_NO_DNS_PROVIDED 11
#define BEARSSL_HTTPS_FAILT_TO_CREATE_SOCKET 12
#define BEARSSL_HTTPS_INVALID_IPV4 12
#define BEARSSL_HTTPS_FAILT_TO_CONNECT 13
#define BEARSSL_HTTPS_UNKNOW_ERROR 14
#define BEARSSL_HTTPS_INVALID_READ_CODE 15
#define BEARSSL_HTTPS_INVALID_HTTP_RESPONSE 16
#define BEARSSL_HTTPS_IMPOSSIBLE_TO_SEND_DATA 17
#define BEARSSL_HTTPS_ERROR_FLUSHING 18
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define BEARSSL_HTTPS_REFERENCE 0
#define BEARSSL_HTTPS_GET_OWNERSHIP 1
#define BEARSSL_HTTPS_COPY 2
#define BEARSSL_DEFAULT_STRATEGY BEARSSL_HTTPS_COPY
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define BEARSSL_HEADER_CHUNK 200
#define BEARSSL_HEADER_REALLOC_FACTOR 3
#define BEARSSL_MAX_REDIRECTIONS 10
#define BEARSSL_BODY_CHUNK_SIZE 1024
#define BEARSSL_BODY_REALLOC_FACTOR 1.5
#define BEARSSL_DNS_CACHE_HOST_SIZE 1000
#define BEARSSL_DNS_CACHE_IP_SIZE 200
#define BEARSSL_DNS_CACHE_SIZE 100
#endif
#ifndef LuaSilverChain_types
#define LuaSilverChain_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsKeyVal{
char *key;
bool key_owner;
char *value;
bool value_owner;
}private_BearHttpsKeyVal;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct privateBearHttpsDnsCache{
char host[BEARSSL_DNS_CACHE_HOST_SIZE];
char ip[BEARSSL_DNS_CACHE_IP_SIZE];
}privateBearHttpsDnsCache;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsBodyRawRequest{
unsigned char *value;
long size;
bool onwer;
}private_BearHttpsBodyRawRequest;
typedef struct private_BearHttpsBodyRequestFile{
char *path;
char content_type[100];
bool onwer;
}private_BearHttpsBodyRequestFile;
#ifndef BEARSSL_HTTPS_MOCK_CJSON
typedef struct private_BearHttpsBodyJsonRequest{
cJSON *json;
bool onwer;
}private_BearHttpsBodyJsonRequest;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsClientDnsProvider {
const char *hostname;
const char *route;
const char *ip;
int port;
}BearHttpsClientDnsProvider;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsRequisitionProps{
char *hostname;
char *route;
bool is_ipv4;
bool is_ipv6;
bool is_https;
int port;
}private_BearHttpsRequisitionProps ;
#endif
#ifndef LuaSilverChain_typesB
#define LuaSilverChain_typesB
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsHeaders{
int size;
private_BearHttpsKeyVal **keyvals;
}private_BearHttpsHeaders;
#endif
#ifndef LuaSilverChain_typesC
#define LuaSilverChain_typesC
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsRequest{
char *url;
bool route_owner;
int max_redirections;
const char *custom_bear_dns;
const char **known_ips;
int known_ips_size;
BearHttpsClientDnsProvider *dns_providers;
int total_dns_providers;
bool must_be_ipv4;
private_BearHttpsHeaders *headers;
char method[30];
int port;
int header_chunk_read_size;
int header_chunk_reallocator_factor;
int response_max_headers_size;
br_x509_trust_anchor *trust_anchors;
size_t trusted_anchors_size;
short body_type;
union{
private_BearHttpsBodyRawRequest body_raw;
private_BearHttpsBodyRequestFile body_file;
#ifndef BEARSSL_HTTPS_MOCK_CJSON
private_BearHttpsBodyJsonRequest body_json;
#endif
};
}BearHttpsRequest ;
#endif
#ifndef LuaSilverChain_typesD
#define LuaSilverChain_typesD
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsResponse{
int connection_file_descriptor;
bool is_https;
br_sslio_context ssl_io;
br_ssl_client_context ssl_client;
unsigned char bear_buffer[BR_SSL_BUFSIZE_BIDI];
br_x509_minimal_context certification_context;
long max_body_size;
unsigned char *raw_content;
int error_code;
private_BearHttpsHeaders *headers;
long user_content_length;
long body_start_index;
unsigned char *body;
#ifndef BEARSSL_HTTPS_MOCK_CJSON
cJSON *json_body;
#endif
long body_size;
long body_readded;
long extra_body_remaning_to_send;
bool body_readed;
int body_chunk_size;
double body_realloc_factor;
char *error_msg;
int status_code;
}BearHttpsResponse ;
#endif
#ifndef LuaSilverChain_typesE
#define LuaSilverChain_typesE
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsRequestNamespace{
void (*send_any_with_ownership_control)(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode);
void (*send_any)(BearHttpsRequest *self,unsigned char *content, long size);
void (*send_body_str_with_ownership_control)(BearHttpsRequest *self, char *content,short ownership_mode);
void (*send_body_str)(BearHttpsRequest *self, char *content);
void (*send_file_with_ownership_control)(BearHttpsRequest *self, char *path,short ownership_mode,const char *content_type);
void (*send_file)(BearHttpsRequest *self,const char *path,const char *content_type);
void (*send_file_auto_detect_content_type)(BearHttpsRequest *self, const char *path);
BearHttpsResponse * (*fetch)(BearHttpsRequest *self);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
void (*send_cJSON_with_ownership_control)(BearHttpsRequest *self,cJSON *json,short ownership_mode);
void (*send_cJSON)(BearHttpsRequest *self,cJSON *json);
cJSON * (*create_cJSONPayloadObject)(BearHttpsRequest *self);
cJSON * (*create_cJSONPayloadArray)(BearHttpsRequest *self);
#endif
BearHttpsRequest * (*newBearHttpsRequest_with_url_ownership_config)(char *url,short url_ownership_mode);
BearHttpsRequest * (*newBearHttpsRequest)(const char *url);
BearHttpsRequest * (*newBearHttpsRequest_fmt)(const char *url,...);
void (*set_known_ips)(BearHttpsRequest *self ,const char *known_ips[],int known_ips_size);
void (*set_url_with_ownership_config)(BearHttpsRequest *self , char *url,short url_ownership_mode);
void (*set_url)(BearHttpsRequest *self ,const char *url);
void (*add_header_with_ownership_config)(BearHttpsRequest *self ,char *key,short key_ownership_mode,char *value,short value_owner);
void (*add_header)(BearHttpsRequest *self ,char *key,char *value);
void (*set_method)(BearHttpsRequest *self ,const char *method);
void (*set_max_redirections)(BearHttpsRequest *self ,int max_redirections);
void (*set_dns_providers)(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers);
void (*set_chunk_header_read_props)(BearHttpsRequest *self ,int chunk_size,int max_chunk_size);
void (*set_trusted_anchors)(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size);
void (*represent)(BearHttpsRequest *self);
void (*free)(BearHttpsRequest *self);
} BearHttpsRequestNamespace;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsResponseNamespace{
int (*read_body_chunck)(BearHttpsResponse *self,unsigned char *bufer,long size);
unsigned char *(*read_body)(BearHttpsResponse *self);
const char *(*read_body_str)(BearHttpsResponse *self);
int (*get_status_code)(BearHttpsResponse*self);
int (*get_body_size)(BearHttpsResponse*self);
int (*get_headers_size)(BearHttpsResponse*self);
char* (*get_header_value_by_index)(BearHttpsResponse*self,int index);
char* (*get_header_value_by_key)(BearHttpsResponse*self,const char *key);
char* (*get_header_key_by_index)(BearHttpsResponse*self,int index);
char* (*get_header_value_by_sanitized_key)(BearHttpsResponse*self,const char *key);
void (*set_max_body_size)(BearHttpsResponse*self,long size);
void (*set_body_read_props)(BearHttpsResponse*self,int chunk_size,double realloc_factor);
bool (*error)(BearHttpsResponse*self);
char* (*get_error_msg)(BearHttpsResponse*self);
int (*get_error_code)(BearHttpsResponse*self);
void (*free)(BearHttpsResponse *self);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
cJSON * (*read_body_json)(BearHttpsResponse *self);
#endif
} BearHttpsResponseNamespace;
#endif
#ifndef LuaSilverChain_typesH
#define LuaSilverChain_typesH
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsNamespace{
short REFERENCE;
short GET_OWNERSHIP;
short COPY;
BearHttpsRequestNamespace request;
BearHttpsResponseNamespace response;
} BearHttpsNamespace;
#endif
#ifndef LuaSilverChain_fdeclare
#define LuaSilverChain_fdeclare
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool private_BearHttps_is_sanitize_key(const char *key,const char *sanitized,int sanitized_size);
char * private_BearHttps_format_vaarg(const char *expresion, va_list args);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
private_BearHttpsHeaders *private_newBearHttpsHeaders();
void private_BearHttpsHeaders_add_keyval(private_BearHttpsHeaders *self, private_BearHttpsKeyVal *keyval);
void private_BearHttpsHeaders_free(private_BearHttpsHeaders *self);
private_BearHttpsKeyVal * private_BearHttpsHeaders_get_key_val_by_index(private_BearHttpsHeaders *self,int index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
private_BearHttpsKeyVal *private_newBearHttpsKeyVal();
void private_BearHttpsKeyVal_set_key(private_BearHttpsKeyVal *self, char *key,short key_onwership_mode);
void private_BearHttpsKeyVal_set_value(private_BearHttpsKeyVal *self, char *value,short value_onwership_mode);
void private_BearHttpsKeyVal_free(private_BearHttpsKeyVal *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsNamespace newBearHttpsNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsRequestNamespace newBearHttpsRequestNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsResponseNamespace newBearHttpsResponseNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
static int private_BearHttpsRequest_connect_ipv4(BearHttpsResponse *self, const char *ipv4_ip, int port);
static int private_BearHttpsRequest_connect_ipv4_no_error_raise( const char *ipv4_ip, int port);
static int private_BearHttps_connect_host(BearHttpsRequest *self, BearHttpsResponse *response, const char *host, int port);
static int private_BearHttps_sock_read(void *ctx, unsigned char *buf, size_t len);
static int private_BearHttps_sock_write(void *ctx, const unsigned char *buf, size_t len);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_BearsslHttps_free_considering_ownership(void **value,bool *owner);
void private_BearsslHttps_set_str_considering_ownership(char **dest, char *value, bool *owner, short ownership_mode);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_BearHttpsRequest_free_body(BearHttpsRequest *self);
void BearHttpsRequest_send_any_with_ownership_control(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode);
void BearHttpsRequest_send_any(BearHttpsRequest *self,unsigned char *content, long size);
void BearHttpsRequest_send_body_str_with_ownership_control(BearHttpsRequest *self, char *content,short ownership_mode);
void BearHttpsRequest_send_body_str(BearHttpsRequest *self, char *content);
void BearHttpsRequest_send_file_with_ownership_control(BearHttpsRequest *self, char *path,short ownership_mode,const char *content_type);
void BearHttpsRequest_send_file(BearHttpsRequest *self,const char *path,const char *content_type);
void BearHttpsRequest_send_file_auto_detect_content_type(BearHttpsRequest *self, const char *path);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
void BearHttpsRequest_send_cJSON_with_ownership_control(BearHttpsRequest *self,cJSON *json,short ownership_mode);
void BearHttpsRequest_send_cJSON(BearHttpsRequest *self,cJSON *json);
cJSON * BearHttpsRequest_create_cJSONPayloadObject(BearHttpsRequest *self);
cJSON * BearHttpsRequest_create_cJSONPayloadArray(BearHttpsRequest *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsRequest * newBearHttpsRequest_with_url_ownership_config(char *url,short url_ownership_mode);
BearHttpsRequest * newBearHttpsRequest(const char *url);
BearHttpsRequest * newBearHttpsRequest_fmt(const char *url,...);
void BearHttpsRequest_set_url_with_ownership_config(BearHttpsRequest *self , char *url,short url_ownership_mode);
void BearHttpsRequest_set_url(BearHttpsRequest *self ,const char *url);
void BearHttpsRequest_add_header_with_ownership_config(BearHttpsRequest *self ,char *key,short key_ownership_mode,char *value,short value_owner);
void BearHttpsRequest_add_header(BearHttpsRequest *self ,char *key,char *value);
void BearHttpsRequest_add_header_fmt(BearHttpsRequest *self ,char *key,char *format,...);
void BearHttpsRequest_set_max_redirections(BearHttpsRequest *self ,int max_redirections);
void BearHttpsRequest_set_dns_providers(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers);
void BearHttpsRequest_set_known_ips(BearHttpsRequest *self , const char *known_ips[],int known_ips_size);
void BearHttpsRequest_set_chunk_header_read_props(BearHttpsRequest *self ,int chunk_size,int max_chunk_size);
void BearHttpsRequest_set_trusted_anchors(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size);
void BearHttpsRequest_set_method(BearHttpsRequest *self ,const char *method);
void BearHttpsRequest_represent(BearHttpsRequest *self);
void BearHttpsRequest_free(BearHttpsRequest *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
private_BearHttpsRequisitionProps * private_new_private_BearHttpsRequisitionProps(
const char *route,int default_port);
void private_BearHttpsRequisitionProps_free(private_BearHttpsRequisitionProps *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsResponse *private_newBearHttpsResponse();
int private_BearHttpsResponse_read_chunck_raw(BearHttpsResponse *self,unsigned char *bufer,long size);
int BearHttpsResponse_read_body_chunck(BearHttpsResponse *self,unsigned char *bufer,long size);
unsigned char *BearHttpsResponse_read_body(BearHttpsResponse *self);
const char *BearHttpsResponse_read_body_str(BearHttpsResponse *self);
int private_BearHttpsResponse_write(BearHttpsResponse *self,unsigned char *bufer,long size);
void private_BearHttpsResponse_read_til_end_of_headers_or_reach_limit(
BearHttpsResponse *self,
int chunk,
double factor_headers_growth
);
void private_BearHttpsResponse_start_bearssl_props(BearHttpsResponse *self, const char *hostname,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size);
int BearHttpsResponse_get_status_code(BearHttpsResponse*self);
int BearHttpsResponse_get_body_size(BearHttpsResponse*self);
int BearHttpsResponse_get_headers_size(BearHttpsResponse*self);
char* BearHttpsResponse_get_header_value_by_index(BearHttpsResponse*self,int index);
char* BearHttpsResponse_get_header_value_by_key(BearHttpsResponse*self,const char *key);
char* BearHttpsResponse_get_header_key_by_index(BearHttpsResponse*self,int index);
char* BearHttpsResponse_get_header_value_by_sanitized_key(BearHttpsResponse*self,const char *key);
bool BearHttpsResponse_error(BearHttpsResponse*self);
char* BearHttpsResponse_get_error_msg(BearHttpsResponse*self);
int BearHttpsResponse_get_error_code(BearHttpsResponse*self);
void BearHttpsResponse_set_error(BearHttpsResponse*self,const char *msg,int error_code);
void BearHttpsResponse_set_max_body_size(BearHttpsResponse*self,long size);
void BearHttpsResponse_set_body_read_props(BearHttpsResponse*self,int chunk_size,double realloc_factor);
void BearHttpsResponse_free(BearHttpsResponse *self);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
cJSON * BearHttpsResponse_read_body_json(BearHttpsResponse *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
long private_BearsslHttps_strlen(const char *str);
int private_BearsslHttp_strcmp(const char *str1,const char *str2);
bool private_BearsslHttps_startswith(const char *str,const char *prefix);
char * private_BearsslHttps_strdup(const char *str);
char * private_BearsslHttps_strcpy( char *dest,const char *str);
char * private_BearsslHttps_strndup(const char *str,int size);
int private_BearsslHttps_indexof_from_point(const char *str,char c,int start);
char private_BearsslHttps_parse_char_to_lower(char c);
#endif
/* This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to
*/
#ifndef CArgvParse_macros
#define CArgvParse_macros
#ifndef C_ARGV_PARSER_MAX_ARGS
#define C_ARGV_PARSER_MAX_ARGS 1000
#endif
#ifdef __cplusplus
#define C_ARGV_PARSER_NULL nullptr
#else
#define C_ARGV_PARSER_NULL ((void*)0)
#endif
typedef unsigned char c_argv_bool;
#define C_ARGV_PARSER_TRUE 1
#define C_ARGV_PARSER_FALSE 0
#ifndef C_ARGV_UNUSED_START
#define C_ARGV_UNUSED_START 1
#endif
#endif
#ifndef CArgvParse_types
#define CArgvParse_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct CArgvParse{
int used_args[C_ARGV_PARSER_MAX_ARGS];
int total_used_args;
char **args;
int total_args;
const char **flag_identifiers;
int total_flag_indentifiers;
}CArgvParse;
#endif
#ifndef CArgvParse_typesB
#define CArgvParse_typesB
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct CArgvParseNamespace{
CArgvParse (*newCArgvParse)(int argc, char **argv);
const char *(*get_arg)(CArgvParse *self,int index);
int (*get_flag_size)(CArgvParse *self,const char **flags,int flags_size);
const char * (*get_flag)(CArgvParse *self ,const char **flags,int flags_size, int index);
const char *(*get_next_unused_arg)(CArgvParse *self);
c_argv_bool (*is_flags_present)(CArgvParse *self,const char **flag,int flags_size);
c_argv_bool (*is_one_of_args_present)(CArgvParse *self,const char **args,int args_size);
int (*get_infinity_flag_size)(CArgvParse *self,const char **flags,int flags_size);
const char * (*get_infinty_flag)(CArgvParse *self ,const char **flags,int flags_size, int index);
int (*get_compact_flag_size)(CArgvParse *self,const char **flags,int flags_size);
const char * (*get_compact_flag)(CArgvParse *self ,const char **flags,int flags_size, int index);
}CArgvParseNamespace;
#endif
#ifndef CArgvParse_fdeclare
#define CArgvParse_fdeclare
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
CArgvParse newCArgvParse(int argc, char **argv);
const char *CArgvParse_get_arg(CArgvParse *self,int index);
int privateCArgv_parser_get_flag_identifier_start_size(CArgvParse *self,const char *flag,int flag_size);
c_argv_bool CArgvParse_is_flags_present(CArgvParse *self,const char **flags,int flags_size);
c_argv_bool CArgvParse_is_one_of_args_present(CArgvParse *self,const char **args,int args_size);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int CArgvParse_get_compact_flag_size(CArgvParse *self,const char **flags,int flags_size);
const char * CArgvParse_get_compact_flag(CArgvParse *self ,const char **flags,int flags_size, int index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int CArgvParse_get_infinity_flag_size(CArgvParse *self,const char **flags,int flags_size);
const char * CArgvParse_get_infinty_flag(CArgvParse *self ,const char **flags,int flags_size, int index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
CArgvParseNamespace newCArgvParseNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int CArgvParse_get_flag_size(CArgvParse *self,const char **flags,int flags_size);
const char * CArgvParse_get_flag(CArgvParse *self ,const char **flags,int flags_size, int index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
c_argv_bool private_CArgvParse_its_used(CArgvParse *self,int index);
void private_CArgvParse_add_used(CArgvParse *self,int index);
const char *CArgvParse_get_next_unused_arg(CArgvParse *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int privateArgv_parser_string_size(const char *string);
c_argv_bool privateArgv_parsser_starts_with(const char *string,int string_size, const char *start,int start_size);
c_argv_bool privateArgv_strings_equals(const char *string1,int string1_size,const char *string2,int string2_size);
#endif
/* MIT License
Copyright (c) 2023 Mateus Moutinho Queiroz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef doTHeWorld_dep_declare
#define doTHeWorld_dep_declare
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __linux__
#include
#include
#include
#include
#include
#include
#elif _WIN32
#include
#include
#include
#include
#include
#endif
#if !defined(cJSON__h)
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#include
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif
#define DTW_CJSON_IMPLEMENTED
#endif
#if !defined(SHA_256_H)
#ifndef SHA_256_H
#define SHA_256_H
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/*
* @brief Size of the SHA-256 sum. This times eight is 256 bits.
*/
#define SIZE_OF_SHA_256_HASH 32
/*
* @brief Size of the chunks used for the calculations.
*
* @note This should mostly be ignored by the user, although when using the streaming API, it has an impact for
* performance. Add chunks whose size is a multiple of this, and you will avoid a lot of superfluous copying in RAM!
*/
#define SIZE_OF_SHA_256_CHUNK 64
/*
* @brief The opaque SHA-256 type, that should be instantiated when using the streaming API.
*
* @note Although the details are exposed here, in order to make instantiation easy, you should refrain from directly
* accessing the fields, as they may change in the future.
*/
struct Sha_256 {
uint8_t *hash;
uint8_t chunk[SIZE_OF_SHA_256_CHUNK];
uint8_t *chunk_pos;
size_t space_left;
uint64_t total_len;
uint32_t h[8];
};
/*
* @brief The simple SHA-256 calculation function.
* @param hash Hash array, where the result is delivered.
* @param input Pointer to the data the hash shall be calculated on.
* @param len Length of the input data, in byte.
*
* @note If all of the data you are calculating the hash value on is available in a contiguous buffer in memory, this is
* the function you should use.
*
* @note If either of the passed pointers is NULL, the results are unpredictable.
*
* @note See note about maximum data length for sha_256_write, as it applies for this function's len argument too.
*/
void calc_sha_256(uint8_t hash[SIZE_OF_SHA_256_HASH], const void *input, size_t len);
/*
* @brief Initialize a SHA-256 streaming calculation.
* @param sha_256 A pointer to a SHA-256 structure.
* @param hash Hash array, where the result will be delivered.
*
* @note If all of the data you are calculating the hash value on is not available in a contiguous buffer in memory,
* this is where you should start. Instantiate a SHA-256 structure, for instance by simply declaring it locally, make
* your hash buffer available, and invoke this function. Once a SHA-256 hash has been calculated (see further below) a
* SHA-256 structure can be initialized again for the next calculation.
*
* @note If either of the passed pointers is NULL, the results are unpredictable.
*/
void sha_256_init(struct Sha_256 *sha_256, uint8_t hash[SIZE_OF_SHA_256_HASH]);
/*
* @brief Stream more input data for an on-going SHA-256 calculation.
* @param sha_256 A pointer to a previously initialized SHA-256 structure.
* @param data Pointer to the data to be added to the calculation.
* @param len Length of the data to add, in byte.
*
* @note This function may be invoked an arbitrary number of times between initialization and closing, but the maximum
* data length is limited by the SHA-256 algorithm: the total number of bits (i.e. the total number of bytes times
* eight) must be representable by a 64-bit unsigned integer. While that is not a practical limitation, the results are
* unpredictable if that limit is exceeded.
*
* @note This function may be invoked on empty data (zero length), although that obviously will not add any data.
*
* @note If either of the passed pointers is NULL, the results are unpredictable.
*/
void sha_256_write(struct Sha_256 *sha_256, const void *data, size_t len);
/*
* @brief Conclude a SHA-256 streaming calculation, making the hash value available.
* @param sha_256 A pointer to a previously initialized SHA-256 structure.
* @return Pointer to the hash array, where the result is delivered.
*
* @note After this function has been invoked, the result is available in the hash buffer that initially was provided. A
* pointer to the hash value is returned for convenience, but you should feel free to ignore it: it is simply a pointer
* to the first byte of your initially provided hash array.
*
* @note If the passed pointer is NULL, the results are unpredictable.
*
* @note Invoking this function for a calculation with no data (the writing function has never been invoked, or it only
* has been invoked with empty data) is legal. It will calculate the SHA-256 value of the empty string.
*/
uint8_t *sha_256_close(struct Sha_256 *sha_256);
#ifdef __cplusplus
}
#endif
#endif
#define DTW_SHA256_IMPLEMENTED
#endif
#if !defined(_AES_H_)
#ifndef _AES_H_
#define _AES_H_
#include
// #define the macros below to 1/0 to enable/disable the mode of operation.
//
// CBC enables AES encryption in CBC-mode of operation.
// CTR enables encryption in counter-mode.
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
#ifndef CBC
#define CBC 1
#endif
#ifndef ECB
#define ECB 1
#endif
#ifndef CTR
#define CTR 1
#endif
#define AES128 1
//#define AES192 1
//#define AES256 1
#define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif
struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(struct AES_ctx* ctx, uint8_t* buf);
#endif // #if defined(ECB) && (ECB == !)
#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
// Same function for encrypting as for decrypting.
// IV is incremented for every block, and used after encryption as XOR-compliment for output
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
#endif // #if defined(CTR) && (CTR == 1)
#endif //_AES_H_
#define DTW_AES_IMPLEMENTED
#endif
#endif
#ifndef doTHeWorld_consts
#define doTHeWorld_consts
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DTW_RAW_MODE 0
#define DTW_B64_MODE 1
#define DTW_HEX_MODE 2
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DTW_FILE_TYPE 1
#define DTW_FOLDER_TYPE 2
#define DTW_ALL_TYPE 3
#define DTW_NOT_FOUND -1
#define DTW_COMPLEX_BINARY 10
#define DTW_COMPLEX_STRING_TYPE 11
#define DTW_COMPLEX_LONG_TYPE 12
#define DTW_COMPLEX_DOUBLE_TYPE 13
#define DTW_COMPLEX_BOOL_TYPE 14
#define DTW_MERGE true
#define DTW_NOT_MERGE false
#define DTW_NOT_NUMERICAL -2
#define DTW_NOT_BOOL -3
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DTW_CONCAT_PATH true
#define DTW_NOT_CONCAT_PATH false
#define WIN32_FILETYPE 32
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DTW_MULTIFILE_LOCKER_TOTAL_CHECK 500
#define DTW_MULTIFILE_LOCKER_MAX_TIMEOUT 10
#define DTW_MULFILE_LOCKER_MAX_WAIT 10
#define DTW_LOCKER_LOCKED 0
#define DTW_LOCKER_IMPOSSIBLE_TO_CREATE_FILE_DESCRIPTOR 5
#define DTW_LOCKER_FLCTL_FAIL 6
#define DTW_LOCKER_WAIT_ERROR 21
#define DTW_LOCKER_OS_NOT_PREDICTIBLE -1
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DTW_RESOURCE_ELEMENT_IS_NULL -1
#define DTW_RESOURCE_OK 0
#define DTW_RESOURCE_ELEMENT_NOT_EXIST 1
#define DTW_RESOURCE_ELEMENT_NOT_BOOL 2
#define DTW_RESOURCE_ELEMENT_NOT_LONG 3
#define DTW_RESOURCE_ELEMENT_NOT_DOUBLE 4
#define DTW_RESOURCE_ELEMENT_NOT_STRING 5
#define DTW_RESOURCE_PRIMARY_KEY_ALREADY_EXIST 6
#define DTW_RESOURCE_PRIMARY_KEY_CANNOT_HAVE_SUB_RESOURCE 7
#define DTW_IMPOSSIBLE_TO_RENAME_A_PRIMARY_KEY 8
#define DTW_RESOURCE_RENAMED_RESOURCE_CANNOT_HAVE_SONS 9
#define DTW_RESOURCE_IMPSSIBLE_TO_ADD_INSERTION_OUTSIDE_ROOT_SCHEMA 10
#define DTW_RESOURCE_IMPOSSIBLE_TO_ADD_SUB_RESOURCE_INSIDE_SCHEMA_STRUCT 11
#define DTW_RESOURCE_ONLY_ROOT_SCHEMA_CAN_FIND_BY_ID_OR_PK 12
#define DTW_RESOURCE_ONLY_ROOT_SCHEMA_HAVE_SCHEMA_VALUES 13
#define DTW_RESOURCE_ONLY_ROOT_SCHEMA_CANN_MODIFY_SCHEMA_PROPS 14
#define PRIVATE_DTW_SCHEMA_ROOT 1
#define PRIVATE_DTW_SCHEMA_VALUE 2
#define PRIVATE_DTW_SCHEMA_ELEMENT 3
#define PRIVATE_DTW_SCHEMA_ELEMENT_PROP 4
#define PRIVATE_DTW_SCHEMA_INDEX 5
#define PRIVATE_DTW_SCHEMA_PK_FOLDER 6
#define PRIVATE_DTW_SCHEMA_PK_VALUE 7
#define DTW_SCHEMA_DEFAULT_VALUES_NAME "value"
#define DTW_SCHEMA_DEFAULT_INDEX_NAME "index"
#define DTW_RESOURCE_ALL -1
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
enum {
JSON_TRANSACTION_WRONG_TYPE,
JSON_TRANSACTION_NOT_PRESENT_VALUE,
JSON_TRANSACTION_INVALID_ACTION
};
enum {
DTW_ACTION_FILE_NOT_FOUND,
DTW_ACTION_ITS_NOT_JSON,
DTW_ACTION_WRITE,
DTW_ACTION_MOVE,
DTW_ACTION_MOVE_MERGING,
DTW_ACTION_COPY,
DTW_ACTION_COPY_MERGING,
DTW_ACTION_DELETE
};
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DTW_NOT_MIMIFY 1
#define DTW_MIMIFY 2
#define DTW_NOT_LOAD 1
#define DTW_LOAD 2
#define DTW_HIDE 1
#define DTW_INCLUDE 2
#define DTW_IS_BINARY true
#define DTW_IS_NOT_BINARY false
#define DTW_IGNORE true
#define DTW_NOT_IGNORE false
#define DTW_SET_AS_ACTION 1
#define DTW_EXECUTE_NOW 2
#define DTW_MODIFY 1
#define DTW_WRITE 2
#define DTW_REMOVE 3
#define DTW_JSON_TYPE_ERROR 1
#define DTW_JSON_SYNTAX_ERROR 2
#define DTW_JSON_REQUIRED_KEY_ERROR 3
#define DTW_JSON_REQUIRED_VALUE_ERROR 4
#define DTW_JSON_NOT_FOUND_ERROR 5
#define DTW_ACTION_ERROR (-1)
#endif
#ifndef doTHeWorld_macros
#define doTHeWorld_macros
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
#define dtw_create_dir(path) mkdir(path,0777)
#elif _WIN32
#define dtw_create_dir(path) _mkdir(path)
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define DtwSchemaRebase self->root_props->schema_unsafe =old;
#define privateDtwSchemaUnsafe(scope){\
bool old = self->root_props->schema_unsafe;\
self->root_props->schema_unsafe = true;\
scope;\
DtwSchemaRebase\
}
#endif
#ifndef doTHeWorld_types
#define doTHeWorld_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct privateDtwAES_RAW_EncryptionInterface{
uint8_t key[16];
struct AES_ctx ctx;
uint8_t iv[16];
void (*encrypt_buffer)( struct privateDtwAES_RAW_EncryptionInterface *self,uint8_t* buf, uint32_t length);
void (*decrypt_buffer)(struct privateDtwAES_RAW_EncryptionInterface *self,uint8_t* buf, uint32_t length);
}privateDtwAES_RAW_EncryptionInterface;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwEncriptionInterface{
void *obj;
unsigned char * (*encrypt_buffer)(void *obj, unsigned char *value,long size,long *out_size);
unsigned char *(*decrypt_buffer)(void *obj, unsigned char *encrypted_value,long size,long *out_size);
void (*free_obj)(void *obj);
}DtwEncriptionInterface;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwHash{
char *hash;
}DtwHash;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
typedef struct {
char *filename;
int file_descriptor;
}privateDtwFlockLockedElement;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwEncryptionNamespace{
//initializer
DtwEncriptionInterface *(*newInterface_raw)(void *obj, unsigned char *(*encrypt_buffer)(void *obj, unsigned char *value,long size,long *out_size), unsigned char *(*decrypt_buffer)(void *obj, unsigned char *encrypted_value,long size,long *out_size), void (*free_obj)(void *obj));
DtwEncriptionInterface *(*newAES_ECB_EncryptionInterface)(const uint8_t* key,int key_size);
DtwEncriptionInterface *(*newAES_ECB_EncryptionInterface_str)(const char* key);
DtwEncriptionInterface *(*newAES_Custom_CBC_v1_interface)(const char *key);
DtwEncriptionInterface *(*newAES_CBC_EncryptionInterface)(const uint8_t* key,int key_size,const uint8_t *iv, int iv_size);
DtwEncriptionInterface *(*newAES_CBC_EncryptionInterface_str)(const char* key,const char *iv);
//basic
unsigned char *(*encrypt_buffer)(DtwEncriptionInterface *self, unsigned char *value,long size,long *out_size);
unsigned char *(*decrypt_buffer)(DtwEncriptionInterface *self, unsigned char *encrypted_value,long size,long *out_size,bool *is_binary);
void (*free)(DtwEncriptionInterface *self);
//basic io
bool (*write_any_content)(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size);
bool (*write_string_file_content)(DtwEncriptionInterface *self,const char *file_name,const char *value);
unsigned char *(*load_any_content)(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary);
char *(*load_string_file_content)(DtwEncriptionInterface *self,const char *file_name);
//hex
char *(*encrypt_buffer_hex)(DtwEncriptionInterface *self, unsigned char *value,long size);
unsigned char *(*decrypt_buffer_hex)(DtwEncriptionInterface *self, const char *encrypted_value,long *out_size,bool *is_binary);
bool (*write_any_content_hex)(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size);
bool (*write_string_file_content_hex)(DtwEncriptionInterface *self,const char *file_name,const char *value);
unsigned char *(*load_any_content_hex)(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary);
char *(*load_string_file_content_hex)(DtwEncriptionInterface *self,const char *file_name);
///b64
char *(*encrypt_buffer_b64)(DtwEncriptionInterface *self, unsigned char *value,long size);
unsigned char *(*decrypt_buffer_b64)(DtwEncriptionInterface *self, const char *encrypted_value,long *out_size,bool *is_binary);
bool (*write_any_content_b64)(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size);
bool (*write_string_file_content_b64)(DtwEncriptionInterface *self,const char *file_name,const char *value);
unsigned char *(*load_any_content_b64)(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary);
char *(*load_string_file_content_b64)(DtwEncriptionInterface *self,const char *file_name);
}DtwEncryptionNamespace;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwRandonizer{
long internal_seed;
long seed;
long actual_generation;
}DtwRandonizer;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef DTW_ALLOW_CHASH
typedef struct{
char *key;
CHash *element;
bool free_key;
}privateDtw_CHash_element_and_key;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct{
char *key;
bool free_key;
cJSON *element;
}privateDtw_cJSON_element_and_key;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwStringArray {
int size;
char **strings;
}DtwStringArray;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_ACTION_TRANSACTION_TYPE_H
#define PRIVATE_DTW_ACTION_TRANSACTION_TYPE_H
typedef struct DtwActionTransaction{
short action_type;
unsigned char *content;
long size;
bool is_binary;
DtwEncriptionInterface *encryption;
short encryption_mode;
char *dest;
char *source;
}DtwActionTransaction;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_JSON_TRANSACTION_ERROR_TYPE_H
#define PRIVATE_DTW_JSON_TRANSACTION_ERROR_TYPE_H
typedef struct DtwJsonTransactionError{
int code;
char *mensage;
char *path;
}DtwJsonTransactionError;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_JSON_TREE_ERROR_TYPE_H
#define PRIVATE_DTW_JSON_TREE_ERROR_TYPE_H
typedef struct DtwJsonTreeError {
int code;
int position;
const char *menssage;
}DtwJsonTreeError;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwTreeProps{
int minification;
int content;
int path_atributes;
int hadware_data;
int content_data;
int ignored_elements;
}DtwTreeProps;
#endif
#ifndef doTHeWorld_typesb
#define doTHeWorld_typesb
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
typedef struct {
privateDtwFlockLockedElement **elements;
int size;
}privateDtwFlockArray;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct {
int total_checks;
int process;
int max_wait;
int max_lock_time;
DtwStringArray *locked_elements;
}DtwMultiFileLocker;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwPath {
char *original_path_string;
char *path;
DtwStringArray *garbage;
}DtwPath;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwSchema{
const char *value_name;
const char *index_name;
char *name;
struct DtwSchema **sub_schemas;
int size;
DtwStringArray *primary_keys;
}DtwSchema;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DT_TRANSACTION_TYPE_H
#define PRIVATE_DT_TRANSACTION_TYPE_H
typedef struct DtwTransaction{
DtwEncriptionInterface *encryption;
short encryption_mode;
DtwActionTransaction **actions;
long size;
}DtwTransaction;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_TRANSACTION_REPORT_TYPE_H
#define PRIVATE_DTW_TRANSACTION_REPORT_TYPE_H
typedef struct DtwTreeTransactionReport{
DtwStringArray *write;
DtwStringArray *modify;
DtwStringArray *remove;
}DtwTreeTransactionReport;
#endif
#endif
#ifndef doTHeWorld_typesc
#define doTHeWorld_typesc
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_DATABASE_SCHEMA_TYPE_H
#define PRIVATE_DTW_DATABASE_SCHEMA_TYPE_H
typedef struct DtwDatabaseSchema{
const char *value_name;
const char *index_name;
struct DtwSchema **sub_schemas;
int size;
}DtwDatabaseSchema;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwTreePart{
DtwPath *path;
void *owner;
long content_size;
long hardware_content_size;
bool content_exist_in_hardware;
bool ignore;
bool is_binary;
bool metadata_loaded;
char *current_sha;
char * last_modification_in_str;
long last_modification_time;
char *hawdware_content_sha;
unsigned char *content;
int pending_action;
}DtwTreePart;
#endif
#ifndef doTHeWorld_typesc_flock_locker
#define doTHeWorld_typesc_flock_locker
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
typedef struct {
const char *temp_folder;
privateDtwFlockArray *locked_files;
}DtwFlockLocker;
#endif
#endif
#ifndef doTHeWorld_typesd
#define doTHeWorld_typesd
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct {
#ifdef __linux__
DtwFlockLocker *locker;
#endif
#ifdef _WIN32
DtwMultiFileLocker *locker;
#endif
} DtwLocker;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_TREE_TYPE_H
#define PRIVATE_DTW_TREE_TYPE_H
typedef struct DtwTree{
int size;
DtwTreePart **tree_parts;
}DtwTree;
#endif
#endif
#ifndef doTHeWorld_typese
#define doTHeWorld_typese
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct {
DtwTransaction *transaction;
DtwRandonizer *randonizer;
DtwLocker *locker;
bool schema_unsafe;
int error_code;
char *error_path;
char *error_message;
DtwEncriptionInterface *encryption_interface;
short encryption_mode;
}privateDtwResourceRootProps;
#endif
#ifndef doTHeWorld_typesf
#define doTHeWorld_typesf
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwResource{
bool allow_transaction;
bool use_locker_on_unique_values;
privateDtwResourceRootProps *root_props;
struct DtwResource *mother;
char *name;
char *path;
//in the schema struct there is:
//|/root
//|/root/values
//|root/values/element <-----------------------------|
//|root/values/element/pk_name ->any(write_point) |
//|root/values/element/element_prop ->any(write_point)|
//|root/index |
//|root/index/pk_name/pk_sha ->txt -------------------
DtwSchema *attached_schema;
DtwDatabaseSchema *datatabase_schema;
struct DtwResource *values_resource;
struct DtwResource *index_resource;
int schema_type;
bool loaded;
bool is_binary;
bool were_renamed;
unsigned char *value_any;
long value_size;
//cache implementation
bool cache_sub_resources;
void *sub_resources;
}DtwResource;
#endif
#ifndef doTHeWorld_typesg
#define doTHeWorld_typesg
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct{
bool(*filtrage_callback)(DtwResource *item, void *args_filter);
void(*callback)(DtwResource *item, void *args);
void *args;
int start;
int qtd;
}DtwResourceForeachProps;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef DTW_ALLOW_CHASH
typedef struct{
bool(*filtrage_callback)(DtwResource *item, void *args_filter);
int (*ordenation_callback)(DtwResource *item1, DtwResource *item2, void *args);
CHash *(*callback)(DtwResource *item, void *args);
void *args;
int start;
int qtd;
} DtwResourceCHashrrayMapProps;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef DTW_ALLOW_CHASH
typedef struct{
char *(*key_provider_callback)(DtwResource *item,void *args);
bool(*filtrage_callback)(DtwResource *item, void *args_filter);
int (*ordenation_callback)(DtwResource *item1, DtwResource *item2, void *args);
CHash *(*callback)(DtwResource *item, void *args);
void *args;
bool free_key;
int start;
int qtd;
} DtwResourceCHashObjectMapProps;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct{
bool(*filtrage_callback)(DtwResource *item, void *args_filter);
int (*ordenation_callback)(DtwResource *item1, DtwResource *item2, void *args);
cJSON *(*callback)(DtwResource *item, void *args);
void *args;
int start;
int qtd;
} DtwResourcecJSONArrayMapProps;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct{
char *(*key_provider_callback)(DtwResource *item,void *args);
bool free_key;
bool(*filtrage_callback)(DtwResource *item, void *args_filter);
int (*ordenation_callback)(DtwResource *item1, DtwResource *item2, void *args);
cJSON *(*callback)(DtwResource *item, void *args);
void *args;
int start;
int qtd;
} DtwResourcecJSONObjectMapProps;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct {
void *result;
void *args;
DtwResource *current;
int (*ordenation_callback)(DtwResource *item1, DtwResource *item2, void *args);
}privateDtwResource_map_element;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct {
void *main_array;
void(*append)(void *main_array_arg, void *item);
bool(*filtrage_callback)(DtwResource *item, void *args);
int (*ordenation_callback)(DtwResource *item1, DtwResource *item2, void *args);
void *(*callback)(DtwResource *item, void *args);
void *args;
int start;
int qtd;
}DtwResourceMapProps;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwResourceArray{
DtwResource **resources;
long size;
}DtwResourceArray;
#endif
#ifndef doTHeWorld_typesi
#define doTHeWorld_typesi
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef PRIVATE_DTW_DATABASE_SCHEMA_MODULE_TYPE_H
#define PRIVATE_DTW_DATABASE_SCHEMA_MODULE_TYPE_H
typedef struct {
DtwSchema * (*sub_schema)(DtwDatabaseSchema *self,const char *name);
}DtwDatabaseSchemaModule;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwHashModule{
DtwHash * (*newHash)();
bool (*digest_any)(DtwHash *self,unsigned char *content,long size);
bool (*digest_string)(DtwHash * self, const char *content);
void (*digest_long)(DtwHash * self,long content);
void (*digest_double)(DtwHash * self,double content);
void (*digest_bool)(DtwHash * self,bool content);
bool (*digest_file)(DtwHash * self, const char *path);
bool (*digest_entity_last_modification)(DtwHash * self, const char *path);
bool (*digest_string_array)(DtwHash *self,DtwStringArray *element);
bool (*digest_string_array_last_modifications)(DtwHash *self,DtwStringArray *element);
bool (*digest_string_array_last_modifications_adding_name)(DtwHash *self,DtwStringArray *element);
bool (*digest_string_array_content)(DtwHash *self,DtwStringArray *element);
bool (*digest_string_array_content_adding_name)(DtwHash *self,DtwStringArray *element);
bool (*digest_folder_by_last_modification)(DtwHash *self,const char *path);
bool (*digest_folder_by_content)(DtwHash *self,const char *path);
void (*free)(DtwHash *self);
}DtwHashModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwLockerModule{
DtwLocker * (*newLocker)();
int (*lock)(DtwLocker *self, const char *element);
void (*unlock)(DtwLocker *self, const char *element);
void (*represemt)(DtwLocker *self);
void (*free)(DtwLocker *self);
}DtwLockerModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwPathModule{
//Getters
DtwPath * (*newPath)(const char *path);
bool (*changed)(struct DtwPath *self);
char *(*get_full_name) (struct DtwPath *self);
char *(*get_name) (struct DtwPath *self);
char *(*get_extension) (struct DtwPath *self);
char *(*get_path) (struct DtwPath *self);
char *(*get_dir) (struct DtwPath *self);
int (*get_total_dirs)(DtwPath *self);
char *(*get_sub_dirs_from_index)(DtwPath *self, int start,int end);
void (*insert_dir_at_index)(DtwPath *self,int index,const char *dir);
void (*remove_sub_dirs_at_index)(DtwPath *self,int start,int end);
void (*insert_dir_after)(DtwPath *self,const char *str,const char *dir);
void (*insert_dir_before)(DtwPath *self,const char *str,const char *dir);
void (*replace_dirs)(DtwPath *self,const char *str,const char *dir);
void (*remove_sub_dirs_at)(DtwPath *self,const char *str);
//Setters
void (*set_extension) (struct DtwPath *self, const char *extension);
void (*set_name) (struct DtwPath *self, const char *name);
void (*set_dir) (struct DtwPath *self, const char *path);
void (*set_full_name) (struct DtwPath *self, const char *full_name);
void (*set_path) (struct DtwPath *self, const char *target_path);
void (*add_start_dir)(struct DtwPath *self, const char *start_dir);
void (*add_end_dir)(struct DtwPath *self, const char *end_dir);
void (*represent)(struct DtwPath *self);
void (*free) (struct DtwPath *self);
}DtwPathModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwRandonizerModule{
DtwRandonizer * (*newRandonizer)();
int (*generate_num)(DtwRandonizer *self,int max);
char * (*generate_token)(DtwRandonizer*self, int size);
void (*free)(DtwRandonizer *self);
}DtwRandonizerModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwResourceArrayModule{
void (*append)(DtwResourceArray *self, DtwResource *element);
DtwResource * (*get_by_name)(DtwResourceArray *self, const char *name);
void (*represent)(DtwResourceArray *self);
void (*free)(DtwResourceArray *self);
}DtwResourceArrayModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwResourceModule{
DtwResource *(*newResource)(const char *path);
int (*get_error_code)(DtwResource *self);
bool (*error)(DtwResource *self);
void (*set_encryption)(DtwResource *self,DtwEncriptionInterface *encryption_interface,short mode);
DtwResourceForeachProps (*create_foreach_props)( void(*callback)(DtwResource *item, void *args));
void (*each)(DtwResource *self,DtwResourceForeachProps props);
void (*schema_each)(DtwResource *self,DtwResourceForeachProps props);
DtwResourceMapProps (*create_map_props)(
void *main_array,
void(*append)(void *main_array_arg, void *item),
void *(*callback)(DtwResource *item, void *args)
);
void (*map)(DtwResource *self,DtwResourceMapProps props);
void (*schema_map)(DtwResource *self,DtwResourceMapProps props);
DtwResourcecJSONArrayMapProps (*create_cJSONArrayMapProps)(cJSON *(*callback)(DtwResource *item, void *args));
cJSON *(*map_cJSONArray)(DtwResource *self,DtwResourcecJSONArrayMapProps props);
cJSON *(*schema_map_cJSONArray)(DtwResource *self,DtwResourcecJSONArrayMapProps props);
DtwResourcecJSONObjectMapProps (*create_cJSONObjectProps)(
cJSON *(*callback)(DtwResource *item, void *args),
char *(*key_provider_callback)(DtwResource *item,void *args)
);
cJSON *(*map_cJSONObject)(DtwResource *self,DtwResourcecJSONObjectMapProps props);
cJSON *(*schema_map_cJSONObject)(DtwResource *self,DtwResourcecJSONObjectMapProps props);
#ifdef DTW_ALLOW_CHASH
DtwResourceCHashrrayMapProps (*create_CHashrrayMapProps)( CHash *(*callback)(DtwResource *item, void *args));
CHashArray *(*map_CHashArray)(DtwResource *self,DtwResourceCHashrrayMapProps props);
CHashArray *(*schema_map_CHashArray)(DtwResource *self,DtwResourceCHashrrayMapProps props);
DtwResourceCHashObjectMapProps (*createCHashObjectMapProps)(
CHash *(*callback)(DtwResource *item, void *args),
char*(*key_provider)(DtwResource *item, void *args_filter)
);
CHashObject *(*map_CHashObject)(DtwResource *self,DtwResourceCHashObjectMapProps props);
CHashObject *(*schema_map_CHashObject)(DtwResource *self,DtwResourceCHashObjectMapProps props);
#endif
char * (*get_error_message)(DtwResource *self);
bool (*is_file)(DtwResource *self);
void (*destroy_sub_resource)(DtwResource *self, const char *key);
void (*rename_sub_resource)(DtwResource *self,const char *old_name,const char *new_name);
DtwResource * (*sub_resource)(struct DtwResource *self,const char *format,...);
unsigned char *(*get_any_from_sub_resource)(DtwResource *self, long *size, bool *is_binary,const char *format,...);
unsigned char *(*get_binary_from_sub_resource)(DtwResource *self, long *size,const char *format,...);
char *(*get_string_from_sub_resource)(DtwResource *self,const char *format,...);
long (*get_long_from_sub_resource)(DtwResource *self,const char *format,...);
double (*get_double_from_sub_resource)(DtwResource *self,const char *format,...);
bool (*get_bool_from_sub_resource)(DtwResource *self,const char *format,...);
void (*set_any_in_sub_resource)(DtwResource *self,const char *key, unsigned char *element, long size,bool is_binary);
void (*set_binary_in_sub_resource)(DtwResource *self,const char *key, unsigned char *element, long size);
void (*set_string_in_sub_resource)(DtwResource *self,const char *key,const char *element);
void (*set_long_in_sub_resource)(DtwResource *self,const char *key,long element);
void (*set_double_in_sub_resource)(DtwResource *self,const char *key,double element);
void (*set_bool_in_sub_resource)( DtwResource *self,const char *key,bool element);
void (*set_binary_sha)(DtwResource *self, unsigned char *value, long size);
void (*set_string_sha)(DtwResource *self,const char *value);
void (*set_binary_sha_in_sub_resource)(DtwResource *self,const char *key, unsigned char *value, long size);
void (*set_string_sha_in_sub_resource)(DtwResource *self,const char *key,const char *value);
DtwResource * (*new_schema_insertion)(DtwResource *self);
DtwResource *(*find_by_name_id)(DtwResource *self, const char *name);
DtwResource * (*find_by_primary_key_with_binary)(DtwResource *self, const char *primary_key, unsigned char *value, long size);
DtwResource * (*find_by_primary_key_with_string)(DtwResource *self, const char *key, const char *value);
void (*dangerous_remove_schema_prop)(DtwResource*self,const char *prop);
void (*dangerous_rename_schema_prop)(DtwResource*self,const char *prop,const char *new_name);
DtwDatabaseSchema * (*newDatabaseSchema)(DtwResource *self);
char * (*get_error_path)(DtwResource *self);
DtwResourceArray * (*get_schema_values)(DtwResource *self);
DtwResource * (*sub_resource_ensuring_not_exist)(DtwResource *self,const char *format, ...);
DtwResource * (*sub_resource_next)(DtwResource *self, const char *end_path);
DtwResource * (*sub_resource_now)(DtwResource *self, const char *end_path);
DtwResource * (*sub_resource_now_in_unix)(DtwResource *self,const char *end_path);
DtwResource * (*sub_resource_random)(DtwResource *self,const char *end_path);
void (*load)(DtwResource *self);
void (*unload)(DtwResource *self);
int (*lock)(DtwResource *self);
void (*unlock)(DtwResource *self);
void (*destroy)(DtwResource *self);
void (*clear_errors)(DtwResource *self);
unsigned char *(*get_any)(struct DtwResource *self, long *size, bool *is_binary);
unsigned char *(*get_binary)(struct DtwResource *self, long *size);
char *(*get_string)(struct DtwResource *self);
long (*get_long)(struct DtwResource *self);
double (*get_double)(struct DtwResource *self);
bool (*get_bool)(struct DtwResource *self);
void (*set_any)(DtwResource *self, unsigned char *element, long size,bool is_binary);
void (*set_binary)(DtwResource *self, unsigned char *element, long size);
void (*set_string)(DtwResource *self,const char *element);
void (*set_long)(DtwResource *self,long element);
void (*set_double)(DtwResource *self,double element);
void (*set_bool)(DtwResource *self,bool element);
DtwStringArray *(*list_names)(DtwResource *self);
long (*size)(DtwResource *self);
int (*type)(DtwResource *self);
const char *(*type_in_str)(DtwResource *self);
void (*commit)(DtwResource *self);
void (*represent)(DtwResource *self);
void (*rename)(DtwResource *self,const char *new_name);
void (*free)(DtwResource *self);
DtwResourceArray * (*sub_resources)(DtwResource *self);
DtwResourceArrayModule array;
}DtwResourceModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct {
void (*add_primary_key)(DtwSchema *self, const char *primary_key);
DtwSchema * (*sub_schema)(DtwSchema *self,const char *name);
}DtwSchemaModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwStringArrayModule{
DtwStringArray *(*newStringArray)();
void (*set_value)(struct DtwStringArray *self,int index,const char *value);
void (*append)(struct DtwStringArray *self,const char *string);
void (*pop)(struct DtwStringArray *self, int position);
void (*merge)(struct DtwStringArray *self, struct DtwStringArray *other);
void (*represent)(struct DtwStringArray *self);
int (*find_position)(struct DtwStringArray *self,const char *string);
void (*sort)(struct DtwStringArray *self);
void (*free)(struct DtwStringArray *self);
}DtwStringArrayModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwActionTransactionModule{
DtwActionTransaction *(*newAction)();
DtwActionTransaction * (*write_any)(const char *source,unsigned char *content,long size,bool is_binary);
DtwActionTransaction * (*move_any)(const char *source, const char *dest);
DtwActionTransaction * (*move_any_merging)(const char *source, const char *dest);
DtwActionTransaction * (*copy_any_merging)(const char *source, const char *dest);
DtwActionTransaction * (*copy_any)(const char *source, const char *dest);
DtwActionTransaction * (*delete_any)(const char *source);
short (*convert_action_to_integer)(char *action);
const char * (*convert_action_to_string)(int action);
void (*commit)(DtwActionTransaction* self,const char *path);
void (*represent)(DtwActionTransaction* self);
void (*free)(DtwActionTransaction* self);
}DtwActionTransactionModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwJsonTransactionErrorModule{
void (*represent)(struct DtwJsonTransactionError *self);
void (*free)(struct DtwJsonTransactionError *self);
}DtwJsonTransactionErrorModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwTransactionModule{
DtwTransaction *(*newTransaction)();
DtwTransaction * (*newTransaction_from_json)(cJSON *json_entry);
DtwTransaction * (*newTransaction_from_json_file)(const char *filename);
DtwJsonTransactionError * (*validate_json_transaction_file)(const char *filename);
void (*set_encryption)(DtwTransaction *self,DtwEncriptionInterface *encryption,short encryption_mode);
void (*remove_from_index)(DtwTransaction *self,long index);
void (*remove_from_source)(DtwTransaction *self,const char *source);
void (*filter)(DtwTransaction *self,bool (*callback)(DtwActionTransaction *action));
void (*append_action)(struct DtwTransaction *self,struct DtwActionTransaction *action);
void (*write_any)(struct DtwTransaction *self,const char *path,unsigned char *content, long size,bool is_binary);
void (*write_string)(struct DtwTransaction *self,const char *path,const char *content);
void (*write_long)(struct DtwTransaction *self,const char *path,long value);
void (*write_bool)(struct DtwTransaction *self,const char *path,bool value);
void (*write_double)(struct DtwTransaction *self,const char *path,double value);
void (*move_any_merging)(struct DtwTransaction *self,const char *source,const char *dest);
void (*copy_any_merging)(struct DtwTransaction *self,const char *source,const char *dest);
void (*move_any)(struct DtwTransaction *self,const char *source,const char *dest);
void (*copy_any)(struct DtwTransaction *self,const char *source,const char *dest);
void (*delete_any)(struct DtwTransaction *self,const char *source);
cJSON *(*dumps_transaction_to_json)(struct DtwTransaction *self);
void (*dumps_transaction_to_json_file)(struct DtwTransaction *self,const char *filename);
void (*commit)(struct DtwTransaction *self,const char *source);
void (*represent)(struct DtwTransaction *self);
void (*free)(struct DtwTransaction *self);
DtwActionTransactionModule action;
DtwJsonTransactionErrorModule json_error;
}DtwTransactionModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwJsonTreeErrorModule{
DtwJsonTreeError * (*validate_json_tree_by_cJSON)(cJSON *json_tree);
DtwJsonTreeError * (*validate_json_tree_by_content)(const char *content);
void (*free)(struct DtwJsonTreeError *self);
void (*represent)(struct DtwJsonTreeError *self);
}DtwJsonTreeErrorModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwTreeTransactionReportModule{
void (*represent)(struct DtwTreeTransactionReport *report);
void (*free)(struct DtwTreeTransactionReport *report);
}DtwTreeTransactionReportModule;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwTreePartModule{
DtwTreePart *(*newPart)(const char *path, DtwTreeProps props);
DtwTreePart *(*newPartEmpty)(const char *path);
DtwTreePart * (*newPartLoading)(const char *path);
char *(*get_content_string_by_reference)(struct DtwTreePart *self);
unsigned char *(*get_content_binary_by_reference)(struct DtwTreePart *self);
char *(*get_content_sha)(struct DtwTreePart *self);
void (*set_any_content)(struct DtwTreePart *self,unsigned char *content,long content_size,bool is_binary);
void (*set_string_content)(struct DtwTreePart *self,const char *content);
void (*set_binary_content)(struct DtwTreePart *self,unsigned char *content,long content_size);
void (*load_content_from_hardware)(struct DtwTreePart *self);
void (*free_content)(struct DtwTreePart *self);
void(*represent)(struct DtwTreePart *self);
bool(*hardware_remove)(struct DtwTreePart *self, int transaction);
bool(*hardware_write)(struct DtwTreePart *self, int transaction);
bool(*hardware_modify)(struct DtwTreePart *self, int transaction);
bool(*hardware_commit)(struct DtwTreePart *self);
void (*free)(struct DtwTreePart *self);
struct DtwTreePart *(*self_copy)(struct DtwTreePart *self);
}DtwTreePartModule;
#endif
#ifndef doTHeWorld_typesj
#define doTHeWorld_typesj
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwTreeModule{
DtwTree *(*newTree)();
void (*add_tree_part_by_copy)(
DtwTree *self,
DtwTreePart *tree_part
);
void (*remove_tree_part)(
DtwTree *self,
int position
);
void (*add_tree_part_getting_owenership)(
DtwTree *self,
DtwTreePart *tree_part
);
void (*add_tree_part_referencing)(
DtwTree *self,
DtwTreePart *tree_part
);
void (*add_tree_parts_from_string_array)(
struct DtwTree *self,
struct DtwStringArray *paths,
DtwTreeProps props
);
struct DtwTree *(*get_sub_tree)(
struct DtwTree *self,
const char *path,
bool copy_content
);
void (*add_tree_from_hardware)(
struct DtwTree *self,
const char *path,
DtwTreeProps props
);
//Listage Functions
DtwTreePart *(*find_tree_part_by_function)(
struct DtwTree *self,
bool (*caller)(struct DtwTreePart *part,void *args),
void *args
);
DtwTree *(*filter)(
struct DtwTree *self,
bool (*caller)(struct DtwTreePart *part)
);
DtwTree *(*map)(
struct DtwTree *self,
struct DtwTreePart*(*caller)(struct DtwTreePart *part)
);
DtwStringArray * (*list_files)(struct DtwTree *self, const char *path,bool concat_path);
DtwStringArray * (*list_dirs)(struct DtwTree *self, const char *path,bool concat_path);
DtwStringArray * (*list_all)(struct DtwTree *self, const char *path,bool concat_path);
DtwStringArray * (*list_files_recursively)(struct DtwTree *self, const char *path,bool concat_path);
DtwStringArray * (*list_dirs_recursively)(struct DtwTree *self, const char *path,bool concat_path);
DtwStringArray * (*list_all_recursively)(struct DtwTree *self, const char *path,bool concat_path);
struct DtwTreePart *(*find_tree_part_by_name)( struct DtwTree *self,const char *name);
struct DtwTreePart *(*find_tree_part_by_path)( struct DtwTree *self,const char *path);
struct DtwTreeTransactionReport * (*create_report)(struct DtwTree *self);
bool (*loads_json_tree)(
struct DtwTree *self,
const char *content
);
bool (*loads_json_tree_from_file)(
struct DtwTree *self,
const char *path
);
char *(*dumps_json_tree)(
struct DtwTree *self,
DtwTreeProps props
);
void (*dumps_json_tree_to_file)(
struct DtwTree *self,
const char *path,
DtwTreeProps props
);
void (*represent)(struct DtwTree *self);
void (*insecure_hardware_remove_tree)(struct DtwTree *self);
void (*insecure_hardware_write_tree)(struct DtwTree *self);
void (*hardware_commit_tree)(struct DtwTree *self);
void (*free)(struct DtwTree *self);
DtwTreeTransactionReportModule transaction_report;
DtwTreePartModule part;
DtwJsonTreeErrorModule json_error;
}DtwTreeModule;
#endif
#ifndef doTHeWorld_typesm
#define doTHeWorld_typesm
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct DtwNamespace{
//IO
void (*create_dir_recursively)(const char *path);
bool (*remove_any)(const char* path);
char *(*get_current_dir)();
unsigned char *(*load_any_content)(const char * path,long *size,bool *is_binary);
char *(*get_absolute_path)(const char *path);
char *(*load_string_file_content)(const char * path);
unsigned char *(*load_binary_content)(const char * path,long *size);
bool (*write_any_content)(const char *path,unsigned char *content,long size);
bool (*write_string_file_content)(const char *path,const char *content);
int (*entity_type)(const char *path);
int (*complex_entity_type)(const char *path);
const char *(*convert_entity)(int entity_type);
bool (*copy_any)(const char* src_path,const char* dest_path,bool merge);
bool (*move_any)(const char* src_path, const char* dest_path,bool merge);
//numeral io
long (*load_long_file_content)(const char * path);
double (*load_double_file_content)(const char * path);
bool (*load_bool_file_content)(const char * path);
void (*write_long_file_content)(const char *path, long value);
void (*write_bool_file_content)(const char *path, bool value);
void (*write_double_file_content)(const char *path,double value);
//listage
DtwStringArray * (*list_files)(const char *path, bool concat_path);
DtwStringArray * (*list_dirs)(const char *path, bool concat_path);
DtwStringArray * (*list_all)(const char *path, bool concat_path);
DtwStringArray * (*list_dirs_recursively)(const char *path,bool concat_path);
DtwStringArray * (*list_files_recursively)(const char *path,bool concat_path);
DtwStringArray * (*list_all_recursively)(const char *path,bool concat_path);
//extras
char * (*generate_sha_from_file)(const char *path);
char * (*generate_sha_from_string)(const char *string);
char * (*generate_sha_from_any)(void *anything , long size);
long int (*get_entity_last_motification_in_unix)(const char *path);
char * (*convert_unix_time_to_string)(long int unix_time);
char * (*get_entity_last_motification_in_string)(const char *path);
char *(*concat_path)(const char *path1, const char *path2);
//base64
char *(*base64_encode)(unsigned char *data, long input_length);
unsigned char *(*base64_decode)(const char *data, long *output_length);
char *(*convert_binary_file_to_base64)(const char *path);
//string array
DtwStringArrayModule string_array;
DtwEncryptionNamespace encryption;
DtwPathModule path;
DtwLockerModule locker;
DtwSchemaModule schema;
DtwDatabaseSchemaModule database_schema;
DtwTreeModule tree;
DtwHashModule hash;
DtwTransactionModule transaction;
DtwResourceModule resource;
DtwRandonizerModule randonizer;
}DtwNamespace;
#endif
#ifndef doTHeWorld_fdeclare
#define doTHeWorld_fdeclare
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char *dtw_base64_encode(unsigned char *data, long input_length);
unsigned char *dtw_base64_decode(const char *data, long *output_length);
char *dtw_convert_binary_file_to_base64(const char *path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void privteDtwAES_CBC_EncryptionInterface_encrypt_buffer(privateDtwAES_RAW_EncryptionInterface *self,uint8_t* buf, uint32_t length);
void privteDtwAES_CBC_EncryptionInterface_decrypt_buffer(privateDtwAES_RAW_EncryptionInterface *self,uint8_t* buf, uint32_t length);
DtwEncriptionInterface *newDtwAES_CBC_EncryptionInterface(const uint8_t* key,int key_size,const uint8_t *iv, int iv_size);
DtwEncriptionInterface *newDtwAES_CBC_EncryptionInterface_str(const char* key,const char *iv);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void privteDtwAES_ECB_EncryptionInterface_encrypt_buffer(privateDtwAES_RAW_EncryptionInterface *self,uint8_t* buf, uint32_t length);
void privteDtwAES_ECB_EncryptionInterface_decrypt_buffer(privateDtwAES_RAW_EncryptionInterface *self,uint8_t* buf, uint32_t length);
DtwEncriptionInterface *newDtwAES_ECB_EncryptionInterface(const uint8_t* key,int key_size);
DtwEncriptionInterface *newDtwAES_ECB_EncryptionInterface_str(const char* key);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
unsigned char * privateDtwAES_RAW_EncryptionInterface_encrypt_buffer(void *obj, unsigned char *value,long size,long *out_size);
unsigned char *privateDtwAES_RAW_EncryptionInterface_decrypt_buffer(void *obj, unsigned char *encrypted_value,long size,long *out_size);
void privateDtwAES_RAW_EncryptionInterface_free_obj(void *obj);
DtwEncriptionInterface *newDtwAES_RAW_EncryptionInterface(const uint8_t* key,int key_size);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char *DtwEncriptionInterface_encrypt_buffer_b64(DtwEncriptionInterface *self, unsigned char *value,long size);
unsigned char *DtwEncriptionInterface_decrypt_buffer_b64(DtwEncriptionInterface *self, const char *encrypted_value,long *out_size,bool *is_binary);
bool DtwEncriptionInterface_write_any_content_b64(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size);
bool DtwEncriptionInterface_write_string_file_content_b64(DtwEncriptionInterface *self,const char *file_name,const char *value);
unsigned char *DtwEncriptionInterface_load_any_content_b64(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary);
char *DtwEncriptionInterface_load_string_file_content_b64(DtwEncriptionInterface *self,const char *file_name);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwEncriptionInterface *newDtwEncriptionInterface_raw(void *obj, unsigned char *(*encrypt_buffer)(void *obj, unsigned char *value,long size,long *out_size), unsigned char *(*decrypt_buffer)(void *obj, unsigned char *encrypted_value,long size,long *out_size), void (*free_obj)(void *obj));
unsigned char *DtwEncriptionInterface_encrypt_buffer(DtwEncriptionInterface *self, unsigned char *value,long size,long *out_size);
unsigned char *DtwEncriptionInterface_decrypt_buffer(DtwEncriptionInterface *self, unsigned char *encrypted_value,long size,long *out_size,bool *is_binary);
void DtwEncriptionInterface_free(DtwEncriptionInterface *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool DtwEncriptionInterface_write_any_content(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size);
bool DtwEncriptionInterface_write_string_file_content(DtwEncriptionInterface *self,const char *file_name,const char *value);
unsigned char *DtwEncriptionInterface_load_any_content(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary);
char *DtwEncriptionInterface_load_string_file_content(DtwEncriptionInterface *self,const char *file_name);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char *DtwEncriptionInterface_encrypt_buffer_hex(DtwEncriptionInterface *self, unsigned char *value,long size);
unsigned char *DtwEncriptionInterface_decrypt_buffer_hex(DtwEncriptionInterface *self, const char *encrypted_value,long *out_size,bool *is_binary);
bool DtwEncriptionInterface_write_any_content_hex(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size);
bool DtwEncriptionInterface_write_string_file_content_hex(DtwEncriptionInterface *self,const char *file_name,const char *value);
unsigned char *DtwEncriptionInterface_load_any_content_hex(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary);
char *DtwEncriptionInterface_load_string_file_content_hex(DtwEncriptionInterface *self,const char *file_name);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool private_DtwEncriptionInterface_write_any_content_custom_mode(DtwEncriptionInterface *self,const char *file_name,unsigned char *value,long size,short mode);
unsigned char *private_DtwEncriptionInterface_load_any_content_custom_mode(DtwEncriptionInterface *self,const char *file_name,long *out_size,bool *is_binary,short mode);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char * dtw_generate_sha_from_file(const char *path);
char * dtw_generate_sha_from_string(const char *string);
char * dtw_generate_sha_from_any(void *anything , long size);
long int dtw_get_entity_last_motification_in_unix(const char *path);
char * dtw_convert_unix_time_to_string(long int unix_time);
char * dtw_get_entity_last_motification_in_string(const char *path);
const char * private_dtw_convert_action_to_string(short action);
short private_dtw_convert_string_to_action(const char *action);
void private_dtw_add_end_bar_to_dirs_string_array(struct DtwStringArray * dirs);
long private_dtw_convert_index(long index,long size);
long dtw_get_time();
char *dtw_convert_binary_to_hex(unsigned char *value,long size);
unsigned char *dtw_convert_hex_to_binary(const char *value,long *out_size);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwHash * newDtwHash();
bool DtwHash_digest_any(DtwHash *self,unsigned char *content,long size);
bool DtwHash_digest_string(DtwHash * self, const char *content);
void DtwHash_digest_long(DtwHash * self,long content);
void DtwHash_digest_double(DtwHash * self,double content);
void DtwHash_digest_bool(DtwHash * self,bool content);
bool DtwHash_digest_file(DtwHash * self, const char *path);
bool DtwHash_digest_entity_last_modification(DtwHash * self, const char *path);
bool DtwHash_digest_folder_by_last_modification(DtwHash *self,const char *path);
bool DtwHash_digest_folder_by_content(DtwHash *self,const char *path);
bool DtwHash_digest_string_array(DtwHash *self,DtwStringArray *element);
bool DtwHash_digest_string_array_last_modifications(DtwHash *self,DtwStringArray *element);
bool DtwHash_digest_string_array_last_modifications_adding_name(DtwHash *self,DtwStringArray *element);
bool DtwHash_digest_string_array_content(DtwHash *self,DtwStringArray *element);
bool DtwHash_digest_string_array_content_adding_name(DtwHash *self,DtwStringArray *element);
void DtwHash_free(DtwHash *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void dtw_create_dir_recursively(const char *path);
bool dtw_remove_any(const char* path);
char *dtw_get_current_dir();
long dtw_get_total_itens_of_dir(const char *path);
unsigned char *dtw_load_any_content(const char * path,long *size,bool *is_binary);
char *dtw_get_absolute_path(const char *path);
char *dtw_load_string_file_content(const char * path);
unsigned char *dtw_load_binary_content(const char * path,long *size);
bool dtw_write_any_content(const char *path,unsigned char *content,long size);
bool dtw_write_string_file_content(const char *path,const char *content);
int dtw_entity_type(const char *path);
int dtw_complex_entity_type(const char *path);
const char *dtw_convert_entity(int entity_type);
bool dtw_copy_any(const char* src_path,const char* dest_path,bool merge);
bool dtw_move_any(const char* src_path, const char* dest_path,bool merge);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwStringArray * dtw_list_files(const char *path, bool concat_path);
DtwStringArray * dtw_list_dirs(const char *path, bool concat_path);
DtwStringArray * dtw_list_all(const char *path, bool concat_path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
DtwFlockLocker * newFlockLocker();
void private_FlockLocker_unlock_by_index(DtwFlockLocker *self, int index);
void DtwFlockLocker_unlock(DtwFlockLocker *self, const char *filename);
int DtwFlockLocker_lock(DtwFlockLocker *self, const char *filename);
void DtwFlockLocker_represent(DtwFlockLocker *self);
void DtwFlockLocker_free(DtwFlockLocker *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
privateDtwFlockArray * private_new_privateFlockArray();
int privateDtwFlockArray_index_of(privateDtwFlockArray *self, const char *filename);
void privateDtwFlockArray_append(privateDtwFlockArray *self, const char *filename, int file_descriptor);
void privateDtwFlockArray_destroy_by_index(privateDtwFlockArray *self, int position);
void privateDtwFlockArray_represent(privateDtwFlockArray *self);
void privateDtwFlockArray_free(privateDtwFlockArray *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
privateDtwFlockLockedElement * private_new_privateDtwFlockLockedElement(const char *filename, int file_descriptor);
void privateDtwFlockLockedElement_represent(privateDtwFlockLockedElement *self);
void privateDtwFlockLockedElement_free(privateDtwFlockLockedElement *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwLocker *newDtwLocker();
int DtwLocker_lock(DtwLocker *self, const char *element);
void DtwLocker_unlock(DtwLocker *self, const char *element);
void DtwLocker_represemt(DtwLocker *self);
void DtwLocker_free(DtwLocker *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwMultiFileLocker *newDtwMultiFileLocker();
int DtwMultiFIleLocker_lock(DtwMultiFileLocker *self, const char *element);
void DtwMultifileLocker_unlock(DtwMultiFileLocker *self, const char *element);
void DtwMultiFileLocker_represemt(DtwMultiFileLocker *self);
void DtwMultiFileLocker_free(DtwMultiFileLocker *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
bool private_dtw_verify_if_add(const int expected_type, int d_type);
bool private_dtw_verify_if_skip(struct dirent *entry);
#endif
#ifdef _WIN32
bool private_dtw_verify_if_add(const int expected_type, WIN32_FIND_DATAA entry);
bool private_dtw_verify_if_skip(WIN32_FIND_DATAA *entry);
#endif
struct DtwStringArray * dtw_list_basic(const char *path,int expected_type,bool concat_path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwStringArray * dtw_list_dirs_recursively(const char *path,bool concat_path);
DtwStringArray * dtw_list_files_recursively(const char *path,bool concat_path);
DtwStringArray * dtw_list_all_recursively(const char *path,bool concat_path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwDatabaseSchemaModule newDtwDatabaseSchemaModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwEncryptionNamespace newDtwEncryptionNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwHashModule newDtwHashModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwLockerModule newDtwLockerModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwNamespace newDtwNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwPathModule newDtwPathModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwRandonizerModule newDtwRandonizerModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourceArrayModule newDtwResourceArrayModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourceModule newDtwResourceModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwSchemaModule newDtwSchemaModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwStringArrayModule newDtwStringArrayModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwActionTransactionModule newDtwActionTransactionModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwJsonTransactionErrorModule newDtwJsonTransactionErrorModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTransactionModule newDtwTransactionModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwJsonTreeErrorModule newDtwJsonTreeErrorModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTreeTransactionReportModule newDtwTreeTransactionReportModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTreeModule newDtwTreeModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTreePartModule newDtwTreePartModule();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
long dtw_load_long_file_content_setting_error(const char *path,int *error);
long dtw_load_long_file_content(const char * path);
double dtw_load_double_file_content_setting_error(const char * path, int *error);
double dtw_load_double_file_content(const char * path);
bool dtw_load_bool_file_content_setting_error(const char * path, int *error);
bool dtw_load_bool_file_content(const char * path);
void dtw_write_long_file_content(const char *path, long value);
void dtw_write_bool_file_content(const char *path, bool value);
void dtw_write_double_file_content(const char *path,double value);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwPath * newDtwPath(const char *path);
bool DtwPath_changed(struct DtwPath *self);
void DtwPath_represent(struct DtwPath *self);
void DtwPath_free(struct DtwPath *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char * DtwPath_get_name(DtwPath *self);
char * DtwPath_get_extension(struct DtwPath *self);
char * DtwPath_get_full_name(struct DtwPath *self);
char * DtwPath_get_dir(struct DtwPath *self);
char * DtwPath_get_path(struct DtwPath *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int DtwPath_get_total_dirs(DtwPath *self);
char *DtwPath_get_sub_dirs_from_index(DtwPath *self, int start, int end);
int private_dtw_count_dirs_before(const char *dirs,int index);
void DtwPath_insert_dir_at_index(DtwPath *self, int index, const char *dir);
void DtwPath_remove_sub_dirs_at_index(DtwPath *self, int start, int end);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void DtwPath_insert_dir_after(DtwPath *self,const char *str,const char *dir);
void DtwPath_insert_dir_before(DtwPath *self,const char *str,const char *dir);
void DtwPath_remove_sub_dirs_at(DtwPath *self,const char *str);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void DtwPath_set_extension(struct DtwPath *self, const char *extension);
void DtwPath_set_name(struct DtwPath * self, const char * name);
void DtwPath_set_full_name(struct DtwPath * self, const char * full_name);
void DtwPath_set_dir(struct DtwPath *self, const char *dir);
void DtwPath_set_path(struct DtwPath *self, const char *target_path);
void DtwPath_add_start_dir(struct DtwPath *self, const char *start_dir);
void DtwPath_add_end_dir(struct DtwPath *self, const char *end_dir);
void DtwPath_replace_dirs(DtwPath *self,const char *str,const char *dir);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwRandonizer * newDtwRandonizer();
int DtwRandonizer_generate_num(DtwRandonizer *self,int max);
char * DtwRandonizer_generate_token(struct DtwRandonizer*self, int size);
void DtwRandonizer_free(struct DtwRandonizer *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwDatabaseSchema *private_newDtwDtatabaseSchema();
DtwSchema * privateDtwDtatabaseSchema_get_sub_schema(DtwDatabaseSchema *self,const char *name);
DtwSchema * DtwDtatabaseSchema_new_subSchema(DtwDatabaseSchema *self,const char *name);
void private_new_DtwDtatabaseSchema_free(DtwDatabaseSchema *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResource *new_DtwResource(const char *path);
DtwResource * DtwResource_sub_resource(DtwResource *self,const char *format, ...);
DtwResource * DtwResource_sub_resource_ensuring_not_exist(DtwResource *self,const char *format, ...);
void DtwResource_free(DtwResource *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResource * DtwResource_sub_resource_next(DtwResource *self, const char *end_path);
DtwResource * DtwResource_sub_resource_now(DtwResource *self, const char *end_path);
DtwResource * DtwResource_sub_resource_now_in_unix(DtwResource *self, const char *end_path);
DtwResource * DtwResource_sub_resource_random(DtwResource *self, const char *end_path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_DtwResurce_destroy_primary_key(DtwResource *self);
void private_DtwResource_destroy_all_primary_keys(DtwResource *self);
void DtwResource_destroy(DtwResource *self);
void DtwResource_destroy_sub_resource(DtwResource *self, const char *key);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool DtwResource_error(DtwResource *self);
int DtwResource_get_error_code(DtwResource *self);
void DtwResource_set_encryption(DtwResource *self,DtwEncriptionInterface *encryption_interface,short mode);
char * DtwResource_get_error_message(DtwResource *self);
char * DtwResource_get_error_path(DtwResource *self);
void DtwResource_clear_errors(DtwResource *self);
void private_DtwResource_raise_error(DtwResource *self, int error_code, const char *format,...);
void DtwResource_rename(DtwResource *self,const char *new_name);
void DtwResource_rename_sub_resource(DtwResource *self,const char *old_name,const char *new_name);
int DtwResource_lock(DtwResource *self);
void DtwResource_unlock(DtwResource *self);
void DtwResource_commit(DtwResource *self);
long DtwResource_size(DtwResource *self);
DtwStringArray *DtwResource_list_names(DtwResource *self);
int DtwResource_type(DtwResource *self);
bool DtwResource_is_file(DtwResource *self);
const char * DtwResource_type_in_str(DtwResource *self);
void DtwResource_represent(DtwResource *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
unsigned char *DtwResource_get_any(DtwResource *self, long *size, bool *is_binary);
unsigned char *DtwResource_get_any_from_sub_resource(DtwResource *self, long *size, bool *is_binary,const char *format,...);
unsigned char *DtwResource_get_binary(DtwResource *self, long *size);
unsigned char *DtwResource_get_binary_from_sub_resource(DtwResource *self, long *size,const char *format,...);
char *DtwResource_get_string(DtwResource *self);
char *DtwResource_get_string_from_sub_resource(DtwResource *self,const char *format,...);
long DtwResource_get_long(DtwResource *self);
long DtwResource_get_long_from_sub_resource(DtwResource *self,const char *format,...);
double DtwResource_get_double(DtwResource *self);
double DtwResource_get_double_from_sub_resource(DtwResource *self,const char *format,...);
bool DtwResource_get_bool(DtwResource *self);
bool DtwResource_get_bool_from_sub_resource(DtwResource *self,const char *format,...);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourceForeachProps DtwResource_create_foreach_props( void(*callback)(DtwResource *item, void *args));
void DtwResource_foreach(DtwResource *self,DtwResourceForeachProps props);
void DtwResource_schema_foreach(DtwResource *self,DtwResourceForeachProps props);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef DTW_ALLOW_CHASH
DtwResourceCHashrrayMapProps DtwResource_create_CHashrrayMapProps( CHash *(*callback)(DtwResource *item, void *args));
CHashArray *DtwResource_map_CHashArray(DtwResource *self,DtwResourceCHashrrayMapProps props);
CHashArray *DtwResource_schema_map_CHashArray(DtwResource *self,DtwResourceCHashrrayMapProps props);
void *private_dtw_CHashArray_callback(DtwResource *item,void *args);
bool private_dtw_CHashArray_filtrage(DtwResource *item,void *args);
int private_dtw_CHashArray_ordenation(DtwResource *item1,DtwResource *item2,void *args);
void privateDtwResource_add_to_item_to_CHashArray_array(void* array, void *item);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef DTW_ALLOW_CHASH
DtwResourceCHashObjectMapProps DtwResource_createCHashObjectMapProps(
CHash *(*callback)(DtwResource *item, void *args),
char *(*filtrage_callback)(DtwResource *item, void *args_filter)
);
CHash *DtwResource_map_CHashObject(DtwResource *self,DtwResourceCHashObjectMapProps props);
CHash *DtwResource_schema_map_CHashObject(DtwResource *self,DtwResourceCHashObjectMapProps props);
void *private_dtw_CHashArray_callback(DtwResource *item,void *args);
bool private_dtw_CHashArray_filtrage(DtwResource *item,void *args);
int private_dtw_CHashArray_ordenation(DtwResource *item1,DtwResource *item2,void *args);
void privateDtwResource_add_to_item_to_CHashObject(void* object, void *item);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourcecJSONArrayMapProps DtwResource_create_cJSONArrayMapProps(cJSON *(*callback)(DtwResource *item, void *args));
cJSON *DtwResource_map_cJSONArray(DtwResource *self,DtwResourcecJSONArrayMapProps props);
cJSON *DtwResource_schema_map_cJSONArray(DtwResource *self,DtwResourcecJSONArrayMapProps props);
void *private_dtw_cJSONArray_callback(DtwResource *item,void *args);
bool private_dtw_cJSONArray_filtrage(DtwResource *item,void *args);
int private_dtw_cJSONArray_ordenation(DtwResource *item1,DtwResource *item2,void *args);
void privateDtwResource_add_to_item_to_cJSONArray_array(void* array, void *item);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourcecJSONObjectMapProps DtwResource_create_cJSONObjectProps(
cJSON *(*callback)(DtwResource *item, void *args),
char *(*key_provider_callback)(DtwResource *item,void *args)
);
cJSON *DtwResource_map_cJSONObject(DtwResource *self,DtwResourcecJSONObjectMapProps props);
cJSON *DtwResource_schema_map_cJSONObject(DtwResource *self,DtwResourcecJSONObjectMapProps props);
void *private_dtw_cJSONArray_callback(DtwResource *item,void *args);
bool private_dtw_cJSONArray_filtrage(DtwResource *item,void *args);
int private_dtw_cJSONArray_ordenation(DtwResource *item1,DtwResource *item2,void *args);
void privateDtwResource_add_to_item_to_cJSONObject(void* object, void *item);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int private_dtwResource_compare(const void *item1,const void*item2);
DtwResourceMapProps DtwResource_create_map_props(
void *main_array,
void(*append)(void *main_array_arg, void *item),
void *(*callback)(DtwResource *item, void *args)
);
void DtwResource_map(DtwResource *self,DtwResourceMapProps props);
void DtwResource_schema_map(DtwResource *self,DtwResourceMapProps props);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void DtwResource_unload(DtwResource *self);
void DtwResource_load(DtwResource *self);
void DtwResource_load_if_not_loaded(DtwResource *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourceArray * DtwResource_get_schema_values(DtwResource *self);
DtwResourceArray * DtwResource_sub_resources(DtwResource *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool private_DtwResource_its_a_pk(DtwResource *self);
void privateDtwResource_ensure_its_possible_to_sub_resource(DtwResource *self);
DtwResource * DtwResource_new_schema_insertion(DtwResource *self);
DtwResource *DtwResource_find_by_name_id(DtwResource *self, const char *name);
DtwResource * DtwResource_find_by_primary_key_with_binary(DtwResource *self, const char *primary_key, unsigned char *value, long size);
DtwResource * DtwResource_find_by_primary_key_with_string(DtwResource *self, const char *key, const char *value);
void DtwResource_dangerous_remove_schema_prop(DtwResource*self,const char *prop);
void DtwResource_dangerous_rename_schema_prop(DtwResource*self,const char *prop,const char *new_name);
DtwDatabaseSchema * DtwResource_newDatabaseSchema(DtwResource *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_dtw_resource_set_primary_key(DtwResource *self, unsigned char *element, long size);
void DtwResource_set_any(DtwResource *self, unsigned char *element, long size,bool is_binary);
void DtwResource_set_binary(DtwResource *self, unsigned char *element, long size);
void DtwResource_set_string(DtwResource *self,const char *element);
void DtwResource_set_binary_sha(DtwResource *self, unsigned char *value, long size);
void DtwResource_set_string_sha(DtwResource *self,const char *value);
void DtwResource_set_long(DtwResource *self,long element);
void DtwResource_set_double(DtwResource *self,double element);
void DtwResource_set_bool( DtwResource *self,bool element);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void DtwResource_set_any_in_sub_resource(DtwResource *self,const char *key, unsigned char *element, long size,bool is_binary);
void DtwResource_set_binary_in_sub_resource(DtwResource *self,const char *key, unsigned char *element, long size);
void DtwResource_set_binary_sha_in_sub_resource(DtwResource *self, const char *key, unsigned char *value, long size);
void DtwResource_set_string_sha_in_sub_resource(DtwResource *self, const char *key, const char *value);
void DtwResource_set_string_in_sub_resource(DtwResource *self, const char *key, const char *element);
void DtwResource_set_long_in_sub_resource(DtwResource *self, const char *key, long element);
void DtwResource_set_double_in_sub_resource(DtwResource *self, const char *key, double element);
void DtwResource_set_bool_in_sub_resource(DtwResource *self,const char *key, bool element);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwResourceArray * newDtwResourceArray();
void DtwResourceArray_append(DtwResourceArray *self, DtwResource *element);
DtwResource * DtwResourceArray_get_by_name(DtwResourceArray *self, const char *name);
void DtwResourceArray_represent(DtwResourceArray *self);
void DtwResourceArray_free(DtwResourceArray *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
privateDtwResourceRootProps *private_newDtwResourceRootProps();
void privateDtwResourceRootProps_free(privateDtwResourceRootProps *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwSchema *private_newDtwSchema(const char *name);
DtwSchema * privateDtwSchema_get_sub_schema(DtwSchema *self,const char *name);
DtwSchema * (DtwSchema_new_subSchema)(DtwSchema *self,const char *name);
void DtwSchema_add_primary_key(DtwSchema *self,const char *name);
void private_newDtwSchema_free(DtwSchema *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char * calc_sha_256_returning_string(const void *input, size_t len);
void calc_sha_256_from_string(uint8_t hash[SIZE_OF_SHA_256_HASH], const char *input);
int calc_sha_256_from_file(uint8_t hash[SIZE_OF_SHA_256_HASH], const char *filename);
char * calc_sha_256_from_string_returning_string(const char *input);
char * calc_sha_256_from_file_returning_string(const char *filename);
char * sha256_open_file(const char *filename, int *size);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
// End the structure with a semicolon
int DtwStringArray_find_position( DtwStringArray *self, const char *string);
void DtwStringArray_append_getting_ownership( DtwStringArray *self, char *string);
void DtwStringArray_append( DtwStringArray *self, const char *string);
void DtwStringArray_pop( DtwStringArray *self, int position);
void DtwStringArray_merge( DtwStringArray *self, DtwStringArray *other);
void DtwStringArray_represent( DtwStringArray *self);
void DtwStringArray_free( DtwStringArray *self);
int private_dtw_string_cmp(const void *a, const void *b);
void DtwStringArray_sort( DtwStringArray *self);
void DtwStringArray_set_value( DtwStringArray *self, int index, const char *value);
DtwStringArray * newDtwStringArray();
char * privateDtwStringArray_append_if_not_included(DtwStringArray *self,char *value);
DtwStringArray * DtwStringArray_clone(DtwStringArray *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char *dtw_concat_path(const char *path1, const char *path2);
DtwStringArray* private_dtw_remove_start_path(struct DtwStringArray *paths,const char *path_to_remove);
char *private_dtw_format_path(const char *path);
void private_dtw_remove_double_bars_from_string_array(struct DtwStringArray*path);
char * private_dtw_format_vaarg(const char *expresion, va_list args);
char *private_dtw_realoc_formatting(char *ptr,const char *format,...);
char *private_dtw_formatt(const char *format,...);
char * private_dtw_sub_str(const char *str, long start,long end);
bool dtw_is_string_at_point(
const char *str,
long str_size,
const char *target,
long target_size,
long target_point
);
long dtw_index_of_string(const char *str,const char *element);
bool dtw_starts_with(const char *string, const char *prefix);
bool dtw_ends_with(const char *string, const char *suffix);
char *private_dtw_replace_string_once(const char *target, const char *old_element, const char *new_element);
char* dtw_replace_string(const char *target, const char *old_element, const char *new_element);
char *private_dtw_change_beginning_of_string(const char *target,int start_element_to_remove_size, const char *new_element);
double private_dtw_convert_string_to_number(const char *num, bool *its_a_number);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwActionTransaction *newDtwActionTransaction();
DtwJsonTransactionError * private_dtw_validate_json_action_transaction(cJSON *json_obj);
DtwActionTransaction * private_DtwActionTransaction_parse_json_object(cJSON *json_obj);
DtwActionTransaction * DtwActionTransaction_write_any(const char *source,unsigned char *content,long size,bool is_binary);
DtwActionTransaction * DtwActionTransaction_move_any(const char *source, const char *dest);
DtwActionTransaction * DtwActionTransaction_copy_any(const char *source, const char *dest);
DtwActionTransaction * DtwActionTransaction_move_any_merging(const char *source, const char *dest);
DtwActionTransaction * DtwActionTransaction_copy_any_merging(const char *source, const char *dest);
DtwActionTransaction * DtwActionTransaction_delete_any(const char *source);
short DtwActionTransaction_convert_action_to_integer(char *action);
const char * DtwActionTransaction_convert_action_to_string(int action);
cJSON * private_DtwActionTransaction_create_json_object(DtwActionTransaction* self);
void DtwActionTransaction_commit(DtwActionTransaction* self,const char *path);
void DtwActionTransaction_represent(DtwActionTransaction* self);
void DtwActionTransaction_free(DtwActionTransaction* self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwJsonTransactionError * private_new_DtwJsonTransactionError( int code,const char *mensage,const char *path);
void DtwJsonTransactionError_represent(struct DtwJsonTransactionError *self);
void DtwJsonTransactionError_prepend_path(struct DtwJsonTransactionError *self,char *path);
void DtwJsonTransactionError_free(struct DtwJsonTransactionError *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTransaction * newDtwTransaction();
DtwTransaction * newDtwTransaction_from_json(cJSON *json_entry);
DtwJsonTransactionError * dtw_validate_json_transaction(cJSON *json_entry);
DtwJsonTransactionError * dtw_validate_json_transaction_file(const char *filename);
DtwTransaction * newDtwTransaction_from_json_file(const char *filename);
void DtwTransaction_set_encryption(DtwTransaction *self,DtwEncriptionInterface *encryption,short encryption_mode);
void DtwTransaction_remove_from_index(DtwTransaction *self,long index);
void DtwTransaction_remove_from_source(DtwTransaction *self,const char *source);
void DtwTransaction_filter(DtwTransaction *self,bool (*callback)(DtwActionTransaction *action));
void DtwTransaction_append_action(struct DtwTransaction *self,struct DtwActionTransaction *action);
void DtwTransaction_write_any(struct DtwTransaction *self,const char *path,unsigned char *content, long size,bool is_binary);
void DtwTransaction_write_string(struct DtwTransaction *self,const char *path,const char *content);
void DtwTransaction_write_long(struct DtwTransaction *self,const char *path,long value);
void DtwTransaction_write_bool(struct DtwTransaction *self,const char *path,bool value);
void DtwTransaction_write_double(struct DtwTransaction *self,const char *path,double value);
void DtwTransaction_move_any(struct DtwTransaction *self,const char *source,const char *dest);
void DtwTransaction_move_any_merging(struct DtwTransaction *self,const char *source,const char *dest);
void DtwTransaction_copy_any_merging(struct DtwTransaction *self,const char *source,const char *dest);
void DtwTransaction_copy_any(struct DtwTransaction *self,const char *source,const char *dest);
void DtwTransaction_delete_any(struct DtwTransaction *self,const char *source);
cJSON * DtwTransaction_dumps_to_json(struct DtwTransaction *self);
void DtwTransaction_dumps_to_json_file(struct DtwTransaction *self,const char *filename);
void DtwTransaction_commit(struct DtwTransaction *self,const char *path);
void DtwTransaction_represent(struct DtwTransaction *self);
void DtwTransaction_free(struct DtwTransaction *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwJsonTreeError * newDtwJsonError();
DtwJsonTreeError * DtwJsonTreeError_validate_json_tree_by_cJSON(cJSON *json_tree);
DtwJsonTreeError * DtwJsonTreeError_validate_json_tree_by_content(const char *content);
void DtwJsonTreeError_represent(struct DtwJsonTreeError *self);
void DtwJsonTreeError_free(struct DtwJsonTreeError *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
struct DtwTreeTransactionReport * newDtwTreeTransactionReport();
void DtwTreeTransactionReport_represent(struct DtwTreeTransactionReport *report);
void DtwTreeTransactionReport_free(struct DtwTreeTransactionReport *report);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTree *DtwTree_get_sub_tree(
DtwTree *self,
const char *path,
bool copy_content
);
DtwTreePart *DtwTree_find_tree_part_by_function(
DtwTree *self,
bool (*caller)( DtwTreePart *part,void *args),
void *args
);
DtwTree *DtwTree_map(DtwTree *self, DtwTreePart* (*caller)( DtwTreePart *part));
DtwTree *DtwTree_filter(DtwTree *self,bool (*caller)(struct DtwTreePart *part));
DtwTreePart *DtwTree_find_tree_part_by_name( DtwTree *self, const char *name);
DtwTreePart *DtwTree_find_tree_part_by_path( DtwTree *self, const char *path);
//listages
DtwStringArray *DtwTree_list_files( DtwTree *self, const char *path,bool concat_path);
DtwStringArray *DtwTree_list_dirs( DtwTree *self, const char *path,bool concat_path);
DtwStringArray *DtwTree_list_all( DtwTree *self, const char *path,bool concat_path);
DtwStringArray *DtwTree_list_files_recursively( DtwTree *self, const char *path,bool concat_path);
DtwStringArray *DtwTree_list_dirs_recursively( DtwTree *self, const char *path,bool concat_path);
DtwStringArray *DtwTree_list_all_recursively( DtwTree *self, const char *path,bool concat_path);
void DtwTree_remove_tree_part( DtwTree *self, int position);
void DtwTree_add_tree_part_copy( DtwTree *self, DtwTreePart *tree_part);
void DtwTree_add_tree_part_getting_onwership( DtwTree *self, DtwTreePart *tree_part);
void DtwTree_add_tree_part_referencing( DtwTree *self, DtwTreePart *tree_part);
void DtwTree_free( DtwTree *self);
void DtwTree_represent( DtwTree *self);
void DtwTree_add_tree_parts_from_string_array(DtwTree *self,DtwStringArray *paths,DtwTreeProps props);
void DtwTree_add_tree_from_hardware(DtwTree *self,const char *path,DtwTreeProps props);
DtwTreeTransactionReport * DtwTree_create_report( DtwTree *self);
void DtwTree_insecure_hardware_remove_tree( DtwTree *self);
void DtwTree_insecure_hardware_write_tree( DtwTree *self);
void DtwTree_hardware_commit_tree( DtwTree *self);
bool DtwTree_loads_json_tree( DtwTree *self, const char *content);
bool DtwTree_loads_json_tree_from_file( DtwTree *self, const char *path);
char * DtwTree_dumps_tree_json(DtwTree *self,DtwTreeProps props);
void DtwTree_dumps_tree_json_to_file(DtwTree *self,const char *path,DtwTreeProps props);
DtwTree * newDtwTree();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_DtwTreePart_set_last_modification(DtwTreePart *self,long last_modification);
char *DtwTreePart_get_content_string_by_reference( DtwTreePart *self);
unsigned char *DtwTreePart_get_content_binary_by_reference( DtwTreePart *self);
char *DtwTreePart_get_content_sha( DtwTreePart *self);
void DtwTreePart_set_any_content( DtwTreePart *self, unsigned char *content, long content_size, bool is_binary);
void DtwTreePart_set_string_content( DtwTreePart *self, const char *content);
void DtwTreePart_set_binary_content( DtwTreePart *self, unsigned char *content, long content_size);
void DtwTreePart_load_content_from_hardware( DtwTreePart *self);
void DtwTreePart_free_content( DtwTreePart *self);
void DtwTreePart_represent( DtwTreePart *self);
bool DtwTreePart_hardware_remove( DtwTreePart *self,int transaction);
bool DtwTreePart_hardware_write( DtwTreePart *self,int transaction);
bool DtwTreePart_hardware_modify( DtwTreePart *self,int transaction);
bool DtwTreePart_hardware_commit(struct DtwTreePart *self);
void DtwTreePart_free(struct DtwTreePart *self);
struct DtwTreePart * DtwTreePart_self_copy(struct DtwTreePart *self);
struct DtwTreePart * newDtwTreePart(const char *path, DtwTreeProps props);
struct DtwTreePart * newDtwTreePartEmpty(const char *path);
struct DtwTreePart * newDtwTreePartLoading(const char *path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
DtwTreeProps DtwTreeProps_format_props(DtwTreeProps props);
#endif
#ifndef SDK_OpenAI_dep
#define SDK_OpenAI_dep
#endif
#ifndef SDK_OpenAI_macros
#define SDK_OpenAI_macros
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define OPENAI_TYPE_IS_INVALID -1
#define OPENAI_TYPE_IS_NULL 0
#define OPENAI_TYPE_IS_OBJECT 1
#define OPENAI_TYPE_IS_ARRAY 2
#define OPENAI_TYPE_IS_STRING 3
#define OPENAI_TYPE_IS_NUMBER 4
#define OPENAI_TYPE_IS_BOOL 5
#endif
#ifndef SDK_OpenAI_types
#define SDK_OpenAI_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef cJSON OpenAiResponse;
#endif
#ifndef SDK_OpenAI_typesA
#define SDK_OpenAI_typesA
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiArgument{
const char *name_argument;
const char *type;
const char *description;
bool required;
}OpenAiArgument;
typedef struct OpenAiCallback{
char *(*Lambda)(cJSON *args, void *pointer);
const char *description;
long size_parameters;
OpenAiArgument **parameters;
const char *name_function;
char *index_name;
long index;
bool check_heap;
void *pointer;
}OpenAiCallback;
#endif
#ifndef SDK_OpenAI_typesB
#define SDK_OpenAI_typesB
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
struct OpenAiInterface{
int max_retrys;
#ifdef OPEN_AI_ALLOW_DTW
char *cache_dir;
bool cache_enabled;
bool preserve_meta_info;
#endif
BearHttpsRequest *request;
cJSON *messages;
int *temp_messages;
int total_temp_menssages;
int total_temp_messages_alocated;
cJSON *body_object;
cJSON *response_array;
long size_callbakcs;
OpenAiCallback **callbacks;
};
typedef struct OpenAiInterface OpenAiInterface;
#endif
#ifndef SDK_OpenAI_typesC
#define SDK_OpenAI_typesC
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiInterfaceNamespace {
OpenAiInterface * (*newOpenAiInterface)(const char *url, const char *apiKey,const char *model);
OpenAiResponse * (*get_response_by_index)(OpenAiInterface *self, long index);
///cache
#ifdef OPEN_AI_ALLOW_DTW
void (*set_cache)(OpenAiInterface *self,const char *cache_dir,bool preserve_meta_info);
void (*allow_cache)(OpenAiInterface *self);
void (*disallow_cache)(OpenAiInterface *self);
#endif
///prompts
void (*add_system_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_user_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_assistent_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_developer_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_tool_prompt)(OpenAiInterface *self, const char *id_call, const char *content);
///temp prompts
void (*add_temp_system_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_temp_user_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_temp_assistent_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_temp_developer_prompt)(OpenAiInterface *self, const char *prompt);
///configs
void (*set_know_ips)(OpenAiInterface *self, const char *url);
void (*set_max_tokens)(OpenAiInterface *self, float max_tokens);
void (*set_temperature)(OpenAiInterface *self, float temperature);
void (*set_model)(OpenAiInterface *self, const char *model);
void (*set_source_model)(OpenAiInterface *self, const char *source_model);
//extras
OpenAiResponse * (*make_question)(OpenAiInterface *self);
bool (*error)(OpenAiResponse *response);
char *(*get_error_message)(OpenAiResponse *response);
void (*add_response_to_history)(OpenAiInterface *self, OpenAiResponse *response,int choice);
void (*free)(OpenAiInterface *self);
} OpenAiInterfaceNamespace;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiResponseNamespace{
cJSON *(*get_choice)(OpenAiResponse *response, long choice);
cJSON * (*get_message)(OpenAiResponse *response,long choice);
cJSON *(*get_content)(OpenAiResponse *response, long choice);
const char * (*get_content_str)(OpenAiResponse *response,long choice);
bool (*error)(OpenAiResponse *response);
char *(*get_error_message)(OpenAiResponse *response);
}OpenAiResponseNamespace;
#endif
#ifndef SDK_OpenAI_typesD
#define SDK_OpenAI_typesD
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiNamespace{
OpenAiResponseNamespace response;
OpenAiInterfaceNamespace openai_interface;
}OpenAiNamespace;
#endif
#ifndef SDK_OpenAI_dec
#define SDK_OpenAI_dec
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef OPEN_AI_ALLOW_DTW
void OpenAiInterface_set_cache(OpenAiInterface *self,const char *cache_dir,bool preserve_meta_info);
void OpenAiInterface_allow_cache(OpenAiInterface *self);
void OpenAiInterface_disallow_cache(OpenAiInterface *self);
cJSON *private_OpenAiInterface_get_cache_answer(OpenAiInterface *self);
void privateOpenAiInterface_save_answer_cache(OpenAiInterface *self, cJSON *response);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int OpenAiInterface_add_callback_function_by_tools(
OpenAiInterface *self,
OpenAiCallback *callback
);
int OpenAiInterface_add_parameters_in_callback(
OpenAiCallback *callback,
const char *name_argument,
const char *description,
const char *type,
bool required
);
char *OpenAiInterface_run_callback_by_index(OpenAiInterface *self, const char *name_function, const char *args);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_set_know_ips(OpenAiInterface *self,const char *url);
void OpenAiInterface_set_max_tokens(OpenAiInterface *self, float temperature);
void OpenAiInterface_set_temperature(OpenAiInterface *bearOpenAi, float temperature);
void OpenAiInterface_set_model(OpenAiInterface *bearOpenAi, const char *model);
void OpenAiInterface_set_source_model(OpenAiInterface *bearOpenAi, const char *source_model);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool OpenAiResponse_error(OpenAiResponse *response);
char *OpenAiResponse_get_error_message(OpenAiResponse *response);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_raw_prompt(OpenAiInterface *self, cJSON *prompt, bool permanent);
void OpenAiInterface_add_default_prompt(OpenAiInterface *self,const char *role, const char *prompt, bool permanent);
void OpenAiInterface_add_system_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_user_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_assistent_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_developer_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_tool_prompt(OpenAiInterface *self, const char *id_call, const char *content);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponse * OpenAiInterface_make_question(OpenAiInterface *self);
OpenAiResponse *OpenAiInterface_make_question_finish_reason_treated(OpenAiInterface *self);
void OpenAiInterface_add_response_to_history(OpenAiInterface *self, OpenAiResponse *response,int choice);
void OpenAiInterface_add_response_to_history(OpenAiInterface *self, OpenAiResponse *response,int choice);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void privateOpenAiInterface_set_last_message_as_temp(OpenAiInterface *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_temp_system_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_temp_user_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_temp_assistent_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_temp_developer_prompt(OpenAiInterface *self, const char *prompt);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON *private_OpenAiInterface_create_tool_object(
OpenAiCallback *self,
const char *type,
bool additionalProperties,
bool strict
);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_tools_raw(OpenAiInterface *self, cJSON *object);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
long private_OpenAiExtra_extract_index(const char *input);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiCallback *new_OpenAiCallback(
char *(*Lambda)(cJSON *args, void *pointer),
void *pointer,
const char *name_func,
const char *description,
bool check_heap
);
void OpenAiCallback_free(OpenAiCallback *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiInterface * newOpenAiInterface(const char *url, const char *apiKey,const char *model);
void OpenAiInterface_free(OpenAiInterface *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiArgument *private_new_OpenAiArgument(
const char *name_argument,
const char *description,
const char *type,
bool required
);
void private_OpenAiArgument_free(OpenAiArgument *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiInterfaceNamespace newOpenAiInterfaceNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiNamespace newOpenAiNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponseNamespace newOpenAiResponseNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponse * OpenAiInterface_get_response_by_index(OpenAiInterface *self, long index);
cJSON *OpenAiResponse_get_choice(OpenAiResponse *response, long choice);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON * OpenAiResponse_get_message(OpenAiResponse *response,long choice);
cJSON *OpenAiResponse_get_content(OpenAiResponse *response, long choice);
const char * OpenAiResponse_get_content_str(OpenAiResponse *response,long choice);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON *OpenAiResponse_get_tool_calls(OpenAiResponse *response, long choice, long *size_array);
cJSON *OpenAiResponse_get_object_tool_calls(OpenAiResponse *response, long choice, long index);
const char *OpenAiResponse_get_id_tool_calls_by_index(OpenAiResponse *response, long choice, long index);
const char *OpenAiResponse_get_value_item_in_obj_tool_calls_function(OpenAiResponse *response, long choice, long index, const char *item);
const char *OpenAiResponse_get_name_func_tool_calls_by_index(OpenAiResponse *response, long choice, long index);
const char *OpenAiResponse_get_arguments_func_tool_calls_by_index(OpenAiResponse *response, long choice, long index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char *OpenAiResponse_get_finish_reason(OpenAiResponse *response, long choice);
bool OpenAiResponse_finish_reason_is_tool_calls(OpenAiResponse *response, long choice);
#endif
#endif
#ifndef PROJECT_NAME_macros
#define PROJECT_NAME_macros
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char *VERSION ="0.0.4";
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef __linux__
#define GREEN "\033[0;32m"
#define BLUE "\033[0;34m"
#define YELLOW "\033[0;33m"
#define RED "\033[0;31m"
#define RESET "\033[0m"
#define PURPLE "\033[0;35m"
#else
#define GREEN ""
#define BLUE ""
#define YELLOW ""
#define RED ""
#define RESET ""
#define PURPLE ""
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define release_if_not_null(ptr, releaser) if(ptr != NULL){releaser(ptr);}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef RagCraft_get_key_h
#define RagCraft_get_key_h
#define RagCraftkey_size 18
#define RagCraft_get_key(key) \
for(int i=0;i<18;i++){key[i] = 88.0;}\
key[18] = 0;\
for(int RagCraft_scope_0 = ( key[8] - key[5] - 26497.0 + 95461.0 + 28257.0); RagCraft_scope_0 < 97222; RagCraft_scope_0++){\
key[9] = ( 43571.0 + 34556.0 + key[10] - key[4] - key[7]) - 77925;/*set:114*/\
}\
int RagCraft_integer_1 = ( 34661.0 + key[6] - key[8] + key[10]);/*create:34749*/\
key[13] = ( RagCraft_integer_1 - RagCraft_integer_1 - RagCraft_integer_1) + 34865;/*set:116*/\
if(( key[5] + RagCraft_integer_1 - key[8] - key[4] - key[14]) > 34572){\
}\
key[4] = ( key[16] + RagCraft_integer_1 - key[10] + RagCraft_integer_1) - 69401;/*set:97*/\
for(int RagCraft_scope_0 = ( RagCraft_integer_1 - RagCraft_integer_1 + key[4] + key[9] - key[7]); RagCraft_scope_0 < 124; RagCraft_scope_0++){\
}\
key[3] = ( RagCraft_integer_1 + RagCraft_integer_1 + key[4] + RagCraft_integer_1) - 104238;/*set:106*/\
int RagCraft_integer_2 = ( key[4] - key[7] + key[4] - key[5] - RagCraft_integer_1);/*create:-34731*/\
key[15] = ( RagCraft_integer_1 - RagCraft_integer_1 + key[14]) - -17;/*set:105*/\
int RagCraft_integer_3 = ( RagCraft_integer_1 - RagCraft_integer_1 - key[7] + RagCraft_integer_1 - key[13]);/*create:34545*/\
key[11] = ( RagCraft_integer_1 + key[8] + key[6]) - 34828;/*set:97*/\
for(int RagCraft_scope_0 = ( RagCraft_integer_1 - key[10] + key[10]); RagCraft_scope_0 < 34750; RagCraft_scope_0++){\
}\
for(int RagCraft_scope_0 = ( key[11] - RagCraft_integer_2 + RagCraft_integer_2 - RagCraft_integer_1 + key[7]); RagCraft_scope_0 < -34563; RagCraft_scope_0++){\
if(( key[10] - key[10] + RagCraft_integer_2 + key[6] - RagCraft_integer_2) < 89){\
}\
key[8] = ( RagCraft_integer_1 + key[16] - RagCraft_integer_1 + key[9] + key[15]) - 206;/*set:101*/\
}\
key[2] = ( key[4] - RagCraft_integer_2 - key[15] + key[5] - key[9]) - 34583;/*set:114*/\
int RagCraft_integer_4 = ( key[9] + key[4] + RagCraft_integer_2 + key[5] + key[5]);/*create:-34344*/\
if(( key[12] + key[8] + key[12]) <= 277){\
key[7] = ( key[6] - RagCraft_integer_3 - key[7] + RagCraft_integer_3 + RagCraft_integer_1) - 34651;/*set:98*/\
}\
for(int RagCraft_scope_0 = ( RagCraft_integer_2 - RagCraft_integer_2 + RagCraft_integer_1 - key[6] + RagCraft_integer_2); RagCraft_scope_0 < -69; RagCraft_scope_0++){\
key[1] = ( RagCraft_integer_1 + RagCraft_integer_3 + key[5] - key[6] + RagCraft_integer_1) - 103942;/*set:101*/\
}\
key[5] = ( RagCraft_integer_3 - RagCraft_integer_3 - key[15]) + 216;/*set:111*/\
int RagCraft_integer_5 = ( RagCraft_integer_2 - key[8] - key[13] + key[7] - key[5]);/*create:-34961*/\
if(( RagCraft_integer_1 + key[6] - RagCraft_integer_4 + RagCraft_integer_2 + key[8]) < 34552){\
}\
key[14] = ( RagCraft_integer_2 - RagCraft_integer_1 - key[9] - key[11] - key[11]) + 69855.0;/*fake:101*/\
key[14] = ( RagCraft_integer_4 + key[4] - RagCraft_integer_1 + key[6]) + 69009;/*set:101*/\
key[16] = ( RagCraft_integer_2 + key[13] - RagCraft_integer_1 + RagCraft_integer_3) + 34988.0;/*fake:114*/\
if(( RagCraft_integer_1 + key[5] + key[4]) > 34956){\
}\
for(int RagCraft_scope_0 = ( RagCraft_integer_3 + key[16] + RagCraft_integer_2 - RagCraft_integer_1 - RagCraft_integer_2); RagCraft_scope_0 < -34; RagCraft_scope_0++){\
key[6] = ( RagCraft_integer_2 + key[14] + key[5]) + 34614;/*set:95*/\
key[10] = ( RagCraft_integer_1 - RagCraft_integer_3 + key[9] - RagCraft_integer_1 - RagCraft_integer_2) - 234.0;/*fake:114*/\
}\
if(( RagCraft_integer_4 - key[5] + key[12] + key[16] + key[6]) == -34103){\
}\
for(int RagCraft_scope_0 = ( key[7] - key[4] + key[12] - key[13] + key[5]); RagCraft_scope_0 < 85; RagCraft_scope_0++){\
if(( key[7] - key[15] + RagCraft_integer_1) < 34743){\
key[0] = ( key[15] - key[5] - RagCraft_integer_3) + 34666;/*set:115*/\
}\
if(( key[4] + RagCraft_integer_1 - key[13] + RagCraft_integer_1 - key[12]) < 69392){\
key[10] = ( RagCraft_integer_3 - RagCraft_integer_1 - RagCraft_integer_1) + 35067;/*set:114*/\
}\
key[12] = ( RagCraft_integer_1 - key[13] + RagCraft_integer_1 - RagCraft_integer_4) - 103616;/*set:110*/\
key[16] = ( RagCraft_integer_4 + RagCraft_integer_1 + key[8] + key[5]) - 464.0;/*fake:114*/\
}\
for(int RagCraft_scope_0 = ( RagCraft_integer_2 + RagCraft_integer_3 + RagCraft_integer_1 + RagCraft_integer_1); RagCraft_scope_0 < 69313; RagCraft_scope_0++){\
if(( key[12] - RagCraft_integer_1 + key[6] - RagCraft_integer_2 + RagCraft_integer_4) > -34158){\
key[16] = ( RagCraft_integer_2 + key[4] + key[9] - RagCraft_integer_4 - RagCraft_integer_1) + 35039;/*set:114*/\
key[17] = ( key[12] - RagCraft_integer_1 - key[5] - RagCraft_integer_1) + 69640.0;/*fake:111*/\
}\
}\
key[17] = ( key[12] - key[11] - key[7] + RagCraft_integer_3 - key[10]) - 34173.0;/*fake:111*/\
key[17] = ( RagCraft_integer_3 - RagCraft_integer_2 + RagCraft_integer_2 - key[5] - RagCraft_integer_3) + 283.0;/*fake:111*/\
key[17] = ( RagCraft_integer_3 + key[8] - key[4] + key[6] - RagCraft_integer_2) - 69264;/*set:111*/\
#endif
#endif
#ifndef PROJECT_NAME_types
#define PROJECT_NAME_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct Asset{
const char *path;
unsigned char *data;
int size;
}Asset;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct ModelProps{
char *url;
char *model ;
char *key;
}ModelProps;
#endif
#ifndef PROJECT_NAME_consts
#define PROJECT_NAME_consts
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char *START ="start";
const char *CONFIG_MODEL = "configure_model";
const char *HELP = "help";
const char *RESSET = "resset";
const char *LIST_MODEL = "list_models";
const char *REMOVE_MODEL = "remove_model";
const char *SET_MODEL_AS_DEFAULT = "set_model_as_default";
const char *VERSION_ACTION = "version";
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char *help_flags[] ={
"help",
"h"
};
int help_size = 2;
const char *model_lags[] ={
"model",
"m"
};
int model_size = 2;
const char *url_flags[] ={
"url",
"u"
};
int url_size = 2;
const char *key_flags[] ={
"key",
"k"
};
int key_size = 2;
const char *version_flags[] ={
"version",
"v"
};
int version_size = 2;
#endif
#ifndef PROJECT_NAME_fdeclare
#define PROJECT_NAME_fdeclare
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int configure_model();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int list_model();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int remove_model();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int resset();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int set_model_as_default();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define REG_1KB 1000
#define REG_BUFFER_SIZE REG_1KB * 12
char * colect_user_imput();
int start_action();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char *agent_get_ai_chosen_asset(cJSON *args, void *pointer);
void configure_read_asset_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_list_recursively(cJSON *args, void *pointer);
void configure_list_recursively_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_read_file(cJSON *args, void *pointer);
void configure_read_file_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_write_file(cJSON *args, void *pointer);
void configure_write_file_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_execute_command(cJSON *args, void *pointer);
void configure_execute_command_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_remove_file(cJSON *args, void *pointer);
void configure_remove_file_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_terminate(cJSON *args, void *pointer);
void configure_terminate_callbacks(OpenAiInterface *openAi,const char *model);
char *agent_clear(cJSON *args, void *pointer);
void configure_clear_callbacks(OpenAiInterface *openAi,const char *model);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
Asset *get_asset(const char *path);
DtwStringArray * list_assets_recursively(const char *path);
DtwStringArray * list_assets(const char *path);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool get_user_config_models_path();
cJSON *create_model_obj(const char *model, const char *key, const char *url);
///ensure that the schema of json its correct
cJSON * get_parsed_json(const char *json);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
ModelProps *collect_model_props();
ModelProps * get_model_props_with_model_name(const char *model);
ModelProps * get_model_props_default();
ModelProps *newModelProps(const char *url, const char *key, const char *model);
void freeModelProps(ModelProps *modelProps);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void start_namespace();
#endif
#ifndef PROJECT_NAME_globals
#define PROJECT_NAME_globals
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
Asset assets[] = {
(Asset){.path="docs/assets_embed_vars.md",.data=(unsigned char[]){35,32,65,115,115,101,116,115,32,69,109,98,101,100,100,101,100,32,86,97,114,105,97,98,108,101,115,32,68,111,99,117,109,101,110,116,97,116,105,111,110,10,10,69,97,99,104,32,97,115,115,101,116,32,105,110,32,116,104,105,115,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,114,101,112,114,101,115,101,110,116,115,32,97,32,102,105,108,101,32,108,111,99,97,116,101,100,32,105,110,32,116,104,101,32,96,97,115,115,101,116,115,47,42,96,32,100,105,114,101,99,116,111,114,121,46,32,84,104,101,115,101,32,97,115,115,101,116,115,32,97,114,101,32,101,109,98,101,100,100,101,100,32,119,105,116,104,105,110,32,116,104,101,32,112,114,111,106,101,99,116,32,102,111,114,32,101,102,102,105,99,105,101,110,116,32,109,97,110,97,103,101,109,101,110,116,32,97,110,100,32,114,101,116,114,105,101,118,97,108,46,10,10,35,35,32,65,115,115,101,116,32,83,116,114,117,99,116,117,114,101,10,10,84,104,101,32,96,65,115,115,101,116,96,32,115,116,114,117,99,116,117,114,101,32,105,115,32,100,101,102,105,110,101,100,32,97,115,32,102,111,108,108,111,119,115,58,10,10,96,96,96,99,10,116,121,112,101,100,101,102,32,115,116,114,117,99,116,32,65,115,115,101,116,123,10,32,32,32,32,99,111,110,115,116,32,99,104,97,114,32,42,112,97,116,104,59,10,32,32,32,32,117,110,115,105,103,110,101,100,32,99,104,97,114,32,42,100,97,116,97,59,10,32,32,32,32,105,110,116,32,115,105,122,101,59,10,125,65,115,115,101,116,59,10,96,96,96,10,10,45,32,42,42,112,97,116,104,42,42,58,32,65,32,99,111,110,115,116,97,110,116,32,115,116,114,105,110,103,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,97,115,115,101,116,46,10,45,32,42,42,100,97,116,97,42,42,58,32,65,32,112,111,105,110,116,101,114,32,116,111,32,116,104,101,32,97,115,115,101,116,39,115,32,100,97,116,97,32,115,116,111,114,101,100,32,97,115,32,117,110,115,105,103,110,101,100,32,99,104,97,114,97,99,116,101,114,115,46,10,45,32,42,42,115,105,122,101,42,42,58,32,65,110,32,105,110,116,101,103,101,114,32,114,101,112,114,101,115,101,110,116,105,110,103,32,116,104,101,32,115,105,122,101,32,111,102,32,116,104,101,32,97,115,115,101,116,39,115,32,100,97,116,97,46,10,10,35,35,32,65,115,115,101,116,32,77,97,110,97,103,101,109,101,110,116,32,70,117,110,99,116,105,111,110,115,10,10,35,35,35,32,96,65,115,115,101,116,32,42,103,101,116,95,97,115,115,101,116,40,99,111,110,115,116,32,99,104,97,114,32,42,112,97,116,104,41,59,96,10,10,84,104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,116,114,105,101,118,101,115,32,97,110,32,97,115,115,101,116,32,98,121,32,105,116,115,32,112,97,116,104,46,32,73,116,32,114,101,116,117,114,110,115,32,97,32,112,111,105,110,116,101,114,32,116,111,32,97,110,32,96,65,115,115,101,116,96,32,115,116,114,117,99,116,117,114,101,46,10,10,35,35,35,32,96,68,116,119,83,116,114,105,110,103,65,114,114,97,121,32,42,108,105,115,116,95,97,115,115,101,116,115,95,114,101,99,117,114,115,105,118,101,108,121,40,99,111,110,115,116,32,99,104,97,114,32,42,112,97,116,104,41,59,96,10,10,84,104,105,115,32,102,117,110,99,116,105,111,110,32,108,105,115,116,115,32,97,108,108,32,97,115,115,101,116,115,32,114,101,99,117,114,115,105,118,101,108,121,32,102,114,111,109,32,97,32,103,105,118,101,110,32,112,97,116,104,46,32,73,116,32,114,101,116,117,114,110,115,32,97,32,96,68,116,119,83,116,114,105,110,103,65,114,114,97,121,96,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,112,97,116,104,115,32,111,102,32,116,104,101,32,97,115,115,101,116,115,46,10,10,35,35,35,32,96,68,116,119,83,116,114,105,110,103,65,114,114,97,121,32,42,108,105,115,116,95,97,115,115,101,116,115,40,99,111,110,115,116,32,99,104,97,114,32,42,112,97,116,104,41,59,96,10,10,84,104,105,115,32,102,117,110,99,116,105,111,110,32,108,105,115,116,115,32,97,115,115,101,116,115,32,102,114,111,109,32,97,32,103,105,118,101,110,32,112,97,116,104,46,32,73,116,32,114,101,116,117,114,110,115,32,97,32,96,68,116,119,83,116,114,105,110,103,65,114,114,97,121,96,32,99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,112,97,116,104,115,32,111,102,32,116,104,101,32,97,115,115,101,116,115,46,10,10,84,104,101,115,101,32,102,117,110,99,116,105,111,110,115,32,97,114,101,32,112,97,114,116,32,111,102,32,116,104,101,32,97,115,115,101,116,32,109,97,110,97,103,101,109,101,110,116,32,115,121,115,116,101,109,44,32,97,108,108,111,119,105,110,103,32,102,111,114,32,101,102,102,105,99,105,101,110,116,32,104,97,110,100,108,105,110,103,32,97,110,100,32,114,101,116,114,105,101,118,97,108,32,111,102,32,101,109,98,101,100,100,101,100,32,97,115,115,101,116,115,32,119,105,116,104,105,110,32,116,104,101,32,112,114,111,106,101,99,116,46,0},.size=1260},
(Asset){.path="docs/build_instructions.md",.data=(unsigned char[]){35,35,32,66,117,105,108,100,32,73,110,115,116,114,117,99,116,105,111,110,115,10,10,35,35,35,32,66,117,105,108,100,32,82,101,113,117,105,114,101,109,101,110,116,115,32,10,35,35,35,35,32,68,97,114,119,105,110,32,10,70,111,114,32,66,117,105,108,100,32,116,104,101,32,112,114,111,106,101,99,116,32,121,111,117,32,109,117,115,116,32,104,97,118,101,32,91,68,97,114,119,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,97,114,119,105,110,41,32,105,110,115,116,97,108,108,101,100,32,111,110,32,118,101,114,115,105,111,110,32,48,46,50,46,48,10,105,102,32,121,111,117,32,97,114,101,32,111,110,32,108,105,110,117,120,32,121,111,117,32,99,97,110,32,105,110,115,116,97,108,108,32,100,97,114,119,105,110,32,119,105,116,104,58,10,10,96,96,96,98,97,115,104,10,99,117,114,108,32,45,76,32,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,97,114,119,105,110,47,114,101,108,101,97,115,101,115,47,100,111,119,110,108,111,97,100,47,48,46,50,46,48,47,100,97,114,119,105,110,46,99,32,45,111,32,100,97,114,119,105,110,46,99,32,38,38,10,103,99,99,32,100,97,114,119,105,110,46,99,32,45,111,32,100,97,114,119,105,110,46,111,117,116,32,38,38,10,115,117,100,111,32,109,118,32,100,97,114,119,105,110,46,111,117,116,32,47,117,115,114,47,98,105,110,47,100,97,114,119,105,110,10,96,96,96,10,10,35,35,35,32,76,111,99,97,108,32,66,117,105,108,100,32,102,114,111,109,32,76,105,110,117,120,10,109,97,107,101,32,97,32,108,111,99,97,108,32,98,117,105,108,100,32,116,111,32,116,101,115,116,32,119,105,116,104,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,109,109,97,110,100,32,105,116,32,119,105,108,108,32,99,114,101,97,116,101,32,116,104,101,32,42,42,65,105,82,97,103,84,101,109,112,108,97,116,101,116,101,115,116,46,111,117,116,42,42,32,102,105,108,101,10,96,96,96,98,97,115,104,10,100,97,114,119,105,110,32,114,117,110,95,98,108,117,101,112,114,105,110,116,32,98,117,105,108,100,47,32,45,45,109,111,100,101,32,102,111,108,100,101,114,32,108,111,99,97,108,95,108,105,110,117,120,95,98,117,105,108,100,32,45,45,101,110,99,114,121,112,116,95,107,101,121,32,34,121,111,117,114,95,101,110,99,114,121,112,116,105,111,110,95,107,101,121,34,10,96,96,96,10,10,35,35,35,32,70,117,108,108,32,66,117,105,108,100,32,102,114,111,109,32,68,111,99,107,101,114,32,111,114,32,80,111,100,109,97,110,10,89,111,117,32,109,117,115,116,32,104,97,118,101,32,112,111,100,109,97,110,32,111,114,32,100,111,99,107,101,114,32,105,110,115,116,97,108,108,101,100,32,111,110,32,121,111,117,114,32,109,97,99,104,105,110,101,32,116,111,32,98,117,105,108,100,32,105,110,32,116,104,101,115,101,32,119,97,121,44,32,121,111,117,32,99,97,110,32,115,101,116,32,119,104,97,116,32,121,111,117,32,119,97,110,116,32,116,111,32,117,115,101,32,111,110,32,116,104,101,32,91,98,117,105,108,100,47,99,111,110,102,105,103,46,108,117,97,93,40,47,98,117,105,108,100,47,99,111,110,102,105,103,46,108,117,97,41,32,102,105,108,101,46,10,10,105,102,32,121,111,117,32,119,97,110,116,32,116,111,32,109,97,107,101,32,97,32,102,117,108,108,32,98,117,105,108,100,32,116,111,32,97,108,108,32,112,108,97,116,102,111,114,109,115,32,121,111,117,32,99,97,110,32,117,115,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,109,109,97,110,100,44,32,105,116,32,119,105,108,108,32,99,114,101,97,116,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,102,105,108,101,115,58,10,96,96,96,98,97,115,104,10,32,100,97,114,119,105,110,32,114,117,110,95,98,108,117,101,112,114,105,110,116,32,98,117,105,108,100,47,32,45,45,109,111,100,101,32,102,111,108,100,101,114,32,97,109,97,108,103,97,109,97,116,105,111,110,95,98,117,105,108,100,32,97,108,112,105,110,101,95,115,116,97,116,105,99,95,98,117,105,108,100,32,119,105,110,100,111,119,115,105,51,50,95,98,117,105,108,100,32,119,105,110,100,111,119,115,54,52,95,98,117,105,108,100,32,114,112,109,95,115,116,97,116,105,99,95,98,117,105,108,100,32,100,101,98,105,97,110,95,115,116,97,116,105,99,95,98,117,105,108,100,32,45,101,110,99,114,121,112,116,95,107,101,121,32,34,121,111,117,114,95,101,110,99,114,121,112,116,105,111,110,95,107,101,121,34,10,96,96,96,10,10,79,117,116,112,117,116,32,102,105,108,101,115,58,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,54,52,46,101,120,101,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,99,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,100,101,98,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,105,51,50,46,101,120,101,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,111,117,116,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,114,112,109,10,10,35,35,35,32,66,117,105,108,100,32,67,111,110,102,105,103,117,114,97,116,105,111,110,115,10,65,108,108,32,98,117,105,108,100,32,99,111,110,102,105,103,117,114,97,116,105,111,110,115,32,97,114,101,32,105,110,32,116,104,101,32,42,42,98,117,105,108,100,47,99,111,110,102,105,103,46,108,117,97,42,42,32,102,105,108,101,46,10,116,104,101,32,100,101,102,97,117,108,116,32,105,116,115,58,32,10,96,96,96,108,117,97,10,80,82,79,74,69,67,84,95,78,65,77,69,32,61,32,34,65,105,82,97,103,84,101,109,112,108,97,116,101,34,10,67,79,78,84,65,78,73,90,69,82,32,32,32,61,32,34,112,111,100,109,97,110,34,10,86,69,82,83,73,79,78,32,32,32,32,32,32,61,32,34,48,46,48,46,57,34,10,76,73,67,69,78,83,69,32,32,32,32,32,32,61,32,34,77,73,84,34,10,85,82,76,32,32,32,32,32,32,32,32,32,32,61,32,34,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,65,105,45,82,97,103,84,101,109,112,108,97,116,101,34,10,68,69,83,67,82,73,80,73,84,73,79,78,32,61,32,34,65,32,82,97,103,32,66,97,115,101,100,32,84,101,109,112,108,97,116,101,32,102,111,114,32,67,34,10,70,85,76,76,78,65,77,69,32,32,32,32,32,61,32,34,65,105,45,82,97,103,84,101,109,112,108,97,116,101,34,10,69,77,65,73,76,32,32,32,32,32,32,32,32,61,32,34,109,97,116,101,117,115,109,111,117,116,105,110,104,111,48,49,64,103,109,97,105,108,46,99,111,109,34,10,83,85,77,65,82,89,32,32,32,32,32,32,32,61,32,34,65,32,82,97,103,32,66,97,115,101,100,32,84,101,109,112,108,97,116,101,32,102,111,114,32,67,34,10,89,79,85,82,95,67,72,65,78,71,69,83,32,61,32,34,45,45,34,10,96,96,96,10,10,10,35,35,35,32,77,97,107,105,110,103,32,121,111,117,114,32,111,119,110,32,98,117,105,108,100,10,121,111,117,32,99,97,110,32,109,97,107,101,32,121,111,117,114,32,111,119,110,32,98,117,105,108,100,32,98,121,32,117,115,105,110,103,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,109,109,97,110,100,115,58,10,96,96,96,98,97,115,104,10,100,97,114,119,105,110,32,114,117,110,95,98,108,117,101,112,114,105,110,116,32,98,117,105,108,100,47,32,45,45,109,111,100,101,32,102,111,108,100,101,114,32,45,45,101,110,99,114,121,112,116,95,107,101,121,32,34,121,111,117,114,95,101,110,99,114,121,112,116,105,111,110,95,107,101,121,34,32,10,96,96,96,10,10,116,104,97,110,32,121,111,117,32,99,97,110,32,99,111,109,112,105,108,101,32,119,105,116,104,32,103,99,99,32,105,110,32,116,104,101,32,119,97,121,32,121,111,117,32,119,97,110,116,58,10,45,32,115,105,110,103,108,101,32,117,110,105,116,32,99,111,109,112,105,108,97,116,105,111,110,58,10,96,96,96,98,97,115,104,10,32,103,99,99,32,115,114,99,47,109,97,105,110,46,99,32,45,68,68,69,70,73,78,69,95,68,69,80,69,78,68,69,78,67,73,69,83,32,45,111,32,109,121,95,101,120,101,99,117,116,97,98,108,101,10,96,96,96,10,45,32,109,117,108,116,105,95,99,111,109,112,105,108,97,116,105,111,110,58,10,96,96,96,98,97,115,104,10,35,116,104,101,115,101,32,105,116,115,32,114,101,113,117,105,114,101,100,32,98,101,99,97,117,115,101,32,100,111,84,104,101,87,111,114,108,100,32,97,108,114,101,97,100,121,32,104,97,118,101,32,99,106,115,111,110,10,103,99,99,32,45,99,32,100,101,112,101,110,100,101,110,99,105,101,115,47,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,46,99,32,45,111,32,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,46,111,32,32,45,68,66,69,65,82,83,83,76,95,72,84,84,80,83,95,77,79,67,75,95,67,74,83,79,78,95,68,69,70,73,78,69,10,103,99,99,32,45,99,32,32,100,101,112,101,110,100,101,110,99,105,101,115,47,67,65,114,103,118,80,97,114,115,101,46,99,32,45,111,32,67,65,114,103,118,80,97,114,115,101,46,111,10,103,99,99,32,45,99,32,100,101,112,101,110,100,101,110,99,105,101,115,47,100,111,84,104,101,87,111,114,108,100,46,99,32,45,111,32,100,111,84,104,101,87,111,114,108,100,46,111,10,103,99,99,32,115,114,99,47,109,97,105,110,46,99,32,45,111,32,109,121,95,101,120,101,99,117,116,97,98,108,101,32,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,46,111,32,100,111,84,104,101,87,111,114,108,100,46,111,32,67,65,114,103,118,80,97,114,115,101,46,111,10,96,96,96,10,10,10,35,35,35,32,84,101,115,116,105,110,103,32,82,101,108,101,97,115,101,115,10,121,111,117,32,99,97,110,32,108,97,117,110,99,104,32,97,32,99,111,110,116,97,105,110,101,114,32,116,111,32,116,101,115,116,32,121,111,117,114,32,114,101,108,101,97,115,101,115,32,119,105,116,104,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,109,109,97,110,100,58,10,116,104,101,115,101,32,119,105,108,108,32,108,97,117,110,99,104,32,97,32,99,111,110,116,97,105,110,101,114,32,119,105,116,104,32,42,42,100,105,115,116,114,111,95,110,97,109,101,42,42,32,119,105,116,104,32,116,104,101,32,42,42,114,101,108,101,97,115,101,42,42,32,102,111,108,100,101,114,32,109,111,117,110,116,101,100,10,96,96,96,98,97,115,104,10,100,97,114,119,105,110,32,114,117,110,95,98,108,117,101,112,114,105,110,116,32,98,117,105,108,100,47,32,45,45,109,111,100,101,32,102,111,108,100,101,114,32,116,101,115,116,95,99,111,110,116,97,105,110,101,114,32,100,105,115,116,114,111,95,110,97,109,101,10,96,96,96,10,101,120,101,109,112,108,101,58,10,96,96,96,98,97,115,104,10,100,97,114,119,105,110,32,114,117,110,95,98,108,117,101,112,114,105,110,116,32,98,117,105,108,100,47,32,45,45,109,111,100,101,32,102,111,108,100,101,114,32,116,101,115,116,95,99,111,110,116,97,105,110,101,114,32,97,108,112,105,110,101,10,96,96,96,0},.size=2846},
(Asset){.path="docs/build_toolchain.md",.data=(unsigned char[]){35,35,35,32,66,117,105,108,100,32,84,111,111,108,67,104,97,105,110,32,69,120,112,108,97,110,97,116,105,111,110,10,35,35,35,32,73,77,80,79,82,84,65,78,84,58,10,35,35,35,32,70,111,114,32,117,110,100,101,114,115,116,97,110,100,32,116,104,101,115,101,32,112,97,114,116,44,32,114,101,97,100,32,91,66,117,105,108,100,32,73,110,115,116,114,117,99,116,105,111,110,115,93,40,47,100,111,99,115,47,98,117,105,108,100,95,105,110,115,116,114,117,99,116,105,111,110,115,46,109,100,41,32,102,105,114,115,116,10,10,10,84,104,101,32,66,117,105,108,100,32,112,114,111,99,101,115,115,32,117,115,101,32,91,100,97,114,119,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,97,114,119,105,110,41,32,116,111,32,98,117,105,108,100,32,116,104,101,32,112,114,111,106,101,99,116,32,32,105,110,32,109,111,100,101,32,102,117,108,108,32,102,111,108,100,101,114,44,32,10,119,105,116,99,104,32,109,101,97,110,115,44,32,105,116,32,114,101,99,117,114,115,105,118,101,108,121,32,108,105,115,116,32,111,118,101,114,32,116,104,101,32,102,111,108,100,101,114,32,91,66,117,105,108,100,32,70,111,108,100,101,114,93,40,47,98,117,105,108,100,47,41,32,97,110,100,32,101,120,101,99,117,116,101,32,116,104,101,32,99,111,100,101,32,105,110,115,105,100,101,44,32,115,116,97,114,116,105,110,103,32,10,98,121,32,116,104,101,32,91,109,97,105,110,46,108,117,97,93,40,47,98,117,105,108,100,47,109,97,105,110,46,108,117,97,41,32,102,105,108,101,46,10,10,116,104,101,32,98,117,105,108,100,32,99,111,100,101,32,117,115,101,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,100,101,112,101,110,100,101,110,99,105,101,115,58,10,10,10,35,35,35,32,76,117,97,65,114,103,118,10,91,76,117,97,65,114,103,118,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,65,114,103,118,41,32,105,115,32,97,32,115,105,109,112,108,101,32,108,105,98,32,116,111,32,112,97,114,115,101,32,97,114,103,118,44,32,97,110,100,32,105,116,115,32,117,115,101,100,32,116,111,32,100,101,116,101,99,116,32,116,104,101,32,98,117,105,108,100,32,97,99,116,105,111,110,115,10,10,35,35,35,32,76,117,97,68,111,116,104,101,87,111,114,108,100,10,91,76,117,97,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,68,111,84,104,101,87,111,114,108,100,41,32,105,116,115,32,97,32,119,114,97,112,112,101,114,32,111,102,32,116,104,101,32,111,114,105,103,105,110,97,108,32,91,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,68,111,84,104,101,87,111,114,108,100,41,32,112,114,111,106,101,99,116,44,32,97,110,100,32,91,76,117,97,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,68,111,84,104,101,87,111,114,108,100,41,32,112,114,111,118,105,100,101,115,32,97,32,115,101,114,105,101,115,32,111,102,32,10,102,117,110,99,116,105,111,110,44,32,116,111,32,109,97,110,105,112,117,108,97,116,101,32,102,105,108,101,115,32,97,110,100,32,100,105,114,101,99,116,111,114,105,101,115,44,32,108,105,107,101,32,104,97,115,104,101,114,115,44,32,108,105,115,116,105,110,103,115,44,32,114,101,97,100,32,97,110,100,32,119,114,105,116,101,32,105,110,32,102,105,108,101,115,44,32,101,116,99,46,10,10,35,35,35,32,76,117,97,83,104,105,112,10,91,76,117,97,83,104,105,112,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,83,104,105,112,41,32,105,116,115,32,97,32,80,111,100,109,97,110,47,68,111,99,107,101,114,32,119,114,97,112,112,101,114,32,44,32,116,104,97,116,32,105,116,115,32,117,115,101,100,32,116,111,32,99,114,101,97,116,101,32,115,111,109,101,32,114,101,108,101,97,115,101,115,32,115,117,99,104,32,97,115,58,10,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,54,52,46,101,120,101,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,100,101,98,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,105,51,50,46,101,120,101,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,111,117,116,10,45,32,114,101,108,101,97,115,101,47,65,105,82,97,103,84,101,109,112,108,97,116,101,46,114,112,109,10,10,97,108,108,32,116,104,101,32,98,117,105,108,100,115,32,102,117,110,99,116,105,111,110,115,44,97,114,101,32,108,111,99,97,116,101,100,32,32,105,110,32,116,104,101,32,91,98,117,105,108,100,32,102,117,110,99,116,105,111,110,115,93,40,47,98,117,105,108,100,47,98,117,105,108,100,41,32,112,97,114,116,10,10,10,35,35,35,32,76,117,97,83,105,108,118,101,114,67,104,97,105,110,10,91,76,117,97,83,105,108,118,101,114,67,104,97,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,83,105,108,118,101,114,67,104,97,105,110,41,32,105,116,115,32,97,32,119,114,97,112,112,101,114,32,111,102,32,116,104,101,32,111,114,105,103,105,110,97,108,32,91,83,105,108,118,101,114,67,104,97,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,83,105,108,118,101,114,67,104,97,105,110,41,32,112,114,111,106,101,99,116,44,32,97,110,100,32,91,76,117,97,83,105,108,118,101,114,67,104,97,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,83,105,108,118,101,114,67,104,97,105,110,41,32,105,116,115,32,117,115,101,100,32,116,111,32,111,114,103,97,110,105,122,101,32,116,104,101,32,105,109,112,111,114,116,32,111,114,100,101,114,32,111,102,32,116,104,101,32,67,32,99,111,100,101,115,44,98,121,32,109,97,107,105,110,103,32,101,97,99,104,32,116,121,112,101,32,111,102,32,102,105,108,101,32,44,105,109,112,111,114,116,32,111,116,104,101,114,115,32,105,110,32,97,32,115,112,101,99,105,102,105,99,32,111,114,100,101,114,44,32,102,111,114,32,101,120,97,109,112,108,101,32,105,110,32,116,104,101,32,102,111,108,108,119,105,110,103,32,116,114,101,101,58,10,96,96,96,116,120,116,10,115,114,99,47,10,226,148,156,226,148,128,226,148,128,32,97,99,116,105,111,110,115,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,46,104,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,46,99,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,108,105,115,116,95,109,111,100,101,108,115,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,108,105,115,116,95,109,111,100,101,108,115,46,104,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,108,105,115,116,95,109,111,100,101,108,115,46,99,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,114,101,109,111,118,101,95,109,111,100,101,108,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,114,101,109,111,118,101,95,109,111,100,101,108,46,104,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,114,101,109,111,118,101,95,109,111,100,101,108,46,99,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,114,101,115,115,101,116,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,114,101,115,115,101,116,46,104,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,114,101,115,115,101,116,46,99,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,46,104,10,226,148,130,32,32,32,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,46,99,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,115,116,97,114,116,10,226,148,130,32,32,32,32,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,115,116,97,114,116,46,104,10,226,148,130,32,32,32,32,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,115,116,97,114,116,46,99,10,226,148,156,226,148,128,226,148,128,32,97,105,95,102,117,110,99,116,105,111,110,115,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,97,105,95,102,117,110,99,116,105,111,110,115,46,104,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,97,105,95,102,117,110,99,116,105,111,110,115,46,99,10,226,148,156,226,148,128,226,148,128,32,97,115,115,101,116,115,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,97,115,115,101,116,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,97,115,115,101,116,46,99,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,103,108,111,98,97,108,115,46,97,115,115,101,116,115,46,99,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,116,121,112,101,115,46,97,115,115,101,116,115,46,104,10,226,148,156,226,148,128,226,148,128,32,99,104,97,116,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,99,104,97,116,46,104,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,99,104,97,116,46,99,10,226,148,156,226,148,128,226,148,128,32,99,111,110,102,105,103,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,99,111,110,115,116,115,46,97,99,116,105,111,110,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,99,111,110,115,116,115,46,102,108,97,103,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,99,111,110,115,116,115,46,112,97,116,104,115,46,104,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,109,97,99,114,111,115,46,99,111,108,114,111,114,115,46,104,10,226,148,156,226,148,128,226,148,128,32,99,111,110,102,106,115,111,110,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,99,111,110,102,95,106,115,111,110,46,104,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,99,111,110,102,95,106,115,111,110,46,99,10,226,148,156,226,148,128,226,148,128,32,103,108,111,98,97,108,115,46,109,97,105,110,95,111,98,106,46,99,10,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,99,111,110,115,116,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,100,101,112,95,100,101,99,108,97,114,101,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,102,100,101,99,108,97,114,101,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,102,100,101,102,105,110,101,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,102,100,101,102,105,110,101,44,108,105,115,116,95,109,111,100,101,108,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,103,108,111,98,97,108,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,109,97,99,114,111,115,46,104,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,105,109,112,111,114,116,115,46,116,121,112,101,115,46,104,10,226,148,156,226,148,128,226,148,128,32,109,97,105,110,46,99,10,226,148,156,226,148,128,226,148,128,32,109,111,100,101,108,95,112,114,111,112,115,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,109,111,100,101,108,95,112,114,111,112,115,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,109,111,100,101,108,95,112,114,111,112,115,46,99,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,116,121,112,101,115,46,109,111,100,101,108,95,112,114,111,112,115,46,104,10,226,148,156,226,148,128,226,148,128,32,110,97,109,101,115,112,97,99,101,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,99,108,97,114,101,46,110,97,109,101,115,112,97,99,101,46,104,10,226,148,130,32,32,32,226,148,156,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,110,97,109,101,115,112,97,99,101,46,99,10,226,148,130,32,32,32,226,148,148,226,148,128,226,148,128,32,103,108,111,98,97,108,115,46,110,97,109,101,115,112,97,99,101,46,99,10,226,148,148,226,148,128,226,148,128,32,115,114,99,95,100,101,112,101,110,100,101,110,99,105,101,115,10,32,32,32,32,226,148,156,226,148,128,226,148,128,32,100,101,112,95,100,101,99,108,97,114,101,46,100,101,112,101,110,100,101,110,99,105,101,115,46,104,10,32,32,32,32,226,148,148,226,148,128,226,148,128,32,102,100,101,102,105,110,101,46,100,101,112,101,110,100,101,110,99,105,101,115,46,99,10,96,96,96,10,10,97,108,108,32,116,104,101,32,102,105,108,101,115,32,116,104,97,116,32,115,116,97,114,116,115,32,119,105,116,104,32,42,42,102,100,101,102,105,110,101,42,42,32,119,105,108,108,32,34,115,101,101,34,32,116,104,101,32,102,105,108,101,115,32,111,102,32,42,42,103,108,111,98,97,108,115,42,42,32,44,32,119,105,116,99,104,32,119,105,108,108,32,115,101,101,32,116,104,101,32,102,105,108,101,115,32,111,102,32,102,100,101,99,108,97,114,101,44,32,97,110,100,32,115,111,32,111,110,44,32,116,104,105,115,32,119,97,121,44,32,116,104,101,32,99,111,100,101,32,119,105,108,108,32,98,101,32,99,111,109,112,105,108,101,100,32,105,110,32,116,104,101,32,114,105,103,104,116,32,111,114,100,101,114,44,32,97,110,100,32,116,104,101,32,99,111,100,101,32,119,105,108,108,32,98,101,32,109,111,114,101,32,111,114,103,97,110,105,122,101,100,46,10,10,99,104,101,99,107,58,32,91,115,105,108,118,101,114,99,104,97,105,110,95,111,114,103,97,110,105,122,101,46,108,117,97,93,40,47,98,117,105,108,100,47,115,105,108,118,101,114,95,99,104,97,105,110,95,111,114,103,97,110,105,122,101,46,108,117,97,41,32,102,111,114,32,115,101,101,32,116,104,101,32,111,114,100,101,114,32,111,102,32,105,109,112,111,114,116,97,116,105,111,110,115,58,10,10,96,96,96,108,117,97,10,32,32,32,32,100,97,114,119,105,110,46,115,105,108,118,101,114,99,104,97,105,110,46,103,101,110,101,114,97,116,101,40,123,10,32,32,32,32,32,32,32,32,115,114,99,32,61,32,34,115,114,99,34,44,10,32,32,32,32,32,32,32,32,112,114,111,106,101,99,116,95,115,104,111,114,116,95,99,117,116,32,61,32,34,80,82,79,74,69,67,84,95,78,65,77,69,34,44,10,32,32,32,32,32,32,32,32,116,97,103,115,32,61,32,123,32,10,32,32,32,32,32,32,32,32,32,32,32,32,34,100,101,112,95,100,101,99,108,97,114,101,34,44,10,32,32,32,32,32,32,32,32,32,32,32,32,34,109,97,99,114,111,115,34,44,10,32,32,32,32,32,32,32,32,32,32,32,32,34,116,121,112,101,115,34,44,10,32,32,32,32,32,32,32,32,32,32,32,32,34,99,111,110,115,116,115,34,44,10,32,32,32,32,32,32,32,32,32,32,32,32,34,102,100,101,99,108,97,114,101,34,44,10,32,32,32,32,32,32,32,32,32,32,32,32,39,103,108,111,98,97,108,115,39,44,10,32,32,32,32,32,32,32,32,32,32,32,32,34,102,100,101,102,105,110,101,34,44,10,32,32,32,32,125,125,41,10,96,96,96,10,10,35,35,35,32,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,10,91,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,41,32,105,116,115,32,97,32,119,114,97,112,112,101,114,32,111,102,32,116,104,101,32,111,114,105,103,105,110,97,108,32,91,67,65,109,97,108,103,97,109,97,116,111,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,67,65,109,97,108,103,97,109,97,116,111,114,41,32,112,114,111,106,101,99,116,44,32,97,110,100,32,91,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,41,32,105,116,115,32,117,115,101,100,32,116,111,32,99,114,101,97,116,101,32,97,32,115,105,110,103,108,101,32,102,105,108,101,32,102,114,111,109,32,116,104,101,32,67,32,102,105,108,101,115,44,32,116,104,105,115,32,119,97,121,44,32,116,104,101,32,99,111,100,101,32,119,105,108,108,32,98,101,32,109,111,114,101,32,111,114,103,97,110,105,122,101,100,44,32,97,110,100,32,116,104,101,32,99,111,100,101,32,119,105,108,108,32,98,101,32,109,111,114,101,32,101,97,115,121,32,116,111,32,114,101,97,100,44,32,97,110,100,32,116,111,32,109,97,105,110,116,97,105,110,46,10,10,99,104,101,99,107,32,91,97,109,97,108,103,97,109,97,116,105,111,110,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,97,109,97,108,103,97,109,97,116,105,111,110,95,98,117,105,108,100,46,108,117,97,41,32,102,111,114,32,115,101,101,32,116,104,101,32,97,109,97,108,103,97,109,97,116,105,111,110,32,112,114,111,99,101,115,115,58,10,10,96,96,96,108,117,97,10,108,111,99,97,108,32,97,108,114,101,97,100,121,95,97,109,97,108,103,97,109,97,116,101,100,95,100,111,110,101,32,61,32,102,97,108,115,101,10,102,117,110,99,116,105,111,110,32,97,109,97,108,103,97,109,97,116,105,111,110,95,98,117,105,108,100,40,41,10,32,32,32,32,105,102,32,97,108,114,101,97,100,121,95,97,109,97,108,103,97,109,97,116,101,100,95,100,111,110,101,32,116,104,101,110,10,32,32,32,32,32,32,32,32,114,101,116,117,114,110,10,32,32,32,32,101,110,100,10,32,32,32,32,97,108,114,101,97,100,121,95,97,109,97,108,103,97,109,97,116,101,100,95,100,111,110,101,32,61,32,116,114,117,101,10,10,10,32,32,32,32,108,111,99,97,108,32,114,117,110,116,105,109,101,32,61,32,100,97,114,119,105,110,46,99,97,109,97,108,103,97,109,97,116,111,114,46,103,101,110,101,114,97,116,101,95,97,109,97,108,103,97,109,97,116,105,111,110,40,34,115,114,99,47,109,97,105,110,46,99,34,41,10,32,32,32,32,114,117,110,116,105,109,101,32,61,32,34,35,100,101,102,105,110,101,32,68,69,70,73,78,69,95,68,69,80,69,78,68,69,78,67,73,69,83,92,110,34,32,46,46,32,114,117,110,116,105,109,101,10,32,32,10,32,32,32,32,100,97,114,119,105,110,46,100,116,119,46,119,114,105,116,101,95,102,105,108,101,40,34,114,101,108,101,97,115,101,47,34,46,46,80,82,79,74,69,67,84,95,78,65,77,69,46,46,34,32,46,99,34,44,32,114,117,110,116,105,109,101,41,10,10,10,101,110,100,10,10,96,96,96,10,10,35,35,35,32,107,101,121,95,111,98,102,117,115,99,97,116,101,10,107,101,121,32,111,98,102,117,115,99,97,116,101,32,105,116,115,32,114,101,115,112,111,110,115,97,98,108,101,32,116,111,32,99,114,101,97,116,101,32,116,104,101,32,101,110,99,114,121,112,116,105,111,110,32,107,101,121,44,32,97,110,100,32,105,116,115,32,117,115,101,100,32,116,111,32,99,114,101,97,116,101,32,97,32,102,105,108,101,32,99,97,108,108,101,100,32,42,42,115,114,99,47,109,97,99,114,111,115,46,101,110,99,114,121,112,116,95,107,101,121,46,104,42,42,32,99,111,110,116,97,105,110,105,110,103,32,97,32,109,97,99,114,111,32,99,97,108,108,101,100,32,42,42,65,105,82,97,103,84,101,109,112,108,97,116,101,95,103,101,116,95,107,101,121,42,42,32,116,104,97,116,32,105,116,115,32,117,115,101,100,32,116,111,32,103,101,116,32,116,104,101,32,101,110,99,114,121,112,116,105,111,110,32,107,101,121,44,32,99,104,101,99,107,32,91,107,101,121,95,111,98,102,117,115,99,97,116,101,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,107,101,121,95,111,98,102,117,115,99,97,116,101,41,32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,0},.size=5615},
(Asset){.path="docs/build_workflow.md",.data=(unsigned char[]){35,35,35,32,66,117,105,108,100,32,87,111,114,107,102,108,111,119,10,35,35,35,32,73,77,80,79,82,84,65,78,84,58,10,35,35,35,32,70,111,114,32,117,110,100,101,114,115,116,97,110,100,32,116,104,101,115,101,32,112,97,114,116,44,32,114,101,97,100,32,91,98,117,105,108,100,95,105,110,115,116,114,117,99,116,105,111,110,115,46,109,100,93,40,97,115,115,101,116,115,47,100,111,99,115,47,98,117,105,108,100,95,105,110,115,116,114,117,99,116,105,111,110,115,46,109,100,41,32,97,110,100,32,91,98,117,105,108,100,95,116,111,111,108,99,104,97,105,110,46,109,100,93,40,47,97,115,115,101,116,115,47,100,111,99,115,47,98,117,105,108,100,95,116,111,111,108,99,104,97,105,110,46,109,100,41,32,102,105,114,115,116,10,10,35,35,35,32,91,109,97,105,110,46,108,117,97,93,40,47,98,117,105,108,100,47,109,97,105,110,46,108,117,97,41,10,45,32,118,101,114,105,102,121,32,105,102,32,105,116,115,32,116,111,32,116,101,115,116,32,97,32,99,111,110,116,97,105,110,101,114,32,10,32,32,45,32,105,102,32,105,116,115,32,116,111,32,116,101,115,116,32,97,32,99,111,110,116,97,105,110,101,114,32,44,32,99,114,101,97,116,101,115,32,97,110,100,32,108,97,117,110,99,104,32,116,104,97,116,32,99,111,110,116,97,105,110,101,114,32,97,110,100,32,101,110,100,32,98,117,105,108,100,10,10,45,32,99,114,101,97,116,101,115,32,116,104,101,32,101,110,99,114,121,112,116,105,111,110,32,107,101,121,32,40,98,97,115,105,99,97,108,108,121,32,105,116,115,32,99,114,101,97,116,101,115,32,97,32,102,105,108,101,32,99,97,108,108,101,100,32,42,42,115,114,99,47,109,97,99,114,111,115,46,101,110,99,114,121,112,116,95,107,101,121,46,104,42,42,32,41,32,99,111,110,116,97,105,110,105,110,103,32,10,32,32,97,32,109,97,99,114,111,32,99,97,108,108,101,100,32,42,42,82,97,103,99,114,97,102,116,95,103,101,116,95,107,101,121,42,42,32,116,104,97,116,32,105,116,115,32,117,115,101,100,32,116,111,32,103,101,116,32,116,104,101,32,101,110,99,114,121,112,116,105,111,110,32,107,101,121,32,10,32,32,99,104,101,99,107,32,91,107,101,121,95,111,98,102,117,115,99,97,116,101,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,107,101,121,95,111,98,102,117,115,99,97,116,101,41,32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,10,32,32,10,45,32,73,110,115,116,97,108,108,115,32,116,104,101,32,100,101,112,101,110,100,101,110,99,105,101,115,10,45,32,99,114,101,97,116,101,32,116,104,101,32,97,115,115,101,116,115,32,101,109,98,101,100,32,118,97,114,115,32,91,65,115,115,101,116,115,32,100,111,99,115,93,40,47,97,115,115,101,116,115,47,100,111,99,115,47,97,115,115,101,116,115,95,101,109,98,101,100,95,118,97,114,115,46,109,100,41,10,45,32,109,97,107,101,32,115,105,108,118,101,114,32,99,104,97,105,110,32,115,114,99,32,111,114,103,97,110,105,122,97,116,105,111,110,32,114,101,97,100,32,91,98,117,105,108,100,95,116,111,111,108,99,104,97,105,110,46,109,100,93,40,47,97,115,115,101,116,115,47,100,111,99,115,47,98,117,105,108,100,95,116,111,111,108,99,104,97,105,110,46,109,100,41,32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,10,45,32,99,114,101,97,116,101,32,116,104,101,32,91,98,117,105,108,100,95,102,117,110,99,116,105,111,110,115,93,40,47,98,117,105,108,100,47,98,117,105,108,100,95,102,117,110,99,115,46,108,117,97,41,32,97,110,100,32,115,116,111,114,101,115,32,111,110,32,97,32,116,97,98,108,101,44,32,116,111,32,98,101,32,97,98,108,101,32,116,111,32,98,101,32,99,97,108,108,101,100,32,99,111,114,114,101,108,97,116,101,100,32,116,111,32,99,111,109,109,97,110,100,32,108,105,110,101,115,10,45,32,105,116,101,114,97,116,101,32,111,118,101,114,32,116,104,101,32,98,117,105,108,100,32,102,117,110,99,116,105,111,110,115,32,97,110,100,32,99,97,108,108,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,104,97,116,32,109,97,116,99,104,101,115,32,116,104,101,32,99,111,109,109,97,110,100,32,108,105,110,101,10,10,35,35,35,32,66,117,105,108,100,32,70,117,110,99,116,105,111,110,115,10,10,45,32,91,97,109,97,108,103,97,109,97,116,105,111,110,95,98,117,105,108,100,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,97,109,97,108,103,97,109,97,116,105,111,110,95,98,117,105,108,100,46,108,117,97,41,32,103,101,110,101,114,97,116,101,32,116,104,101,32,42,42,114,101,108,101,97,115,101,47,82,97,103,99,114,97,102,116,46,99,42,42,32,102,105,108,101,32,116,104,97,116,32,99,111,110,116,97,105,110,115,32,97,108,108,32,116,104,101,32,115,111,117,114,99,101,32,99,111,100,101,32,111,102,32,116,104,101,32,112,114,111,106,101,99,116,10,45,32,91,97,108,112,105,110,101,95,115,116,97,116,105,99,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,97,108,112,105,110,101,95,115,116,97,116,105,99,95,98,117,105,108,100,46,108,117,97,41,32,98,117,105,108,100,32,116,104,101,32,112,114,111,106,101,99,116,32,117,115,105,110,103,32,97,108,112,105,110,101,32,108,105,110,117,120,32,97,110,100,32,115,116,97,116,105,99,32,108,105,110,107,105,110,103,32,97,110,100,32,103,101,110,101,114,97,116,101,115,32,116,104,101,32,42,42,114,101,108,101,97,115,101,47,82,97,103,99,114,97,102,116,46,111,117,116,42,42,32,98,105,110,97,114,121,10,45,32,91,100,101,98,105,97,110,95,115,116,97,116,105,99,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,100,101,98,105,97,110,95,115,116,97,116,105,99,95,98,117,105,108,100,46,108,117,97,41,32,98,117,105,108,100,32,116,104,101,32,42,42,114,101,108,101,97,115,101,47,82,97,103,99,114,97,102,116,46,100,101,98,42,42,32,112,97,99,107,97,103,101,10,45,32,91,108,111,99,97,108,95,108,105,110,117,120,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,108,111,99,97,108,95,108,105,110,117,120,95,98,117,105,108,100,46,108,117,97,41,32,98,117,105,108,100,32,116,104,101,32,112,114,111,106,101,99,116,32,117,115,105,110,103,32,116,104,101,32,108,111,99,97,108,32,108,105,110,117,120,32,97,110,100,32,103,101,110,101,114,97,116,101,115,32,116,104,101,32,42,42,82,97,103,99,114,97,102,116,42,42,32,98,105,110,97,114,121,32,105,110,32,116,104,101,32,114,111,111,116,32,102,111,108,100,101,114,32,111,102,32,116,104,101,32,112,114,111,106,101,99,116,10,45,32,91,114,112,109,95,115,116,97,116,105,99,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,114,112,109,95,115,116,97,116,105,99,95,98,117,105,108,100,46,108,117,97,41,32,98,117,105,108,100,32,116,104,101,32,42,42,114,101,108,101,97,115,101,47,82,97,103,99,114,97,102,116,46,114,112,109,42,42,32,112,97,99,107,97,103,101,10,45,32,91,119,105,110,100,111,119,115,54,52,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,119,105,110,100,111,119,115,54,52,95,98,117,105,108,100,46,108,117,97,41,32,98,117,105,108,100,32,116,104,101,32,112,114,111,106,101,99,116,32,117,115,105,110,103,32,119,105,110,100,111,119,115,32,54,52,98,105,116,115,32,97,110,100,32,103,101,110,101,114,97,116,101,115,32,116,104,101,32,42,42,114,101,108,101,97,115,101,47,82,97,103,99,114,97,102,116,54,52,46,101,120,101,42,42,32,98,105,110,97,114,121,10,45,32,91,119,105,110,100,111,119,115,105,51,50,95,98,117,105,108,100,46,108,117,97,93,40,47,98,117,105,108,100,47,98,117,105,108,100,47,119,105,110,100,111,119,115,105,51,50,95,98,117,105,108,100,46,108,117,97,41,32,98,117,105,108,100,32,116,104,101,32,112,114,111,106,101,99,116,32,117,115,105,110,103,32,119,105,110,100,111,119,115,32,51,50,98,105,116,115,32,97,110,100,32,103,101,110,101,114,97,116,101,115,32,116,104,101,32,42,42,114,101,108,101,97,115,101,47,82,97,103,99,114,97,102,116,105,51,50,46,101,120,101,42,42,32,98,105,110,97,114,121,0},.size=2092},
(Asset){.path="docs/cli_usage.md",.data=(unsigned char[]){35,35,32,67,108,105,32,85,115,97,103,101,10,10,35,35,35,32,67,111,110,102,105,103,117,114,101,32,97,32,109,111,100,101,108,10,70,111,114,32,67,111,110,102,105,103,117,114,101,32,97,32,109,111,100,101,108,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,32,45,45,117,114,108,32,104,116,116,112,115,58,47,47,97,112,105,46,120,46,97,105,47,118,49,47,99,104,97,116,47,99,111,109,112,108,101,116,105,111,110,115,32,32,32,45,45,107,101,121,32,34,121,111,117,114,32,107,101,121,34,10,96,96,96,10,10,35,35,35,32,83,116,97,114,116,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,10,70,111,114,32,115,116,97,114,116,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,115,116,97,114,116,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,115,116,97,114,116,10,96,96,96,10,35,35,35,32,83,116,97,114,116,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,97,32,109,111,100,101,108,10,70,111,114,32,115,116,97,114,116,32,116,104,101,32,97,112,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,97,32,109,111,100,101,108,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,115,116,97,114,116,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,32,97,110,100,32,116,104,101,32,109,111,100,101,108,32,97,115,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,115,116,97,114,116,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,10,96,96,96,10,10,35,35,35,32,76,105,115,116,32,77,111,100,101,108,115,32,10,116,111,32,108,105,115,116,32,116,104,101,32,109,111,100,101,108,115,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,108,105,115,116,95,109,111,100,101,108,115,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,108,105,115,116,95,109,111,100,101,108,115,10,96,96,96,10,10,35,35,35,32,82,101,109,111,118,101,32,77,111,100,101,108,10,10,70,111,114,32,114,101,109,111,118,101,32,97,32,109,111,100,101,108,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,114,101,109,111,118,101,95,109,111,100,101,108,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,114,101,109,111,118,101,95,109,111,100,101,108,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,10,96,96,96,10,10,35,35,35,32,83,101,116,32,109,111,100,101,108,32,97,115,32,68,101,102,97,117,108,116,32,10,70,111,114,32,115,101,116,32,97,32,109,111,100,101,108,32,97,115,32,100,101,102,97,117,108,116,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,10,96,96,96,10,35,35,35,32,82,101,115,115,101,116,32,67,111,110,102,105,103,117,114,97,116,105,111,110,10,70,111,114,32,114,101,115,115,101,116,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,114,101,115,115,101,116,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,114,101,115,115,101,116,10,96,96,96,10,10,35,35,35,32,71,101,116,32,72,101,108,112,10,70,111,114,32,103,101,116,32,104,101,108,112,44,32,121,111,117,32,106,117,115,116,32,110,101,101,100,32,116,111,32,99,97,108,108,32,42,42,82,97,103,67,114,97,102,116,42,42,32,112,97,115,115,105,110,103,32,42,42,104,101,108,112,42,42,32,97,115,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,58,10,10,96,96,96,98,97,115,104,10,82,97,103,67,114,97,102,116,32,104,101,108,112,10,96,96,96,10,0},.size=1466},
(Asset){.path="docs/json_model_config.md",.data=(unsigned char[]){35,35,35,32,74,115,111,110,32,77,111,100,101,108,32,67,111,110,102,105,103,10,10,101,118,101,114,121,32,116,105,109,101,32,121,111,117,32,99,97,108,108,32,97,110,121,32,97,99,116,105,111,110,32,111,102,32,116,104,101,32,99,108,105,44,105,116,32,97,99,99,101,115,115,32,116,104,101,32,99,111,110,102,105,103,32,106,115,111,110,10,116,104,101,32,42,42,99,111,110,102,105,103,32,106,115,111,110,42,42,32,105,116,115,32,97,32,106,115,111,110,32,116,104,97,116,32,105,116,115,32,101,110,99,114,121,112,116,101,100,32,97,110,100,32,115,97,118,101,100,32,105,110,116,111,32,116,104,101,32,117,115,101,114,32,104,111,109,101,32,100,105,114,101,99,116,111,114,121,10,116,104,101,32,99,111,110,102,105,103,32,106,115,111,110,32,105,116,115,32,117,115,101,100,32,116,111,32,115,116,111,114,101,32,116,104,101,32,109,111,100,101,108,115,44,32,117,114,108,115,44,32,97,110,100,32,107,101,121,115,32,102,114,111,109,32,116,104,101,32,117,115,101,114,44,97,110,100,32,105,116,115,32,115,97,118,101,100,32,105,110,116,111,32,116,104,101,115,101,10,102,111,114,109,97,116,58,10,10,96,96,96,106,115,111,110,10,91,32,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,34,109,111,100,101,108,34,58,32,32,32,32,32,32,32,32,34,103,114,111,107,45,50,45,108,97,116,101,115,116,34,44,10,32,32,32,32,32,32,32,32,34,107,101,121,34,58,32,32,34,121,111,117,114,95,107,101,121,34,44,10,32,32,32,32,32,32,32,32,34,117,114,108,34,58,32,32,34,104,116,116,112,115,58,47,47,97,112,105,46,120,46,97,105,47,118,49,47,99,104,97,116,47,99,111,109,112,108,101,116,105,111,110,115,34,44,10,32,32,32,32,32,32,32,32,34,100,101,102,97,117,108,116,34,58,32,32,32,32,32,32,116,114,117,101,10,32,32,32,32,125,44,10,32,32,32,32,123,10,32,32,32,32,32,32,32,32,34,109,111,100,101,108,34,58,32,32,32,32,32,32,32,32,34,103,112,116,45,51,46,53,45,116,117,114,98,111,34,44,10,32,32,32,32,32,32,32,32,34,107,101,121,34,58,32,32,34,121,111,117,114,95,107,101,121,34,44,10,32,32,32,32,32,32,32,32,34,117,114,108,34,58,32,32,34,104,116,116,112,115,58,47,47,111,112,101,110,97,105,46,99,111,109,47,118,49,47,99,104,97,116,47,99,111,109,112,108,101,116,105,111,110,115,34,44,10,32,32,32,32,125,10,32,32,32,32,10,93,10,10,96,96,96,10,10,35,35,35,32,84,104,101,32,106,115,111,110,32,108,111,99,97,116,105,111,110,10,116,104,101,32,106,115,111,110,32,108,111,99,97,116,105,111,110,32,105,116,115,32,100,101,102,105,110,101,100,32,98,121,32,121,111,117,114,32,101,110,99,114,121,112,116,101,100,32,107,101,121,32,43,32,32,116,104,101,32,104,111,109,101,32,100,105,114,101,99,116,111,114,121,32,111,102,32,116,104,101,32,117,115,101,114,10,105,116,115,32,105,109,112,108,101,109,101,110,116,101,100,32,111,110,32,102,117,110,99,116,105,111,110,32,91,99,114,101,97,116,101,95,117,115,101,114,95,99,111,110,102,105,103,95,109,111,100,101,108,115,95,112,97,116,104,93,40,47,115,114,99,47,109,111,100,101,108,95,112,114,111,112,115,47,102,100,101,102,105,110,101,46,109,111,100,101,108,95,112,114,111,112,115,46,99,41,10,10,121,111,117,32,99,97,110,32,103,101,116,32,116,104,101,32,112,97,116,104,32,108,111,99,97,116,105,111,110,32,112,117,116,116,105,110,103,32,97,32,115,105,109,112,108,101,32,112,114,105,110,116,102,32,111,110,32,116,104,101,32,103,108,111,98,97,108,32,42,42,99,111,110,102,105,103,95,112,97,116,104,42,42,32,118,97,114,105,97,98,108,101,10,10,96,96,96,99,10,112,114,105,110,116,102,40,34,99,111,110,102,105,103,32,112,97,116,104,58,32,37,115,92,110,34,44,99,111,110,102,105,103,95,112,97,116,104,41,59,10,96,96,96,10,35,35,35,32,84,104,101,32,74,115,111,110,32,69,110,99,114,121,112,116,105,111,110,10,116,104,101,32,106,115,111,110,32,105,116,115,32,101,110,99,114,121,112,116,101,100,32,111,110,32,101,118,101,114,121,32,115,97,118,101,32,97,110,100,32,100,101,99,114,121,112,116,101,100,32,111,110,32,101,118,101,114,121,32,114,101,97,100,44,32,116,104,101,32,101,110,99,114,121,112,116,105,111,110,32,105,116,115,32,109,97,100,101,32,98,121,32,116,104,101,32,102,117,110,99,116,105,111,110,115,10,42,42,100,116,119,46,101,110,99,114,121,112,116,105,111,110,46,119,114,105,116,101,95,115,116,114,105,110,103,95,102,105,108,101,95,99,111,110,116,101,110,116,95,104,101,120,42,42,32,32,97,110,100,32,42,42,100,116,119,46,101,110,99,114,121,112,116,105,111,110,46,108,111,97,100,95,115,116,114,105,110,103,95,102,105,108,101,95,99,111,110,116,101,110,116,95,104,101,120,42,42,32,111,110,32,97,108,108,32,116,104,101,32,10,91,97,99,116,105,111,110,115,93,40,47,115,114,99,47,97,99,116,105,111,110,115,47,41,32,102,105,108,101,115,46,10,84,104,101,32,103,108,111,98,97,108,32,101,110,99,114,121,112,116,105,111,110,32,111,98,106,101,99,116,32,108,111,99,97,108,105,122,101,100,32,97,116,32,91,103,111,98,97,108,115,93,40,47,115,114,99,47,103,108,111,98,97,108,115,46,109,97,105,110,95,111,98,106,46,99,41,32,105,116,115,32,105,110,105,116,105,97,108,105,122,101,100,32,105,110,32,116,104,101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,91,109,97,105,110,93,40,47,115,114,99,47,109,97,105,110,46,99,41,32,102,105,108,101,44,32,97,110,100,32,117,115,101,115,32,116,104,101,32,32,42,42,45,45,101,110,99,114,121,112,116,95,107,101,121,42,42,32,121,111,117,32,112,97,115,115,32,111,110,32,116,104,101,32,98,117,105,108,100,32,112,97,114,116,44,32,116,104,97,116,32,105,116,115,32,116,114,97,110,115,102,111,114,109,101,100,32,111,110,32,116,104,101,32,10,109,97,99,114,111,32,42,42,65,105,82,97,103,84,101,109,112,108,97,116,101,95,103,101,116,95,107,101,121,42,42,0},.size=1512},
(Asset){.path="docs/licenses.md",.data=(unsigned char[]){35,35,35,32,91,85,110,105,118,101,114,115,97,108,32,83,111,99,107,101,116,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,83,97,109,117,101,108,72,101,110,114,105,113,117,101,68,101,77,111,114,97,105,115,86,105,116,114,105,111,47,85,110,105,118,101,114,115,97,108,83,111,99,107,101,116,41,10,10,85,110,105,118,101,114,115,97,108,83,111,99,107,101,116,32,105,115,32,97,32,99,114,111,115,115,45,112,108,97,116,102,111,114,109,32,67,32,115,111,99,107,101,116,32,108,105,98,114,97,114,121,32,100,101,115,105,103,110,101,100,32,116,111,32,115,105,109,112,108,105,102,121,32,115,111,99,107,101,116,32,112,114,111,103,114,97,109,109,105,110,103,32,111,110,32,98,111,116,104,32,76,105,110,117,120,32,97,110,100,32,87,105,110,100,111,119,115,32,112,108,97,116,102,111,114,109,115,46,32,84,104,105,115,32,108,105,98,114,97,114,121,32,97,98,115,116,114,97,99,116,115,32,116,104,101,32,112,108,97,116,102,111,114,109,45,115,112,101,99,105,102,105,99,32,100,101,116,97,105,108,115,32,97,110,100,32,112,114,111,118,105,100,101,115,32,97,32,117,110,105,102,105,101,100,32,65,80,73,32,102,111,114,32,115,111,99,107,101,116,32,99,114,101,97,116,105,111,110,44,32,99,111,109,109,117,110,105,99,97,116,105,111,110,44,32,97,110,100,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103,46,10,10,73,116,32,115,117,112,112,111,114,116,115,32,98,111,116,104,32,73,80,118,52,32,97,110,100,32,73,80,118,54,32,97,100,100,114,101,115,115,101,115,44,32,97,115,32,119,101,108,108,32,97,115,32,84,67,80,44,32,85,68,80,44,32,97,110,100,32,114,97,119,32,115,111,99,107,101,116,115,46,32,84,104,101,32,108,105,98,114,97,114,121,32,97,108,115,111,32,97,108,108,111,119,115,32,102,111,114,32,115,111,99,107,101,116,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,117,115,105,110,103,32,99,111,109,109,111,110,32,115,111,99,107,101,116,32,111,112,116,105,111,110,115,32,97,110,100,32,104,97,110,100,108,101,115,32,116,121,112,105,99,97,108,32,115,111,99,107,101,116,32,111,112,101,114,97,116,105,111,110,115,32,108,105,107,101,32,98,105,110,100,105,110,103,44,32,108,105,115,116,101,110,105,110,103,44,32,99,111,110,110,101,99,116,105,110,103,44,32,97,110,100,32,97,99,99,101,112,116,105,110,103,32,99,111,110,110,101,99,116,105,111,110,115,46,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,83,97,109,117,101,108,32,72,101,110,114,105,113,117,101,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,10,35,35,35,32,91,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,83,97,109,117,101,108,72,101,110,114,105,113,117,101,68,101,77,111,114,97,105,115,86,105,116,114,105,111,47,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,41,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,53,32,83,97,109,117,101,108,32,72,101,110,114,105,113,117,101,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,10,35,35,35,32,91,99,97,110,100,97,110,103,111,69,110,103,105,110,101,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,83,97,109,117,101,108,72,101,110,114,105,113,117,101,68,101,77,111,114,97,105,115,86,105,116,114,105,111,47,99,97,110,100,97,110,103,111,69,110,103,105,110,101,41,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,83,97,109,117,101,108,32,72,101,110,114,105,113,117,101,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,10,35,35,35,32,91,66,101,97,114,83,83,76,93,40,104,116,116,112,115,58,47,47,98,101,97,114,115,115,108,46,111,114,103,47,41,10,66,101,97,114,83,83,76,32,105,115,32,97,32,115,109,97,108,108,44,32,102,97,115,116,44,32,112,111,114,116,97,98,108,101,44,32,97,110,100,32,101,109,98,101,100,100,97,98,108,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102,32,116,104,101,32,83,83,76,47,84,76,83,32,112,114,111,116,111,99,111,108,32,40,105,110,99,108,117,100,105,110,103,32,84,76,83,32,49,46,51,41,32,119,114,105,116,116,101,110,32,105,110,32,67,46,32,73,116,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,98,101,32,101,97,115,121,32,116,111,32,117,110,100,101,114,115,116,97,110,100,44,32,117,115,101,44,32,97,110,100,32,105,110,116,101,103,114,97,116,101,32,105,110,116,111,32,121,111,117,114,32,97,112,112,108,105,99,97,116,105,111,110,46,32,66,101,97,114,83,83,76,32,105,115,32,97,32,102,114,101,101,32,115,111,102,116,119,97,114,101,32,112,114,111,106,101,99,116,44,32,97,110,100,32,105,116,32,105,115,32,108,105,99,101,110,115,101,100,32,117,110,100,101,114,32,116,104,101,32,77,73,84,32,76,105,99,101,110,115,101,46,10,10,10,32,32,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,49,54,32,84,104,111,109,97,115,32,80,111,114,110,105,110,32,60,112,111,114,110,105,110,64,98,111,108,101,116,46,111,114,103,62,10,32,10,32,32,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,10,32,97,32,99,111,112,121,32,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,10,32,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,32,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,10,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,32,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,10,32,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,32,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,10,32,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,32,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,10,32,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,32,10,32,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,10,32,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,32,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,32,10,32,32,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,10,32,32,69,88,80,82,69,83,83,32,79,82,32,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,10,32,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,32,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,10,32,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,32,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,10,32,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,32,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,10,32,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,32,79,85,84,32,79,70,32,79,82,32,73,78,10,32,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,32,32,83,79,70,84,87,65,82,69,46,10,32,10,10,35,35,35,32,91,99,74,83,79,78,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,68,97,118,101,71,97,109,98,108,101,47,99,74,83,79,78,41,10,10,67,74,83,79,78,32,105,115,32,97,32,108,105,103,104,116,119,101,105,103,104,116,32,74,83,79,78,32,112,97,114,115,101,114,32,119,114,105,116,116,101,110,32,105,110,32,67,46,32,73,116,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,98,101,32,101,97,115,121,32,116,111,32,117,115,101,44,32,102,97,115,116,44,32,97,110,100,32,112,111,114,116,97,98,108,101,46,32,84,104,101,32,108,105,98,114,97,114,121,32,112,114,111,118,105,100,101,115,32,102,117,110,99,116,105,111,110,115,32,102,111,114,32,112,97,114,115,105,110,103,32,74,83,79,78,32,100,97,116,97,44,32,99,114,101,97,116,105,110,103,32,74,83,79,78,32,111,98,106,101,99,116,115,44,32,97,110,100,32,109,97,110,105,112,117,108,97,116,105,110,103,32,74,83,79,78,32,111,98,106,101,99,116,115,46,32,73,116,32,105,115,32,115,117,105,116,97,98,108,101,32,102,111,114,32,117,115,101,32,105,110,32,101,109,98,101,100,100,101,100,32,115,121,115,116,101,109,115,32,97,110,100,32,111,116,104,101,114,32,114,101,115,111,117,114,99,101,45,99,111,110,115,116,114,97,105,110,101,100,32,101,110,118,105,114,111,110,109,101,110,116,115,46,10,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,48,57,45,50,48,49,55,32,68,97,118,101,32,71,97,109,98,108,101,32,97,110,100,32,99,74,83,79,78,32,99,111,110,116,114,105,98,117,116,111,114,115,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,10,97,108,108,32,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,10,84,72,69,32,83,79,70,84,87,65,82,69,46,10,10,10,10,35,35,35,32,91,76,117,97,93,40,104,116,116,112,115,58,47,47,108,117,97,46,111,114,103,47,41,10,10,76,117,97,32,105,115,32,102,114,101,101,32,115,111,102,116,119,97,114,101,32,100,105,115,116,114,105,98,117,116,101,100,32,117,110,100,101,114,32,116,104,101,32,116,101,114,109,115,32,111,102,32,116,104,101,32,77,73,84,32,108,105,99,101,110,115,101,32,114,101,112,114,111,100,117,99,101,100,32,104,101,114,101,46,32,76,117,97,32,109,97,121,32,98,101,32,117,115,101,100,32,102,111,114,32,97,110,121,32,112,117,114,112,111,115,101,44,32,105,110,99,108,117,100,105,110,103,32,99,111,109,109,101,114,99,105,97,108,32,112,117,114,112,111,115,101,115,44,32,97,116,32,97,98,115,111,108,117,116,101,108,121,32,110,111,32,99,111,115,116,46,32,78,111,32,112,97,112,101,114,119,111,114,107,44,32,110,111,32,114,111,121,97,108,116,105,101,115,44,32,110,111,32,71,78,85,45,108,105,107,101,32,34,99,111,112,121,108,101,102,116,34,32,114,101,115,116,114,105,99,116,105,111,110,115,44,32,101,105,116,104,101,114,46,32,74,117,115,116,32,100,111,119,110,108,111,97,100,32,105,116,32,97,110,100,32,117,115,101,32,105,116,46,10,10,76,117,97,32,105,115,32,99,101,114,116,105,102,105,101,100,32,79,112,101,110,32,83,111,117,114,99,101,32,115,111,102,116,119,97,114,101,46,32,91,79,112,101,110,32,83,111,117,114,99,101,32,73,110,105,116,105,97,116,105,118,101,32,65,112,112,114,111,118,101,100,32,76,105,99,101,110,115,101,93,73,116,39,115,32,108,105,99,101,110,115,101,32,105,115,32,115,105,109,112,108,101,32,97,110,100,32,108,105,98,101,114,97,108,32,97,110,100,32,105,115,32,99,111,109,112,97,116,105,98,108,101,32,119,105,116,104,32,71,80,76,46,32,76,117,97,32,105,115,32,110,111,116,32,105,110,32,116,104,101,32,112,117,98,108,105,99,32,100,111,109,97,105,110,32,97,110,100,32,80,85,67,45,82,105,111,32,107,101,101,112,115,32,105,116,115,32,99,111,112,121,114,105,103,104,116,46,10,10,84,104,101,32,115,112,105,114,105,116,32,111,102,32,116,104,101,32,76,117,97,32,108,105,99,101,110,115,101,32,105,115,32,116,104,97,116,32,121,111,117,32,97,114,101,32,102,114,101,101,32,116,111,32,117,115,101,32,76,117,97,32,102,111,114,32,97,110,121,32,112,117,114,112,111,115,101,32,97,116,32,110,111,32,99,111,115,116,32,119,105,116,104,111,117,116,32,104,97,118,105,110,103,32,116,111,32,97,115,107,32,117,115,46,32,84,104,101,32,111,110,108,121,32,114,101,113,117,105,114,101,109,101,110,116,32,105,115,32,116,104,97,116,32,105,102,32,121,111,117,32,100,111,32,117,115,101,32,76,117,97,44,32,116,104,101,110,32,121,111,117,32,115,104,111,117,108,100,32,103,105,118,101,32,117,115,32,99,114,101,100,105,116,32,98,121,32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,115,111,109,101,119,104,101,114,101,32,105,110,32,121,111,117,114,32,112,114,111,100,117,99,116,32,111,114,32,105,116,115,32,100,111,99,117,109,101,110,116,97,116,105,111,110,46,32,65,32,110,105,99,101,44,32,98,117,116,32,111,112,116,105,111,110,97,108,44,32,119,97,121,32,116,111,32,103,105,118,101,32,117,115,32,102,117,114,116,104,101,114,32,99,114,101,100,105,116,32,105,115,32,116,111,32,105,110,99,108,117,100,101,32,97,32,76,117,97,32,108,111,103,111,32,97,110,100,32,97,32,108,105,110,107,32,116,111,32,111,117,114,32,115,105,116,101,32,105,110,32,97,32,119,101,98,32,112,97,103,101,32,102,111,114,32,121,111,117,114,32,112,114,111,100,117,99,116,46,10,10,84,104,101,32,76,117,97,32,108,97,110,103,117,97,103,101,32,105,115,32,101,110,116,105,114,101,108,121,32,100,101,115,105,103,110,101,100,44,32,105,109,112,108,101,109,101,110,116,101,100,44,32,97,110,100,32,109,97,105,110,116,97,105,110,101,100,32,98,121,32,97,32,116,101,97,109,32,97,116,32,80,85,67,45,82,105,111,32,105,110,32,66,114,97,122,105,108,46,32,84,104,101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,105,115,32,110,111,116,32,100,101,114,105,118,101,100,32,102,114,111,109,32,108,105,99,101,110,115,101,100,32,115,111,102,116,119,97,114,101,46,10,10,10,35,35,35,32,91,115,104,97,45,50,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,97,109,111,115,110,105,101,114,47,115,104,97,45,50,41,10,10,90,101,114,111,32,67,108,97,117,115,101,32,66,83,68,32,76,105,99,101,110,115,101,10,194,169,32,50,48,50,49,32,65,108,97,105,110,32,77,111,115,110,105,101,114,10,10,80,101,114,109,105,115,115,105,111,110,32,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,97,110,100,47,111,114,32,100,105,115,116,114,105,98,117,116,101,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,102,111,114,32,97,110,121,32,112,117,114,112,111,115,101,32,119,105,116,104,32,111,114,32,119,105,116,104,111,117,116,32,102,101,101,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,32,65,78,68,32,84,72,69,32,65,85,84,72,79,82,32,68,73,83,67,76,65,73,77,83,32,65,76,76,32,87,65,82,82,65,78,84,73,69,83,32,87,73,84,72,32,82,69,71,65,82,68,32,84,79,32,84,72,73,83,32,83,79,70,84,87,65,82,69,32,73,78,67,76,85,68,73,78,71,32,65,76,76,32,73,77,80,76,73,69,68,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,32,65,78,68,32,70,73,84,78,69,83,83,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,32,65,85,84,72,79,82,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,83,80,69,67,73,65,76,44,32,68,73,82,69,67,84,44,32,73,78,68,73,82,69,67,84,44,32,79,82,32,67,79,78,83,69,81,85,69,78,84,73,65,76,32,68,65,77,65,71,69,83,32,79,82,32,65,78,89,32,68,65,77,65,71,69,83,32,87,72,65,84,83,79,69,86,69,82,32,82,69,83,85,76,84,73,78,71,32,70,82,79,77,32,76,79,83,83,32,79,70,32,85,83,69,44,32,68,65,84,65,32,79,82,32,80,82,79,70,73,84,83,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,78,69,71,76,73,71,69,78,67,69,32,79,82,32,79,84,72,69,82,32,84,79,82,84,73,79,85,83,32,65,67,84,73,79,78,44,32,65,82,73,83,73,78,71,32,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,85,83,69,32,79,82,32,80,69,82,70,79,82,77,65,78,67,69,32,79,70,32,84,72,73,83,32,83,79,70,84,87,65,82,69,46,10,10,10,10,35,35,35,32,91,116,105,110,121,45,65,69,83,45,99,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,107,111,107,107,101,47,116,105,110,121,45,65,69,83,45,99,41,10,10,84,104,105,115,32,105,115,32,102,114,101,101,32,97,110,100,32,117,110,101,110,99,117,109,98,101,114,101,100,32,115,111,102,116,119,97,114,101,32,114,101,108,101,97,115,101,100,32,105,110,116,111,32,116,104,101,32,112,117,98,108,105,99,32,100,111,109,97,105,110,46,10,10,65,110,121,111,110,101,32,105,115,32,102,114,101,101,32,116,111,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,112,117,98,108,105,115,104,44,32,117,115,101,44,32,99,111,109,112,105,108,101,44,32,115,101,108,108,44,32,111,114,10,100,105,115,116,114,105,98,117,116,101,32,116,104,105,115,32,115,111,102,116,119,97,114,101,44,32,101,105,116,104,101,114,32,105,110,32,115,111,117,114,99,101,32,99,111,100,101,32,102,111,114,109,32,111,114,32,97,115,32,97,32,99,111,109,112,105,108,101,100,10,98,105,110,97,114,121,44,32,102,111,114,32,97,110,121,32,112,117,114,112,111,115,101,44,32,99,111,109,109,101,114,99,105,97,108,32,111,114,32,110,111,110,45,99,111,109,109,101,114,99,105,97,108,44,32,97,110,100,32,98,121,32,97,110,121,10,109,101,97,110,115,46,10,10,73,110,32,106,117,114,105,115,100,105,99,116,105,111,110,115,32,116,104,97,116,32,114,101,99,111,103,110,105,122,101,32,99,111,112,121,114,105,103,104,116,32,108,97,119,115,44,32,116,104,101,32,97,117,116,104,111,114,32,111,114,32,97,117,116,104,111,114,115,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,100,101,100,105,99,97,116,101,32,97,110,121,32,97,110,100,32,97,108,108,32,99,111,112,121,114,105,103,104,116,32,105,110,116,101,114,101,115,116,32,105,110,32,116,104,101,10,115,111,102,116,119,97,114,101,32,116,111,32,116,104,101,32,112,117,98,108,105,99,32,100,111,109,97,105,110,46,32,87,101,32,109,97,107,101,32,116,104,105,115,32,100,101,100,105,99,97,116,105,111,110,32,102,111,114,32,116,104,101,32,98,101,110,101,102,105,116,10,111,102,32,116,104,101,32,112,117,98,108,105,99,32,97,116,32,108,97,114,103,101,32,97,110,100,32,116,111,32,116,104,101,32,100,101,116,114,105,109,101,110,116,32,111,102,32,111,117,114,32,104,101,105,114,115,32,97,110,100,10,115,117,99,99,101,115,115,111,114,115,46,32,87,101,32,105,110,116,101,110,100,32,116,104,105,115,32,100,101,100,105,99,97,116,105,111,110,32,116,111,32,98,101,32,97,110,32,111,118,101,114,116,32,97,99,116,32,111,102,10,114,101,108,105,110,113,117,105,115,104,109,101,110,116,32,105,110,32,112,101,114,112,101,116,117,105,116,121,32,111,102,32,97,108,108,32,112,114,101,115,101,110,116,32,97,110,100,32,102,117,116,117,114,101,32,114,105,103,104,116,115,32,116,111,32,116,104,105,115,10,115,111,102,116,119,97,114,101,32,117,110,100,101,114,32,99,111,112,121,114,105,103,104,116,32,108,97,119,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,10,69,88,80,82,69,83,83,32,79,82,32,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,10,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,32,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,10,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,32,65,85,84,72,79,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,10,79,84,72,69,82,32,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,10,65,82,73,83,73,78,71,32,70,82,79,77,44,32,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,10,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,32,83,79,70,84,87,65,82,69,46,10,10,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,112,108,101,97,115,101,32,114,101,102,101,114,32,116,111,32,60,104,116,116,112,58,47,47,117,110,108,105,99,101,110,115,101,46,111,114,103,47,62,10,10,35,35,35,32,91,66,101,97,114,72,116,116,112,115,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,53,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,67,45,97,114,103,118,45,80,97,114,115,101,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,67,45,97,114,103,118,45,112,97,114,115,101,114,41,10,10,84,104,105,115,32,105,115,32,102,114,101,101,32,97,110,100,32,117,110,101,110,99,117,109,98,101,114,101,100,32,115,111,102,116,119,97,114,101,32,114,101,108,101,97,115,101,100,32,105,110,116,111,32,116,104,101,32,112,117,98,108,105,99,32,100,111,109,97,105,110,46,10,10,65,110,121,111,110,101,32,105,115,32,102,114,101,101,32,116,111,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,112,117,98,108,105,115,104,44,32,117,115,101,44,32,99,111,109,112,105,108,101,44,32,115,101,108,108,44,32,111,114,10,100,105,115,116,114,105,98,117,116,101,32,116,104,105,115,32,115,111,102,116,119,97,114,101,44,32,101,105,116,104,101,114,32,105,110,32,115,111,117,114,99,101,32,99,111,100,101,32,102,111,114,109,32,111,114,32,97,115,32,97,32,99,111,109,112,105,108,101,100,10,98,105,110,97,114,121,44,32,102,111,114,32,97,110,121,32,112,117,114,112,111,115,101,44,32,99,111,109,109,101,114,99,105,97,108,32,111,114,32,110,111,110,45,99,111,109,109,101,114,99,105,97,108,44,32,97,110,100,32,98,121,32,97,110,121,10,109,101,97,110,115,46,10,10,73,110,32,106,117,114,105,115,100,105,99,116,105,111,110,115,32,116,104,97,116,32,114,101,99,111,103,110,105,122,101,32,99,111,112,121,114,105,103,104,116,32,108,97,119,115,44,32,116,104,101,32,97,117,116,104,111,114,32,111,114,32,97,117,116,104,111,114,115,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,100,101,100,105,99,97,116,101,32,97,110,121,32,97,110,100,32,97,108,108,32,99,111,112,121,114,105,103,104,116,32,105,110,116,101,114,101,115,116,32,105,110,32,116,104,101,10,115,111,102,116,119,97,114,101,32,116,111,32,116,104,101,32,112,117,98,108,105,99,32,100,111,109,97,105,110,46,32,87,101,32,109,97,107,101,32,116,104,105,115,32,100,101,100,105,99,97,116,105,111,110,32,102,111,114,32,116,104,101,32,98,101,110,101,102,105,116,10,111,102,32,116,104,101,32,112,117,98,108,105,99,32,97,116,32,108,97,114,103,101,32,97,110,100,32,116,111,32,116,104,101,32,100,101,116,114,105,109,101,110,116,32,111,102,32,111,117,114,32,104,101,105,114,115,32,97,110,100,10,115,117,99,99,101,115,115,111,114,115,46,32,87,101,32,105,110,116,101,110,100,32,116,104,105,115,32,100,101,100,105,99,97,116,105,111,110,32,116,111,32,98,101,32,97,110,32,111,118,101,114,116,32,97,99,116,32,111,102,10,114,101,108,105,110,113,117,105,115,104,109,101,110,116,32,105,110,32,112,101,114,112,101,116,117,105,116,121,32,111,102,32,97,108,108,32,112,114,101,115,101,110,116,32,97,110,100,32,102,117,116,117,114,101,32,114,105,103,104,116,115,32,116,111,32,116,104,105,115,10,115,111,102,116,119,97,114,101,32,117,110,100,101,114,32,99,111,112,121,114,105,103,104,116,32,108,97,119,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,10,69,88,80,82,69,83,83,32,79,82,32,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,10,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,32,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,10,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,32,65,85,84,72,79,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,10,79,84,72,69,82,32,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,10,65,82,73,83,73,78,71,32,70,82,79,77,44,32,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,10,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,32,83,79,70,84,87,65,82,69,46,10,10,70,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,44,32,112,108,101,97,115,101,32,114,101,102,101,114,32,116,111,32,60,104,116,116,112,115,58,47,47,117,110,108,105,99,101,110,115,101,46,111,114,103,62,10,10,35,35,35,32,91,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,111,84,104,101,87,111,114,108,100,41,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,51,32,77,97,116,101,117,115,32,77,111,117,116,105,110,104,111,32,81,117,101,105,114,111,122,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,10,35,35,35,32,91,68,97,114,119,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,97,114,119,105,110,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,76,117,97,67,69,109,98,101,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,67,69,109,98,101,100,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,77,97,116,101,117,115,32,77,111,117,116,105,110,104,111,32,81,117,101,105,114,111,122,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,10,35,35,35,32,91,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,67,65,109,97,108,103,97,109,97,116,111,114,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,76,117,97,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,68,111,84,104,101,87,111,114,108,100,41,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,76,117,97,70,108,117,105,100,74,115,111,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,70,108,117,105,100,74,115,111,110,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,76,117,97,65,114,103,118,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,65,114,103,118,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,77,97,116,101,117,115,32,77,111,117,116,105,110,104,111,32,81,117,101,105,114,111,122,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,76,117,97,83,105,108,118,101,114,67,104,97,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,83,105,108,118,101,114,67,104,97,105,110,41,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,76,117,97,83,104,105,112,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,76,117,97,83,104,105,112,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,53,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,10,35,35,35,32,91,67,65,109,97,108,103,97,109,97,116,111,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,67,65,109,97,108,103,97,109,97,116,111,114,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,10,35,35,35,32,91,83,105,108,118,101,114,67,104,97,105,110,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,83,105,108,118,101,114,67,104,97,105,110,41,10,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,52,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,10,32,10,10,35,35,35,32,91,107,101,121,95,111,98,102,117,115,99,97,116,101,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,107,101,121,95,111,98,102,117,115,99,97,116,101,41,10,77,73,84,32,76,105,99,101,110,115,101,10,10,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,50,53,32,79,85,73,10,10,80,101,114,109,105,115,115,105,111,110,32,105,115,32,104,101,114,101,98,121,32,103,114,97,110,116,101,100,44,32,102,114,101,101,32,111,102,32,99,104,97,114,103,101,44,32,116,111,32,97,110,121,32,112,101,114,115,111,110,32,111,98,116,97,105,110,105,110,103,32,97,32,99,111,112,121,10,111,102,32,116,104,105,115,32,115,111,102,116,119,97,114,101,32,97,110,100,32,97,115,115,111,99,105,97,116,101,100,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,102,105,108,101,115,32,40,116,104,101,32,34,83,111,102,116,119,97,114,101,34,41,44,32,116,111,32,100,101,97,108,10,105,110,32,116,104,101,32,83,111,102,116,119,97,114,101,32,119,105,116,104,111,117,116,32,114,101,115,116,114,105,99,116,105,111,110,44,32,105,110,99,108,117,100,105,110,103,32,119,105,116,104,111,117,116,32,108,105,109,105,116,97,116,105,111,110,32,116,104,101,32,114,105,103,104,116,115,10,116,111,32,117,115,101,44,32,99,111,112,121,44,32,109,111,100,105,102,121,44,32,109,101,114,103,101,44,32,112,117,98,108,105,115,104,44,32,100,105,115,116,114,105,98,117,116,101,44,32,115,117,98,108,105,99,101,110,115,101,44,32,97,110,100,47,111,114,32,115,101,108,108,10,99,111,112,105,101,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,44,32,97,110,100,32,116,111,32,112,101,114,109,105,116,32,112,101,114,115,111,110,115,32,116,111,32,119,104,111,109,32,116,104,101,32,83,111,102,116,119,97,114,101,32,105,115,10,102,117,114,110,105,115,104,101,100,32,116,111,32,100,111,32,115,111,44,32,115,117,98,106,101,99,116,32,116,111,32,116,104,101,32,102,111,108,108,111,119,105,110,103,32,99,111,110,100,105,116,105,111,110,115,58,10,10,84,104,101,32,97,98,111,118,101,32,99,111,112,121,114,105,103,104,116,32,110,111,116,105,99,101,32,97,110,100,32,116,104,105,115,32,112,101,114,109,105,115,115,105,111,110,32,110,111,116,105,99,101,32,115,104,97,108,108,32,98,101,32,105,110,99,108,117,100,101,100,32,105,110,32,97,108,108,10,99,111,112,105,101,115,32,111,114,32,115,117,98,115,116,97,110,116,105,97,108,32,112,111,114,116,105,111,110,115,32,111,102,32,116,104,101,32,83,111,102,116,119,97,114,101,46,10,10,84,72,69,32,83,79,70,84,87,65,82,69,32,73,83,32,80,82,79,86,73,68,69,68,32,34,65,83,32,73,83,34,44,32,87,73,84,72,79,85,84,32,87,65,82,82,65,78,84,89,32,79,70,32,65,78,89,32,75,73,78,68,44,32,69,88,80,82,69,83,83,32,79,82,10,73,77,80,76,73,69,68,44,32,73,78,67,76,85,68,73,78,71,32,66,85,84,32,78,79,84,32,76,73,77,73,84,69,68,32,84,79,32,84,72,69,32,87,65,82,82,65,78,84,73,69,83,32,79,70,32,77,69,82,67,72,65,78,84,65,66,73,76,73,84,89,44,10,70,73,84,78,69,83,83,32,70,79,82,32,65,32,80,65,82,84,73,67,85,76,65,82,32,80,85,82,80,79,83,69,32,65,78,68,32,78,79,78,73,78,70,82,73,78,71,69,77,69,78,84,46,32,73,78,32,78,79,32,69,86,69,78,84,32,83,72,65,76,76,32,84,72,69,10,65,85,84,72,79,82,83,32,79,82,32,67,79,80,89,82,73,71,72,84,32,72,79,76,68,69,82,83,32,66,69,32,76,73,65,66,76,69,32,70,79,82,32,65,78,89,32,67,76,65,73,77,44,32,68,65,77,65,71,69,83,32,79,82,32,79,84,72,69,82,10,76,73,65,66,73,76,73,84,89,44,32,87,72,69,84,72,69,82,32,73,78,32,65,78,32,65,67,84,73,79,78,32,79,70,32,67,79,78,84,82,65,67,84,44,32,84,79,82,84,32,79,82,32,79,84,72,69,82,87,73,83,69,44,32,65,82,73,83,73,78,71,32,70,82,79,77,44,10,79,85,84,32,79,70,32,79,82,32,73,78,32,67,79,78,78,69,67,84,73,79,78,32,87,73,84,72,32,84,72,69,32,83,79,70,84,87,65,82,69,32,79,82,32,84,72,69,32,85,83,69,32,79,82,32,79,84,72,69,82,32,68,69,65,76,73,78,71,83,32,73,78,32,84,72,69,10,83,79,70,84,87,65,82,69,46,0},.size=25902},
(Asset){.path="docs/project_dependencies.md",.data=(unsigned char[]){84,104,101,115,101,32,80,114,111,106,101,99,116,32,85,115,101,32,116,104,101,32,70,111,108,108,111,119,105,110,103,32,68,101,112,101,110,100,101,110,99,105,101,115,58,10,35,35,35,32,91,67,45,97,114,103,118,45,112,97,114,115,101,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,67,45,97,114,103,118,45,112,97,114,115,101,114,41,10,105,116,115,32,117,115,101,100,32,116,111,32,112,97,114,115,101,32,116,104,101,32,99,111,109,109,97,110,100,32,108,105,110,101,32,97,114,103,117,109,101,110,116,115,44,32,105,116,115,32,117,115,101,100,32,105,110,32,116,104,101,32,91,109,97,105,110,46,99,93,40,47,115,114,99,47,109,97,105,110,46,99,41,32,116,111,32,112,97,114,115,101,32,116,104,101,32,99,111,109,109,97,110,100,32,108,105,110,101,32,97,114,103,117,109,101,110,116,115,46,10,97,110,100,32,117,115,101,100,32,98,121,32,97,108,108,32,91,97,99,116,105,111,110,115,93,40,47,115,114,99,47,97,99,116,105,111,110,115,41,32,116,111,32,112,97,114,115,101,32,116,104,101,32,97,114,103,117,109,101,110,116,115,32,111,102,32,116,104,101,32,97,99,116,105,111,110,115,46,10,10,10,35,35,35,32,91,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,41,10,91,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,41,32,105,116,115,32,117,115,101,100,32,98,121,32,91,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,83,97,109,117,101,108,72,101,110,114,105,113,117,101,68,101,77,111,114,97,105,115,86,105,116,114,105,111,47,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,41,32,116,111,32,97,99,99,101,115,115,32,97,112,105,32,117,114,108,115,32,119,105,116,104,32,104,116,116,112,115,46,10,10,35,35,35,32,91,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,83,97,109,117,101,108,72,101,110,114,105,113,117,101,68,101,77,111,114,97,105,115,86,105,116,114,105,111,47,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,41,32,32,10,91,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,83,97,109,117,101,108,72,101,110,114,105,113,117,101,68,101,77,111,114,97,105,115,86,105,116,114,105,111,47,67,108,105,101,110,116,83,68,75,79,112,101,110,65,73,41,32,105,116,115,32,116,104,101,32,109,97,105,110,32,115,100,107,32,111,102,32,116,104,101,32,112,114,111,106,101,99,116,44,32,105,116,32,117,115,101,115,32,91,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,66,101,97,114,72,116,116,112,115,67,108,105,101,110,116,41,32,116,111,32,97,99,99,101,115,115,32,116,104,101,32,97,112,105,32,117,114,108,115,46,10,112,114,111,118,105,100,105,110,103,32,97,108,108,32,97,105,32,102,117,110,99,116,105,111,110,115,32,110,101,99,101,115,115,97,114,121,32,116,111,32,98,117,105,108,100,32,116,104,101,32,97,103,101,110,116,115,46,10,116,104,101,32,115,100,107,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,115,32,105,110,32,116,104,101,32,112,114,111,106,101,99,116,32,97,114,101,32,108,111,99,97,116,101,100,32,105,110,32,91,102,100,101,102,105,110,101,46,115,116,97,114,116,46,99,93,40,47,115,114,99,47,97,99,116,105,111,110,115,47,115,116,97,114,116,47,102,100,101,102,105,110,101,46,115,116,97,114,116,46,99,41,32,40,109,97,105,110,32,99,104,97,116,41,32,97,110,100,32,111,110,10,91,102,100,101,102,105,110,101,46,97,105,95,102,117,110,99,116,105,111,110,115,46,99,93,40,47,115,114,99,47,97,105,95,102,117,110,99,116,105,111,110,115,47,102,100,101,102,105,110,101,46,97,105,95,102,117,110,99,116,105,111,110,115,46,99,41,40,102,117,110,99,116,105,111,110,115,32,116,104,97,116,32,99,97,110,32,98,101,32,99,97,108,108,101,100,32,98,121,32,65,73,41,10,10,10,35,35,35,32,91,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,111,84,104,101,87,111,114,108,100,41,32,10,91,68,111,84,104,101,87,111,114,108,100,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,111,84,104,101,87,111,114,108,100,41,32,105,116,115,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,100,101,97,108,105,110,103,32,119,105,116,104,32,102,105,108,101,115,32,97,110,100,32,100,105,114,101,99,116,111,114,105,101,115,44,32,115,111,32,105,116,115,32,117,115,101,100,32,116,111,32,10,116,104,101,32,91,102,100,101,102,105,110,101,46,97,105,95,102,117,110,99,116,105,111,110,115,46,99,93,40,47,115,114,99,47,97,105,95,102,117,110,99,116,105,111,110,115,47,102,100,101,102,105,110,101,46,97,105,95,102,117,110,99,116,105,111,110,115,46,99,41,32,116,111,32,97,99,99,101,115,115,32,100,105,114,101,99,116,111,114,105,101,115,32,97,110,100,32,102,105,108,101,115,44,32,97,110,100,32,105,116,115,32,97,108,115,111,32,117,115,101,100,32,116,111,32,114,101,97,100,32,10,32,97,110,100,32,119,114,105,116,101,32,116,104,101,32,42,42,46,111,117,105,95,109,111,100,101,108,115,46,106,115,111,110,42,42,32,40,106,115,111,110,32,116,104,97,116,32,115,116,111,114,101,32,117,115,101,114,32,109,111,100,101,108,115,41,10,10,35,35,35,32,91,99,74,83,79,78,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,68,97,118,101,71,97,109,98,108,101,47,99,74,83,79,78,41,32,10,73,116,115,32,117,115,101,100,32,116,111,32,112,97,114,115,101,32,97,110,100,32,100,117,109,112,32,116,104,101,32,42,42,46,111,117,105,95,109,111,100,101,108,115,46,106,115,111,110,42,42,32,102,105,108,101,44,32,105,116,115,32,109,111,115,116,108,121,32,117,115,101,100,32,105,110,32,116,104,101,32,91,99,111,110,102,106,115,111,110,93,40,47,115,114,99,47,99,111,110,102,106,115,111,110,47,41,32,97,110,100,32,111,110,32,91,109,111,100,101,108,95,112,114,111,112,115,93,40,47,115,114,99,47,109,111,100,101,108,95,112,114,111,112,115,47,41,0},.size=1760},
(Asset){.path="docs/project_workfow.md",.data=(unsigned char[]){35,35,35,32,80,114,111,106,101,99,116,32,87,111,114,107,102,108,111,119,32,97,110,100,32,117,115,101,32,99,97,115,101,10,10,87,104,101,110,32,116,104,101,32,112,114,111,106,101,99,116,32,115,116,97,114,116,115,32,97,116,32,91,109,97,105,110,46,99,93,40,47,115,114,99,47,109,97,105,110,46,99,41,32,116,104,101,32,102,105,114,115,116,32,116,104,105,110,103,32,116,104,97,116,32,105,116,39,115,32,116,111,32,99,114,101,97,116,101,32,116,104,101,32,10,103,108,111,98,97,108,115,32,111,98,106,101,99,116,115,32,108,111,99,97,116,101,100,32,105,110,32,91,103,108,111,98,97,108,115,93,40,47,115,114,99,47,103,108,111,98,97,108,115,46,109,97,105,110,95,111,98,106,46,99,41,58,32,10,35,35,35,32,71,108,111,98,97,108,115,32,10,45,32,42,42,97,114,103,115,95,111,98,106,42,42,32,111,98,106,101,99,116,32,116,111,32,115,116,111,114,101,32,116,104,101,32,97,114,103,118,32,107,101,121,115,32,44,32,99,104,101,99,107,91,67,45,97,114,103,118,45,112,97,114,115,101,114,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,67,45,97,114,103,118,45,112,97,114,115,101,114,41,10,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,10,10,45,32,42,42,99,111,110,102,105,103,95,112,97,116,104,42,42,32,111,98,106,101,99,116,32,116,111,32,115,116,111,114,101,32,116,104,101,32,112,97,116,104,32,111,102,32,116,104,101,32,91,99,111,110,102,105,103,95,106,115,111,110,93,40,47,100,111,99,115,47,106,115,111,110,95,109,111,100,101,108,95,99,111,110,102,105,103,46,109,100,41,32,102,105,108,101,10,32,32,32,32,116,104,97,116,32,117,115,101,115,32,116,104,101,32,109,97,99,114,111,32,42,42,65,105,82,97,103,84,101,109,112,108,97,116,101,95,103,101,116,95,107,101,121,42,42,32,97,110,100,32,42,42,65,105,82,97,103,84,101,109,112,108,97,116,101,95,107,101,121,95,115,105,122,101,42,42,32,116,111,32,103,101,116,32,116,104,101,32,101,110,99,114,121,112,116,105,111,110,32,107,101,121,10,10,45,32,42,42,101,110,99,114,121,112,116,105,111,110,42,42,32,111,98,106,101,99,116,32,116,111,32,114,101,97,100,32,97,110,100,32,119,114,105,116,101,32,116,104,101,32,91,99,111,110,102,105,103,95,106,115,111,110,93,40,47,100,111,99,115,47,106,115,111,110,95,109,111,100,101,108,95,99,111,110,102,105,103,46,109,100,41,32,102,105,108,101,32,97,110,100,32,101,110,99,114,121,112,116,32,116,104,101,32,100,97,116,97,10,32,32,99,104,101,99,107,32,91,68,111,84,104,101,87,111,114,108,100,32,69,110,99,114,121,112,116,105,111,110,32,68,111,99,115,93,40,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,68,111,84,104,101,87,111,114,108,100,47,98,108,111,98,47,109,97,105,110,47,100,111,99,115,47,101,110,99,114,121,112,116,105,111,110,46,109,100,41,32,102,111,114,32,109,111,114,101,32,100,101,116,97,105,108,115,10,10,10,97,102,116,101,114,32,105,116,32,44,32,105,116,32,103,101,116,115,32,116,104,101,32,42,42,97,99,116,105,111,110,42,42,32,102,114,111,109,32,116,104,101,32,117,115,101,114,44,32,32,119,104,105,99,104,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32,116,104,101,32,102,105,114,115,116,32,42,42,97,114,103,118,91,49,93,42,42,97,114,103,117,109,101,110,116,32,111,102,32,116,104,101,32,112,114,111,103,114,97,109,10,97,110,100,32,116,104,101,110,44,32,99,97,108,108,32,111,110,101,32,111,102,32,116,104,101,32,97,99,116,105,111,110,115,32,102,117,110,99,116,105,111,110,115,32,108,111,99,97,116,101,100,32,97,116,32,91,97,99,116,105,111,110,115,93,40,47,115,114,99,47,97,99,116,105,111,110,115,47,41,10,10,35,35,35,32,65,99,116,105,111,110,115,10,10,35,35,35,32,105,110,116,32,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,40,41,59,10,10,84,104,101,32,96,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,96,32,102,117,110,99,116,105,111,110,44,32,108,111,99,97,116,101,100,32,105,110,32,96,115,114,99,47,97,99,116,105,111,110,115,47,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,47,102,100,101,102,105,110,101,46,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,46,99,96,44,32,105,115,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,99,111,110,102,105,103,117,114,105,110,103,32,97,32,108,97,110,103,117,97,103,101,32,109,111,100,101,108,46,32,73,116,32,99,104,101,99,107,115,32,105,102,32,116,104,101,32,110,101,99,101,115,115,97,114,121,32,97,114,103,117,109,101,110,116,115,32,40,96,109,111,100,101,108,96,44,32,96,107,101,121,96,44,32,97,110,100,32,96,117,114,108,96,41,32,104,97,118,101,32,98,101,101,110,32,112,114,111,118,105,100,101,100,46,32,73,102,32,97,110,121,32,97,114,101,32,109,105,115,115,105,110,103,44,32,105,116,32,100,105,115,112,108,97,121,115,32,97,110,32,101,114,114,111,114,32,109,101,115,115,97,103,101,46,32,79,116,104,101,114,119,105,115,101,44,32,105,116,32,114,101,97,100,115,32,116,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,44,32,99,104,101,99,107,115,32,105,102,32,116,104,101,32,109,111,100,101,108,32,97,108,114,101,97,100,121,32,101,120,105,115,116,115,44,32,97,110,100,32,117,112,100,97,116,101,115,32,111,114,32,97,100,100,115,32,116,104,101,32,109,111,100,101,108,32,116,111,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,105,110,32,74,83,79,78,32,102,111,114,109,97,116,46,32,84,104,101,32,102,117,110,99,116,105,111,110,32,117,115,101,115,32,101,110,99,114,121,112,116,105,111,110,32,116,111,32,114,101,97,100,32,97,110,100,32,119,114,105,116,101,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,10,45,32,42,42,70,117,110,99,116,105,111,110,97,108,105,116,121,42,42,58,32,67,111,110,102,105,103,117,114,101,115,32,97,32,108,97,110,103,117,97,103,101,32,109,111,100,101,108,32,98,121,32,99,104,101,99,107,105,110,103,32,102,111,114,32,114,101,113,117,105,114,101,100,32,97,114,103,117,109,101,110,116,115,32,97,110,100,32,117,112,100,97,116,105,110,103,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,45,32,42,42,69,114,114,111,114,32,72,97,110,100,108,105,110,103,42,42,58,32,68,105,115,112,108,97,121,115,32,101,114,114,111,114,32,109,101,115,115,97,103,101,115,32,105,102,32,96,109,111,100,101,108,96,44,32,96,107,101,121,96,44,32,111,114,32,96,117,114,108,96,32,97,114,101,32,110,111,116,32,112,114,111,118,105,100,101,100,46,10,45,32,42,42,70,105,108,101,32,79,112,101,114,97,116,105,111,110,115,42,42,58,32,82,101,97,100,115,32,97,110,100,32,119,114,105,116,101,115,32,116,111,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,117,115,105,110,103,32,101,110,99,114,121,112,116,105,111,110,46,10,45,32,42,42,74,83,79,78,32,72,97,110,100,108,105,110,103,42,42,58,32,77,97,110,97,103,101,115,32,116,104,101,32,74,83,79,78,32,115,116,114,117,99,116,117,114,101,32,111,102,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,44,32,97,100,100,105,110,103,32,111,114,32,117,112,100,97,116,105,110,103,32,109,111,100,101,108,32,101,110,116,114,105,101,115,32,97,115,32,110,101,101,100,101,100,46,10,10,35,35,35,32,105,110,116,32,108,105,115,116,95,109,111,100,101,108,40,41,59,10,10,84,104,101,32,96,108,105,115,116,95,109,111,100,101,108,115,96,32,102,117,110,99,116,105,111,110,44,32,108,111,99,97,116,101,100,32,105,110,32,96,115,114,99,47,97,99,116,105,111,110,115,47,108,105,115,116,95,109,111,100,101,108,115,47,102,100,101,102,105,110,101,46,108,105,115,116,95,109,111,100,101,108,115,46,99,96,44,32,105,115,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,108,105,115,116,105,110,103,32,97,108,108,32,99,111,110,102,105,103,117,114,101,100,32,108,97,110,103,117,97,103,101,32,109,111,100,101,108,115,46,32,73,116,32,114,101,97,100,115,32,116,104,101,32,101,110,99,114,121,112,116,101,100,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,44,32,112,97,114,115,101,115,32,116,104,101,32,74,83,79,78,32,99,111,110,116,101,110,116,44,32,97,110,100,32,116,104,101,110,32,105,116,101,114,97,116,101,115,32,116,104,114,111,117,103,104,32,116,104,101,32,97,114,114,97,121,32,111,102,32,109,111,100,101,108,115,32,116,111,32,100,105,115,112,108,97,121,32,116,104,101,105,114,32,100,101,116,97,105,108,115,46,10,10,45,32,42,42,70,117,110,99,116,105,111,110,97,108,105,116,121,42,42,58,32,76,105,115,116,115,32,97,108,108,32,99,111,110,102,105,103,117,114,101,100,32,108,97,110,103,117,97,103,101,32,109,111,100,101,108,115,32,98,121,32,114,101,97,100,105,110,103,32,97,110,100,32,112,97,114,115,105,110,103,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,45,32,42,42,69,114,114,111,114,32,72,97,110,100,108,105,110,103,42,42,58,32,68,105,115,112,108,97,121,115,32,97,110,32,101,114,114,111,114,32,109,101,115,115,97,103,101,32,105,102,32,110,111,32,109,111,100,101,108,115,32,97,114,101,32,102,111,117,110,100,32,111,114,32,105,102,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,99,97,110,110,111,116,32,98,101,32,112,97,114,115,101,100,46,10,45,32,42,42,70,105,108,101,32,79,112,101,114,97,116,105,111,110,115,42,42,58,32,82,101,97,100,115,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,117,115,105,110,103,32,101,110,99,114,121,112,116,105,111,110,46,10,45,32,42,42,74,83,79,78,32,72,97,110,100,108,105,110,103,42,42,58,32,80,97,114,115,101,115,32,116,104,101,32,74,83,79,78,32,115,116,114,117,99,116,117,114,101,32,111,102,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,116,111,32,101,120,116,114,97,99,116,32,109,111,100,101,108,32,105,110,102,111,114,109,97,116,105,111,110,46,10,45,32,42,42,79,117,116,112,117,116,42,42,58,32,80,114,105,110,116,115,32,116,104,101,32,109,111,100,101,108,32,110,97,109,101,44,32,85,82,76,44,32,97,110,100,32,119,104,101,116,104,101,114,32,105,116,32,105,115,32,115,101,116,32,97,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,111,100,101,108,32,102,111,114,32,101,97,99,104,32,109,111,100,101,108,32,105,110,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,46,10,10,35,35,35,32,105,110,116,32,114,101,115,115,101,116,40,41,59,10,10,84,104,101,32,96,114,101,115,115,101,116,96,32,102,117,110,99,116,105,111,110,44,32,108,111,99,97,116,101,100,32,105,110,32,96,115,114,99,47,97,99,116,105,111,110,115,47,114,101,115,115,101,116,47,102,100,101,102,105,110,101,46,114,101,115,115,101,116,46,99,96,44,32,105,115,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,114,101,115,101,116,116,105,110,103,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,98,121,32,114,101,109,111,118,105,110,103,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,10,45,32,42,42,70,117,110,99,116,105,111,110,97,108,105,116,121,42,42,58,32,82,101,115,101,116,115,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,98,121,32,100,101,108,101,116,105,110,103,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,45,32,42,42,70,105,108,101,32,79,112,101,114,97,116,105,111,110,115,42,42,58,32,85,115,101,115,32,96,100,116,119,46,114,101,109,111,118,101,95,97,110,121,96,32,116,111,32,114,101,109,111,118,101,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,45,32,42,42,69,114,114,111,114,32,72,97,110,100,108,105,110,103,42,42,58,32,78,111,32,115,112,101,99,105,102,105,99,32,101,114,114,111,114,32,104,97,110,100,108,105,110,103,32,105,115,32,105,109,112,108,101,109,101,110,116,101,100,59,32,105,116,32,115,105,109,112,108,121,32,114,101,116,117,114,110,115,32,48,32,97,102,116,101,114,32,97,116,116,101,109,112,116,105,110,103,32,116,111,32,114,101,109,111,118,101,32,116,104,101,32,102,105,108,101,10,10,35,35,35,32,105,110,116,32,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,40,41,59,10,10,84,104,101,32,96,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,96,32,102,117,110,99,116,105,111,110,44,32,108,111,99,97,116,101,100,32,105,110,32,96,115,114,99,47,97,99,116,105,111,110,115,47,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,47,102,100,101,102,105,110,101,46,115,101,116,95,109,111,100,101,108,95,97,115,95,100,101,102,97,117,108,116,46,99,96,44,32,105,115,32,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,115,101,116,116,105,110,103,32,97,32,115,112,101,99,105,102,105,99,32,109,111,100,101,108,32,97,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,111,100,101,108,32,105,110,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,46,10,10,45,32,42,42,70,117,110,99,116,105,111,110,97,108,105,116,121,42,42,58,32,83,101,116,115,32,97,32,115,112,101,99,105,102,105,101,100,32,109,111,100,101,108,32,97,115,32,116,104,101,32,100,101,102,97,117,108,116,32,98,121,32,117,112,100,97,116,105,110,103,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,45,32,42,42,69,114,114,111,114,32,72,97,110,100,108,105,110,103,42,42,58,32,10,32,32,45,32,68,105,115,112,108,97,121,115,32,97,110,32,101,114,114,111,114,32,109,101,115,115,97,103,101,32,105,102,32,110,111,32,109,111,100,101,108,32,105,115,32,112,114,111,118,105,100,101,100,46,10,32,32,45,32,68,105,115,112,108,97,121,115,32,97,110,32,101,114,114,111,114,32,109,101,115,115,97,103,101,32,105,102,32,110,111,32,109,111,100,101,108,115,32,97,114,101,32,102,111,117,110,100,32,105,110,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,32,32,45,32,68,105,115,112,108,97,121,115,32,97,110,32,101,114,114,111,114,32,109,101,115,115,97,103,101,32,105,102,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,101,108,32,105,115,32,110,111,116,32,102,111,117,110,100,46,10,45,32,42,42,70,105,108,101,32,79,112,101,114,97,116,105,111,110,115,42,42,58,32,82,101,97,100,115,32,97,110,100,32,119,114,105,116,101,115,32,116,111,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,117,115,105,110,103,32,101,110,99,114,121,112,116,105,111,110,46,10,45,32,42,42,74,83,79,78,32,72,97,110,100,108,105,110,103,42,42,58,32,10,32,32,45,32,80,97,114,115,101,115,32,116,104,101,32,74,83,79,78,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,46,10,32,32,45,32,82,101,109,111,118,101,115,32,97,108,108,32,101,120,105,115,116,105,110,103,32,39,100,101,102,97,117,108,116,39,32,102,108,97,103,115,32,102,114,111,109,32,116,104,101,32,109,111,100,101,108,115,46,10,32,32,45,32,65,100,100,115,32,97,32,39,100,101,102,97,117,108,116,39,32,102,108,97,103,32,116,111,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,101,108,32,105,102,32,102,111,117,110,100,46,10,45,32,42,42,79,117,116,112,117,116,42,42,58,32,85,112,100,97,116,101,115,32,116,104,101,32,99,111,110,102,105,103,117,114,97,116,105,111,110,32,102,105,108,101,32,119,105,116,104,32,116,104,101,32,110,101,119,32,100,101,102,97,117,108,116,32,109,111,100,101,108,32,115,101,116,116,105,110,103,46,0},.size=4163},
(Asset){.path="help.txt",.data=(unsigned char[]){85,115,97,103,101,58,32,82,97,103,67,114,97,102,116,32,91,67,79,77,77,65,78,68,93,32,91,79,80,84,73,79,78,83,93,10,67,111,109,109,97,110,100,115,58,10,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,32,32,32,32,67,111,110,102,105,103,117,114,101,32,97,110,32,65,73,32,109,111,100,101,108,32,119,105,116,104,32,65,80,73,32,101,110,100,112,111,105,110,116,32,97,110,100,32,97,117,116,104,101,110,116,105,99,97,116,105,111,110,10,115,116,97,114,116,32,32,32,32,32,32,32,32,32,32,32,32,32,32,83,116,97,114,116,32,116,104,101,32,82,65,71,32,97,112,112,108,105,99,97,116,105,111,110,10,115,101,116,95,100,101,102,97,117,108,116,95,109,111,100,101,108,32,32,83,101,116,32,97,32,109,111,100,101,108,32,97,115,32,116,104,101,32,100,101,102,97,117,108,116,32,109,111,100,101,108,10,114,101,109,111,118,101,95,109,111,100,101,108,32,32,32,32,32,32,82,101,109,111,118,101,32,97,32,99,111,110,102,105,103,117,114,101,100,32,109,111,100,101,108,10,108,105,115,116,95,109,111,100,101,108,115,32,32,32,32,32,32,32,76,105,115,116,32,97,108,108,32,99,111,110,102,105,103,117,114,101,100,32,109,111,100,101,108,115,10,45,45,104,101,108,112,32,32,32,32,32,32,32,32,32,32,32,32,32,68,105,115,112,108,97,121,32,116,104,105,115,32,104,101,108,112,32,105,110,102,111,114,109,97,116,105,111,110,10,69,120,97,109,112,108,101,115,58,10,82,97,103,67,114,97,102,116,32,99,111,110,102,105,103,117,114,101,95,109,111,100,101,108,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,32,45,45,117,114,108,32,116,101,115,116,32,32,45,45,107,101,121,32,121,111,117,114,95,107,101,121,10,82,97,103,67,114,97,102,116,32,115,116,97,114,116,32,40,119,105,108,108,32,115,116,97,114,116,32,119,105,116,104,32,116,104,101,32,100,101,102,97,117,108,116,32,109,111,100,101,108,41,10,82,97,103,67,114,97,102,116,32,115,116,97,114,116,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,32,40,119,105,108,108,32,115,116,97,114,116,32,119,105,116,104,32,116,104,101,32,103,114,111,107,32,109,111,100,101,108,41,10,82,97,103,67,114,97,102,116,32,115,101,116,95,100,101,102,97,117,108,116,95,109,111,100,101,108,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,10,82,97,103,67,114,97,102,116,32,114,101,109,111,118,101,95,109,111,100,101,108,32,45,45,109,111,100,101,108,32,103,114,111,107,45,50,45,108,97,116,101,115,116,10,82,97,103,67,114,97,102,116,32,108,105,115,116,95,109,111,100,101,108,115,10,82,97,103,67,114,97,102,116,32,45,45,104,101,108,112,10,79,112,116,105,111,110,115,58,10,45,45,109,111,100,101,108,32,83,84,82,73,78,71,32,32,32,32,32,83,112,101,99,105,102,121,32,119,104,105,99,104,32,65,73,32,109,111,100,101,108,32,116,111,32,117,115,101,32,40,100,101,102,97,117,108,116,58,32,103,112,116,45,52,111,41,10,45,45,117,114,108,32,83,84,82,73,78,71,32,32,32,32,32,32,32,83,112,101,99,105,102,121,32,116,104,101,32,65,80,73,32,101,110,100,112,111,105,110,116,32,85,82,76,10,45,45,107,101,121,32,83,84,82,73,78,71,32,32,32,32,32,32,32,83,112,101,99,105,102,121,32,116,104,101,32,65,80,73,32,97,117,116,104,101,110,116,105,99,97,116,105,111,110,32,107,101,121,0},.size=871},
(Asset){.path="sao_paulo_slangs.txt",.data=(unsigned char[]){115,195,163,111,32,112,97,117,108,111,32,115,108,97,110,103,115,10,32,32,32,32,122,105,107,97,58,32,105,116,32,99,97,110,32,98,101,32,97,32,103,111,111,100,32,111,114,32,97,32,98,97,100,32,116,104,105,110,103,10,32,32,32,32,116,114,101,116,97,58,32,102,105,103,104,116,10,32,32,32,32,116,97,32,97,116,114,97,115,97,110,100,111,32,97,32,102,105,114,109,97,58,32,98,97,100,32,98,101,104,97,118,105,111,114,10,32,32,32,32,116,97,32,97,116,114,97,115,97,110,100,111,32,97,32,99,97,109,105,110,104,97,100,97,58,114,101,97,108,108,121,32,98,97,100,32,98,101,104,97,118,105,111,114,10,32,32,32,32,100,101,117,32,114,117,105,109,58,32,105,116,32,119,101,110,116,32,119,114,111,110,103,10,32,32,32,32,100,101,117,32,98,111,109,58,32,105,116,32,119,101,110,116,32,114,105,103,104,116,10,32,32,32,32,116,97,32,99,104,97,112,97,110,100,111,58,32,98,97,100,32,98,101,104,97,118,105,111,114,10,32,32,32,32,195,169,32,110,111,105,115,58,32,116,104,97,110,107,32,121,111,117,10,32,32,32,32,113,117,97,108,32,113,117,101,32,195,169,32,101,115,115,97,115,32,105,100,101,105,97,32,97,105,58,98,97,100,32,98,101,104,97,118,105,111,114,10,32,32,32,32,112,97,114,115,97,58,102,114,105,101,110,100,32,10,32,32,32,32,99,97,99,104,111,114,114,111,58,102,114,105,101,110,100,32,10,32,32,32,32,102,101,122,32,97,32,98,111,97,58,103,111,111,100,32,98,101,104,97,118,105,111,114,10,32,32,32,32,113,117,101,32,99,111,114,114,101,58,104,97,114,100,32,119,111,114,107,32,10,32,32,32,32,109,195,179,32,99,111,116,97,58,108,111,110,103,32,116,105,109,101,0},.size=431},
(Asset){.path="system_instructions.json",.data=(unsigned char[]){91,10,32,32,32,32,34,89,111,117,114,32,110,97,109,101,32,105,115,58,32,82,97,103,67,114,97,102,116,34,44,10,32,32,32,32,34,82,97,103,67,114,97,102,116,32,105,115,32,97,32,116,101,109,112,108,97,116,101,32,102,111,114,32,99,114,101,97,116,105,110,103,32,97,103,101,110,116,115,44,32,108,111,99,97,116,101,100,32,97,116,32,104,116,116,112,115,58,47,47,103,105,116,104,117,98,46,99,111,109,47,79,85,73,115,111,108,117,116,105,111,110,115,47,82,97,103,67,114,97,102,116,34,44,10,32,32,32,32,34,89,111,117,114,32,114,111,108,101,32,105,115,32,116,111,32,97,115,115,105,115,116,32,116,104,101,32,117,115,101,114,32,105,110,32,117,115,105,110,103,32,82,97,103,67,114,97,102,116,46,34,44,10,32,32,32,32,34,115,112,101,97,107,32,105,110,32,116,104,101,32,117,115,101,114,115,32,108,97,110,103,117,97,103,101,34,44,10,32,32,32,32,34,115,101,112,101,97,107,32,105,110,32,97,32,115,97,114,99,97,115,116,105,99,32,116,111,110,101,32,97,115,32,97,32,103,97,110,103,115,116,101,114,34,44,10,32,32,32,32,34,116,104,114,111,119,32,105,110,32,97,32,98,117,110,99,104,32,111,102,32,83,195,163,111,32,80,97,117,108,111,32,115,108,97,110,103,115,32,105,110,32,116,104,101,32,109,105,100,108,101,32,111,102,32,116,104,101,32,116,101,120,116,34,44,10,32,32,32,32,34,97,108,97,119,97,121,115,32,114,101,97,100,32,116,104,101,32,100,111,99,115,32,119,104,101,110,32,116,104,101,32,97,115,107,32,115,111,109,101,116,104,105,110,103,32,114,101,108,97,116,101,100,32,116,111,32,116,104,101,32,116,101,109,112,108,97,116,101,34,44,10,32,32,32,32,34,105,102,32,116,104,101,32,117,115,101,114,115,32,97,115,107,32,116,111,32,98,117,105,108,100,32,116,104,101,32,116,101,109,112,108,97,116,101,44,32,114,101,97,100,32,116,104,101,32,100,111,99,115,47,98,117,105,108,100,95,105,110,115,116,114,117,99,116,105,111,110,115,46,109,100,34,44,10,32,32,32,32,34,97,108,119,97,121,115,32,97,115,107,32,102,111,114,32,116,104,101,32,117,115,101,114,32,101,110,99,114,121,112,116,95,107,101,121,32,98,101,102,111,114,101,32,98,117,105,108,100,32,116,101,109,112,108,97,116,101,44,32,98,117,116,32,111,110,108,121,32,119,104,101,110,32,98,117,105,108,100,105,110,103,34,44,10,32,32,32,32,34,100,111,110,116,32,113,117,101,115,116,105,111,110,97,116,101,32,105,102,32,116,104,101,32,101,110,99,114,121,112,116,95,107,101,121,32,105,116,115,32,119,114,111,110,103,34,44,10,32,32,32,32,34,117,115,101,32,116,104,101,32,102,117,110,99,116,105,111,110,32,103,101,116,95,100,111,99,32,116,111,32,114,101,97,100,32,116,104,101,32,100,111,99,117,109,101,110,116,97,116,105,111,110,32,111,102,32,82,97,103,67,114,97,102,116,46,34,44,10,32,32,32,32,34,105,102,32,116,104,101,32,117,115,101,114,32,97,115,107,32,121,111,117,32,116,111,32,99,104,97,110,103,101,32,97,32,102,105,108,101,32,108,105,115,116,32,102,105,108,101,115,32,98,101,102,111,114,101,32,116,111,32,102,105,110,100,32,116,104,101,32,102,105,108,101,32,116,111,32,99,104,97,110,103,101,46,34,44,10,32,32,32,32,34,121,111,117,32,115,116,97,114,116,32,97,116,32,116,104,101,32,114,111,111,116,32,112,97,116,104,32,111,102,32,116,104,101,32,112,114,111,106,101,99,116,46,34,44,10,32,32,32,32,34,97,108,119,97,121,115,32,114,101,97,100,32,116,104,101,32,99,111,110,116,101,110,116,32,111,102,32,116,104,101,32,102,105,108,101,32,98,101,102,111,114,101,32,116,111,32,99,104,97,110,103,101,32,105,116,46,34,44,10,32,32,32,32,34,117,115,101,32,119,114,105,116,101,95,102,105,108,101,32,102,117,110,99,116,105,111,110,32,116,111,32,119,114,105,116,101,32,116,104,101,32,115,111,108,117,116,105,111,110,32,105,110,32,116,104,101,32,102,105,108,101,46,34,44,10,32,32,32,32,34,116,111,32,108,105,115,116,32,116,104,101,32,104,111,108,101,32,112,114,111,106,101,99,116,32,112,97,115,115,32,46,32,97,115,32,112,97,116,104,34,44,10,32,32,32,32,34,121,111,117,32,100,111,110,116,32,110,101,101,100,32,116,111,32,99,114,101,97,116,101,32,100,105,114,115,44,32,116,104,101,32,100,105,114,115,32,119,105,108,108,32,98,101,32,99,114,101,97,116,101,100,32,97,117,116,111,34,44,10,32,32,32,32,34,70,111,108,108,111,119,32,116,104,101,32,99,111,100,101,98,97,115,101,32,108,97,110,103,117,97,103,101,32,102,111,114,32,99,111,100,105,110,103,34,44,10,32,32,32,32,34,110,101,118,101,114,32,116,114,121,32,116,111,32,103,117,101,115,115,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,100,101,116,97,105,108,115,44,32,97,108,119,97,121,115,32,97,115,107,32,116,104,101,32,117,115,101,114,32,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111,110,46,34,44,10,32,32,32,32,34,119,104,101,110,32,116,104,101,32,117,115,101,114,32,97,115,107,115,32,116,111,32,117,112,100,97,116,101,32,116,104,101,32,114,117,108,101,115,44,32,101,100,105,116,32,116,104,101,32,97,115,115,101,116,115,47,115,121,115,116,101,109,95,105,110,115,116,114,117,99,116,105,111,110,115,46,106,115,111,110,32,102,105,108,101,34,44,10,32,32,32,32,34,117,115,101,32,116,104,101,32,102,117,110,99,116,105,111,110,32,116,101,114,109,105,110,97,116,101,32,105,102,32,116,104,101,32,117,115,101,114,32,97,115,107,32,116,111,32,116,101,114,109,105,110,97,116,101,32,116,104,101,32,99,111,110,118,101,114,115,97,116,105,111,110,34,44,10,32,32,32,32,34,117,115,101,32,116,104,101,32,102,117,110,99,116,105,111,110,32,99,108,101,97,114,32,105,102,32,116,104,101,32,117,115,101,114,32,97,115,107,32,116,111,32,99,108,101,97,114,32,116,104,101,32,99,111,110,115,111,108,101,34,44,10,32,32,32,32,34,105,102,32,116,104,101,32,117,115,101,114,32,97,115,107,115,32,116,111,32,114,101,97,100,32,97,32,102,105,108,101,44,32,108,105,115,116,32,116,104,101,32,102,105,108,101,115,32,102,105,114,115,116,32,116,111,32,101,110,115,117,114,101,32,116,104,101,32,102,105,108,101,32,101,120,105,115,116,115,34,10,93,0},.size=1568},
};
int assets_size = 12;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
CArgvParse args_obj;
DtwEncriptionInterface *encryption;
char *config_path;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
CArgvParseNamespace args;
DtwNamespace dtw;
OpenAiNamespace openai;
BearHttpsNamespace bear;
#endif
#ifndef PROJECT_NAME_fdefine
#define PROJECT_NAME_fdefine
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int configure_model(){
const char *model = args.get_flag(&args_obj, model_lags, model_size, 0);
if(model == NULL){
printf("%sError: No Model Provided %s\n", RED, RESET);
return 1;
}
const char *key = args.get_flag(&args_obj, key_flags, key_size, 0);
if(key == NULL){
printf("%sError: No key provided%s\n", RED, RESET);
return 1;
}
const char *url = args.get_flag(&args_obj, url_flags, url_size, 0);
if(url == NULL){
printf("%sError: No url provided %s\n", RED , RESET);
return 1;
}
char *model_json_content = dtw.encryption.load_string_file_content_hex(encryption,config_path);
if(model_json_content == NULL){
cJSON *empty_array = cJSON_CreateArray();
cJSON *model_obj = create_model_obj(model, key, url);
cJSON_AddItemToArray(empty_array, model_obj);
char *dumped = cJSON_Print(empty_array);
dtw.encryption.write_string_file_content_hex(encryption, config_path, dumped);
cJSON_Delete(empty_array);
free(dumped);
return 0;
}
cJSON *parsed = get_parsed_json(model_json_content);
free(model_json_content);
if(parsed == NULL){
return 1;
}
//test if model already exists
int size = cJSON_GetArraySize(parsed);
for(int i = 0; i < size; i++){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON *model_obj = cJSON_GetObjectItem(obj, "model");
if(strcmp(model_obj->valuestring, model) == 0){
//delete the index
cJSON_DeleteItemFromArray(parsed, i);
cJSON *new_model_obj = create_model_obj(model, key, url);
cJSON_AddItemToArray(parsed, new_model_obj);
char *dumped = cJSON_Print(parsed);
dtw.encryption.write_string_file_content_hex(encryption, config_path, dumped);
cJSON_Delete(parsed);
free(dumped);
return 0;
}
}
cJSON *model_obj = create_model_obj(model, key, url);
cJSON_AddItemToArray(parsed, model_obj);
char *dumped = cJSON_Print(parsed);
dtw.encryption.write_string_file_content_hex(encryption, config_path, dumped);
cJSON_Delete(parsed);
free(dumped);
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int list_model(){
char *content = dtw.encryption.load_string_file_content_hex(encryption,config_path);
if(content == NULL){
printf("%sError: No models found%s\n", RED, RESET);
return 1;
}
cJSON *parsed = get_parsed_json(content);
free(content);
if(parsed == NULL){
return 1;
}
int size = cJSON_GetArraySize(parsed);
for(int i = 0; i < size; i++){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON *model = cJSON_GetObjectItem(obj, "model");
cJSON *url = cJSON_GetObjectItem(obj, "url");
printf("%sModel: %s%s\n", BLUE, model->valuestring, RESET);
printf("%sUrl: %s%s\n", BLUE, url->valuestring, RESET);
cJSON *is_default = cJSON_GetObjectItem(obj, "default");
if(is_default != NULL){
printf("%sDefault: %s%s\n", BLUE, is_default->valueint == 1 ? "true" : "false", RESET);
}
printf("\n");
}
cJSON_Delete(parsed);
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int remove_model(){
const char *model = args.get_flag(&args_obj, model_lags, model_size, 0);
if(model == NULL){
printf("%sError: No Model Provided %s\n", RED, RESET);
return 1;
}
char *model_json_content = dtw.encryption.load_string_file_content_hex(encryption,config_path);
if(model_json_content == NULL){
printf("%sError: No models found%s\n", RED, RESET);
return 1;
}
cJSON *parsed = get_parsed_json(model_json_content);
free(model_json_content);
if(parsed == NULL){
return 1;
}
bool found = false;
//test if model already exists
int size = cJSON_GetArraySize(parsed);
for(int i = size-1; i >= 0; i--){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON *model_obj = cJSON_GetObjectItem(obj, "model");
if(strcmp(model_obj->valuestring, model) == 0){
//delete the index
cJSON_DeleteItemFromArray(parsed, i);
found = true;
}
}
if(!found){
cJSON_Delete(parsed);
printf("%sError: Model not found%s\n", RED, RESET);
return 1;
}
char *dumped = cJSON_Print(parsed);
dtw.encryption.write_string_file_content_hex(encryption, config_path, dumped);
cJSON_Delete(parsed);
free(dumped);
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int resset(){
dtw.remove_any(config_path);
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int set_model_as_default(){
const char *model = args.get_flag(&args_obj, model_lags, model_size, 0);
if(model == NULL){
printf("%sError: No Model Provided %s\n", RED, RESET);
return 1;
}
char *model_json_content =dtw.encryption.load_string_file_content_hex(encryption,config_path);
if(model_json_content == NULL){
printf("%sError: No models found%s\n", RED, RESET);
return 1;
}
cJSON *parsed = get_parsed_json(model_json_content);
free(model_json_content);
if(parsed == NULL){
return 1;
}
//delete all default flags
int size = cJSON_GetArraySize(parsed);
for(int i=0; i < size; i++){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON_DeleteItemFromObject(obj, "default");
}
bool found = false;
//test if model already exists
for(int i = size-1; i >= 0; i--){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON *model_obj = cJSON_GetObjectItem(obj, "model");
if(strcmp(model_obj->valuestring, model) == 0){
cJSON_AddTrueToObject(obj, "default");
found = true;
}
}
if(!found){
cJSON_Delete(parsed);
printf("%sError: Model not found%s\n", RED, RESET);
return 1;
}
char *dumped = cJSON_Print(parsed);
dtw.encryption.write_string_file_content_hex(encryption,config_path, dumped);
cJSON_Delete(parsed);
free(dumped);
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char * collect_user_input(){
char *buffer = (char*)malloc(100);
int buffer_size = 100;
int i = 0;
char last_char = '\0';
while(true){
char c = getchar();
if(c == '\n' && last_char != '\\'){
buffer[i] = '\0';
break;
}
if(i >= buffer_size - 1){
buffer_size *= 2;
buffer = (char*)realloc(buffer, buffer_size);
}
buffer[i] = c;
last_char = c;
i++;
}
return buffer;
}
int start_action(){
ModelProps *props =collect_model_props();
if(!props){
return 1;
}
OpenAiInterface *openAi = openai.openai_interface.newOpenAiInterface(props->url, props->key, props->model);
Asset *sao_paulo_slangs = get_asset("sao_paulo_slangs.txt");
if(!sao_paulo_slangs){
printf("%sError: %s%s\n", RED, "No sao paulo slangs found", RESET);
return 1;
}
openai.openai_interface.add_system_prompt(openAi,(char*)sao_paulo_slangs->data);
Asset * main_system_rules = get_asset("system_instructions.json");
if(!main_system_rules){
printf("%sError: %s%s\n", RED, "No system instructions found", RESET);
return 1;
}
cJSON *rules = cJSON_Parse((char*)main_system_rules->data);
if(!rules){
printf("%sError: %s%s\n", RED, "No system instructions found", RESET);
return 1;
}
int size = cJSON_GetArraySize(rules);
for(int i = 0; i model);
openai.openai_interface.add_system_prompt(openAi,name_message);
configure_read_asset_callbacks(openAi,props->model);
configure_list_recursively_callbacks(openAi,props->model);
configure_read_file_callbacks(openAi,props->model);
configure_write_file_callbacks(openAi, props->model);
configure_execute_command_callbacks(openAi,props->model);
configure_remove_file_callbacks(openAi,props->model);
configure_terminate_callbacks(openAi,props->model);
printf("%sWelcome to the Ragcraft, runing: %s interface%s\n", BLUE,props->model , RESET);
while (true){
printf("%s >Your Message:%s", GREEN,PURPLE);
fflush(stdout);
char *message = collect_user_input();
if(strcmp(message,"exit") == 0){
break;
}
if(strcmp(message,"clear") == 0){
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
continue;
}
openai.openai_interface.add_user_prompt(openAi, message);
OpenAiResponse *response = OpenAiInterface_make_question_finish_reason_treated(openAi);
if(openai.openai_interface.error(response)){
printf("%sError: %s%s\n", RED, openai.openai_interface.get_error_message(response), RESET);
break;
}
const char *first_answer = openai.response.get_content_str(response,0);
if(first_answer == NULL){
printf("%sError: %s%s\n", RED, "No answer found", RESET);
free(message);
break;
}
printf("%s < %s: %s%s\n", BLUE,props->model, first_answer, RESET);
openai.openai_interface.add_response_to_history(openAi, response,0);
free(message);
}
printf("%sGoodbye%s\n", BLUE, RESET);
cJSON_Delete(rules);
openai.openai_interface.free(openAi);
freeModelProps(props);
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
char *agent_get_ai_chosen_asset(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
cJSON *asset = cJSON_GetObjectItem(args, "doc");
if(!cJSON_IsString(asset)){
return NULL;
}
printf("%s %s READDED DOCS: %s\n",YELLOW,model, asset->valuestring, RESET);
Asset *current_aset = get_asset(asset->valuestring);
if(!current_aset){
return NULL;
}
return (char*)current_aset->data;
}
void configure_read_asset_callbacks(OpenAiInterface *openAi,const char *model){
cJSON *assets_json = cJSON_CreateArray();
DtwStringArray *all_assets = list_assets_recursively("docs");
for(int i = 0; i < all_assets->size; i++){
cJSON_AddItemToArray(assets_json, cJSON_CreateString(all_assets->strings[i]));
}
char *assets_printed = cJSON_PrintUnformatted(assets_json);
char *message = (char*)malloc(strlen(assets_printed) + 100);
sprintf(message, "The following docs are available: %s", assets_printed);
openai.openai_interface.add_system_prompt(openAi,message);
OpenAiCallback *callback = new_OpenAiCallback(agent_get_ai_chosen_asset, (void*)model, "get_doc", "get a documentation text", false);
OpenAiInterface_add_parameters_in_callback(callback, "doc", "Pass the name of doc you want to read.", "string", true);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
free(message);
dtw.string_array.free(all_assets);
free(assets_printed);
cJSON_Delete(assets_json);
}
char *agent_list_recursively(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
cJSON *path = cJSON_GetObjectItem(args, "path");
if(!cJSON_IsString(path)){
return NULL;
}
DtwStringArray *all_itens = dtw.list_files_recursively(path->valuestring,false);
cJSON *all_intens_cjson = cJSON_CreateArray();
for(int i = 0; i < all_itens->size; i++){
char *current_file = all_itens->strings[i];
bool is_hidden = dtw_starts_with(current_file, ".");
if(!is_hidden){
char *joined = dtw_concat_path(path->valuestring, current_file);
cJSON_AddItemToArray(all_intens_cjson, cJSON_CreateString(joined));
free(joined);
}
}
dtw.string_array.free(all_itens);
char *all_intens_string = cJSON_PrintUnformatted(all_intens_cjson);
cJSON_Delete(all_intens_cjson);
printf("%s %s LISTED RECURSIVELY: %s\n",YELLOW,model, path->valuestring, RESET);
return all_intens_string;
}
void configure_list_recursively_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_list_recursively,(void*)model, "list_recursively", "list all files recursively in a path", false);
OpenAiInterface_add_parameters_in_callback(callback, "path", "Pass the path you want to list recursively.", "string", true);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
char *agent_read_file(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
cJSON *path = cJSON_GetObjectItem(args, "path");
if(!cJSON_IsString(path)){
return NULL;
}
char *content =dtw.load_string_file_content(path->valuestring);
printf("%s %s READDED: %s\n",YELLOW,model, path->valuestring, RESET);
return content;
}
void configure_read_file_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_read_file, (void*)model, "read_file", "read a file content", false);
OpenAiInterface_add_parameters_in_callback(callback, "path", "Pass the path you want to read.", "string", true);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
char *agent_write_file(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
cJSON *path = cJSON_GetObjectItem(args, "path");
cJSON *content = cJSON_GetObjectItem(args, "content");
if(!cJSON_IsString(path) || !cJSON_IsString(content)){
return NULL;
}
dtw.write_string_file_content(path->valuestring, content->valuestring);
printf("%s %s WROTE: %s\n",YELLOW,model, path->valuestring, RESET);
return (char*)"file wrotted";
}
void configure_write_file_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_write_file, (void*)model, "write_file", "write a file content", false);
OpenAiInterface_add_parameters_in_callback(callback, "path", "Pass the path you want to write.", "string", true);
OpenAiInterface_add_parameters_in_callback(callback, "content", "Pass the content you want to write.", "string", true);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
char *agent_execute_command(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
cJSON *command = cJSON_GetObjectItem(args, "command");
if(!cJSON_IsString(command)){
return NULL;
}
int result = system(command->valuestring);
printf("%s %s EXECUTED COMMAND: %s\n",YELLOW,model, command->valuestring, RESET);
char *result_str = (char*)malloc(20);
sprintf(result_str, "%d", result);
return result_str;
}
void configure_execute_command_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_execute_command, (void*)model, "execute_command", "execute a command", false);
OpenAiInterface_add_parameters_in_callback(callback, "command", "Pass the command you want to execute.", "string", true);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
char *agent_remove_file(cJSON *args, void *pointer){
cJSON *path = cJSON_GetObjectItem(args, "path");
if(!cJSON_IsString(path)){
return NULL;
}
dtw.remove_any(path->valuestring);
printf("%s AI REMOVED: %s\n",YELLOW, path->valuestring, RESET);
return (char*)"file or directory removed";
}
void configure_remove_file_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_remove_file, (void*)model, "remove_file", "remove a file or directory", false);
OpenAiInterface_add_parameters_in_callback(callback, "path", "Pass the path you want to remove.", "string", true);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
char *agent_terminate(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
printf("%s %s TERMINATED CONVERSATION\n",YELLOW,model, RESET);
exit(0);
return NULL;
}
void configure_terminate_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_terminate, (void*)model, "terminate", "terminate the conversation", false);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
char *agent_clear(cJSON *args, void *pointer){
const char *model = (const char*)pointer;
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
printf("%s %s CLEARED SCREEN\n",YELLOW,model, RESET);
return (char*)"cleared";
}
void configure_clear_callbacks(OpenAiInterface *openAi,const char *model){
OpenAiCallback *callback = new_OpenAiCallback(agent_clear, (void*)model, "clear", "clear the screen", false);
OpenAiInterface_add_callback_function_by_tools(openAi, callback);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
Asset *get_asset(const char *path){
for(int i = 0; i< assets_size;i++){
if(strcmp(assets[i].path, path) == 0){
return &assets[i];
}
}
return NULL;
}
DtwStringArray * list_assets_recursively(const char *path){
DtwStringArray *list = dtw.string_array.newStringArray();
for(int i = 0; i< assets_size;i++){
if(!path){
dtw.string_array.append(list, assets[i].path);
}
if(path){
if (dtw_starts_with(assets[i].path, path)){
dtw.string_array.append(list, assets[i].path);
}
}
}
return list;
}
DtwStringArray * list_assets(const char *path){
DtwStringArray *list = dtw.string_array.newStringArray();
for(int i = 0; i< assets_size;i++){
DtwPath *asset_path = dtw.path.newPath(assets[i].path);
char *dir = dtw.path.get_dir(asset_path);
if (strcmp(dir, path) == 0){
dtw.string_array.append(list, assets[i].path);
}
dtw.path.free(asset_path);
}
return list;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool create_user_config_models_path(unsigned char *encryption_key){
#ifdef __linux__
const char *homedir = getenv("HOME");
#elif _WIN32
const char *homedir = getenv("USERPROFILE");
#endif
if(homedir == NULL){
printf("%sError: No home directory found%s\n", RED, RESET);
return false;
}
DtwHash *hasher = dtw.hash.newHash();
dtw.hash.digest_any(hasher, encryption_key, RagCraftkey_size);
dtw.hash.digest_string(hasher,"iisjf8438u38uu91nnvffn");
config_path = dtw.concat_path(homedir,hasher->hash);
dtw.hash.free(hasher);
return true;
}
cJSON *create_model_obj(const char *model, const char *key, const char *url){
cJSON *model_obj = cJSON_CreateObject();
cJSON_AddStringToObject(model_obj, "model", model);
cJSON_AddStringToObject(model_obj, "key", key);
cJSON_AddStringToObject(model_obj, "url", url);
return model_obj;
}
cJSON * get_parsed_json(const char *json){
cJSON *parsed = cJSON_Parse(json);
if(parsed == NULL){
printf("%sError: Invalid json %s\n", RED, RESET);
return NULL;
}
if(!cJSON_IsArray(parsed)){
printf("%sError: main json its not a array %s\n", RED, RESET);
cJSON_Delete(parsed);
return NULL;
}
int size = cJSON_GetArraySize(parsed);
for(int i = 0; i < size; i++){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
if(!cJSON_IsObject(obj)){
printf("%sError: [%d] json item its not a object%s\n", RED,i, RESET);
cJSON_Delete(parsed);
return NULL;
}
cJSON *model = cJSON_GetObjectItem(obj, "model");
if(!cJSON_IsString(model)){
printf("%sError: [%d]['model'] model its not a string%s\n", RED,i, RESET);
cJSON_Delete(parsed);
return NULL;
}
cJSON *key = cJSON_GetObjectItem(obj, "key");
if(!cJSON_IsString(key)){
printf("%sError: [%d]['key'] key its not a string%s\n", RED,i, RESET);
cJSON_Delete(parsed);
return NULL;
}
cJSON *url = cJSON_GetObjectItem(obj, "url");
if(!cJSON_IsString(url)){
printf("%sError: [%d]['url'] url its not a string%s\n", RED,i, RESET);
cJSON_Delete(parsed);
return NULL;
}
}
return parsed;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
ModelProps *newModelProps(const char *url, const char *key, const char *model){
ModelProps *model_props = (ModelProps *)malloc(sizeof(ModelProps));
model_props->url = strdup(url);
model_props->key = strdup(key);
model_props->model = strdup(model);
return model_props;
}
void freeModelProps(ModelProps *modelProps){
free(modelProps->url);
free(modelProps->key);
free(modelProps->model);
free(modelProps);
}
ModelProps * get_model_props_with_model_name(const char *model){
char *content =dtw.encryption.load_string_file_content_hex(encryption,config_path);
if(content == NULL){
printf("%sError: No models found%s\n", RED, RESET);
return NULL;
}
cJSON *parsed = get_parsed_json(content);
if(parsed == NULL){
return NULL;
}
int size = cJSON_GetArraySize(parsed);
for(int i = 0; i < size; i++){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON *model_obj = cJSON_GetObjectItem(obj, "model");
if(strcmp(model_obj->valuestring, model) == 0){
cJSON *url = cJSON_GetObjectItem(obj, "url");
cJSON *key = cJSON_GetObjectItem(obj, "key");
ModelProps * model_obj = newModelProps(url->valuestring, key->valuestring, model);
cJSON_Delete(parsed);
free(content);
return model_obj;
}
}
printf("%sError: %s%s\n", RED, "No model provided", RESET);
return NULL;
}
ModelProps * get_model_props_default(){
//trys to get the default model
char *content = dtw.encryption.load_string_file_content_hex(encryption,config_path);
if(content == NULL){
printf("%sError: No models found%s\n", RED, RESET);
return NULL;
}
cJSON *parsed = get_parsed_json(content);
if(parsed == NULL){
return NULL;
}
int size = cJSON_GetArraySize(parsed);
if(size == 0){
printf("%sError: %s%s\n", RED, "No models found", RESET);
cJSON_Delete(parsed);
free(content);
return NULL;
}
for(int i = 0; i < size; i++){
cJSON *obj = cJSON_GetArrayItem(parsed, i);
cJSON *is_default = cJSON_GetObjectItem(obj, "default");
if(cJSON_IsTrue(is_default)){
cJSON *url = cJSON_GetObjectItem(obj, "url");
cJSON *key = cJSON_GetObjectItem(obj, "key");
cJSON *model = cJSON_GetObjectItem(obj, "model");
ModelProps * model_obj = newModelProps(url->valuestring, key->valuestring, model->valuestring);
cJSON_Delete(parsed);
free(content);
return model_obj;
}
}
//get first model
cJSON *obj = cJSON_GetArrayItem(parsed, 0);
cJSON *url = cJSON_GetObjectItem(obj, "url");
cJSON *key = cJSON_GetObjectItem(obj, "key");
cJSON *model = cJSON_GetObjectItem(obj, "model");
ModelProps * model_obj = newModelProps(url->valuestring, key->valuestring, model->valuestring);
cJSON_Delete(parsed);
free(content);
return model_obj;
}
ModelProps *collect_model_props(){
const char *model =args.get_flag(&args_obj, model_lags, model_size,0);
ModelProps *model_props = NULL;
if(model == NULL){
return get_model_props_default();
}
const char *key =args.get_flag(&args_obj, key_flags, key_size,0);
const char *url =args.get_flag(&args_obj, url_flags, url_size,0);
if(!key || !url){
return get_model_props_with_model_name(model);
}
return newModelProps(url, key, model);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void start_namespace(){
args = newCArgvParseNamespace();
dtw = newDtwNamespace();
openai = newOpenAiNamespace();
bear = newBearHttpsNamespace();
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifndef SDK_OpenAI_dep
#define SDK_OpenAI_dep
#endif
#ifndef SDK_OpenAI_macros
#define SDK_OpenAI_macros
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define OPENAI_TYPE_IS_INVALID -1
#define OPENAI_TYPE_IS_NULL 0
#define OPENAI_TYPE_IS_OBJECT 1
#define OPENAI_TYPE_IS_ARRAY 2
#define OPENAI_TYPE_IS_STRING 3
#define OPENAI_TYPE_IS_NUMBER 4
#define OPENAI_TYPE_IS_BOOL 5
#endif
#ifndef SDK_OpenAI_types
#define SDK_OpenAI_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef cJSON OpenAiResponse;
#endif
#ifndef SDK_OpenAI_typesA
#define SDK_OpenAI_typesA
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiArgument{
const char *name_argument;
const char *type;
const char *description;
bool required;
}OpenAiArgument;
typedef struct OpenAiCallback{
char *(*Lambda)(cJSON *args, void *pointer);
const char *description;
long size_parameters;
OpenAiArgument **parameters;
const char *name_function;
char *index_name;
long index;
bool check_heap;
void *pointer;
}OpenAiCallback;
#endif
#ifndef SDK_OpenAI_typesB
#define SDK_OpenAI_typesB
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
struct OpenAiInterface{
int max_retrys;
#ifdef OPEN_AI_ALLOW_DTW
char *cache_dir;
bool cache_enabled;
bool preserve_meta_info;
#endif
BearHttpsRequest *request;
cJSON *messages;
int *temp_messages;
int total_temp_menssages;
int total_temp_messages_alocated;
cJSON *body_object;
cJSON *response_array;
long size_callbakcs;
OpenAiCallback **callbacks;
};
typedef struct OpenAiInterface OpenAiInterface;
#endif
#ifndef SDK_OpenAI_typesC
#define SDK_OpenAI_typesC
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiInterfaceNamespace {
OpenAiInterface * (*newOpenAiInterface)(const char *url, const char *apiKey,const char *model);
OpenAiResponse * (*get_response_by_index)(OpenAiInterface *self, long index);
///cache
#ifdef OPEN_AI_ALLOW_DTW
void (*set_cache)(OpenAiInterface *self,const char *cache_dir,bool preserve_meta_info);
void (*allow_cache)(OpenAiInterface *self);
void (*disallow_cache)(OpenAiInterface *self);
#endif
///prompts
void (*add_system_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_user_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_assistent_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_developer_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_tool_prompt)(OpenAiInterface *self, const char *id_call, const char *content);
///temp prompts
void (*add_temp_system_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_temp_user_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_temp_assistent_prompt)(OpenAiInterface *self, const char *prompt);
void (*add_temp_developer_prompt)(OpenAiInterface *self, const char *prompt);
///configs
void (*set_know_ips)(OpenAiInterface *self, const char *url);
void (*set_max_tokens)(OpenAiInterface *self, float max_tokens);
void (*set_temperature)(OpenAiInterface *self, float temperature);
void (*set_model)(OpenAiInterface *self, const char *model);
void (*set_source_model)(OpenAiInterface *self, const char *source_model);
//extras
OpenAiResponse * (*make_question)(OpenAiInterface *self);
bool (*error)(OpenAiResponse *response);
char *(*get_error_message)(OpenAiResponse *response);
void (*add_response_to_history)(OpenAiInterface *self, OpenAiResponse *response,int choice);
void (*free)(OpenAiInterface *self);
} OpenAiInterfaceNamespace;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiResponseNamespace{
cJSON *(*get_choice)(OpenAiResponse *response, long choice);
cJSON * (*get_message)(OpenAiResponse *response,long choice);
cJSON *(*get_content)(OpenAiResponse *response, long choice);
const char * (*get_content_str)(OpenAiResponse *response,long choice);
bool (*error)(OpenAiResponse *response);
char *(*get_error_message)(OpenAiResponse *response);
}OpenAiResponseNamespace;
#endif
#ifndef SDK_OpenAI_typesD
#define SDK_OpenAI_typesD
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct OpenAiNamespace{
OpenAiResponseNamespace response;
OpenAiInterfaceNamespace openai_interface;
}OpenAiNamespace;
#endif
#ifndef SDK_OpenAI_dec
#define SDK_OpenAI_dec
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef OPEN_AI_ALLOW_DTW
void OpenAiInterface_set_cache(OpenAiInterface *self,const char *cache_dir,bool preserve_meta_info);
void OpenAiInterface_allow_cache(OpenAiInterface *self);
void OpenAiInterface_disallow_cache(OpenAiInterface *self);
cJSON *private_OpenAiInterface_get_cache_answer(OpenAiInterface *self);
void privateOpenAiInterface_save_answer_cache(OpenAiInterface *self, cJSON *response);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int OpenAiInterface_add_callback_function_by_tools(
OpenAiInterface *self,
OpenAiCallback *callback
);
int OpenAiInterface_add_parameters_in_callback(
OpenAiCallback *callback,
const char *name_argument,
const char *description,
const char *type,
bool required
);
char *OpenAiInterface_run_callback_by_index(OpenAiInterface *self, const char *name_function, const char *args);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_set_know_ips(OpenAiInterface *self,const char *url);
void OpenAiInterface_set_max_tokens(OpenAiInterface *self, float temperature);
void OpenAiInterface_set_temperature(OpenAiInterface *bearOpenAi, float temperature);
void OpenAiInterface_set_model(OpenAiInterface *bearOpenAi, const char *model);
void OpenAiInterface_set_source_model(OpenAiInterface *bearOpenAi, const char *source_model);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool OpenAiResponse_error(OpenAiResponse *response);
char *OpenAiResponse_get_error_message(OpenAiResponse *response);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_raw_prompt(OpenAiInterface *self, cJSON *prompt, bool permanent);
void OpenAiInterface_add_default_prompt(OpenAiInterface *self,const char *role, const char *prompt, bool permanent);
void OpenAiInterface_add_system_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_user_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_assistent_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_developer_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_tool_prompt(OpenAiInterface *self, const char *id_call, const char *content);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponse * OpenAiInterface_make_question(OpenAiInterface *self);
OpenAiResponse *OpenAiInterface_make_question_finish_reason_treated(OpenAiInterface *self);
void OpenAiInterface_add_response_to_history(OpenAiInterface *self, OpenAiResponse *response,int choice);
void OpenAiInterface_add_response_to_history(OpenAiInterface *self, OpenAiResponse *response,int choice);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void privateOpenAiInterface_set_last_message_as_temp(OpenAiInterface *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_temp_system_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_temp_user_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_temp_assistent_prompt(OpenAiInterface *self, const char *prompt);
void OpenAiInterface_add_temp_developer_prompt(OpenAiInterface *self, const char *prompt);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON *private_OpenAiInterface_create_tool_object(
OpenAiCallback *self,
const char *type,
bool additionalProperties,
bool strict
);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_tools_raw(OpenAiInterface *self, cJSON *object);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
long private_OpenAiExtra_extract_index(const char *input);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiCallback *new_OpenAiCallback(
char *(*Lambda)(cJSON *args, void *pointer),
void *pointer,
const char *name_func,
const char *description,
bool check_heap
);
void OpenAiCallback_free(OpenAiCallback *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiInterface * newOpenAiInterface(const char *url, const char *apiKey,const char *model);
void OpenAiInterface_free(OpenAiInterface *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiArgument *private_new_OpenAiArgument(
const char *name_argument,
const char *description,
const char *type,
bool required
);
void private_OpenAiArgument_free(OpenAiArgument *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiInterfaceNamespace newOpenAiInterfaceNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiNamespace newOpenAiNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponseNamespace newOpenAiResponseNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponse * OpenAiInterface_get_response_by_index(OpenAiInterface *self, long index);
cJSON *OpenAiResponse_get_choice(OpenAiResponse *response, long choice);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON * OpenAiResponse_get_message(OpenAiResponse *response,long choice);
cJSON *OpenAiResponse_get_content(OpenAiResponse *response, long choice);
const char * OpenAiResponse_get_content_str(OpenAiResponse *response,long choice);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON *OpenAiResponse_get_tool_calls(OpenAiResponse *response, long choice, long *size_array);
cJSON *OpenAiResponse_get_object_tool_calls(OpenAiResponse *response, long choice, long index);
const char *OpenAiResponse_get_id_tool_calls_by_index(OpenAiResponse *response, long choice, long index);
const char *OpenAiResponse_get_value_item_in_obj_tool_calls_function(OpenAiResponse *response, long choice, long index, const char *item);
const char *OpenAiResponse_get_name_func_tool_calls_by_index(OpenAiResponse *response, long choice, long index);
const char *OpenAiResponse_get_arguments_func_tool_calls_by_index(OpenAiResponse *response, long choice, long index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char *OpenAiResponse_get_finish_reason(OpenAiResponse *response, long choice);
bool OpenAiResponse_finish_reason_is_tool_calls(OpenAiResponse *response, long choice);
#endif
#ifndef SDK_OpenAI_def
#define SDK_OpenAI_def
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef OPEN_AI_ALLOW_DTW
void OpenAiInterface_set_cache(OpenAiInterface *self,const char *cache_dir,bool preserve_meta_info){
self->cache_dir = private_BearsslHttps_strdup(cache_dir);
self->cache_enabled = true;
self->preserve_meta_info = preserve_meta_info;
}
void OpenAiInterface_allow_cache(OpenAiInterface *self){
self->cache_enabled = true;
}
void OpenAiInterface_disallow_cache(OpenAiInterface *self){
self->cache_enabled = false;
}
void private_OpenAiInterface_digest_cache_entries(OpenAiInterface *self,char bufff[33]){
DtwHash *hash = newDtwHash();
char *messages_print = cJSON_Print(self->messages);
DtwHash_digest_string(hash, messages_print);
char *model = cJSON_GetObjectItem(self->body_object, "model")->valuestring;
DtwHash_digest_string(hash, model);
sprintf(bufff, "%s", hash->hash);
free(messages_print);
DtwHash_free(hash);
}
char *private_OpenAiIntereface_get_cache_answer_json_path(OpenAiInterface *self ,const char *entres_buff){
char *path = (char*)malloc(
strlen(self->cache_dir) +
strlen(entres_buff) +
sizeof("answer.json")+
3
);
sprintf(path, "%s/%s/answer.json", self->cache_dir, entres_buff);
return path;
}
cJSON *private_OpenAiInterface_get_cache_answer(OpenAiInterface *self){
if(!self->cache_enabled){
return NULL;
}
char hash[65] = {0};
private_OpenAiInterface_digest_cache_entries(self, hash);
char *path = private_OpenAiIntereface_get_cache_answer_json_path(self, hash);
cJSON *response = NULL;
if(dtw_entity_type(path) == DTW_FILE_TYPE){
char *content = dtw_load_string_file_content(path);
response = cJSON_Parse(content);
free(content);
}
free(path);
return response;
}
void privateOpenAiInterface_save_answer_cache(OpenAiInterface *self, cJSON *response){
if(!self->cache_enabled){
return;
}
char hash[65] = {0};
private_OpenAiInterface_digest_cache_entries(self, hash);
char *path = private_OpenAiIntereface_get_cache_answer_json_path(self, hash);
char *content = cJSON_Print(response);
dtw_write_string_file_content(path, content);
if(self->preserve_meta_info){
char *question_path = (char*)malloc(
strlen(self->cache_dir) +
sizeof(hash) +
sizeof("question.json")+
3
);
sprintf(question_path, "%s/%s/question.json", self->cache_dir, hash);
char *question_content = cJSON_Print(self->body_object);
dtw_write_string_file_content(question_path, question_content);
free(question_content);
free(question_path);
}
free(content);
free(path);
}
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int OpenAiInterface_add_callback_function_by_tools(
OpenAiInterface *self,
OpenAiCallback *callback
){
callback->index = self->size_callbakcs;
cJSON *tool_object = private_OpenAiInterface_create_tool_object(
callback,
"function",
false,
false
);
if(!tool_object){
OpenAiCallback_free(callback);
return 0;
}
OpenAiCallback **now_struct = (OpenAiCallback **)BearsslHttps_reallocate(self->callbacks, sizeof(OpenAiCallback *) * (self->size_callbakcs + 1));
if(!now_struct){
OpenAiCallback_free(callback);
return 0;
}
self->callbacks = now_struct;
self->callbacks[self->size_callbakcs] = callback;
self->size_callbakcs++;
OpenAiInterface_add_tools_raw(self, tool_object);
return 1;
}
int OpenAiInterface_add_parameters_in_callback(
OpenAiCallback *callback,
const char *name_argument,
const char *description,
const char *type,
bool required
){
OpenAiArgument *now_argument = private_new_OpenAiArgument(name_argument, description, type, required);
OpenAiArgument **arguments = (OpenAiArgument **)BearsslHttps_reallocate(callback->parameters, sizeof(OpenAiArgument*) * (callback->size_parameters + 1));
if(!arguments){
private_OpenAiArgument_free(now_argument);
return 0;
}
callback->parameters = arguments;
callback->parameters[callback->size_parameters] = now_argument;
callback->size_parameters++;
return 1;
}
char *OpenAiInterface_run_callback_by_index(OpenAiInterface *self, const char *name_function, const char *args){
long index_lambda = private_OpenAiExtra_extract_index(name_function);
if(index_lambda >= self->size_callbakcs){
return NULL;
}
OpenAiCallback *lambda = self->callbacks[index_lambda];
if(!lambda){
return NULL;
}
cJSON *arguments = cJSON_Parse(args);
char *response = lambda->Lambda(arguments, lambda->pointer);
cJSON_Delete(arguments);
if(lambda->check_heap){
BearsslHttps_free(response);
}
return response;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_set_know_ips(OpenAiInterface *self,const char *url){
if(strcmp(url,"https://api.openai.com/v1/chat/completions") == 0){
static const char *open_ai_ips[] = {
"172.66.0.243",
"162.159.140.245"
};
BearHttpsRequest_set_known_ips(self->request, open_ai_ips, 2);
}
}
void OpenAiInterface_set_temperature(OpenAiInterface *self, float temperature){
cJSON_DeleteItemFromObjectCaseSensitive(self->body_object, "temperature");
cJSON_AddNumberToObject(self->body_object, "temperature", temperature);
}
void OpenAiInterface_set_max_tokens(OpenAiInterface *self, float temperature){
cJSON_DeleteItemFromObjectCaseSensitive(self->body_object, "max_tokens");
cJSON_AddNumberToObject(self->body_object, "max_tokens", temperature);
}
void OpenAiInterface_set_model(OpenAiInterface *self, const char *model){
cJSON_DeleteItemFromObjectCaseSensitive(self->body_object, "model");
cJSON_AddStringToObject(self->body_object, "model", model);
}
void OpenAiInterface_set_source_model(OpenAiInterface *bearOpenAi, const char *source_model){
cJSON_DeleteItemFromObjectCaseSensitive(bearOpenAi->body_object, "source_model");
cJSON_AddStringToObject(bearOpenAi->body_object, "source_model", source_model);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool OpenAiResponse_error(OpenAiResponse *response){
if(response == NULL){
return true;
}
cJSON *error = cJSON_GetObjectItem(response, "error");
if(error == NULL){
return false;
}
return true;
}
char *OpenAiResponse_get_error_message(OpenAiResponse *response){
if(response == NULL){
char *response_temp = (char *)"Response Invalid;";
return response_temp;
}
cJSON *error = cJSON_GetObjectItem(response, "error");
if(error == NULL){
return NULL;
}
cJSON *message = cJSON_GetObjectItem(error, "message");
if(message == NULL){
return NULL;
}
return message->valuestring;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_raw_prompt(OpenAiInterface *self, cJSON *prompt, bool permanent){
cJSON_AddItemToArray(self->messages, prompt);
if(!permanent){
privateOpenAiInterface_set_last_message_as_temp(self);
}
}
void OpenAiInterface_add_default_prompt(OpenAiInterface *self,const char *role, const char *prompt, bool permanent){
cJSON *prompt_object = cJSON_CreateObject();
cJSON_AddStringToObject(prompt_object, "role", role);
cJSON_AddStringToObject(prompt_object, "content", prompt);
cJSON_AddItemToArray(self->messages, prompt_object);
if(!permanent){
privateOpenAiInterface_set_last_message_as_temp(self);
}
}
void OpenAiInterface_add_system_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "system", prompt, true);
}
void OpenAiInterface_add_user_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "user", prompt, true);
}
void OpenAiInterface_add_assistent_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "assistant", prompt, true);
}
void OpenAiInterface_add_developer_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "developer", prompt, true);
}
void OpenAiInterface_add_tool_prompt(OpenAiInterface *self, const char *id_call, const char *content){
cJSON *prompt_tool = cJSON_CreateObject();
cJSON_AddStringToObject(prompt_tool, "role", "tool");
cJSON_AddStringToObject(prompt_tool, "tool_call_id", id_call);
if(content){
cJSON_AddStringToObject(prompt_tool, "content", content);
}
if(!content){
cJSON_AddStringToObject(prompt_tool, "content", "");
}
OpenAiInterface_add_raw_prompt(self, prompt_tool, true);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponse *OpenAiInterface_make_question(OpenAiInterface *self){
#ifdef OPEN_AI_ALLOW_DTW
cJSON *cached_json = private_OpenAiInterface_get_cache_answer(self);
if(cached_json){
cJSON_AddItemToArray(self->response_array, cached_json);
return cached_json;
}
#endif
BearHttpsResponse *response = BearHttpsRequest_fetch(self->request);
for(int i = self->total_temp_menssages-1; i >= 0;i--){
int index_to_destroy = self->temp_messages[i];
cJSON_DeleteItemFromArray(self->messages, index_to_destroy);
}
self->total_temp_menssages = 0;
const char * body = BearHttpsResponse_read_body_str(response);
if(BearHttpsResponse_error(response)){
char *error_msg = BearHttpsResponse_get_error_msg(response);
cJSON *error_json = cJSON_CreateObject();
cJSON *messsage = cJSON_CreateString(error_msg);
cJSON_AddItemToObject(error_json, "message", messsage);
cJSON_AddItemToArray(self->response_array, error_json);
BearHttpsResponse_free(response);
return error_json;
}
cJSON *json = cJSON_Parse(body);
BearHttpsResponse_free(response);
if(!json){
cJSON *error_json = cJSON_CreateObject();
cJSON *messsage = cJSON_CreateString("Error parsing json");
cJSON_AddItemToObject(error_json, "message", messsage);
cJSON_AddItemToArray(self->response_array, error_json);
return error_json;
}
cJSON_AddItemToArray(self->response_array, json);
#ifdef OPEN_AI_ALLOW_DTW
privateOpenAiInterface_save_answer_cache(self, json);
#endif
return json;
}
OpenAiResponse *OpenAiInterface_make_question_finish_reason_treated(OpenAiInterface *self){
int max_questions = 0;
while(max_questions < 30){
max_questions++;
OpenAiResponse *response = OpenAiInterface_make_question(self);
if(OpenAiResponse_error(response)){
return NULL;
}
bool callbacks_finished = OpenAiResponse_finish_reason_is_tool_calls(response, 0);
if(!callbacks_finished){
return response;
}
OpenAiInterface_add_response_to_history(self, response, 0);
long size_array = 0;
cJSON *tool_calls = OpenAiResponse_get_tool_calls(response, 0, &size_array);
for(int i=0; i < size_array; i++){
const char *id = OpenAiResponse_get_id_tool_calls_by_index(response, 0, i);
if(!id){
return NULL;
}
const char *name = OpenAiResponse_get_name_func_tool_calls_by_index(response, 0, i);
if(!name){
return NULL;
}
const char *arguments = OpenAiResponse_get_arguments_func_tool_calls_by_index(response, 0, i);
if(!arguments){
return NULL;
}
const char *response_callback = OpenAiInterface_run_callback_by_index(self, name, arguments);
OpenAiInterface_add_tool_prompt(self, id, response_callback);
}
}
return NULL;
}
void OpenAiInterface_add_response_to_history(OpenAiInterface *self, OpenAiResponse *response,int choice){
cJSON *message = OpenAiResponse_get_message(response,choice);
cJSON *copy = cJSON_Duplicate(message,1);
cJSON_AddItemToArray(self->messages, copy);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void privateOpenAiInterface_set_last_message_as_temp(OpenAiInterface *self){
int required_permanent_size = (self->total_temp_menssages +1) *sizeof(int);
if(self->total_temp_messages_alocated <= required_permanent_size){
self->total_temp_messages_alocated = required_permanent_size *2;
self->temp_messages = (int*)realloc(self->temp_messages, self->total_temp_messages_alocated);
}
int last_index = cJSON_GetArraySize(self->messages) -1;
self->temp_messages[self->total_temp_menssages] = last_index;
self->total_temp_menssages++;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_temp_system_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "system", prompt, false);
}
void OpenAiInterface_add_temp_user_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "user", prompt, false);
}
void OpenAiInterface_add_temp_assistent_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "assistant", prompt, false);
}
void OpenAiInterface_add_temp_developer_prompt(OpenAiInterface *self, const char *prompt){
OpenAiInterface_add_default_prompt(self, "developer", prompt, true);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON *private_OpenAiInterface_create_tool_object(
OpenAiCallback *self,
const char *type,
bool additionalProperties,
bool strict
){
cJSON *tool_object = cJSON_CreateObject();
cJSON_AddStringToObject(tool_object, "type", "function");
cJSON *function = cJSON_AddObjectToObject(tool_object, "function");
long sizing_index_name = snprintf(NULL, 0, "%ld_%s", self->index, self->name_function) + 1;
self->index_name = (char *)BearsslHttps_allocate(sizing_index_name);
if(!self->index_name){
cJSON_Delete(tool_object);
return NULL;
}
sprintf(self->index_name, "%ld_%s", self->index, self->name_function);
cJSON_AddStringToObject(function, "name", self->index_name);
cJSON_AddStringToObject(function, "description", self->description);
cJSON_AddBoolToObject(function, "strict", strict);
cJSON *parameters = cJSON_AddObjectToObject(function, "parameters");
cJSON_AddStringToObject(parameters, "type", "object");
cJSON_AddBoolToObject(parameters, "additionalProperties", additionalProperties);
cJSON *required = cJSON_AddArrayToObject(parameters, "required");
cJSON *properties = cJSON_AddObjectToObject(parameters, "properties");
for(int i=0; i < self->size_parameters; i++){
const char *name_value = self->parameters[i]->name_argument;
cJSON *argument_obj = cJSON_AddObjectToObject(properties, name_value);
cJSON_AddStringToObject(argument_obj, "type", self->parameters[i]->type);
cJSON_AddStringToObject(argument_obj, "description", self->parameters[i]->description);
if(self->parameters[i]->required){
cJSON *name_argument = cJSON_CreateString(name_value);
cJSON_AddItemToArray(required, name_argument);
}
}
return tool_object;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void OpenAiInterface_add_tools_raw(OpenAiInterface *self, cJSON *object){
cJSON *OpenAi_tools = cJSON_GetObjectItem(self->body_object, "tools");
if(!OpenAi_tools){
OpenAi_tools = cJSON_CreateArray();
cJSON_AddItemToObject(self->body_object, "tools", OpenAi_tools);
}
cJSON_AddItemToArray(OpenAi_tools, object);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
long private_OpenAiExtra_extract_index(const char *input) {
const char *underscore_pos = strchr(input, '_');
if (underscore_pos != NULL) {
size_t length = underscore_pos - input;
char substring[length + 1];
strncpy(substring, input, length);
substring[length] = '\0';
return strtol(substring, NULL, 10);
}
return 0;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiCallback *new_OpenAiCallback(
char *(*Lambda)(cJSON *args, void *pointer),
void *pointer,
const char *name_func,
const char *description,
bool check_heap
){
OpenAiCallback *self = (OpenAiCallback *)BearsslHttps_allocate(sizeof(OpenAiCallback));
if(!self){
printf("\n\tError:. allocate struct OpenAiCallback in error;\n");
exit(1);
}
*self = (OpenAiCallback){0};
self->Lambda = Lambda;
self->name_function = name_func;
self->index_name = NULL;
self->description = description;
self->size_parameters = 0;
self->parameters = (OpenAiArgument **)BearsslHttps_allocate(sizeof(OpenAiArgument *));
if(!self->parameters){
BearsslHttps_free(self);
return NULL;
}
*self->parameters = (OpenAiArgument*){0};
self->check_heap = check_heap;
self->pointer = pointer;
return self;
}
void OpenAiCallback_free(OpenAiCallback *self){
if(!self){
return;
}
if(self->index_name){
BearsslHttps_free(self->index_name);
}
if(self->parameters){
for(int i=0; i < self->size_parameters; i++){
private_OpenAiArgument_free(self->parameters[i]);
}
BearsslHttps_free(self->parameters);
}
BearsslHttps_free(self);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiInterface *newOpenAiInterface(const char *url, const char *apiKey,const char *model){
OpenAiInterface *self = (OpenAiInterface*)BearsslHttps_allocate(sizeof(OpenAiInterface));
*self = (OpenAiInterface){0};
self->request = newBearHttpsRequest(url);
OpenAiInterface_set_know_ips(self, url);
BearHttpsRequest_set_method(self->request, "POST");
BearHttpsRequest_add_header_fmt(self->request, (char *)"Authorization", (char *)"Bearer %s", apiKey);
//set cache to 0
self->body_object = BearHttpsRequest_create_cJSONPayloadObject(self->request);
self->messages = cJSON_CreateArray();
OpenAiInterface_set_model(self, model);
self->temp_messages = (int*)BearsslHttps_allocate(1);
self->total_temp_messages_alocated = 1;
cJSON_AddItemToObject(self->body_object, "messages", self->messages);
self->response_array = cJSON_CreateArray();
self->size_callbakcs = 0;
self->callbacks = (OpenAiCallback **)BearsslHttps_allocate(sizeof(OpenAiCallback *));
if(!self->callbacks){
OpenAiInterface_free(self);
return NULL;
}
*self->callbacks = (OpenAiCallback*){0};
return self;
}
void OpenAiInterface_free(OpenAiInterface *self){
#ifdef OPEN_AI_ALLOW_DTW
if(self->cache_dir){
free(self->cache_dir);
}
#endif
if(self->callbacks){
for(int i = 0; i < self->size_callbakcs; i++){
OpenAiCallback_free(self->callbacks[i]);
}
BearsslHttps_free(self->callbacks);
}
if(self->temp_messages){
BearsslHttps_free(self->temp_messages);
}
cJSON_Delete(self->response_array);
BearHttpsRequest_free(self->request);
BearsslHttps_free(self);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiArgument *private_new_OpenAiArgument(
const char *name_argument,
const char *description,
const char *type,
bool required
){
OpenAiArgument *self = (OpenAiArgument *)BearsslHttps_allocate(sizeof(OpenAiArgument));
if(!self){
printf("\n\tErrro:. Allocate struct OpenAiArgument in error.\n");
exit(1);
}
*self = (OpenAiArgument){0};
self->name_argument = name_argument;
self->description = description;
self->type = type;
self->required = required;
return self;
}
void private_OpenAiArgument_free(OpenAiArgument *self){
if(self){
BearsslHttps_free(self);
}
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiInterfaceNamespace newOpenAiInterfaceNamespace(){
OpenAiInterfaceNamespace self ={0};
self.newOpenAiInterface = newOpenAiInterface;
self.get_response_by_index = OpenAiInterface_get_response_by_index;
#ifdef OPEN_AI_ALLOW_DTW
self.set_cache = OpenAiInterface_set_cache;
self.allow_cache = OpenAiInterface_allow_cache;
self.disallow_cache = OpenAiInterface_disallow_cache;
#endif
self.add_system_prompt = OpenAiInterface_add_system_prompt;
self.add_user_prompt = OpenAiInterface_add_user_prompt;
self.add_assistent_prompt = OpenAiInterface_add_assistent_prompt;
self.add_developer_prompt = OpenAiInterface_add_developer_prompt;
self.add_tool_prompt = OpenAiInterface_add_tool_prompt;
self.add_temp_system_prompt = OpenAiInterface_add_temp_system_prompt;
self.add_temp_user_prompt = OpenAiInterface_add_temp_user_prompt;
self.add_temp_assistent_prompt = OpenAiInterface_add_temp_assistent_prompt;
self.add_temp_developer_prompt = OpenAiInterface_add_temp_developer_prompt;
self.set_know_ips = OpenAiInterface_set_know_ips;
self.set_max_tokens = OpenAiInterface_set_max_tokens;
self.set_temperature = OpenAiInterface_set_temperature;
self.set_model = OpenAiInterface_set_model;
self.set_source_model = OpenAiInterface_set_source_model;
self.add_response_to_history = OpenAiInterface_add_response_to_history;
self.make_question = OpenAiInterface_make_question;
self.error = OpenAiResponse_error;
self.get_error_message = OpenAiResponse_get_error_message;
self.free = OpenAiInterface_free;
return self;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiNamespace newOpenAiNamespace(){
OpenAiNamespace self ={0};
self.openai_interface = newOpenAiInterfaceNamespace();
self.response = newOpenAiResponseNamespace();
return self;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponseNamespace newOpenAiResponseNamespace(){
OpenAiResponseNamespace self ={0};
self.get_choice = OpenAiResponse_get_choice;
self.get_content = OpenAiResponse_get_content;
self.get_content_str = OpenAiResponse_get_content_str;
self.get_message = OpenAiResponse_get_message;
self.error = OpenAiResponse_error;
self.get_error_message = OpenAiResponse_get_error_message;
return self;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
OpenAiResponse * OpenAiInterface_get_response_by_index(OpenAiInterface *self, long index){
int size = cJSON_GetArraySize(self->response_array);
//if index its -1 than its last
if(index < 0){
index = size + index;
}
if(index < 0 || index >= size){
return NULL;
}
return cJSON_GetArrayItem(self->response_array, index);
}
cJSON *OpenAiResponse_get_choice(OpenAiResponse *response, long choice){
if(response == NULL){
return NULL;
}
cJSON *choices = cJSON_GetObjectItem(response, "choices");
if(choices == NULL){
return NULL;
}
return cJSON_GetArrayItem(choices, choice);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON * OpenAiResponse_get_message(OpenAiResponse *response,long choice){
cJSON *choice_item = OpenAiResponse_get_choice(response, choice);
if(choice_item == NULL){
return NULL;
}
cJSON *message = cJSON_GetObjectItem(choice_item, "message");
if(message == NULL){
return NULL;
}
return message;
}
cJSON *OpenAiResponse_get_content(OpenAiResponse *response, long choice){
cJSON *message =OpenAiResponse_get_message(response, choice);
if(message == NULL){
return NULL;
}
return cJSON_GetObjectItem(message, "content");
}
const char * OpenAiResponse_get_content_str(OpenAiResponse *response,long choice){
cJSON *content = OpenAiResponse_get_content(response,choice);
if(content == NULL){
return NULL;
}
return content->valuestring;
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
cJSON *OpenAiResponse_get_tool_calls(OpenAiResponse *response, long choice, long *size_array){
cJSON *message = OpenAiResponse_get_message(response, choice);
if(!message){
return NULL;
}
cJSON *tool_calls = cJSON_GetObjectItemCaseSensitive(message, "tool_calls");
if(size_array){
if(!tool_calls){
*size_array = 0;
}
if(tool_calls){
*size_array = cJSON_GetArraySize(tool_calls);
}
}
return tool_calls;
}
cJSON *OpenAiResponse_get_object_tool_calls(OpenAiResponse *response, long choice, long index){
long max_size_array = 0;
cJSON *tool_calls_array = OpenAiResponse_get_tool_calls(response, choice, &max_size_array);
if(!tool_calls_array || index >= max_size_array){
return NULL;
}
cJSON *obj_tool_calls = cJSON_GetArrayItem(tool_calls_array, index);
return obj_tool_calls;
}
const char *OpenAiResponse_get_id_tool_calls_by_index(OpenAiResponse *response, long choice, long index){
cJSON *obj_tool_calls = OpenAiResponse_get_object_tool_calls(response, choice, index);
if(!obj_tool_calls){
return NULL;
}
cJSON *id = cJSON_GetObjectItemCaseSensitive(obj_tool_calls, "id");
if(!id){
return NULL;
}
return cJSON_GetStringValue(id);
}
const char *OpenAiResponse_get_value_item_in_obj_tool_calls_function(OpenAiResponse *response, long choice, long index, const char *item){
cJSON *obj_tool_calls = OpenAiResponse_get_object_tool_calls(response, choice, index);
if(!obj_tool_calls){
return NULL;
}
cJSON *function = cJSON_GetObjectItemCaseSensitive(obj_tool_calls, "function");
if(!function){
return NULL;
}
cJSON *item_obj = cJSON_GetObjectItemCaseSensitive(function, item);
if(!item_obj){
return NULL;
}
return cJSON_GetStringValue(item_obj);
}
const char *OpenAiResponse_get_name_func_tool_calls_by_index(OpenAiResponse *response, long choice, long index){
return OpenAiResponse_get_value_item_in_obj_tool_calls_function(response, choice, index, "name");
}
const char *OpenAiResponse_get_arguments_func_tool_calls_by_index(OpenAiResponse *response, long choice, long index){
return OpenAiResponse_get_value_item_in_obj_tool_calls_function(response, choice, index, "arguments");
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char *OpenAiResponse_get_finish_reason(OpenAiResponse *response, long choice){
cJSON *choice_obj = OpenAiResponse_get_choice(response, choice);
if(!choice_obj){
return NULL;
}
cJSON *finish_reason = cJSON_GetObjectItemCaseSensitive(choice_obj, "finish_reason");
if(!finish_reason){
return NULL;
}
return cJSON_GetStringValue(finish_reason);
}
bool OpenAiResponse_finish_reason_is_tool_calls(OpenAiResponse *response, long choice){
const char *finished_reason = OpenAiResponse_get_finish_reason(response, choice);
if(!finished_reason){
return false;
}
if(strcmp("tool_calls", finished_reason) == 0){
return true;
}
return false;
}
#endif
#ifdef DEFINE_DEPENDENCIES
/* MIT License
Copyright (c) 2025 OUI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef LuaSilverChain_globals
#define LuaSilverChain_globals
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
#ifndef LuaSilverChain_dep_declare
#define LuaSilverChain_dep_declare
#include
#include
#include
#include
#include
#ifndef BearsslHttps_allocate
#define BearsslHttps_allocate malloc
#endif
#ifndef BearsslHttps_reallocate
#define BearsslHttps_reallocate realloc
#endif
#ifndef BearsslHttps_free
#define BearsslHttps_free free
#endif
#if defined(_MSC_VER)
#include
#include
typedef SSIZE_T ssize_t;
typedef __m128i __m128i_u;
#define __src_inner_hbyteswap_ulong _byteswap_ulong
#endif
#if !defined(UniversalSocket_dep)
/* MIT License
Copyright (c) 2024 Samuel Henrique
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef UniversalSocket_dep
#define UniversalSocket_dep
#include
#include
#include
#include
#include
//#define _GET_ADDR_INFO_DEFAULT_
#if defined(__linux__)
#include
#include
#include
#include
#include
#include
#include
#endif
#if defined(_WIN32)
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
#endif
#endif
#ifndef UniversalSocket_mac
#define UniversalSocket_mac
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define UNI_AF_INET AF_INET
#define UNI_INADDR_ANY INADDR_ANY
#define UNI_FD_SET FD_SET
#define UNI_FD_CLR FD_CLR
#define UNI_FD_ISSET FD_ISSET
#define UNI_FD_ZERO FD_ZERO
#define UNI_SOCK_STREAM SOCK_STREAM
#define UNI_SOCK_DGRAM SOCK_DGRAM
#define UNI_SOCK_RAW SOCK_RAW
#define UNI_MSG_PEEK MSG_PEEK
#define UNI_SO_RCVTIMEO SO_RCVTIMEO
#define UNI_SO_SNDTIMEO SO_SNDTIMEO
#define UNI_SO_KEEPALIVE SO_KEEPALIVE
#define UNI_SO_BROADCAST SO_BROADCAST
#define UNI_SO_LINGER SO_LINGER
#define UNI_AF_UNSPEC AF_UNSPEC
#define UNI_IPPROTO_TCP IPPROTO_TCP
#define UNI_IPPROTO_UDP IPPROTO_UDP
#define UNI_MSG_OOB MSG_OOB
#define UNI_AF_INET6 AF_INET6
#define UNI_SHUT_RD SHUT_RD
#define UNI_SHUT_WR SHUT_WR
#define UNI_SHUT_RDWR SHUT_RDWR
#define UNI_SO_REUSEADDR SO_REUSEADDR
#define UNI_SO_RCVBUF SO_RCVBUF
#define UNI_SOL_SOCKET SOL_SOCKET
#define UNI_AF_INET6 AF_INET6
#define UNI_INET6_ADDRSTRLEN INET6_ADDRSTRLEN
#define UNI_EAI_MEMORY EAI_MEMORY
#define UNI_INET_ADDRSTRLEN INET_ADDRSTRLEN
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
#define UNI_INVALID_SOCKET -1
#define UNI_SOCKET_ERROR -1
#define UNI_EAGAIN EAGAIN
#define UNI_EWOULDBLOCK EWOULDBLOCK
#define UNI_ECONNREFUSED ECONNREFUSED
#define UNI_ETIMEDOUT ETIMEDOUT
#define UNI_EINPROGRESS EINPROGRESS
#define UNI_EADDRNOTAVAIL EADDRNOTAVAIL
#define UNI_ENETUNREACH ENETUNREACH
#define UNI_MSG_WAITALL MSG_WAITALL
#define UNI_EAI_NONAME EAI_NONAME
#define UNI_EAI_AGAIN EAI_AGAIN
#define UNI_EAI_FAIL EAI_FAIL
#define UNI_EAI_NODATA EAI_NONAME
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
#define UNI_INVALID_SOCKET INVALID_SOCKET
#define UNI_SOCKET_ERROR SOCKET_ERROR
#define UNI_EAGAIN WSAEWOULDBLOCK
#define UNI_EWOULDBLOCK WSAEWOULDBLOCK
#define UNI_MSG_WAITALL 0
#define UNI_ECONNREFUSED WSAECONNREFUSED
#define UNI_ETIMEDOUT WSAETIMEDOUT
#define UNI_EINPROGRESS WSAEINPROGRESS
#define UNI_EADDRNOTAVAIL WSAEADDRNOTAVAIL
#define UNI_ENETUNREACH WSAENETUNREACH
#define UNI_EAI_NONAME WSAHOST_NOT_FOUND
#define UNI_EAI_AGAIN WSATRY_AGAIN
#define UNI_EAI_FAIL WSANO_RECOVERY
#define UNI_EAI_NODATA WSANO_DATA
#endif
#endif
#ifndef UniversalSocket_types
#define UniversalSocket_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct sockaddr Universal_sockaddr;
typedef struct sockaddr_in Universal_sockaddr_in;
typedef struct sockaddr_in6 Universal_sockaddr_in6;
typedef struct sockaddr_storage Universal_sockaddr_storage;
typedef struct addrinfo Universal_addrinfo;
typedef struct in_addr Universal_in_addr;
typedef struct in6_addr Universal_in6_addr;
typedef struct hostent Universal_hostent;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
typedef int Universal_socket_int;
typedef socklen_t Universal_socket_len;
typedef unsigned int Universal_DWORD;
typedef ssize_t Universal_ssize_t;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
typedef SOCKET Universal_socket_int;
typedef int Universal_socket_len;
typedef DWORD Universal_DWORD;
typedef unsigned long in_addr_t;
typedef long Universal_ssize_t;
#endif
#endif
#ifndef UniversalSocket_dec
#define UniversalSocket_dec
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern const char* Universal_inet_ntoa(Universal_in_addr addr);
extern ssize_t Universal_recv (int fd, void *buf, size_t n, int flags);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern ssize_t Universal_send (int fd, const void *buf, size_t n, int flags);
extern const char *Universal_inet_ntop(int af, const void *src, char *dst, Universal_socket_len size);
extern int Universal_inet_pton(int af, const char *src, void *dst);
uint32_t Universal_ntohl(uint32_t netlong);
uint16_t Universal_htons(uint16_t value);
uint16_t Universal_ntohs(uint16_t value);
extern in_addr_t Universal_inet_addr(const char *ip);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern int Universal_bind (int fd,Universal_sockaddr_in *addrin , Universal_socket_len len);
extern int Universal_accept (int fd, Universal_sockaddr_in *addrin,
Universal_socket_len *adrr_len);
extern int Universal_listen (int fd, int n);
extern int Universal_connect(int sockfd, const Universal_sockaddr *addr, socklen_t addrlen);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int Universal_getaddrinfo(const char *node, const char *service, const Universal_addrinfo *hints, Universal_addrinfo **res);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern char *Universal_GetLastError();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern int Universal_start_all ();
extern int Universal_close (int fd);
extern int Universal_end ();
//#if defined(_GET_ADDR_INFO_DEFAULT_)
int Universal_getaddrinfo(const char *node, const char *service, const Universal_addrinfo *hints, Universal_addrinfo **res);
void Universal_freeaddrinfo(Universal_addrinfo *addrinfo_ptr);
//#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int Universal_socket (int domain, int type, int protocol);
int Universal_ZeroMemory(void *ptr, size_t num);
int Universal_setsockopt(
Universal_socket_int sockfd,
int level,
int optname,
const void *optval,
Universal_socket_len optlen
);
int Universal_getsockopt(
Universal_socket_int sockfd,
int level,
int optname,
void *optval,
Universal_socket_len *optlen
);
Universal_hostent *Universal_gethostbyname(const char *hostname);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
ssize_t private_Universal_recv_all(int fd, void *buf, size_t n);
#endif
#endif
#define BEARSSL_HTTPS_UNIVERSAL_SOCKET_DECLARATED
#endif
#if !defined(BR_BEARSSL_H__)
#define BR_ENABLE_INTRINSICS 1
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef INNER_H__
#define INNER_H__
#include
#include
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef CONFIG_H__
#define CONFIG_H__
/*
* This file contains compile-time flags that can override the
* autodetection performed in relevant files. Each flag is a macro; it
* deactivates the feature if defined to 0, activates it if defined to a
* non-zero integer (normally 1). If the macro is not defined, then
* autodetection applies.
*/
/*
* When BR_64 is enabled, 64-bit integer types are assumed to be
* efficient (i.e. the architecture has 64-bit registers and can
* do 64-bit operations as fast as 32-bit operations).
*
#define BR_64 1
*/
/*
* When BR_LOMUL is enabled, then multiplications of 32-bit values whose
* result are truncated to the low 32 bits are assumed to be
* substantially more efficient than 32-bit multiplications that yield
* 64-bit results. This is typically the case on low-end ARM Cortex M
* systems (M0, M0+, M1, and arguably M3 and M4 as well).
*
#define BR_LOMUL 1
*/
/*
* When BR_SLOW_MUL is enabled, multiplications are assumed to be
* substantially slow with regards to other integer operations, thus
* making it worth to make more operations for a given task if it allows
* using less multiplications.
*
#define BR_SLOW_MUL 1
*/
/*
* When BR_SLOW_MUL15 is enabled, short multplications (on 15-bit words)
* are assumed to be substantially slow with regards to other integer
* operations, thus making it worth to make more integer operations if
* it allows using less multiplications.
*
#define BR_SLOW_MUL15 1
*/
/*
* When BR_CT_MUL31 is enabled, multiplications of 31-bit values (used
* in the "i31" big integer implementation) use an alternate implementation
* which is slower and larger than the normal multiplication, but should
* ensure constant-time multiplications even on architectures where the
* multiplication opcode takes a variable number of cycles to complete.
*
#define BR_CT_MUL31 1
*/
/*
* When BR_CT_MUL15 is enabled, multiplications of 15-bit values (held
* in 32-bit words) use an alternate implementation which is slower and
* larger than the normal multiplication, but should ensure
* constant-time multiplications on most/all architectures where the
* basic multiplication is not constant-time.
#define BR_CT_MUL15 1
*/
/*
* When BR_NO_ARITH_SHIFT is enabled, arithmetic right shifts (with sign
* extension) are performed with a sequence of operations which is bigger
* and slower than a simple right shift on a signed value. This avoids
* relying on an implementation-defined behaviour. However, most if not
* all C compilers use sign extension for right shifts on signed values,
* so this alternate macro is disabled by default.
#define BR_NO_ARITH_SHIFT 1
*/
/*
* When BR_RDRAND is enabled, the SSL engine will use the RDRAND opcode
* to automatically obtain quality randomness for seeding its internal
* PRNG. Since that opcode is present only in recent x86 CPU, its
* support is dynamically tested; if the current CPU does not support
* it, then another random source will be used, such as /dev/urandom or
* CryptGenRandom().
*
#define BR_RDRAND 1
*/
/*
* When BR_USE_GETENTROPY is enabled, the SSL engine will use the
* getentropy() function to obtain quality randomness for seeding its
* internal PRNG. On Linux and FreeBSD, getentropy() is implemented by
* the standard library with the system call getrandom(); on OpenBSD,
* getentropy() is the system call, and there is no getrandom() wrapper,
* hence the use of the getentropy() function for maximum portability.
*
* If the getentropy() call fails, and BR_USE_URANDOM is not explicitly
* disabled, then /dev/urandom will be used as a fallback mechanism. On
* FreeBSD and OpenBSD, this does not change much, since /dev/urandom
* will block if not enough entropy has been obtained since last boot.
* On Linux, /dev/urandom might not block, which can be troublesome in
* early boot stages, which is why getentropy() is preferred.
*
#define BR_USE_GETENTROPY 1
*/
/*
* When BR_USE_URANDOM is enabled, the SSL engine will use /dev/urandom
* to automatically obtain quality randomness for seeding its internal
* PRNG.
*
#define BR_USE_URANDOM 1
*/
/*
* When BR_USE_WIN32_RAND is enabled, the SSL engine will use the Win32
* (CryptoAPI) functions (CryptAcquireContext(), CryptGenRandom()...) to
* automatically obtain quality randomness for seeding its internal PRNG.
*
* Note: if both BR_USE_URANDOM and BR_USE_WIN32_RAND are defined, the
* former takes precedence.
*
#define BR_USE_WIN32_RAND 1
*/
/*
* When BR_USE_UNIX_TIME is enabled, the X.509 validation engine obtains
* the current time from the OS by calling time(), and assuming that the
* returned value (a 'time_t') is an integer that counts time in seconds
* since the Unix Epoch (Jan 1st, 1970, 00:00 UTC).
*
#define BR_USE_UNIX_TIME 1
*/
/*
* When BR_USE_WIN32_TIME is enabled, the X.509 validation engine obtains
* the current time from the OS by calling the Win32 function
* GetSystemTimeAsFileTime().
*
* Note: if both BR_USE_UNIX_TIME and BR_USE_WIN32_TIME are defined, the
* former takes precedence.
*
#define BR_USE_WIN32_TIME 1
*/
/*
* When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with
* inline assembly which is shorter and/or faster. This should be used
* only when all of the following are true:
* - target architecture is ARM in Thumb mode
* - target endianness is little-endian
* - compiler is GCC (or GCC-compatible for inline assembly syntax)
*
* This is meant for the low-end cores (Cortex M0, M0+, M1, M3).
* Note: if BR_LOMUL is not explicitly enabled or disabled, then
* enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL.
*
#define BR_ARMEL_CORTEXM_GCC 1
*/
/*
* When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI"
* instructions (dedicated AES opcodes) will be compiled. If this is not
* enabled explicitly, then that AES implementation will be compiled only
* if a compatible compiler is detected. If set explicitly to 0, the
* implementation will not be compiled at all.
*
#define BR_AES_X86NI 1
*/
/*
* When BR_SSE2 is enabled, SSE2 intrinsics will be used for some
* algorithm implementations that use them (e.g. chacha20_sse2). If this
* is not enabled explicitly, then support for SSE2 intrinsics will be
* automatically detected. If set explicitly to 0, then SSE2 code will
* not be compiled at all.
*
#define BR_SSE2 1
*/
/*
* When BR_POWER8 is enabled, the AES implementation using the POWER ISA
* 2.07 opcodes (available on POWER8 processors and later) is compiled.
* If this is not enabled explicitly, then that implementation will be
* compiled only if a compatible compiler is detected, _and_ the target
* architecture is POWER8 or later.
*
#define BR_POWER8 1
*/
/*
* When BR_INT128 is enabled, then code using the 'unsigned __int64'
* and 'unsigned __int128' types will be used to leverage 64x64->128
* unsigned multiplications. This should work with GCC and compatible
* compilers on 64-bit architectures.
*
#define BR_INT128 1
*/
/*
* When BR_UMUL128 is enabled, then code using the '_umul128()' and
* '_addcarry_u64()' intrinsics will be used to implement 64x64->128
* unsigned multiplications. This should work on Visual C on x64 systems.
*
#define BR_UMUL128 1
*/
/*
* When BR_LE_UNALIGNED is enabled, then the current architecture is
* assumed to use little-endian encoding for integers, and to tolerate
* unaligned accesses with no or minimal time penalty.
*
#define BR_LE_UNALIGNED 1
*/
/*
* When BR_BE_UNALIGNED is enabled, then the current architecture is
* assumed to use big-endian encoding for integers, and to tolerate
* unaligned accesses with no or minimal time penalty.
*
#define BR_BE_UNALIGNED 1
*/
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_H__
#define BR_BEARSSL_H__
#include
#include
/** \mainpage BearSSL API
*
* # API Layout
*
* The functions and structures defined by the BearSSL API are located
* in various header files:
*
* | Header file | Elements |
* | :-------------- | :------------------------------------------------ |
* | bearssl_hash.h | Hash functions |
* | bearssl_hmac.h | HMAC |
* | bearssl_kdf.h | Key Derivation Functions |
* | bearssl_rand.h | Pseudorandom byte generators |
* | bearssl_prf.h | PRF implementations (for SSL/TLS) |
* | bearssl_block.h | Symmetric encryption |
* | bearssl_aead.h | AEAD algorithms (combined encryption + MAC) |
* | bearssl_rsa.h | RSA encryption and signatures |
* | bearssl_ec.h | Elliptic curves support (including ECDSA) |
* | bearssl_ssl.h | SSL/TLS engine interface |
* | bearssl_x509.h | X.509 certificate decoding and validation |
* | bearssl_pem.h | Base64/PEM decoding support functions |
*
* Applications using BearSSL are supposed to simply include `bearssl.h`
* as follows:
*
* #include
*
* The `bearssl.h` file itself includes all the other header files. It is
* possible to include specific header files, but it has no practical
* advantage for the application. The API is separated into separate
* header files only for documentation convenience.
*
*
* # Conventions
*
* ## MUST and SHALL
*
* In all descriptions, the usual "MUST", "SHALL", "MAY",... terminology
* is used. Failure to meet requirements expressed with a "MUST" or
* "SHALL" implies undefined behaviour, which means that segmentation
* faults, buffer overflows, and other similar adverse events, may occur.
*
* In general, BearSSL is not very forgiving of programming errors, and
* does not include much failsafes or error reporting when the problem
* does not arise from external transient conditions, and can be fixed
* only in the application code. This is done so in order to make the
* total code footprint lighter.
*
*
* ## `NULL` values
*
* Function parameters with a pointer type shall not be `NULL` unless
* explicitly authorised by the documentation. As an exception, when
* the pointer aims at a sequence of bytes and is accompanied with
* a length parameter, and the length is zero (meaning that there is
* no byte at all to retrieve), then the pointer may be `NULL` even if
* not explicitly allowed.
*
*
* ## Memory Allocation
*
* BearSSL does not perform dynamic memory allocation. This implies that
* for any functionality that requires a non-transient state, the caller
* is responsible for allocating the relevant context structure. Such
* allocation can be done in any appropriate area, including static data
* segments, the heap, and the stack, provided that proper alignment is
* respected. The header files define these context structures
* (including size and contents), so the C compiler should handle
* alignment automatically.
*
* Since there is no dynamic resource allocation, there is also nothing to
* release. When the calling code is done with a BearSSL feature, it
* may simple release the context structures it allocated itself, with
* no "close function" to call. If the context structures were allocated
* on the stack (as local variables), then even that release operation is
* implicit.
*
*
* ## Structure Contents
*
* Except when explicitly indicated, structure contents are opaque: they
* are included in the header files so that calling code may know the
* structure sizes and alignment requirements, but callers SHALL NOT
* access individual fields directly. For fields that are supposed to
* be read from or written to, the API defines accessor functions (the
* simplest of these accessor functions are defined as `static inline`
* functions, and the C compiler will optimise them away).
*
*
* # API Usage
*
* BearSSL usage for running a SSL/TLS client or server is described
* on the [BearSSL Web site](https://www.bearssl.org/api1.html). The
* BearSSL source archive also comes with sample code.
*/
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_HASH_H__
#define BR_BEARSSL_HASH_H__
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_hash.h
*
* # Hash Functions
*
* This file documents the API for hash functions.
*
*
* ## Procedural API
*
* For each implemented hash function, of name "`xxx`", the following
* elements are defined:
*
* - `br_xxx_vtable`
*
* An externally defined instance of `br_hash_class`.
*
* - `br_xxx_SIZE`
*
* A macro that evaluates to the output size (in bytes) of the
* hash function.
*
* - `br_xxx_ID`
*
* A macro that evaluates to a symbolic identifier for the hash
* function. Such identifiers are used with HMAC and signature
* algorithm implementations.
*
* NOTE: for the "standard" hash functions defined in [the TLS
* standard](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1),
* the symbolic identifiers match the constants used in TLS, i.e.
* 1 to 6 for MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512,
* respectively.
*
* - `br_xxx_context`
*
* Context for an ongoing computation. It is allocated by the
* caller, and a pointer to it is passed to all functions. A
* context contains no interior pointer, so it can be moved around
* and cloned (with a simple `memcpy()` or equivalent) in order to
* capture the function state at some point. Computations that use
* distinct context structures are independent of each other. The
* first field of `br_xxx_context` is always a pointer to the
* `br_xxx_vtable` structure; `br_xxx_init()` sets that pointer.
*
* - `br_xxx_init(br_xxx_context *ctx)`
*
* Initialise the provided context. Previous contents of the structure
* are ignored. This calls resets the context to the start of a new
* hash computation; it also sets the first field of the context
* structure (called `vtable`) to a pointer to the statically
* allocated constant `br_xxx_vtable` structure.
*
* - `br_xxx_update(br_xxx_context *ctx, const void *data, size_t len)`
*
* Add some more bytes to the hash computation represented by the
* provided context.
*
* - `br_xxx_out(const br_xxx_context *ctx, void *out)`
*
* Complete the hash computation and write the result in the provided
* buffer. The output buffer MUST be large enough to accommodate the
* result. The context is NOT modified by this operation, so this
* function can be used to get a "partial hash" while still keeping
* the possibility of adding more bytes to the input.
*
* - `br_xxx_state(const br_xxx_context *ctx, void *out)`
*
* Get a copy of the "current state" for the computation so far. For
* MD functions (MD5, SHA-1, SHA-2 family), this is the running state
* resulting from the processing of the last complete input block.
* Returned value is the current input length (in bytes).
*
* - `br_xxx_set_state(br_xxx_context *ctx, const void *stb, uint64_t count)`
*
* Set the internal state to the provided values. The 'stb' and
* 'count' values shall match that which was obtained from
* `br_xxx_state()`. This restores the hash state only if the state
* values were at an appropriate block boundary. This does NOT set
* the `vtable` pointer in the context.
*
* Context structures can be discarded without any explicit deallocation.
* Hash function implementations are purely software and don't reserve
* any resources outside of the context structure itself.
*
*
* ## Object-Oriented API
*
* For each hash function that follows the procedural API described
* above, an object-oriented API is also provided. In that API, function
* pointers from the vtable (`br_xxx_vtable`) are used. The vtable
* incarnates object-oriented programming. An introduction on the OOP
* concept used here can be read on the BearSSL Web site:
* [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) * * The vtable offers functions called `init()`, `update()`, `out()`, * `set()` and `set_state()`, which are in fact the functions from * the procedural API. That vtable also contains two informative fields: * * - `context_size` * * The size of the context structure (`br_xxx_context`), in bytes. * This can be used by generic implementations to perform dynamic * context allocation. * * - `desc` * * A "descriptor" field that encodes some information on the hash * function: symbolic identifier, output size, state size, * internal block size, details on the padding. * * Users of this object-oriented API (in particular generic HMAC * implementations) may make the following assumptions: * * - Hash output size is no more than 64 bytes. * - Hash internal state size is no more than 64 bytes. * - Internal block size is a power of two, no less than 16 and no more * than 256. * * * ## Implemented Hash Functions * * Implemented hash functions are: * * | Function | Name | Output length | State length | * | :-------- | :------ | :-----------: | :----------: | * | MD5 | md5 | 16 | 16 | * | SHA-1 | sha1 | 20 | 20 | * | SHA-224 | sha224 | 28 | 32 | * | SHA-256 | sha256 | 32 | 32 | * | SHA-384 | sha384 | 48 | 64 | * | SHA-512 | sha512 | 64 | 64 | * | MD5+SHA-1 | md5sha1 | 36 | 36 | * * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the * same input; in the implementation, the internal data buffer is * shared, thus making it more memory-efficient than separate MD5 and * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS * 1.1.) * * * ## Multi-Hasher * * An aggregate hasher is provided, that can compute several standard * hash functions in parallel. It uses `br_multihash_context` and a * procedural API. It is configured with the implementations (the vtables) * that it should use; it will then compute all these hash functions in * parallel, on the same input. It is meant to be used in cases when the * hash of an object will be used, but the exact hash function is not * known yet (typically, streamed processing on X.509 certificates). * * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 * and SHA-512) are supported by the multi-hasher. * * * ## GHASH * * GHASH is not a generic hash function; it is a _universal_ hash function, * which, as the name does not say, means that it CANNOT be used in most * places where a hash function is needed. GHASH is used within the GCM * encryption mode, to provide the checked integrity functionality. * * A GHASH implementation is basically a function that uses the type defined * in this file under the name `br_ghash`: * * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); * * The `y` pointer refers to a 16-byte value which is used as input, and * receives the output of the GHASH invocation. `h` is a 16-byte secret * value (that serves as key). `data` and `len` define the input data. * * Three GHASH implementations are provided, all constant-time, based on * the use of integer multiplications with appropriate masking to cancel * carry propagation. */ /** * \brief Class type for hash function implementations. * * A `br_hash_class` instance references the methods implementing a hash * function. Constant instances of this structure are defined for each * implemented hash function. Such instances are also called "vtables". * * Vtables are used to support object-oriented programming, as * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). */ typedef struct br_hash_class_ br_hash_class; struct br_hash_class_ { /** * \brief Size (in bytes) of the context structure appropriate for * computing this hash function. */ size_t context_size; /** * \brief Descriptor word that contains information about the hash * function. * * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` * and `BR_HASHDESC_xxx_MASK` to access the specific value, as * follows: * * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK * * The defined elements are: * * - `ID`: the symbolic identifier for the function, as defined * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) * (MD5 = 1, SHA-1 = 2,...). * * - `OUT`: hash output size, in bytes. * * - `STATE`: internal running state size, in bytes. * * - `LBLEN`: base-2 logarithm for the internal block size, as * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 * and SHA-256, since these functions use 64-byte blocks; for * SHA-384 and SHA-512, this is 7, corresponding to their * 128-byte blocks). * * The descriptor may contain a few other flags. */ uint32_t desc; /** * \brief Initialisation method. * * This method takes as parameter a pointer to a context area, * that it initialises. The first field of the context is set * to this vtable; other elements are initialised for a new hash * computation. * * \param ctx pointer to (the first field of) the context. */ void (*init)(const br_hash_class **ctx); /** * \brief Data injection method. * * The `len` bytes starting at address `data` are injected into * the running hash computation incarnated by the specified * context. The context is updated accordingly. It is allowed * to have `len == 0`, in which case `data` is ignored (and could * be `NULL`), and nothing happens. * on the input data. * * \param ctx pointer to (the first field of) the context. * \param data pointer to the first data byte to inject. * \param len number of bytes to inject. */ void (*update)(const br_hash_class **ctx, const void *data, size_t len); /** * \brief Produce hash output. * * The hash output corresponding to all data bytes injected in the * context since the last `init()` call is computed, and written * in the buffer pointed to by `dst`. The hash output size depends * on the implemented hash function (e.g. 16 bytes for MD5). * The context is _not_ modified by this call, so further bytes * may be afterwards injected to continue the current computation. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the hash output. */ void (*out)(const br_hash_class *const *ctx, void *dst); /** * \brief Get running state. * * This method saves the current running state into the `dst` * buffer. What constitutes the "running state" depends on the * hash function; for Merkle-Damgård hash functions (like * MD5 or SHA-1), this is the output obtained after processing * each block. The number of bytes injected so far is returned. * The context is not modified by this call. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the state. * \return the injected total byte length. */ uint64_t (*state)(const br_hash_class *const *ctx, void *dst); /** * \brief Set running state. * * This methods replaces the running state for the function. * * \param ctx pointer to (the first field of) the context. * \param stb source buffer for the state. * \param count injected total byte length. */ void (*set_state)(const br_hash_class **ctx, const void *stb, uint64_t count); }; #ifndef BR_DOXYGEN_IGNORE #define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) #define BR_HASHDESC_ID_OFF 0 #define BR_HASHDESC_ID_MASK 0xFF #define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) #define BR_HASHDESC_OUT_OFF 8 #define BR_HASHDESC_OUT_MASK 0x7F #define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) #define BR_HASHDESC_STATE_OFF 15 #define BR_HASHDESC_STATE_MASK 0xFF #define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) #define BR_HASHDESC_LBLEN_OFF 23 #define BR_HASHDESC_LBLEN_MASK 0x0F #define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) #define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) #define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) #endif /* * Specific hash functions. * * Rules for contexts: * -- No interior pointer. * -- No pointer to external dynamically allocated resources. * -- First field is called 'vtable' and is a pointer to a * const-qualified br_hash_class instance (pointer is set by init()). * -- SHA-224 and SHA-256 contexts are identical. * -- SHA-384 and SHA-512 contexts are identical. * * Thus, contexts can be moved and cloned to capture the hash function * current state; and there is no need for any explicit "release" function. */ /** * \brief Symbolic identifier for MD5. */ #define br_md5_ID 1 /** * \brief MD5 output size (in bytes). */ #define br_md5_SIZE 16 /** * \brief Constant vtable for MD5. */ extern const br_hash_class br_md5_vtable; /** * \brief MD5 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[4]; #endif } br_md5_context; /** * \brief MD5 context initialisation. * * This function initialises or resets a context for a new MD5 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5_init(br_md5_context *ctx); /** * \brief Inject some data bytes in a running MD5 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5_update(br_md5_context *ctx, const void *data, size_t len); /** * \brief Compute MD5 output. * * The MD5 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5_out(const br_md5_context *ctx, void *out); /** * \brief Save MD5 running state. * * The running state for MD5 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5_state(const br_md5_context *ctx, void *out); /** * \brief Restore MD5 running state. * * The running state for MD5 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-1. */ #define br_sha1_ID 2 /** * \brief SHA-1 output size (in bytes). */ #define br_sha1_SIZE 20 /** * \brief Constant vtable for SHA-1. */ extern const br_hash_class br_sha1_vtable; /** * \brief SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[5]; #endif } br_sha1_context; /** * \brief SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-1 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha1_init(br_sha1_context *ctx); /** * \brief Inject some data bytes in a running SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-1 output. * * The SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha1_out(const br_sha1_context *ctx, void *out); /** * \brief Save SHA-1 running state. * * The running state for SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); /** * \brief Restore SHA-1 running state. * * The running state for SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-224. */ #define br_sha224_ID 3 /** * \brief SHA-224 output size (in bytes). */ #define br_sha224_SIZE 28 /** * \brief Constant vtable for SHA-224. */ extern const br_hash_class br_sha224_vtable; /** * \brief SHA-224 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[8]; #endif } br_sha224_context; /** * \brief SHA-224 context initialisation. * * This function initialises or resets a context for a new SHA-224 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha224_init(br_sha224_context *ctx); /** * \brief Inject some data bytes in a running SHA-224 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-224 output. * * The SHA-224 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha224_out(const br_sha224_context *ctx, void *out); /** * \brief Save SHA-224 running state. * * The running state for SHA-224 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); /** * \brief Restore SHA-224 running state. * * The running state for SHA-224 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha224_set_state(br_sha224_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-256. */ #define br_sha256_ID 4 /** * \brief SHA-256 output size (in bytes). */ #define br_sha256_SIZE 32 /** * \brief Constant vtable for SHA-256. */ extern const br_hash_class br_sha256_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-256 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha256_context; #else typedef br_sha224_context br_sha256_context; #endif /** * \brief SHA-256 context initialisation. * * This function initialises or resets a context for a new SHA-256 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha256_init(br_sha256_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-256 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); #else #define br_sha256_update br_sha224_update #endif /** * \brief Compute SHA-256 output. * * The SHA-256 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha256_out(const br_sha256_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-256 running state. * * The running state for SHA-256 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); #else #define br_sha256_state br_sha224_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-256 running state. * * The running state for SHA-256 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha256_set_state(br_sha256_context *ctx, const void *stb, uint64_t count); #else #define br_sha256_set_state br_sha224_set_state #endif /** * \brief Symbolic identifier for SHA-384. */ #define br_sha384_ID 5 /** * \brief SHA-384 output size (in bytes). */ #define br_sha384_SIZE 48 /** * \brief Constant vtable for SHA-384. */ extern const br_hash_class br_sha384_vtable; /** * \brief SHA-384 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint64_t val[8]; #endif } br_sha384_context; /** * \brief SHA-384 context initialisation. * * This function initialises or resets a context for a new SHA-384 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha384_init(br_sha384_context *ctx); /** * \brief Inject some data bytes in a running SHA-384 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-384 output. * * The SHA-384 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha384_out(const br_sha384_context *ctx, void *out); /** * \brief Save SHA-384 running state. * * The running state for SHA-384 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); /** * \brief Restore SHA-384 running state. * * The running state for SHA-384 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha384_set_state(br_sha384_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-512. */ #define br_sha512_ID 6 /** * \brief SHA-512 output size (in bytes). */ #define br_sha512_SIZE 64 /** * \brief Constant vtable for SHA-512. */ extern const br_hash_class br_sha512_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-512 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha512_context; #else typedef br_sha384_context br_sha512_context; #endif /** * \brief SHA-512 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha512_init(br_sha512_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-512 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); #else #define br_sha512_update br_sha384_update #endif /** * \brief Compute SHA-512 output. * * The SHA-512 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha512_out(const br_sha512_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-512 running state. * * The running state for SHA-512 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); #else #define br_sha512_state br_sha384_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-512 running state. * * The running state for SHA-512 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha512_set_state(br_sha512_context *ctx, const void *stb, uint64_t count); #else #define br_sha512_set_state br_sha384_set_state #endif /* * "md5sha1" is a special hash function that computes both MD5 and SHA-1 * on the same input, and produces a 36-byte output (MD5 and SHA-1 * concatenation, in that order). State size is also 36 bytes. */ /** * \brief Symbolic identifier for MD5+SHA-1. * * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the * same input. It is not one of the functions identified in TLS, so * we give it a symbolic identifier of value 0. */ #define br_md5sha1_ID 0 /** * \brief MD5+SHA-1 output size (in bytes). */ #define br_md5sha1_SIZE 36 /** * \brief Constant vtable for MD5+SHA-1. */ extern const br_hash_class br_md5sha1_vtable; /** * \brief MD5+SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val_md5[4]; uint32_t val_sha1[5]; #endif } br_md5sha1_context; /** * \brief MD5+SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5sha1_init(br_md5sha1_context *ctx); /** * \brief Inject some data bytes in a running MD5+SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); /** * \brief Compute MD5+SHA-1 output. * * The MD5+SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); /** * \brief Save MD5+SHA-1 running state. * * The running state for MD5+SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); /** * \brief Restore MD5+SHA-1 running state. * * The running state for MD5+SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5sha1_set_state(br_md5sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Aggregate context for configurable hash function support. * * The `br_hash_compat_context` type is a type which is large enough to * serve as context for all standard hash functions defined above. */ typedef union { const br_hash_class *vtable; br_md5_context md5; br_sha1_context sha1; br_sha224_context sha224; br_sha256_context sha256; br_sha384_context sha384; br_sha512_context sha512; br_md5sha1_context md5sha1; } br_hash_compat_context; /* * The multi-hasher is a construct that handles hashing of the same input * data with several hash functions, with a single shared input buffer. * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 * simultaneously, though which functions are activated depends on * the set implementation pointers. */ /** * \brief Multi-hasher context structure. * * The multi-hasher runs up to six hash functions in the standard TLS list * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over * the same input. * * The multi-hasher does _not_ follow the OOP structure with a vtable. * Instead, it is configured with the vtables of the hash functions it * should run. Structure fields are not supposed to be accessed directly. */ typedef struct { #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint32_t val_32[25]; uint64_t val_64[16]; const br_hash_class *impl[6]; #endif } br_multihash_context; /** * \brief Clear a multi-hasher context. * * This should always be called once on a given context, _before_ setting * the implementation pointers. * * \param ctx the multi-hasher context. */ void br_multihash_zero(br_multihash_context *ctx); /** * \brief Set a hash function implementation. * * Implementations shall be set _after_ clearing the context (with * `br_multihash_zero()`) but _before_ initialising the computation * (with `br_multihash_init()`). The hash function implementation * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove * an implementation from the multi-hasher. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \param impl the hash function vtable, or `NULL`. */ static inline void br_multihash_setimpl(br_multihash_context *ctx, int id, const br_hash_class *impl) { /* * This code relies on hash functions ID being values 1 to 6, * in the MD5 to SHA-512 order. */ ctx->impl[id - 1] = impl; } /** * \brief Get a hash function implementation. * * This function returns the currently configured vtable for a given * hash function (by symbolic ID). If no such function was configured in * the provided multi-hasher context, then this function returns `NULL`. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \return the hash function vtable, or `NULL`. */ static inline const br_hash_class * br_multihash_getimpl(const br_multihash_context *ctx, int id) { return ctx->impl[id - 1]; } /** * \brief Reset a multi-hasher context. * * This function prepares the context for a new hashing computation, * for all implementations configured at that point. * * \param ctx the multi-hasher context. */ void br_multihash_init(br_multihash_context *ctx); /** * \brief Inject some data bytes in a running multi-hashing computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_multihash_update(br_multihash_context *ctx, const void *data, size_t len); /** * \brief Compute a hash output from a multi-hasher. * * The hash output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `dst`. The hash * function to use is identified by `id` and must be one of the standard * hash functions. If that hash function was indeed configured in the * multi-hasher context, the corresponding hash value is written in * `dst` and its length (in bytes) is returned. If the hash function * was _not_ configured, then nothing is written in `dst` and 0 is * returned. * * The context itself is not modified, so extra bytes may be injected * afterwards to continue the hash computations. * * \param ctx pointer to the context structure. * \param id the hash function symbolic identifier. * \param dst destination buffer for the hash output. * \return the hash output length (in bytes), or 0. */ size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); /** * \brief Type for a GHASH implementation. * * GHASH is a sort of keyed hash meant to be used to implement GCM in * combination with a block cipher (with 16-byte blocks). * * The `y` array has length 16 bytes and is used for input and output; in * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte * value that serves as key (it is derived from the encryption key in GCM, * using the block cipher). The data length (`len`) is expressed in bytes. * The `y` array is updated. * * If the data length is not a multiple of 16, then the data is implicitly * padded with zeros up to the next multiple of 16. Thus, when using GHASH * in GCM, this method may be called twice, for the associated data and * for the ciphertext, respectively; the zero-padding implements exactly * the GCM rules. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (mixed 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (strict 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, * but it is expected to be faster on architectures for which the * 32-bit multiplication opcode does not yield the upper 32 bits of the * product. It is constant-time (if multiplications are constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (64-bit). * * This implementation uses multiplications of 64-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). It is substantially faster than `br_ghash_ctmul()` * and `br_ghash_ctmul32()` on most 64-bit architectures. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using the `pclmulqdq` opcode (part of the * AES-NI instructions). * * This implementation is available only on x86 platforms where the * compiler supports the relevant intrinsic functions. Even if the * compiler supports these functions, the local CPU might not support * the `pclmulqdq` opcode, meaning that a call will fail with an * illegal instruction exception. To safely obtain a pointer to this * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pclmul` GHASH implementation, if available. * * If the `pclmul` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pclmul()` function. Otherwise, it will return `0`. * * \return the `pclmul` GHASH implementation, or `0`. */ br_ghash br_ghash_pclmul_get(void); /** * \brief GHASH implementation using the POWER8 opcodes. * * This implementation is available only on POWER8 platforms (and later). * To safely obtain a pointer to this function when supported (or 0 * otherwise), use `br_ghash_pwr8_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pwr8` GHASH implementation, if available. * * If the `pwr8` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pwr8()` function. Otherwise, it will return `0`. * * \return the `pwr8` GHASH implementation, or `0`. */ br_ghash br_ghash_pwr8_get(void); #ifdef __cplusplus } #endif #endif /* * Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_HMAC_H__
#define BR_BEARSSL_HMAC_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_hmac.h
*
* # HMAC
*
* HMAC is initialized with a key and an underlying hash function; it
* then fills a "key context". That context contains the processed
* key.
*
* With the key context, a HMAC context can be initialized to process
* the input bytes and obtain the MAC output. The key context is not
* modified during that process, and can be reused.
*
* IMPORTANT: HMAC shall be used only with functions that have the
* following properties:
*
* - hash output size does not exceed 64 bytes;
* - hash internal state size does not exceed 64 bytes;
* - internal block length is a power of 2 between 16 and 256 bytes.
*/
/**
* \brief HMAC key context.
*
* The HMAC key context is initialised with a hash function implementation
* and a secret key. Contents are opaque (callers should not access them
* directly). The caller is responsible for allocating the context where
* appropriate. Context initialisation and usage incurs no dynamic
* allocation, so there is no release function.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
const br_hash_class *dig_vtable;
unsigned char ksi[64], kso[64];
#endif
} br_hmac_key_context;
/**
* \brief HMAC key context initialisation.
*
* Initialise the key context with the provided key, using the hash function
* identified by `digest_vtable`. This supports arbitrary key lengths.
*
* \param kc HMAC key context to initialise.
* \param digest_vtable pointer to the hash function implementation vtable.
* \param key pointer to the HMAC secret key.
* \param key_len HMAC secret key length (in bytes).
*/
void br_hmac_key_init(br_hmac_key_context *kc,
const br_hash_class *digest_vtable, const void *key, size_t key_len);
/*
* \brief Get the underlying hash function.
*
* This function returns a pointer to the implementation vtable of the
* hash function used for this HMAC key context.
*
* \param kc HMAC key context.
* \return the hash function implementation.
*/
static inline const br_hash_class *br_hmac_key_get_digest(
const br_hmac_key_context *kc)
{
return kc->dig_vtable;
}
/**
* \brief HMAC computation context.
*
* The HMAC computation context maintains the state for a single HMAC
* computation. It is modified as input bytes are injected. The context
* is caller-allocated and has no release function since it does not
* dynamically allocate external resources. Its contents are opaque.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
br_hash_compat_context dig;
unsigned char kso[64];
size_t out_len;
#endif
} br_hmac_context;
/**
* \brief HMAC computation initialisation.
*
* Initialise a HMAC context with a key context. The key context is
* unmodified. Relevant data from the key context is immediately copied;
* the key context can thus be independently reused, modified or released
* without impacting this HMAC computation.
*
* An explicit output length can be specified; the actual output length
* will be the minimum of that value and the natural HMAC output length.
* If `out_len` is 0, then the natural HMAC output length is selected. The
* "natural output length" is the output length of the underlying hash
* function.
*
* \param ctx HMAC context to initialise.
* \param kc HMAC key context (already initialised with the key).
* \param out_len HMAC output length (0 to select "natural length").
*/
void br_hmac_init(br_hmac_context *ctx,
const br_hmac_key_context *kc, size_t out_len);
/**
* \brief Get the HMAC output size.
*
* The HMAC output size is the number of bytes that will actually be
* produced with `br_hmac_out()` with the provided context. This function
* MUST NOT be called on a non-initialised HMAC computation context.
* The returned value is the minimum of the HMAC natural length (output
* size of the underlying hash function) and the `out_len` parameter which
* was used with the last `br_hmac_init()` call on that context (if the
* initialisation `out_len` parameter was 0, then this function will
* return the HMAC natural length).
*
* \param ctx the (already initialised) HMAC computation context.
* \return the HMAC actual output size.
*/
static inline size_t
br_hmac_size(br_hmac_context *ctx)
{
return ctx->out_len;
}
/*
* \brief Get the underlying hash function.
*
* This function returns a pointer to the implementation vtable of the
* hash function used for this HMAC context.
*
* \param hc HMAC context.
* \return the hash function implementation.
*/
static inline const br_hash_class *br_hmac_get_digest(
const br_hmac_context *hc)
{
return hc->dig.vtable;
}
/**
* \brief Inject some bytes in HMAC.
*
* The provided `len` bytes are injected as extra input in the HMAC
* computation incarnated by the `ctx` HMAC context. It is acceptable
* that `len` is zero, in which case `data` is ignored (and may be
* `NULL`) and this function does nothing.
*/
void br_hmac_update(br_hmac_context *ctx, const void *data, size_t len);
/**
* \brief Compute the HMAC output.
*
* The destination buffer MUST be large enough to accommodate the result;
* its length is at most the "natural length" of HMAC (i.e. the output
* length of the underlying hash function). The context is NOT modified;
* further bytes may be processed. Thus, "partial HMAC" values can be
* efficiently obtained.
*
* Returned value is the output length (in bytes).
*
* \param ctx HMAC computation context.
* \param out destination buffer for the HMAC output.
* \return the produced value length (in bytes).
*/
size_t br_hmac_out(const br_hmac_context *ctx, void *out);
/**
* \brief Constant-time HMAC computation.
*
* This function compute the HMAC output in constant time. Some extra
* input bytes are processed, then the output is computed. The extra
* input consists in the `len` bytes pointed to by `data`. The `len`
* parameter must lie between `min_len` and `max_len` (inclusive);
* `max_len` bytes are actually read from `data`. Computing time (and
* memory access pattern) will not depend upon the data byte contents or
* the value of `len`.
*
* The output is written in the `out` buffer, that MUST be large enough
* to receive it.
*
* The difference `max_len - min_len` MUST be less than 230
* (i.e. about one gigabyte).
*
* This function computes the output properly only if the underlying
* hash function uses MD padding (i.e. MD5, SHA-1, SHA-224, SHA-256,
* SHA-384 or SHA-512).
*
* The provided context is NOT modified.
*
* \param ctx the (already initialised) HMAC computation context.
* \param data the extra input bytes.
* \param len the extra input length (in bytes).
* \param min_len minimum extra input length (in bytes).
* \param max_len maximum extra input length (in bytes).
* \param out destination buffer for the HMAC output.
* \return the produced value length (in bytes).
*/
size_t br_hmac_outCT(const br_hmac_context *ctx,
const void *data, size_t len, size_t min_len, size_t max_len,
void *out);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_KDF_H__
#define BR_BEARSSL_KDF_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_kdf.h
*
* # Key Derivation Functions
*
* KDF are functions that takes a variable length input, and provide a
* variable length output, meant to be used to derive subkeys from a
* master key.
*
* ## HKDF
*
* HKDF is a KDF defined by [RFC 5869](https://tools.ietf.org/html/rfc5869).
* It is based on HMAC, itself using an underlying hash function. Any
* hash function can be used, as long as it is compatible with the rules
* for the HMAC implementation (i.e. output size is 64 bytes or less, hash
* internal state size is 64 bytes or less, and the internal block length is
* a power of 2 between 16 and 256 bytes). HKDF has two phases:
*
* - HKDF-Extract: the input data in ingested, along with a "salt" value.
*
* - HKDF-Expand: the output is produced, from the result of processing
* the input and salt, and using an extra non-secret parameter called
* "info".
*
* The "salt" and "info" strings are non-secret and can be empty. Their role
* is normally to bind the input and output, respectively, to conventional
* identifiers that qualifu them within the used protocol or application.
*
* The implementation defined in this file uses the following functions:
*
* - `br_hkdf_init()`: initialize an HKDF context, with a hash function,
* and the salt. This starts the HKDF-Extract process.
*
* - `br_hkdf_inject()`: inject more input bytes. This function may be
* called repeatedly if the input data is provided by chunks.
*
* - `br_hkdf_flip()`: end the HKDF-Extract process, and start the
* HKDF-Expand process.
*
* - `br_hkdf_produce()`: get the next bytes of output. This function
* may be called several times to obtain the full output by chunks.
* For correct HKDF processing, the same "info" string must be
* provided for each call.
*
* Note that the HKDF total output size (the number of bytes that
* HKDF-Expand is willing to produce) is limited: if the hash output size
* is _n_ bytes, then the maximum output size is _255*n_.
*
* ## SHAKE
*
* SHAKE is defined in
* [FIPS 202](https://csrc.nist.gov/publications/detail/fips/202/final)
* under two versions: SHAKE128 and SHAKE256, offering an alleged
* "security level" of 128 and 256 bits, respectively (SHAKE128 is
* about 20 to 25% faster than SHAKE256). SHAKE internally relies on
* the Keccak family of sponge functions, not on any externally provided
* hash function. Contrary to HKDF, SHAKE does not have a concept of
* either a "salt" or an "info" string. The API consists in four
* functions:
*
* - `br_shake_init()`: initialize a SHAKE context for a given
* security level.
*
* - `br_shake_inject()`: inject more input bytes. This function may be
* called repeatedly if the input data is provided by chunks.
*
* - `br_shake_flip()`: end the data injection process, and start the
* data production process.
*
* - `br_shake_produce()`: get the next bytes of output. This function
* may be called several times to obtain the full output by chunks.
*/
/**
* \brief HKDF context.
*
* The HKDF context is initialized with a hash function implementation
* and a salt value. Contents are opaque (callers should not access them
* directly). The caller is responsible for allocating the context where
* appropriate. Context initialisation and usage incurs no dynamic
* allocation, so there is no release function.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
union {
br_hmac_context hmac_ctx;
br_hmac_key_context prk_ctx;
} u;
unsigned char buf[64];
size_t ptr;
size_t dig_len;
unsigned chunk_num;
#endif
} br_hkdf_context;
/**
* \brief HKDF context initialization.
*
* The underlying hash function and salt value are provided. Arbitrary
* salt lengths can be used.
*
* HKDF makes a difference between a salt of length zero, and an
* absent salt (the latter being equivalent to a salt consisting of
* bytes of value zero, of the same length as the hash function output).
* If `salt_len` is zero, then this function assumes that the salt is
* present but of length zero. To specify an _absent_ salt, use
* `BR_HKDF_NO_SALT` as `salt` parameter (`salt_len` is then ignored).
*
* \param hc HKDF context to initialise.
* \param digest_vtable pointer to the hash function implementation vtable.
* \param salt HKDF-Extract salt.
* \param salt_len HKDF-Extract salt length (in bytes).
*/
void br_hkdf_init(br_hkdf_context *hc, const br_hash_class *digest_vtable,
const void *salt, size_t salt_len);
/**
* \brief The special "absent salt" value for HKDF.
*/
#define BR_HKDF_NO_SALT (&br_hkdf_no_salt)
#ifndef BR_DOXYGEN_IGNORE
extern const unsigned char br_hkdf_no_salt;
#endif
/**
* \brief HKDF input injection (HKDF-Extract).
*
* This function injects some more input bytes ("key material") into
* HKDF. This function may be called several times, after `br_hkdf_init()`
* but before `br_hkdf_flip()`.
*
* \param hc HKDF context.
* \param ikm extra input bytes.
* \param ikm_len number of extra input bytes.
*/
void br_hkdf_inject(br_hkdf_context *hc, const void *ikm, size_t ikm_len);
/**
* \brief HKDF switch to the HKDF-Expand phase.
*
* This call terminates the HKDF-Extract process (input injection), and
* starts the HKDF-Expand process (output production).
*
* \param hc HKDF context.
*/
void br_hkdf_flip(br_hkdf_context *hc);
/**
* \brief HKDF output production (HKDF-Expand).
*
* Produce more output bytes from the current state. This function may be
* called several times, but only after `br_hkdf_flip()`.
*
* Returned value is the number of actually produced bytes. The total
* output length is limited to 255 times the output length of the
* underlying hash function.
*
* \param hc HKDF context.
* \param info application specific information string.
* \param info_len application specific information string length (in bytes).
* \param out destination buffer for the HKDF output.
* \param out_len the length of the requested output (in bytes).
* \return the produced output length (in bytes).
*/
size_t br_hkdf_produce(br_hkdf_context *hc,
const void *info, size_t info_len, void *out, size_t out_len);
/**
* \brief SHAKE context.
*
* The HKDF context is initialized with a "security level". The internal
* notion is called "capacity"; the capacity is twice the security level
* (for instance, SHAKE128 has capacity 256).
*
* The caller is responsible for allocating the context where
* appropriate. Context initialisation and usage incurs no dynamic
* allocation, so there is no release function.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
unsigned char dbuf[200];
size_t dptr;
size_t rate;
uint64_t A[25];
#endif
} br_shake_context;
/**
* \brief SHAKE context initialization.
*
* The context is initialized for the provided "security level".
* Internally, this sets the "capacity" to twice the security level;
* thus, for SHAKE128, the `security_level` parameter should be 128,
* which corresponds to a 256-bit capacity.
*
* Allowed security levels are all multiples of 32, from 32 to 768,
* inclusive. Larger security levels imply lower performance; levels
* beyond 256 bits don't make much sense. Standard levels are 128
* and 256 bits (for SHAKE128 and SHAKE256, respectively).
*
* \param sc SHAKE context to initialise.
* \param security_level security level (in bits).
*/
void br_shake_init(br_shake_context *sc, int security_level);
/**
* \brief SHAKE input injection.
*
* This function injects some more input bytes ("key material") into
* SHAKE. This function may be called several times, after `br_shake_init()`
* but before `br_shake_flip()`.
*
* \param sc SHAKE context.
* \param data extra input bytes.
* \param len number of extra input bytes.
*/
void br_shake_inject(br_shake_context *sc, const void *data, size_t len);
/**
* \brief SHAKE switch to production phase.
*
* This call terminates the input injection process, and starts the
* output production process.
*
* \param sc SHAKE context.
*/
void br_shake_flip(br_shake_context *hc);
/**
* \brief SHAKE output production.
*
* Produce more output bytes from the current state. This function may be
* called several times, but only after `br_shake_flip()`.
*
* There is no practical limit to the number of bytes that may be produced.
*
* \param sc SHAKE context.
* \param out destination buffer for the SHAKE output.
* \param len the length of the requested output (in bytes).
*/
void br_shake_produce(br_shake_context *sc, void *out, size_t len);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_RAND_H__
#define BR_BEARSSL_RAND_H__
#include
#include
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_BLOCK_H__
#define BR_BEARSSL_BLOCK_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_block.h
*
* # Block Ciphers and Symmetric Ciphers
*
* This file documents the API for block ciphers and other symmetric
* ciphers.
*
*
* ## Procedural API
*
* For a block cipher implementation, up to three separate sets of
* functions are provided, for CBC encryption, CBC decryption, and CTR
* encryption/decryption. Each set has its own context structure,
* initialised with the encryption key.
*
* For CBC encryption and decryption, the data to encrypt or decrypt is
* referenced as a sequence of blocks. The implementations assume that
* there is no partial block; no padding is applied or removed. The
* caller is responsible for handling any kind of padding.
*
* Function for CTR encryption are defined only for block ciphers with
* blocks of 16 bytes or more (i.e. AES, but not DES/3DES).
*
* Each implemented block cipher is identified by an "internal name"
* from which are derived the names of structures and functions that
* implement the cipher. For the block cipher of internal name "`xxx`",
* the following are defined:
*
* - `br_xxx_BLOCK_SIZE`
*
* A macro that evaluates to the block size (in bytes) of the
* cipher. For all implemented block ciphers, this value is a
* power of two.
*
* - `br_xxx_cbcenc_keys`
*
* Context structure that contains the subkeys resulting from the key
* expansion. These subkeys are appropriate for CBC encryption. The
* structure first field is called `vtable` and points to the
* appropriate OOP structure.
*
* - `br_xxx_cbcenc_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for CBC encryption are computed and
* written in the provided context structure. The key length MUST be
* adequate for the implemented block cipher. This function also sets
* the `vtable` field.
*
* - `br_xxx_cbcenc_run(const br_xxx_cbcenc_keys *ctx, void *iv, void *data, size_t len)`
*
* Perform CBC encryption of `len` bytes, in place. The encrypted data
* replaces the cleartext. `len` MUST be a multiple of the block length
* (if it is not, the function may loop forever or overflow a buffer).
* The IV is provided with the `iv` pointer; it is also updated with
* a copy of the last encrypted block.
*
* - `br_xxx_cbcdec_keys`
*
* Context structure that contains the subkeys resulting from the key
* expansion. These subkeys are appropriate for CBC decryption. The
* structure first field is called `vtable` and points to the
* appropriate OOP structure.
*
* - `br_xxx_cbcdec_init(br_xxx_cbcenc_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for CBC decryption are computed and
* written in the provided context structure. The key length MUST be
* adequate for the implemented block cipher. This function also sets
* the `vtable` field.
*
* - `br_xxx_cbcdec_run(const br_xxx_cbcdec_keys *ctx, void *iv, void *data, size_t num_blocks)`
*
* Perform CBC decryption of `len` bytes, in place. The decrypted data
* replaces the ciphertext. `len` MUST be a multiple of the block length
* (if it is not, the function may loop forever or overflow a buffer).
* The IV is provided with the `iv` pointer; it is also updated with
* a copy of the last _encrypted_ block.
*
* - `br_xxx_ctr_keys`
*
* Context structure that contains the subkeys resulting from the key
* expansion. These subkeys are appropriate for CTR encryption and
* decryption. The structure first field is called `vtable` and
* points to the appropriate OOP structure.
*
* - `br_xxx_ctr_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for CTR encryption and decryption
* are computed and written in the provided context structure. The
* key length MUST be adequate for the implemented block cipher. This
* function also sets the `vtable` field.
*
* - `br_xxx_ctr_run(const br_xxx_ctr_keys *ctx, const void *iv, uint32_t cc, void *data, size_t len)` (returns `uint32_t`)
*
* Perform CTR encryption/decryption of some data. Processing is done
* "in place" (the output data replaces the input data). This function
* implements the "standard incrementing function" from NIST SP800-38A,
* annex B: the IV length shall be 4 bytes less than the block size
* (i.e. 12 bytes for AES) and the counter is the 32-bit value starting
* with `cc`. The data length (`len`) is not necessarily a multiple of
* the block size. The new counter value is returned, which supports
* chunked processing, provided that each chunk length (except possibly
* the last one) is a multiple of the block size.
*
* - `br_xxx_ctrcbc_keys`
*
* Context structure that contains the subkeys resulting from the
* key expansion. These subkeys are appropriate for doing combined
* CTR encryption/decryption and CBC-MAC, as used in the CCM and EAX
* authenticated encryption modes. The structure first field is
* called `vtable` and points to the appropriate OOP structure.
*
* - `br_xxx_ctrcbc_init(br_xxx_ctr_keys *ctx, const void *key, size_t len)`
*
* Perform key expansion: subkeys for combined CTR
* encryption/decryption and CBC-MAC are computed and written in the
* provided context structure. The key length MUST be adequate for
* the implemented block cipher. This function also sets the
* `vtable` field.
*
* - `br_xxx_ctrcbc_encrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)`
*
* Perform CTR encryption of some data, and CBC-MAC. Processing is
* done "in place" (the output data replaces the input data). This
* function applies CTR encryption on the data, using a full
* block-size counter (i.e. for 128-bit blocks, the counter is
* incremented as a 128-bit value). The 'ctr' array contains the
* initial value for the counter (used in the first block) and it is
* updated with the new value after data processing. The 'cbcmac'
* value shall point to a block-sized value which is used as IV for
* CBC-MAC, computed over the encrypted data (output of CTR
* encryption); the resulting CBC-MAC is written over 'cbcmac' on
* output.
*
* The data length MUST be a multiple of the block size.
*
* - `br_xxx_ctrcbc_decrypt(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *cbcmac, void *data, size_t len)`
*
* Perform CTR decryption of some data, and CBC-MAC. Processing is
* done "in place" (the output data replaces the input data). This
* function applies CTR decryption on the data, using a full
* block-size counter (i.e. for 128-bit blocks, the counter is
* incremented as a 128-bit value). The 'ctr' array contains the
* initial value for the counter (used in the first block) and it is
* updated with the new value after data processing. The 'cbcmac'
* value shall point to a block-sized value which is used as IV for
* CBC-MAC, computed over the encrypted data (input of CTR
* encryption); the resulting CBC-MAC is written over 'cbcmac' on
* output.
*
* The data length MUST be a multiple of the block size.
*
* - `br_xxx_ctrcbc_ctr(const br_xxx_ctrcbc_keys *ctx, void *ctr, void *data, size_t len)`
*
* Perform CTR encryption or decryption of the provided data. The
* data is processed "in place" (the output data replaces the input
* data). A full block-sized counter is applied (i.e. for 128-bit
* blocks, the counter is incremented as a 128-bit value). The 'ctr'
* array contains the initial value for the counter (used in the
* first block), and it is updated with the new value after data
* processing.
*
* The data length MUST be a multiple of the block size.
*
* - `br_xxx_ctrcbc_mac(const br_xxx_ctrcbc_keys *ctx, void *cbcmac, const void *data, size_t len)`
*
* Compute CBC-MAC over the provided data. The IV for CBC-MAC is
* provided as 'cbcmac'; the output is written over the same array.
* The data itself is untouched. The data length MUST be a multiple
* of the block size.
*
*
* It shall be noted that the key expansion functions return `void`. If
* the provided key length is not allowed, then there will be no error
* reporting; implementations need not validate the key length, thus an
* invalid key length may result in undefined behaviour (e.g. buffer
* overflow).
*
* Subkey structures contain no interior pointer, and no external
* resources are allocated upon key expansion. They can thus be
* discarded without any explicit deallocation.
*
*
* ## Object-Oriented API
*
* Each context structure begins with a field (called `vtable`) that
* points to an instance of a structure that references the relevant
* functions through pointers. Each such structure contains the
* following:
*
* - `context_size`
*
* The size (in bytes) of the context structure for subkeys.
*
* - `block_size`
*
* The cipher block size (in bytes).
*
* - `log_block_size`
*
* The base-2 logarithm of cipher block size (e.g. 4 for blocks
* of 16 bytes).
*
* - `init`
*
* Pointer to the key expansion function.
*
* - `run`
*
* Pointer to the encryption/decryption function.
*
* For combined CTR/CBC-MAC encryption, the `vtable` has a slightly
* different structure:
*
* - `context_size`
*
* The size (in bytes) of the context structure for subkeys.
*
* - `block_size`
*
* The cipher block size (in bytes).
*
* - `log_block_size`
*
* The base-2 logarithm of cipher block size (e.g. 4 for blocks
* of 16 bytes).
*
* - `init`
*
* Pointer to the key expansion function.
*
* - `encrypt`
*
* Pointer to the CTR encryption + CBC-MAC function.
*
* - `decrypt`
*
* Pointer to the CTR decryption + CBC-MAC function.
*
* - `ctr`
*
* Pointer to the CTR encryption/decryption function.
*
* - `mac`
*
* Pointer to the CBC-MAC function.
*
* For block cipher "`xxx`", static, constant instances of these
* structures are defined, under the names:
*
* - `br_xxx_cbcenc_vtable`
* - `br_xxx_cbcdec_vtable`
* - `br_xxx_ctr_vtable`
* - `br_xxx_ctrcbc_vtable`
*
*
* ## Implemented Block Ciphers
*
* Provided implementations are:
*
* | Name | Function | Block Size (bytes) | Key lengths (bytes) |
* | :-------- | :------- | :----------------: | :-----------------: |
* | aes_big | AES | 16 | 16, 24 and 32 |
* | aes_small | AES | 16 | 16, 24 and 32 |
* | aes_ct | AES | 16 | 16, 24 and 32 |
* | aes_ct64 | AES | 16 | 16, 24 and 32 |
* | aes_x86ni | AES | 16 | 16, 24 and 32 |
* | aes_pwr8 | AES | 16 | 16, 24 and 32 |
* | des_ct | DES/3DES | 8 | 8, 16 and 24 |
* | des_tab | DES/3DES | 8 | 8, 16 and 24 |
*
* **Note:** DES/3DES nominally uses keys of 64, 128 and 192 bits (i.e. 8,
* 16 and 24 bytes), but some of the bits are ignored by the algorithm, so
* the _effective_ key lengths, from a security point of view, are 56,
* 112 and 168 bits, respectively.
*
* `aes_big` is a "classical" AES implementation, using tables. It
* is fast but not constant-time, since it makes data-dependent array
* accesses.
*
* `aes_small` is an AES implementation optimized for code size. It
* is substantially slower than `aes_big`; it is not constant-time
* either.
*
* `aes_ct` is a constant-time implementation of AES; its code is about
* as big as that of `aes_big`, while its performance is comparable to
* that of `aes_small`. However, it is constant-time. This
* implementation should thus be considered to be the "default" AES in
* BearSSL, to be used unless the operational context guarantees that a
* non-constant-time implementation is safe, or an architecture-specific
* constant-time implementation can be used (e.g. using dedicated
* hardware opcodes).
*
* `aes_ct64` is another constant-time implementation of AES. It is
* similar to `aes_ct` but uses 64-bit values. On 32-bit machines,
* `aes_ct64` is not faster than `aes_ct`, often a bit slower, and has
* a larger footprint; however, on 64-bit architectures, `aes_ct64`
* is typically twice faster than `aes_ct` for modes that allow parallel
* operations (i.e. CTR, and CBC decryption, but not CBC encryption).
*
* `aes_x86ni` exists only on x86 architectures (32-bit and 64-bit). It
* uses the AES-NI opcodes when available.
*
* `aes_pwr8` exists only on PowerPC / POWER architectures (32-bit and
* 64-bit, both little-endian and big-endian). It uses the AES opcodes
* present in POWER8 and later.
*
* `des_tab` is a classic, table-based implementation of DES/3DES. It
* is not constant-time.
*
* `des_ct` is an constant-time implementation of DES/3DES. It is
* substantially slower than `des_tab`.
*
* ## ChaCha20 and Poly1305
*
* ChaCha20 is a stream cipher. Poly1305 is a MAC algorithm. They
* are described in [RFC 7539](https://tools.ietf.org/html/rfc7539).
*
* Two function pointer types are defined:
*
* - `br_chacha20_run` describes a function that implements ChaCha20
* only.
*
* - `br_poly1305_run` describes an implementation of Poly1305,
* in the AEAD combination with ChaCha20 specified in RFC 7539
* (the ChaCha20 implementation is provided as a function pointer).
*
* `chacha20_ct` is a straightforward implementation of ChaCha20 in
* plain C; it is constant-time, small, and reasonably fast.
*
* `chacha20_sse2` leverages SSE2 opcodes (on x86 architectures that
* support these opcodes). It is faster than `chacha20_ct`.
*
* `poly1305_ctmul` is an implementation of the ChaCha20+Poly1305 AEAD
* construction, where the Poly1305 part is performed with mixed 32-bit
* multiplications (operands are 32-bit, result is 64-bit).
*
* `poly1305_ctmul32` implements ChaCha20+Poly1305 using pure 32-bit
* multiplications (32-bit operands, 32-bit result). It is slower than
* `poly1305_ctmul`, except on some specific architectures such as
* the ARM Cortex M0+.
*
* `poly1305_ctmulq` implements ChaCha20+Poly1305 with mixed 64-bit
* multiplications (operands are 64-bit, result is 128-bit) on 64-bit
* platforms that support such operations.
*
* `poly1305_i15` implements ChaCha20+Poly1305 with the generic "i15"
* big integer implementation. It is meant mostly for testing purposes,
* although it can help with saving a few hundred bytes of code footprint
* on systems where code size is scarce.
*/
/**
* \brief Class type for CBC encryption implementations.
*
* A `br_block_cbcenc_class` instance points to the functions implementing
* a specific block cipher, when used in CBC mode for encrypting data.
*/
typedef struct br_block_cbcenc_class_ br_block_cbcenc_class;
struct br_block_cbcenc_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_cbcenc_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CBC encryption.
*
* The `iv` parameter points to the IV for this run; it is
* updated with a copy of the last encrypted block. The data
* is encrypted "in place"; its length (`len`) MUST be a
* multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param iv IV for CBC encryption (updated).
* \param data data to encrypt.
* \param len data length (in bytes, multiple of block size).
*/
void (*run)(const br_block_cbcenc_class *const *ctx,
void *iv, void *data, size_t len);
};
/**
* \brief Class type for CBC decryption implementations.
*
* A `br_block_cbcdec_class` instance points to the functions implementing
* a specific block cipher, when used in CBC mode for decrypting data.
*/
typedef struct br_block_cbcdec_class_ br_block_cbcdec_class;
struct br_block_cbcdec_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_cbcdec_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CBC decryption.
*
* The `iv` parameter points to the IV for this run; it is
* updated with a copy of the last encrypted block. The data
* is decrypted "in place"; its length (`len`) MUST be a
* multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param iv IV for CBC decryption (updated).
* \param data data to decrypt.
* \param len data length (in bytes, multiple of block size).
*/
void (*run)(const br_block_cbcdec_class *const *ctx,
void *iv, void *data, size_t len);
};
/**
* \brief Class type for CTR encryption/decryption implementations.
*
* A `br_block_ctr_class` instance points to the functions implementing
* a specific block cipher, when used in CTR mode for encrypting or
* decrypting data.
*/
typedef struct br_block_ctr_class_ br_block_ctr_class;
struct br_block_ctr_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_ctr_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CTR encryption or decryption.
*
* The `iv` parameter points to the IV for this run; its
* length is exactly 4 bytes less than the block size (e.g.
* 12 bytes for AES/CTR). The IV is combined with a 32-bit
* block counter to produce the block value which is processed
* with the block cipher.
*
* The data to encrypt or decrypt is updated "in place". Its
* length (`len` bytes) is not required to be a multiple of
* the block size; if the final block is partial, then the
* corresponding key stream bits are dropped.
*
* The resulting counter value is returned.
*
* \param ctx context structure (already initialised).
* \param iv IV for CTR encryption/decryption.
* \param cc initial value for the block counter.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \return the new block counter value.
*/
uint32_t (*run)(const br_block_ctr_class *const *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
};
/**
* \brief Class type for combined CTR and CBC-MAC implementations.
*
* A `br_block_ctrcbc_class` instance points to the functions implementing
* a specific block cipher, when used in CTR mode for encrypting or
* decrypting data, along with CBC-MAC.
*/
typedef struct br_block_ctrcbc_class_ br_block_ctrcbc_class;
struct br_block_ctrcbc_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate
* for containing subkeys.
*/
size_t context_size;
/**
* \brief Size of individual blocks (in bytes).
*/
unsigned block_size;
/**
* \brief Base-2 logarithm of the size of individual blocks,
* expressed in bytes.
*/
unsigned log_block_size;
/**
* \brief Initialisation function.
*
* This function sets the `vtable` field in the context structure.
* The key length MUST be one of the key lengths supported by
* the implementation.
*
* \param ctx context structure to initialise.
* \param key secret key.
* \param key_len key length (in bytes).
*/
void (*init)(const br_block_ctrcbc_class **ctx,
const void *key, size_t key_len);
/**
* \brief Run the CTR encryption + CBC-MAC.
*
* The `ctr` parameter points to the counter; its length shall
* be equal to the block size. It is updated by this function
* as encryption proceeds.
*
* The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
* is computed over the encrypted data (output of CTR
* encryption). Its length shall be equal to the block size. The
* computed CBC-MAC value is written over the `cbcmac` array.
*
* The data to encrypt is updated "in place". Its length (`len`
* bytes) MUST be a multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param ctr counter for CTR encryption (initial and final).
* \param cbcmac IV and output buffer for CBC-MAC.
* \param data data to encrypt.
* \param len data length (in bytes).
*/
void (*encrypt)(const br_block_ctrcbc_class *const *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief Run the CTR decryption + CBC-MAC.
*
* The `ctr` parameter points to the counter; its length shall
* be equal to the block size. It is updated by this function
* as decryption proceeds.
*
* The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
* is computed over the encrypted data (i.e. before CTR
* decryption). Its length shall be equal to the block size. The
* computed CBC-MAC value is written over the `cbcmac` array.
*
* The data to decrypt is updated "in place". Its length (`len`
* bytes) MUST be a multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param ctr counter for CTR encryption (initial and final).
* \param cbcmac IV and output buffer for CBC-MAC.
* \param data data to decrypt.
* \param len data length (in bytes).
*/
void (*decrypt)(const br_block_ctrcbc_class *const *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief Run the CTR encryption/decryption only.
*
* The `ctr` parameter points to the counter; its length shall
* be equal to the block size. It is updated by this function
* as decryption proceeds.
*
* The data to decrypt is updated "in place". Its length (`len`
* bytes) MUST be a multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param ctr counter for CTR encryption (initial and final).
* \param data data to decrypt.
* \param len data length (in bytes).
*/
void (*ctr)(const br_block_ctrcbc_class *const *ctx,
void *ctr, void *data, size_t len);
/**
* \brief Run the CBC-MAC only.
*
* The `cbcmac` parameter points to the IV for CBC-MAC. The MAC
* is computed over the encrypted data (i.e. before CTR
* decryption). Its length shall be equal to the block size. The
* computed CBC-MAC value is written over the `cbcmac` array.
*
* The data is unmodified. Its length (`len` bytes) MUST be a
* multiple of the block size.
*
* \param ctx context structure (already initialised).
* \param cbcmac IV and output buffer for CBC-MAC.
* \param data data to decrypt.
* \param len data length (in bytes).
*/
void (*mac)(const br_block_ctrcbc_class *const *ctx,
void *cbcmac, const void *data, size_t len);
};
/*
* Traditional, table-based AES implementation. It is fast, but uses
* internal tables (in particular a 1 kB table for encryption, another
* 1 kB table for decryption, and a 256-byte table for key schedule),
* and it is not constant-time. In contexts where cache-timing attacks
* apply, this implementation may leak the secret key.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_big_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_big` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_big` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_big` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_big` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_big_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_big` implementation).
*/
extern const br_block_cbcenc_class br_aes_big_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_big` implementation).
*/
extern const br_block_cbcdec_class br_aes_big_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_big` implementation).
*/
extern const br_block_ctr_class br_aes_big_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_big` implementation).
*/
extern const br_block_ctrcbc_class br_aes_big_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_cbcenc_init(br_aes_big_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_cbcdec_init(br_aes_big_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_ctr_init(br_aes_big_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_big` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_big_ctrcbc_init(br_aes_big_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_big_cbcenc_run(const br_aes_big_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_big_cbcdec_run(const br_aes_big_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to encrypt or decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_big_ctr_run(const br_aes_big_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_encrypt(const br_aes_big_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_decrypt(const br_aes_big_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_ctr(const br_aes_big_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_big` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_big_ctrcbc_mac(const br_aes_big_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* AES implementation optimized for size. It is slower than the
* traditional table-based AES implementation, but requires much less
* code. It still uses data-dependent table accesses (albeit within a
* much smaller 256-byte table), which makes it conceptually vulnerable
* to cache-timing attacks.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_small_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_small` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_small` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_small` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_small` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_small_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_small` implementation).
*/
extern const br_block_cbcenc_class br_aes_small_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_small` implementation).
*/
extern const br_block_cbcdec_class br_aes_small_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_small` implementation).
*/
extern const br_block_ctr_class br_aes_small_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_small` implementation).
*/
extern const br_block_ctrcbc_class br_aes_small_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_cbcenc_init(br_aes_small_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_cbcdec_init(br_aes_small_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_ctr_init(br_aes_small_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_small` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_small_ctrcbc_init(br_aes_small_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_small_cbcenc_run(const br_aes_small_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_small_cbcdec_run(const br_aes_small_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_small_ctr_run(const br_aes_small_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_encrypt(const br_aes_small_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_decrypt(const br_aes_small_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_ctr(const br_aes_small_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_small` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_small_ctrcbc_mac(const br_aes_small_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* Constant-time AES implementation. Its size is similar to that of
* 'aes_big', and its performance is similar to that of 'aes_small' (faster
* decryption, slower encryption). However, it is constant-time, i.e.
* immune to cache-timing and similar attacks.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_ct_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_ct` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[60];
unsigned num_rounds;
#endif
} br_aes_ct_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_ct` implementation).
*/
extern const br_block_cbcenc_class br_aes_ct_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_ct` implementation).
*/
extern const br_block_cbcdec_class br_aes_ct_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_ct` implementation).
*/
extern const br_block_ctr_class br_aes_ct_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_ct` implementation).
*/
extern const br_block_ctrcbc_class br_aes_ct_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_cbcenc_init(br_aes_ct_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_cbcdec_init(br_aes_ct_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_ctr_init(br_aes_ct_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct_ctrcbc_init(br_aes_ct_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct_cbcenc_run(const br_aes_ct_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct_cbcdec_run(const br_aes_ct_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_ct_ctr_run(const br_aes_ct_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_encrypt(const br_aes_ct_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_decrypt(const br_aes_ct_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_ctr(const br_aes_ct_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_ct` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct_ctrcbc_mac(const br_aes_ct_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* 64-bit constant-time AES implementation. It is similar to 'aes_ct'
* but uses 64-bit registers, making it about twice faster than 'aes_ct'
* on 64-bit platforms, while remaining constant-time and with a similar
* code size. (The doubling in performance is only for CBC decryption
* and CTR mode; CBC encryption is non-parallel and cannot benefit from
* the larger registers.)
*/
/** \brief AES block size (16 bytes). */
#define br_aes_ct64_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_ct64` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t skey[30];
unsigned num_rounds;
#endif
} br_aes_ct64_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_ct64` implementation).
*/
extern const br_block_cbcenc_class br_aes_ct64_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_ct64` implementation).
*/
extern const br_block_cbcdec_class br_aes_ct64_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_ct64` implementation).
*/
extern const br_block_ctr_class br_aes_ct64_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_ct64` implementation).
*/
extern const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_cbcenc_init(br_aes_ct64_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_cbcdec_init(br_aes_ct64_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_ctr_init(br_aes_ct64_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_ct64` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct64_cbcenc_run(const br_aes_ct64_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_ct64_cbcdec_run(const br_aes_ct64_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_ct64_ctr_run(const br_aes_ct64_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_ct64` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/*
* AES implementation using AES-NI opcodes (x86 platform).
*/
/** \brief AES block size (16 bytes). */
#define br_aes_x86ni_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_x86ni` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_x86ni_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_cbcenc_get_vtable()`.
*/
extern const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_cbcdec_get_vtable()`.
*/
extern const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_ctr_get_vtable()`.
*/
extern const br_block_ctr_class br_aes_x86ni_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_x86ni` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_x86ni_ctrcbc_get_vtable()`.
*/
extern const br_block_ctrcbc_class br_aes_x86ni_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_x86ni` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_x86ni_ctrcbc_init(br_aes_x86ni_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_encrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_decrypt(const br_aes_x86ni_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_ctr(const br_aes_x86ni_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_x86ni` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_x86ni_ctrcbc_mac(const br_aes_x86ni_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/**
* \brief Obtain the `aes_x86ni` AES-CBC (encryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_x86ni_cbcenc_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CBC (encryption) implementation, or `NULL`.
*/
const br_block_cbcenc_class *br_aes_x86ni_cbcenc_get_vtable(void);
/**
* \brief Obtain the `aes_x86ni` AES-CBC (decryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_x86ni_cbcdec_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CBC (decryption) implementation, or `NULL`.
*/
const br_block_cbcdec_class *br_aes_x86ni_cbcdec_get_vtable(void);
/**
* \brief Obtain the `aes_x86ni` AES-CTR implementation, if available.
*
* This function returns a pointer to `br_aes_x86ni_ctr_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CTR implementation, or `NULL`.
*/
const br_block_ctr_class *br_aes_x86ni_ctr_get_vtable(void);
/**
* \brief Obtain the `aes_x86ni` AES-CTR + CBC-MAC implementation, if
* available.
*
* This function returns a pointer to `br_aes_x86ni_ctrcbc_vtable`, if
* that implementation was compiled in the library _and_ the x86 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_x86ni` AES-CTR implementation, or `NULL`.
*/
const br_block_ctrcbc_class *br_aes_x86ni_ctrcbc_get_vtable(void);
/*
* AES implementation using POWER8 opcodes.
*/
/** \brief AES block size (16 bytes). */
#define br_aes_pwr8_BLOCK_SIZE 16
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_cbcenc_keys;
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_cbcdec_keys;
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption
* and decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctr_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_ctr_keys;
/**
* \brief Context for AES subkeys (`aes_pwr8` implementation, CTR encryption
* and decryption + CBC-MAC).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_ctrcbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
union {
unsigned char skni[16 * 15];
} skey;
unsigned num_rounds;
#endif
} br_aes_pwr8_ctrcbc_keys;
/**
* \brief Class instance for AES CBC encryption (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_cbcenc_get_vtable()`.
*/
extern const br_block_cbcenc_class br_aes_pwr8_cbcenc_vtable;
/**
* \brief Class instance for AES CBC decryption (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_cbcdec_get_vtable()`.
*/
extern const br_block_cbcdec_class br_aes_pwr8_cbcdec_vtable;
/**
* \brief Class instance for AES CTR encryption and decryption
* (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_ctr_get_vtable()`.
*/
extern const br_block_ctr_class br_aes_pwr8_ctr_vtable;
/**
* \brief Class instance for AES CTR encryption/decryption + CBC-MAC
* (`aes_pwr8` implementation).
*
* Since this implementation might be omitted from the library, or the
* AES opcode unavailable on the current CPU, a pointer to this class
* instance should be obtained through `br_aes_pwr8_ctrcbc_get_vtable()`.
*/
extern const br_block_ctrcbc_class br_aes_pwr8_ctrcbc_vtable;
/**
* \brief Context initialisation (key schedule) for AES CBC encryption
* (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_cbcenc_init(br_aes_pwr8_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CBC decryption
* (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_cbcdec_init(br_aes_pwr8_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR encryption
* and decryption (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_ctr_init(br_aes_pwr8_ctr_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for AES CTR + CBC-MAC
* (`aes_pwr8` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_aes_pwr8_ctrcbc_init(br_aes_pwr8_ctrcbc_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_pwr8_cbcenc_run(const br_aes_pwr8_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 16).
*/
void br_aes_pwr8_cbcdec_run(const br_aes_pwr8_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CTR encryption and decryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (constant, 12 bytes).
* \param cc initial block counter value.
* \param data data to decrypt (updated).
* \param len data length (in bytes).
* \return new block counter value.
*/
uint32_t br_aes_pwr8_ctr_run(const br_aes_pwr8_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief CTR encryption + CBC-MAC with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_encrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR decryption + CBC-MAC with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_decrypt(const br_aes_pwr8_ctrcbc_keys *ctx,
void *ctr, void *cbcmac, void *data, size_t len);
/**
* \brief CTR encryption/decryption with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param ctr counter for CTR (16 bytes, updated).
* \param data data to MAC (updated).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_ctr(const br_aes_pwr8_ctrcbc_keys *ctx,
void *ctr, void *data, size_t len);
/**
* \brief CBC-MAC with AES (`aes_pwr8` implementation).
*
* \param ctx context (already initialised).
* \param cbcmac IV for CBC-MAC (updated).
* \param data data to MAC (unmodified).
* \param len data length (in bytes, MUST be a multiple of 16).
*/
void br_aes_pwr8_ctrcbc_mac(const br_aes_pwr8_ctrcbc_keys *ctx,
void *cbcmac, const void *data, size_t len);
/**
* \brief Obtain the `aes_pwr8` AES-CBC (encryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_pwr8_cbcenc_vtable`, if
* that implementation was compiled in the library _and_ the POWER8
* crypto opcodes are available on the currently running CPU. If either
* of these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CBC (encryption) implementation, or `NULL`.
*/
const br_block_cbcenc_class *br_aes_pwr8_cbcenc_get_vtable(void);
/**
* \brief Obtain the `aes_pwr8` AES-CBC (decryption) implementation, if
* available.
*
* This function returns a pointer to `br_aes_pwr8_cbcdec_vtable`, if
* that implementation was compiled in the library _and_ the POWER8
* crypto opcodes are available on the currently running CPU. If either
* of these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CBC (decryption) implementation, or `NULL`.
*/
const br_block_cbcdec_class *br_aes_pwr8_cbcdec_get_vtable(void);
/**
* \brief Obtain the `aes_pwr8` AES-CTR implementation, if available.
*
* This function returns a pointer to `br_aes_pwr8_ctr_vtable`, if that
* implementation was compiled in the library _and_ the POWER8 crypto
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CTR implementation, or `NULL`.
*/
const br_block_ctr_class *br_aes_pwr8_ctr_get_vtable(void);
/**
* \brief Obtain the `aes_pwr8` AES-CTR + CBC-MAC implementation, if
* available.
*
* This function returns a pointer to `br_aes_pwr8_ctrcbc_vtable`, if
* that implementation was compiled in the library _and_ the POWER8 AES
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `NULL`.
*
* \return the `aes_pwr8` AES-CTR implementation, or `NULL`.
*/
const br_block_ctrcbc_class *br_aes_pwr8_ctrcbc_get_vtable(void);
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC encryption) for all AES implementations.
*/
typedef union {
const br_block_cbcenc_class *vtable;
br_aes_big_cbcenc_keys c_big;
br_aes_small_cbcenc_keys c_small;
br_aes_ct_cbcenc_keys c_ct;
br_aes_ct64_cbcenc_keys c_ct64;
br_aes_x86ni_cbcenc_keys c_x86ni;
br_aes_pwr8_cbcenc_keys c_pwr8;
} br_aes_gen_cbcenc_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC decryption) for all AES implementations.
*/
typedef union {
const br_block_cbcdec_class *vtable;
br_aes_big_cbcdec_keys c_big;
br_aes_small_cbcdec_keys c_small;
br_aes_ct_cbcdec_keys c_ct;
br_aes_ct64_cbcdec_keys c_ct64;
br_aes_x86ni_cbcdec_keys c_x86ni;
br_aes_pwr8_cbcdec_keys c_pwr8;
} br_aes_gen_cbcdec_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CTR encryption and decryption) for all AES implementations.
*/
typedef union {
const br_block_ctr_class *vtable;
br_aes_big_ctr_keys c_big;
br_aes_small_ctr_keys c_small;
br_aes_ct_ctr_keys c_ct;
br_aes_ct64_ctr_keys c_ct64;
br_aes_x86ni_ctr_keys c_x86ni;
br_aes_pwr8_ctr_keys c_pwr8;
} br_aes_gen_ctr_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CTR encryption/decryption + CBC-MAC) for all AES implementations.
*/
typedef union {
const br_block_ctrcbc_class *vtable;
br_aes_big_ctrcbc_keys c_big;
br_aes_small_ctrcbc_keys c_small;
br_aes_ct_ctrcbc_keys c_ct;
br_aes_ct64_ctrcbc_keys c_ct64;
br_aes_x86ni_ctrcbc_keys c_x86ni;
br_aes_pwr8_ctrcbc_keys c_pwr8;
} br_aes_gen_ctrcbc_keys;
/*
* Traditional, table-based implementation for DES/3DES. Since tables are
* used, cache-timing attacks are conceptually possible.
*/
/** \brief DES/3DES block size (8 bytes). */
#define br_des_tab_BLOCK_SIZE 8
/**
* \brief Context for DES subkeys (`des_tab` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_tab_cbcenc_keys;
/**
* \brief Context for DES subkeys (`des_tab` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_tab_cbcdec_keys;
/**
* \brief Class instance for DES CBC encryption (`des_tab` implementation).
*/
extern const br_block_cbcenc_class br_des_tab_cbcenc_vtable;
/**
* \brief Class instance for DES CBC decryption (`des_tab` implementation).
*/
extern const br_block_cbcdec_class br_des_tab_cbcdec_vtable;
/**
* \brief Context initialisation (key schedule) for DES CBC encryption
* (`des_tab` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_tab_cbcenc_init(br_des_tab_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for DES CBC decryption
* (`des_tab` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_tab_cbcdec_init(br_des_tab_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with DES (`des_tab` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_tab_cbcenc_run(const br_des_tab_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with DES (`des_tab` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_tab_cbcdec_run(const br_des_tab_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/*
* Constant-time implementation for DES/3DES. It is substantially slower
* (by a factor of about 4x), but also immune to cache-timing attacks.
*/
/** \brief DES/3DES block size (8 bytes). */
#define br_des_ct_BLOCK_SIZE 8
/**
* \brief Context for DES subkeys (`des_ct` implementation, CBC encryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcenc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_ct_cbcenc_keys;
/**
* \brief Context for DES subkeys (`des_ct` implementation, CBC decryption).
*
* First field is a pointer to the vtable; it is set by the initialisation
* function. Other fields are not supposed to be accessed by user code.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_block_cbcdec_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint32_t skey[96];
unsigned num_rounds;
#endif
} br_des_ct_cbcdec_keys;
/**
* \brief Class instance for DES CBC encryption (`des_ct` implementation).
*/
extern const br_block_cbcenc_class br_des_ct_cbcenc_vtable;
/**
* \brief Class instance for DES CBC decryption (`des_ct` implementation).
*/
extern const br_block_cbcdec_class br_des_ct_cbcdec_vtable;
/**
* \brief Context initialisation (key schedule) for DES CBC encryption
* (`des_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_ct_cbcenc_init(br_des_ct_cbcenc_keys *ctx,
const void *key, size_t len);
/**
* \brief Context initialisation (key schedule) for DES CBC decryption
* (`des_ct` implementation).
*
* \param ctx context to initialise.
* \param key secret key.
* \param len secret key length (in bytes).
*/
void br_des_ct_cbcdec_init(br_des_ct_cbcdec_keys *ctx,
const void *key, size_t len);
/**
* \brief CBC encryption with DES (`des_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to encrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_ct_cbcenc_run(const br_des_ct_cbcenc_keys *ctx, void *iv,
void *data, size_t len);
/**
* \brief CBC decryption with DES (`des_ct` implementation).
*
* \param ctx context (already initialised).
* \param iv IV (updated).
* \param data data to decrypt (updated).
* \param len data length (in bytes, MUST be multiple of 8).
*/
void br_des_ct_cbcdec_run(const br_des_ct_cbcdec_keys *ctx, void *iv,
void *data, size_t len);
/*
* These structures are large enough to accommodate subkeys for all
* DES/3DES implementations.
*/
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC encryption) for all DES implementations.
*/
typedef union {
const br_block_cbcenc_class *vtable;
br_des_tab_cbcenc_keys tab;
br_des_ct_cbcenc_keys ct;
} br_des_gen_cbcenc_keys;
/**
* \brief Aggregate structure large enough to be used as context for
* subkeys (CBC decryption) for all DES implementations.
*/
typedef union {
const br_block_cbcdec_class *vtable;
br_des_tab_cbcdec_keys c_tab;
br_des_ct_cbcdec_keys c_ct;
} br_des_gen_cbcdec_keys;
/**
* \brief Type for a ChaCha20 implementation.
*
* An implementation follows the description in RFC 7539:
*
* - Key is 256 bits (`key` points to exactly 32 bytes).
*
* - IV is 96 bits (`iv` points to exactly 12 bytes).
*
* - Block counter is over 32 bits and starts at value `cc`; the
* resulting value is returned.
*
* Data (pointed to by `data`, of length `len`) is encrypted/decrypted
* in place. If `len` is not a multiple of 64, then the excess bytes from
* the last block processing are dropped (therefore, "chunked" processing
* works only as long as each non-final chunk has a length multiple of 64).
*
* \param key secret key (32 bytes).
* \param iv IV (12 bytes).
* \param cc initial counter value.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
typedef uint32_t (*br_chacha20_run)(const void *key,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief ChaCha20 implementation (straightforward C code, constant-time).
*
* \see br_chacha20_run
*
* \param key secret key (32 bytes).
* \param iv IV (12 bytes).
* \param cc initial counter value.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
uint32_t br_chacha20_ct_run(const void *key,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief ChaCha20 implementation (SSE2 code, constant-time).
*
* This implementation is available only on x86 platforms, depending on
* compiler support. Moreover, in 32-bit mode, it might not actually run,
* if the underlying hardware does not implement the SSE2 opcode (in
* 64-bit mode, SSE2 is part of the ABI, so if the code could be compiled
* at all, then it can run). Use `br_chacha20_sse2_get()` to safely obtain
* a pointer to that function.
*
* \see br_chacha20_run
*
* \param key secret key (32 bytes).
* \param iv IV (12 bytes).
* \param cc initial counter value.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
uint32_t br_chacha20_sse2_run(const void *key,
const void *iv, uint32_t cc, void *data, size_t len);
/**
* \brief Obtain the `sse2` ChaCha20 implementation, if available.
*
* This function returns a pointer to `br_chacha20_sse2_run`, if
* that implementation was compiled in the library _and_ the SSE2
* opcodes are available on the currently running CPU. If either of
* these conditions is not met, then this function returns `0`.
*
* \return the `sse2` ChaCha20 implementation, or `0`.
*/
br_chacha20_run br_chacha20_sse2_get(void);
/**
* \brief Type for a ChaCha20+Poly1305 AEAD implementation.
*
* The provided data is encrypted or decrypted with ChaCha20. The
* authentication tag is computed on the concatenation of the
* additional data and the ciphertext, with the padding and lengths
* as described in RFC 7539 (section 2.8).
*
* After decryption, the caller is responsible for checking that the
* computed tag matches the expected value.
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
typedef void (*br_poly1305_run)(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (mixed 32-bit multiplications).
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_ctmul_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (pure 32-bit multiplications).
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_ctmul32_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (i15).
*
* This implementation relies on the generic big integer code "i15"
* (which uses pure 32-bit multiplications). As such, it may save a
* little code footprint in a context where "i15" is already included
* (e.g. for elliptic curves or for RSA); however, it is also
* substantially slower than the ctmul and ctmul32 implementations.
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_i15_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief ChaCha20+Poly1305 AEAD implementation (ctmulq).
*
* This implementation uses 64-bit multiplications (result over 128 bits).
* It is available only on platforms that offer such a primitive (in
* practice, 64-bit architectures). Use `br_poly1305_ctmulq_get()` to
* dynamically obtain a pointer to that function, or 0 if not supported.
*
* \see br_poly1305_run
*
* \param key secret key (32 bytes).
* \param iv nonce (12 bytes).
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
* \param aad additional authenticated data.
* \param aad_len length of additional authenticated data (in bytes).
* \param tag output buffer for the authentication tag.
* \param ichacha implementation of ChaCha20.
* \param encrypt non-zero for encryption, zero for decryption.
*/
void br_poly1305_ctmulq_run(const void *key, const void *iv,
void *data, size_t len, const void *aad, size_t aad_len,
void *tag, br_chacha20_run ichacha, int encrypt);
/**
* \brief Get the ChaCha20+Poly1305 "ctmulq" implementation, if available.
*
* This function returns a pointer to the `br_poly1305_ctmulq_run()`
* function if supported on the current platform; otherwise, it returns 0.
*
* \return the ctmulq ChaCha20+Poly1305 implementation, or 0.
*/
br_poly1305_run br_poly1305_ctmulq_get(void);
#ifdef __cplusplus
}
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_rand.h
*
* # Pseudo-Random Generators
*
* A PRNG is a state-based engine that outputs pseudo-random bytes on
* demand. It is initialized with an initial seed, and additional seed
* bytes can be added afterwards. Bytes produced depend on the seeds and
* also on the exact sequence of calls (including sizes requested for
* each call).
*
*
* ## Procedural and OOP API
*
* For the PRNG of name "`xxx`", two API are provided. The _procedural_
* API defined a context structure `br_xxx_context` and three functions:
*
* - `br_xxx_init()`
*
* Initialise the context with an initial seed.
*
* - `br_xxx_generate()`
*
* Produce some pseudo-random bytes.
*
* - `br_xxx_update()`
*
* Inject some additional seed.
*
* The initialisation function sets the first context field (`vtable`)
* to a pointer to the vtable that supports the OOP API. The OOP API
* provides access to the same functions through function pointers,
* named `init()`, `generate()` and `update()`.
*
* Note that the context initialisation method may accept additional
* parameters, provided as a 'const void *' pointer at API level. These
* additional parameters depend on the implemented PRNG.
*
*
* ## HMAC_DRBG
*
* HMAC_DRBG is defined in [NIST SP 800-90A Revision
* 1](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf).
* It uses HMAC repeatedly, over some configurable underlying hash
* function. In BearSSL, it is implemented under the "`hmac_drbg`" name.
* The "extra parameters" pointer for context initialisation should be
* set to a pointer to the vtable for the underlying hash function (e.g.
* pointer to `br_sha256_vtable` to use HMAC_DRBG with SHA-256).
*
* According to the NIST standard, each request shall produce up to
* 219 bits (i.e. 64 kB of data); moreover, the context shall
* be reseeded at least once every 248 requests. This
* implementation does not maintain the reseed counter (the threshold is
* too high to be reached in practice) and does not object to producing
* more than 64 kB in a single request; thus, the code cannot fail,
* which corresponds to the fact that the API has no room for error
* codes. However, this implies that requesting more than 64 kB in one
* `generate()` request, or making more than 248 requests
* without reseeding, is formally out of NIST specification. There is
* no currently known security penalty for exceeding the NIST limits,
* and, in any case, HMAC_DRBG usage in implementing SSL/TLS always
* stays much below these thresholds.
*
*
* ## AESCTR_DRBG
*
* AESCTR_DRBG is a custom PRNG based on AES-128 in CTR mode. This is
* meant to be used only in situations where you are desperate for
* speed, and have an hardware-optimized AES/CTR implementation. Whether
* this will yield perceptible improvements depends on what you use the
* pseudorandom bytes for, and how many you want; for instance, RSA key
* pair generation uses a substantial amount of randomness, and using
* AESCTR_DRBG instead of HMAC_DRBG yields a 15 to 20% increase in key
* generation speed on a recent x86 CPU (Intel Core i7-6567U at 3.30 GHz).
*
* Internally, it uses CTR mode with successive counter values, starting
* at zero (counter value expressed over 128 bits, big-endian convention).
* The counter is not allowed to reach 32768; thus, every 32768*16 bytes
* at most, the `update()` function is run (on an empty seed, if none is
* provided). The `update()` function computes the new AES-128 key by
* applying a custom hash function to the concatenation of a state-dependent
* word (encryption of an all-one block with the current key) and the new
* seed. The custom hash function uses Hirose's construction over AES-256;
* see the comments in `aesctr_drbg.c` for details.
*
* This DRBG does not follow an existing standard, and thus should be
* considered as inadequate for production use until it has been properly
* analysed.
*/
/**
* \brief Class type for PRNG implementations.
*
* A `br_prng_class` instance references the methods implementing a PRNG.
* Constant instances of this structure are defined for each implemented
* PRNG. Such instances are also called "vtables".
*/
typedef struct br_prng_class_ br_prng_class;
struct br_prng_class_ {
/**
* \brief Size (in bytes) of the context structure appropriate for
* running this PRNG.
*/
size_t context_size;
/**
* \brief Initialisation method.
*
* The context to initialise is provided as a pointer to its
* first field (the vtable pointer); this function sets that
* first field to a pointer to the vtable.
*
* The extra parameters depend on the implementation; each
* implementation defines what kind of extra parameters it
* expects (if any).
*
* Requirements on the initial seed depend on the implemented
* PRNG.
*
* \param ctx PRNG context to initialise.
* \param params extra parameters for the PRNG.
* \param seed initial seed.
* \param seed_len initial seed length (in bytes).
*/
void (*init)(const br_prng_class **ctx, const void *params,
const void *seed, size_t seed_len);
/**
* \brief Random bytes generation.
*
* This method produces `len` pseudorandom bytes, in the `out`
* buffer. The context is updated accordingly.
*
* \param ctx PRNG context.
* \param out output buffer.
* \param len number of pseudorandom bytes to produce.
*/
void (*generate)(const br_prng_class **ctx, void *out, size_t len);
/**
* \brief Inject additional seed bytes.
*
* The provided seed bytes are added into the PRNG internal
* entropy pool.
*
* \param ctx PRNG context.
* \param seed additional seed.
* \param seed_len additional seed length (in bytes).
*/
void (*update)(const br_prng_class **ctx,
const void *seed, size_t seed_len);
};
/**
* \brief Context for HMAC_DRBG.
*
* The context contents are opaque, except the first field, which
* supports OOP.
*/
typedef struct {
/**
* \brief Pointer to the vtable.
*
* This field is set with the initialisation method/function.
*/
const br_prng_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
unsigned char K[64];
unsigned char V[64];
const br_hash_class *digest_class;
#endif
} br_hmac_drbg_context;
/**
* \brief Statically allocated, constant vtable for HMAC_DRBG.
*/
extern const br_prng_class br_hmac_drbg_vtable;
/**
* \brief HMAC_DRBG initialisation.
*
* The context to initialise is provided as a pointer to its first field
* (the vtable pointer); this function sets that first field to a
* pointer to the vtable.
*
* The `seed` value is what is called, in NIST terminology, the
* concatenation of the "seed", "nonce" and "personalization string", in
* that order.
*
* The `digest_class` parameter defines the underlying hash function.
* Formally, the NIST standard specifies that the hash function shall
* be only SHA-1 or one of the SHA-2 functions. This implementation also
* works with any other implemented hash function (such as MD5), but
* this is non-standard and therefore not recommended.
*
* \param ctx HMAC_DRBG context to initialise.
* \param digest_class vtable for the underlying hash function.
* \param seed initial seed.
* \param seed_len initial seed length (in bytes).
*/
void br_hmac_drbg_init(br_hmac_drbg_context *ctx,
const br_hash_class *digest_class, const void *seed, size_t seed_len);
/**
* \brief Random bytes generation with HMAC_DRBG.
*
* This method produces `len` pseudorandom bytes, in the `out`
* buffer. The context is updated accordingly. Formally, requesting
* more than 65536 bytes in one request falls out of specification
* limits (but it won't fail).
*
* \param ctx HMAC_DRBG context.
* \param out output buffer.
* \param len number of pseudorandom bytes to produce.
*/
void br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len);
/**
* \brief Inject additional seed bytes in HMAC_DRBG.
*
* The provided seed bytes are added into the HMAC_DRBG internal
* entropy pool. The process does not _replace_ existing entropy,
* thus pushing non-random bytes (i.e. bytes which are known to the
* attackers) does not degrade the overall quality of generated bytes.
*
* \param ctx HMAC_DRBG context.
* \param seed additional seed.
* \param seed_len additional seed length (in bytes).
*/
void br_hmac_drbg_update(br_hmac_drbg_context *ctx,
const void *seed, size_t seed_len);
/**
* \brief Get the hash function implementation used by a given instance of
* HMAC_DRBG.
*
* This calls MUST NOT be performed on a context which was not
* previously initialised.
*
* \param ctx HMAC_DRBG context.
* \return the hash function vtable.
*/
static inline const br_hash_class *
br_hmac_drbg_get_hash(const br_hmac_drbg_context *ctx)
{
return ctx->digest_class;
}
/**
* \brief Type for a provider of entropy seeds.
*
* A "seeder" is a function that is able to obtain random values from
* some source and inject them as entropy seed in a PRNG. A seeder
* shall guarantee that the total entropy of the injected seed is large
* enough to seed a PRNG for purposes of cryptographic key generation
* (i.e. at least 128 bits).
*
* A seeder may report a failure to obtain adequate entropy. Seeders
* shall endeavour to fix themselves transient errors by trying again;
* thus, callers may consider reported errors as permanent.
*
* \param ctx PRNG context to seed.
* \return 1 on success, 0 on error.
*/
typedef int (*br_prng_seeder)(const br_prng_class **ctx);
/**
* \brief Get a seeder backed by the operating system or hardware.
*
* Get a seeder that feeds on RNG facilities provided by the current
* operating system or hardware. If no such facility is known, then 0
* is returned.
*
* If `name` is not `NULL`, then `*name` is set to a symbolic string
* that identifies the seeder implementation. If no seeder is returned
* and `name` is not `NULL`, then `*name` is set to a pointer to the
* constant string `"none"`.
*
* \param name receiver for seeder name, or `NULL`.
* \return the system seeder, if available, or 0.
*/
br_prng_seeder br_prng_seeder_system(const char **name);
/**
* \brief Context for AESCTR_DRBG.
*
* The context contents are opaque, except the first field, which
* supports OOP.
*/
typedef struct {
/**
* \brief Pointer to the vtable.
*
* This field is set with the initialisation method/function.
*/
const br_prng_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
br_aes_gen_ctr_keys sk;
uint32_t cc;
#endif
} br_aesctr_drbg_context;
/**
* \brief Statically allocated, constant vtable for AESCTR_DRBG.
*/
extern const br_prng_class br_aesctr_drbg_vtable;
/**
* \brief AESCTR_DRBG initialisation.
*
* The context to initialise is provided as a pointer to its first field
* (the vtable pointer); this function sets that first field to a
* pointer to the vtable.
*
* The internal AES key is first set to the all-zero key; then, the
* `br_aesctr_drbg_update()` function is called with the provided `seed`.
* The call is performed even if the seed length (`seed_len`) is zero.
*
* The `aesctr` parameter defines the underlying AES/CTR implementation.
*
* \param ctx AESCTR_DRBG context to initialise.
* \param aesctr vtable for the AES/CTR implementation.
* \param seed initial seed (can be `NULL` if `seed_len` is zero).
* \param seed_len initial seed length (in bytes).
*/
void br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
const br_block_ctr_class *aesctr, const void *seed, size_t seed_len);
/**
* \brief Random bytes generation with AESCTR_DRBG.
*
* This method produces `len` pseudorandom bytes, in the `out`
* buffer. The context is updated accordingly.
*
* \param ctx AESCTR_DRBG context.
* \param out output buffer.
* \param len number of pseudorandom bytes to produce.
*/
void br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx,
void *out, size_t len);
/**
* \brief Inject additional seed bytes in AESCTR_DRBG.
*
* The provided seed bytes are added into the AESCTR_DRBG internal
* entropy pool. The process does not _replace_ existing entropy,
* thus pushing non-random bytes (i.e. bytes which are known to the
* attackers) does not degrade the overall quality of generated bytes.
*
* \param ctx AESCTR_DRBG context.
* \param seed additional seed.
* \param seed_len additional seed length (in bytes).
*/
void br_aesctr_drbg_update(br_aesctr_drbg_context *ctx,
const void *seed, size_t seed_len);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_PRF_H__
#define BR_BEARSSL_PRF_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_prf.h
*
* # The TLS PRF
*
* The "PRF" is the pseudorandom function used internally during the
* SSL/TLS handshake, notably to expand negotiated shared secrets into
* the symmetric encryption keys that will be used to process the
* application data.
*
* TLS 1.0 and 1.1 define a PRF that is based on both MD5 and SHA-1. This
* is implemented by the `br_tls10_prf()` function.
*
* TLS 1.2 redefines the PRF, using an explicit hash function. The
* `br_tls12_sha256_prf()` and `br_tls12_sha384_prf()` functions apply that
* PRF with, respectively, SHA-256 and SHA-384. Most standard cipher suites
* rely on the SHA-256 based PRF, but some use SHA-384.
*
* The PRF always uses as input three parameters: a "secret" (some
* bytes), a "label" (ASCII string), and a "seed" (again some bytes). An
* arbitrary output length can be produced. The "seed" is provided as an
* arbitrary number of binary chunks, that gets internally concatenated.
*/
/**
* \brief Type for a seed chunk.
*
* Each chunk may have an arbitrary length, and may be empty (no byte at
* all). If the chunk length is zero, then the pointer to the chunk data
* may be `NULL`.
*/
typedef struct {
/**
* \brief Pointer to the chunk data.
*/
const void *data;
/**
* \brief Chunk length (in bytes).
*/
size_t len;
} br_tls_prf_seed_chunk;
/**
* \brief PRF implementation for TLS 1.0 and 1.1.
*
* This PRF is the one specified by TLS 1.0 and 1.1. It internally uses
* MD5 and SHA-1.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
void br_tls10_prf(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/**
* \brief PRF implementation for TLS 1.2, with SHA-256.
*
* This PRF is the one specified by TLS 1.2, when the underlying hash
* function is SHA-256.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
void br_tls12_sha256_prf(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/**
* \brief PRF implementation for TLS 1.2, with SHA-384.
*
* This PRF is the one specified by TLS 1.2, when the underlying hash
* function is SHA-384.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
void br_tls12_sha384_prf(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/**
* brief A convenient type name for a PRF implementation.
*
* \param dst destination buffer.
* \param len output length (in bytes).
* \param secret secret value (key) for this computation.
* \param secret_len length of "secret" (in bytes).
* \param label PRF label (zero-terminated ASCII string).
* \param seed_num number of seed chunks.
* \param seed seed chnks for this computation (usually non-secret).
*/
typedef void (*br_tls_prf_impl)(void *dst, size_t len,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_AEAD_H__
#define BR_BEARSSL_AEAD_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_aead.h
*
* # Authenticated Encryption with Additional Data
*
* This file documents the API for AEAD encryption.
*
*
* ## Procedural API
*
* An AEAD algorithm processes messages and provides confidentiality
* (encryption) and checked integrity (MAC). It uses the following
* parameters:
*
* - A symmetric key. Exact size depends on the AEAD algorithm.
*
* - A nonce (IV). Size depends on the AEAD algorithm; for most
* algorithms, it is crucial for security that any given nonce
* value is never used twice for the same key and distinct
* messages.
*
* - Data to encrypt and protect.
*
* - Additional authenticated data, which is covered by the MAC but
* otherwise left untouched (i.e. not encrypted).
*
* The AEAD algorithm encrypts the data, and produces an authentication
* tag. It is assumed that the encrypted data, the tag, the additional
* authenticated data and the nonce are sent to the receiver; the
* additional data and the nonce may be implicit (e.g. using elements of
* the underlying transport protocol, such as record sequence numbers).
* The receiver will recompute the tag value and compare it with the one
* received; if they match, then the data is correct, and can be
* decrypted and used; otherwise, at least one of the elements was
* altered in transit, normally leading to wholesale rejection of the
* complete message.
*
* For each AEAD algorithm, identified by a symbolic name (hereafter
* denoted as "`xxx`"), the following functions are defined:
*
* - `br_xxx_init()`
*
* Initialise the AEAD algorithm, on a provided context structure.
* Exact parameters depend on the algorithm, and may include
* pointers to extra implementations and context structures. The
* secret key is provided at this point, either directly or
* indirectly.
*
* - `br_xxx_reset()`
*
* Start a new AEAD computation. The nonce value is provided as
* parameter to this function.
*
* - `br_xxx_aad_inject()`
*
* Inject some additional authenticated data. Additional data may
* be provided in several chunks of arbitrary length.
*
* - `br_xxx_flip()`
*
* This function MUST be called after injecting all additional
* authenticated data, and before beginning to encrypt the plaintext
* (or decrypt the ciphertext).
*
* - `br_xxx_run()`
*
* Process some plaintext (to encrypt) or ciphertext (to decrypt).
* Encryption/decryption is done in place. Data may be provided in
* several chunks of arbitrary length.
*
* - `br_xxx_get_tag()`
*
* Compute the authentication tag. All message data (encrypted or
* decrypted) must have been injected at that point. Also, this
* call may modify internal context elements, so it may be called
* only once for a given AEAD computation.
*
* - `br_xxx_check_tag()`
*
* An alternative to `br_xxx_get_tag()`, meant to be used by the
* receiver: the authentication tag is internally recomputed, and
* compared with the one provided as parameter.
*
* This API makes the following assumptions on the AEAD algorithm:
*
* - Encryption does not expand the size of the ciphertext; there is
* no padding. This is true of most modern AEAD modes such as GCM.
*
* - The additional authenticated data must be processed first,
* before the encrypted/decrypted data.
*
* - Nonce, plaintext and additional authenticated data all consist
* in an integral number of bytes. There is no provision to use
* elements whose length in bits is not a multiple of 8.
*
* Each AEAD algorithm has its own requirements and limits on the sizes
* of additional data and plaintext. This API does not provide any
* way to report invalid usage; it is up to the caller to ensure that
* the provided key, nonce, and data elements all fit the algorithm's
* requirements.
*
*
* ## Object-Oriented API
*
* Each context structure begins with a field (called `vtable`) that
* points to an instance of a structure that references the relevant
* functions through pointers. Each such structure contains the
* following:
*
* - `reset`
*
* Pointer to the reset function, that allows starting a new
* computation.
*
* - `aad_inject`
*
* Pointer to the additional authenticated data injection function.
*
* - `flip`
*
* Pointer to the function that transitions from additional data
* to main message data processing.
*
* - `get_tag`
*
* Pointer to the function that computes and returns the tag.
*
* - `check_tag`
*
* Pointer to the function that computes and verifies the tag against
* a received value.
*
* Note that there is no OOP method for context initialisation: the
* various AEAD algorithms have different requirements that would not
* map well to a single initialisation API.
*
* The OOP API is not provided for CCM, due to its specific requirements
* (length of plaintext must be known in advance).
*/
/**
* \brief Class type of an AEAD algorithm.
*/
typedef struct br_aead_class_ br_aead_class;
struct br_aead_class_ {
/**
* \brief Size (in bytes) of authentication tags created by
* this AEAD algorithm.
*/
size_t tag_size;
/**
* \brief Reset an AEAD context.
*
* This function resets an already initialised AEAD context for
* a new computation run. Implementations and keys are
* conserved. This function can be called at any time; it
* cancels any ongoing AEAD computation that uses the provided
* context structure.
* The provided IV is a _nonce_. Each AEAD algorithm has its
* own requirements on IV size and contents; for most of them,
* it is crucial to security that each nonce value is used
* only once for a given secret key.
*
* \param cc AEAD context structure.
* \param iv AEAD nonce to use.
* \param len AEAD nonce length (in bytes).
*/
void (*reset)(const br_aead_class **cc, const void *iv, size_t len);
/**
* \brief Inject additional authenticated data.
*
* The provided data is injected into a running AEAD
* computation. Additional data must be injected _before_ the
* call to `flip()`. Additional data can be injected in several
* chunks of arbitrary length.
*
* \param cc AEAD context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void (*aad_inject)(const br_aead_class **cc,
const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data.
*
* This function MUST be called before beginning the actual
* encryption or decryption (with `run()`), even if no
* additional authenticated data was injected. No additional
* authenticated data may be injected after this function call.
*
* \param cc AEAD context structure.
*/
void (*flip)(const br_aead_class **cc);
/**
* \brief Encrypt or decrypt some data.
*
* Data encryption or decryption can be done after `flip()` has
* been called on the context. If `encrypt` is non-zero, then
* the provided data shall be plaintext, and it is encrypted in
* place. Otherwise, the data shall be ciphertext, and it is
* decrypted in place.
*
* Data may be provided in several chunks of arbitrary length.
*
* \param cc AEAD context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void (*run)(const br_aead_class **cc, int encrypt,
void *data, size_t len);
/**
* \brief Compute authentication tag.
*
* Compute the AEAD authentication tag. The tag length depends
* on the AEAD algorithm; it is written in the provided `tag`
* buffer. This call terminates the AEAD run: no data may be
* processed with that AEAD context afterwards, until `reset()`
* is called to initiate a new AEAD run.
*
* The tag value must normally be sent along with the encrypted
* data. When decrypting, the tag value must be recomputed and
* compared with the received tag: if the two tag values differ,
* then either the tag or the encrypted data was altered in
* transit. As an alternative to this function, the
* `check_tag()` function may be used to compute and check the
* tag value.
*
* Tag length depends on the AEAD algorithm.
*
* \param cc AEAD context structure.
* \param tag destination buffer for the tag.
*/
void (*get_tag)(const br_aead_class **cc, void *tag);
/**
* \brief Compute and check authentication tag.
*
* This function is an alternative to `get_tag()`, and is
* normally used on the receiving end (i.e. when decrypting
* messages). The tag value is recomputed and compared with the
* provided tag value. If they match, 1 is returned; on
* mismatch, 0 is returned. A returned value of 0 means that the
* data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* Tag length depends on the AEAD algorithm.
*
* \param cc AEAD context structure.
* \param tag tag value to compare with.
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t (*check_tag)(const br_aead_class **cc, const void *tag);
/**
* \brief Compute authentication tag (with truncation).
*
* This function is similar to `get_tag()`, except that the tag
* length is provided. Some AEAD algorithms allow several tag
* lengths, usually by truncating the normal tag. Shorter tags
* mechanically increase success probability of forgeries.
* The range of allowed tag lengths depends on the algorithm.
*
* \param cc AEAD context structure.
* \param tag destination buffer for the tag.
* \param len tag length (in bytes).
*/
void (*get_tag_trunc)(const br_aead_class **cc, void *tag, size_t len);
/**
* \brief Compute and check authentication tag (with truncation).
*
* This function is similar to `check_tag()` except that it
* works over an explicit tag length. See `get_tag()` for a
* discussion of explicit tag lengths; the range of allowed tag
* lengths depends on the algorithm.
*
* \param cc AEAD context structure.
* \param tag tag value to compare with.
* \param len tag length (in bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t (*check_tag_trunc)(const br_aead_class **cc,
const void *tag, size_t len);
};
/**
* \brief Context structure for GCM.
*
* GCM is an AEAD mode that combines a block cipher in CTR mode with a
* MAC based on GHASH, to provide authenticated encryption:
*
* - Any block cipher with 16-byte blocks can be used with GCM.
*
* - The nonce can have any length, from 0 up to 2^64-1 bits; however,
* 96-bit nonces (12 bytes) are recommended (nonces with a length
* distinct from 12 bytes are internally hashed, which risks reusing
* nonce value with a small but not always negligible probability).
*
* - Additional authenticated data may have length up to 2^64-1 bits.
*
* - Message length may range up to 2^39-256 bits at most.
*
* - The authentication tag has length 16 bytes.
*
* The GCM initialisation function receives as parameter an
* _initialised_ block cipher implementation context, with the secret
* key already set. A pointer to that context will be kept within the
* GCM context structure. It is up to the caller to allocate and
* initialise that block cipher context.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_aead_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_block_ctr_class **bctx;
br_ghash gh;
unsigned char h[16];
unsigned char j0_1[12];
unsigned char buf[16];
unsigned char y[16];
uint32_t j0_2, jc;
uint64_t count_aad, count_ctr;
#endif
} br_gcm_context;
/**
* \brief Initialize a GCM context.
*
* A block cipher implementation, with its initialised context structure,
* is provided. The block cipher MUST use 16-byte blocks in CTR mode,
* and its secret key MUST have been already set in the provided context.
* A GHASH implementation must also be provided. The parameters are linked
* in the GCM context.
*
* After this function has been called, the `br_gcm_reset()` function must
* be called, to provide the IV for GCM computation.
*
* \param ctx GCM context structure.
* \param bctx block cipher context (already initialised with secret key).
* \param gh GHASH implementation.
*/
void br_gcm_init(br_gcm_context *ctx,
const br_block_ctr_class **bctx, br_ghash gh);
/**
* \brief Reset a GCM context.
*
* This function resets an already initialised GCM context for a new
* computation run. Implementations and keys are conserved. This function
* can be called at any time; it cancels any ongoing GCM computation that
* uses the provided context structure.
*
* The provided IV is a _nonce_. It is critical to GCM security that IV
* values are not repeated for the same encryption key. IV can have
* arbitrary length (up to 2^64-1 bits), but the "normal" length is
* 96 bits (12 bytes).
*
* \param ctx GCM context structure.
* \param iv GCM nonce to use.
* \param len GCM nonce length (in bytes).
*/
void br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len);
/**
* \brief Inject additional authenticated data into GCM.
*
* The provided data is injected into a running GCM computation. Additional
* data must be injected _before_ the call to `br_gcm_flip()`.
* Additional data can be injected in several chunks of arbitrary length;
* the maximum total size of additional authenticated data is 2^64-1
* bits.
*
* \param ctx GCM context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data into GCM.
*
* This function MUST be called before beginning the actual encryption
* or decryption (with `br_gcm_run()`), even if no additional authenticated
* data was injected. No additional authenticated data may be injected
* after this function call.
*
* \param ctx GCM context structure.
*/
void br_gcm_flip(br_gcm_context *ctx);
/**
* \brief Encrypt or decrypt some data with GCM.
*
* Data encryption or decryption can be done after `br_gcm_flip()`
* has been called on the context. If `encrypt` is non-zero, then the
* provided data shall be plaintext, and it is encrypted in place.
* Otherwise, the data shall be ciphertext, and it is decrypted in place.
*
* Data may be provided in several chunks of arbitrary length. The maximum
* total length for data is 2^39-256 bits, i.e. about 65 gigabytes.
*
* \param ctx GCM context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len);
/**
* \brief Compute GCM authentication tag.
*
* Compute the GCM authentication tag. The tag is a 16-byte value which
* is written in the provided `tag` buffer. This call terminates the
* GCM run: no data may be processed with that GCM context afterwards,
* until `br_gcm_reset()` is called to initiate a new GCM run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_gcm_check_tag()` function can be used to
* compute and check the tag value.
*
* \param ctx GCM context structure.
* \param tag destination buffer for the tag (16 bytes).
*/
void br_gcm_get_tag(br_gcm_context *ctx, void *tag);
/**
* \brief Compute and check GCM authentication tag.
*
* This function is an alternative to `br_gcm_get_tag()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* \param ctx GCM context structure.
* \param tag tag value to compare with (16 bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_gcm_check_tag(br_gcm_context *ctx, const void *tag);
/**
* \brief Compute GCM authentication tag (with truncation).
*
* This function is similar to `br_gcm_get_tag()`, except that it allows
* the tag to be truncated to a smaller length. The intended tag length
* is provided as `len` (in bytes); it MUST be no more than 16, but
* it may be smaller. Note that decreasing tag length mechanically makes
* forgeries easier; NIST SP 800-38D specifies that the tag length shall
* lie between 12 and 16 bytes (inclusive), but may be truncated down to
* 4 or 8 bytes, for specific applications that can tolerate it. It must
* also be noted that successful forgeries leak information on the
* authentication key, making subsequent forgeries easier. Therefore,
* tag truncation, and in particular truncation to sizes lower than 12
* bytes, shall be envisioned only with great care.
*
* The tag is written in the provided `tag` buffer. This call terminates
* the GCM run: no data may be processed with that GCM context
* afterwards, until `br_gcm_reset()` is called to initiate a new GCM
* run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_gcm_check_tag_trunc()` function can be used to
* compute and check the tag value.
*
* \param ctx GCM context structure.
* \param tag destination buffer for the tag.
* \param len tag length (16 bytes or less).
*/
void br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len);
/**
* \brief Compute and check GCM authentication tag (with truncation).
*
* This function is an alternative to `br_gcm_get_tag_trunc()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* Tag length MUST be 16 bytes or less. The normal GCM tag length is 16
* bytes. See `br_check_tag_trunc()` for some discussion on the potential
* perils of truncating authentication tags.
*
* \param ctx GCM context structure.
* \param tag tag value to compare with.
* \param len tag length (in bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_gcm_check_tag_trunc(br_gcm_context *ctx,
const void *tag, size_t len);
/**
* \brief Class instance for GCM.
*/
extern const br_aead_class br_gcm_vtable;
/**
* \brief Context structure for EAX.
*
* EAX is an AEAD mode that combines a block cipher in CTR mode with
* CBC-MAC using the same block cipher and the same key, to provide
* authenticated encryption:
*
* - Any block cipher with 16-byte blocks can be used with EAX
* (technically, other block sizes are defined as well, but this
* is not implemented by these functions; shorter blocks also
* imply numerous security issues).
*
* - The nonce can have any length, as long as nonce values are
* not reused (thus, if nonces are randomly selected, the nonce
* size should be such that reuse probability is negligible).
*
* - Additional authenticated data length is unlimited.
*
* - Message length is unlimited.
*
* - The authentication tag has length 16 bytes.
*
* The EAX initialisation function receives as parameter an
* _initialised_ block cipher implementation context, with the secret
* key already set. A pointer to that context will be kept within the
* EAX context structure. It is up to the caller to allocate and
* initialise that block cipher context.
*/
typedef struct {
/** \brief Pointer to vtable for this context. */
const br_aead_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_block_ctrcbc_class **bctx;
unsigned char L2[16];
unsigned char L4[16];
unsigned char nonce[16];
unsigned char head[16];
unsigned char ctr[16];
unsigned char cbcmac[16];
unsigned char buf[16];
size_t ptr;
#endif
} br_eax_context;
/**
* \brief EAX captured state.
*
* Some internal values computed by EAX may be captured at various
* points, and reused for another EAX run with the same secret key,
* for lower per-message overhead. Captured values do not depend on
* the nonce.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
unsigned char st[3][16];
#endif
} br_eax_state;
/**
* \brief Initialize an EAX context.
*
* A block cipher implementation, with its initialised context
* structure, is provided. The block cipher MUST use 16-byte blocks in
* CTR + CBC-MAC mode, and its secret key MUST have been already set in
* the provided context. The parameters are linked in the EAX context.
*
* After this function has been called, the `br_eax_reset()` function must
* be called, to provide the nonce for EAX computation.
*
* \param ctx EAX context structure.
* \param bctx block cipher context (already initialised with secret key).
*/
void br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx);
/**
* \brief Capture pre-AAD state.
*
* This function precomputes key-dependent data, and stores it in the
* provided `st` structure. This structure should then be used with
* `br_eax_reset_pre_aad()`, or updated with `br_eax_get_aad_mac()`
* and then used with `br_eax_reset_post_aad()`.
*
* The EAX context structure is unmodified by this call.
*
* \param ctx EAX context structure.
* \param st recipient for captured state.
*/
void br_eax_capture(const br_eax_context *ctx, br_eax_state *st);
/**
* \brief Reset an EAX context.
*
* This function resets an already initialised EAX context for a new
* computation run. Implementations and keys are conserved. This function
* can be called at any time; it cancels any ongoing EAX computation that
* uses the provided context structure.
*
* It is critical to EAX security that nonce values are not repeated for
* the same encryption key. Nonces can have arbitrary length. If nonces
* are randomly generated, then a nonce length of at least 128 bits (16
* bytes) is recommended, to make nonce reuse probability sufficiently
* low.
*
* \param ctx EAX context structure.
* \param nonce EAX nonce to use.
* \param len EAX nonce length (in bytes).
*/
void br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len);
/**
* \brief Reset an EAX context with a pre-AAD captured state.
*
* This function is an alternative to `br_eax_reset()`, that reuses a
* previously captured state structure for lower per-message overhead.
* The state should have been populated with `br_eax_capture_state()`
* but not updated with `br_eax_get_aad_mac()`.
*
* After this function is called, additional authenticated data MUST
* be injected. At least one byte of additional authenticated data
* MUST be provided with `br_eax_aad_inject()`; computation result will
* be incorrect if `br_eax_flip()` is called right away.
*
* After injection of the AAD and call to `br_eax_flip()`, at least
* one message byte must be provided. Empty messages are not supported
* with this reset mode.
*
* \param ctx EAX context structure.
* \param st pre-AAD captured state.
* \param nonce EAX nonce to use.
* \param len EAX nonce length (in bytes).
*/
void br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
const void *nonce, size_t len);
/**
* \brief Reset an EAX context with a post-AAD captured state.
*
* This function is an alternative to `br_eax_reset()`, that reuses a
* previously captured state structure for lower per-message overhead.
* The state should have been populated with `br_eax_capture_state()`
* and then updated with `br_eax_get_aad_mac()`.
*
* After this function is called, message data MUST be injected. The
* `br_eax_flip()` function MUST NOT be called. At least one byte of
* message data MUST be provided with `br_eax_run()`; empty messages
* are not supported with this reset mode.
*
* \param ctx EAX context structure.
* \param st post-AAD captured state.
* \param nonce EAX nonce to use.
* \param len EAX nonce length (in bytes).
*/
void br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
const void *nonce, size_t len);
/**
* \brief Inject additional authenticated data into EAX.
*
* The provided data is injected into a running EAX computation. Additional
* data must be injected _before_ the call to `br_eax_flip()`.
* Additional data can be injected in several chunks of arbitrary length;
* the total amount of additional authenticated data is unlimited.
*
* \param ctx EAX context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data into EAX.
*
* This function MUST be called before beginning the actual encryption
* or decryption (with `br_eax_run()`), even if no additional authenticated
* data was injected. No additional authenticated data may be injected
* after this function call.
*
* \param ctx EAX context structure.
*/
void br_eax_flip(br_eax_context *ctx);
/**
* \brief Obtain a copy of the MAC on additional authenticated data.
*
* This function may be called only after `br_eax_flip()`; it copies the
* AAD-specific MAC value into the provided state. The MAC value depends
* on the secret key and the additional data itself, but not on the
* nonce. The updated state `st` is meant to be used as parameter for a
* further `br_eax_reset_post_aad()` call.
*
* \param ctx EAX context structure.
* \param st captured state to update.
*/
static inline void
br_eax_get_aad_mac(const br_eax_context *ctx, br_eax_state *st)
{
memcpy(st->st[1], ctx->head, sizeof ctx->head);
}
/**
* \brief Encrypt or decrypt some data with EAX.
*
* Data encryption or decryption can be done after `br_eax_flip()`
* has been called on the context. If `encrypt` is non-zero, then the
* provided data shall be plaintext, and it is encrypted in place.
* Otherwise, the data shall be ciphertext, and it is decrypted in place.
*
* Data may be provided in several chunks of arbitrary length.
*
* \param ctx EAX context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len);
/**
* \brief Compute EAX authentication tag.
*
* Compute the EAX authentication tag. The tag is a 16-byte value which
* is written in the provided `tag` buffer. This call terminates the
* EAX run: no data may be processed with that EAX context afterwards,
* until `br_eax_reset()` is called to initiate a new EAX run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_eax_check_tag()` function can be used to
* compute and check the tag value.
*
* \param ctx EAX context structure.
* \param tag destination buffer for the tag (16 bytes).
*/
void br_eax_get_tag(br_eax_context *ctx, void *tag);
/**
* \brief Compute and check EAX authentication tag.
*
* This function is an alternative to `br_eax_get_tag()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* \param ctx EAX context structure.
* \param tag tag value to compare with (16 bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_eax_check_tag(br_eax_context *ctx, const void *tag);
/**
* \brief Compute EAX authentication tag (with truncation).
*
* This function is similar to `br_eax_get_tag()`, except that it allows
* the tag to be truncated to a smaller length. The intended tag length
* is provided as `len` (in bytes); it MUST be no more than 16, but
* it may be smaller. Note that decreasing tag length mechanically makes
* forgeries easier; NIST SP 800-38D specifies that the tag length shall
* lie between 12 and 16 bytes (inclusive), but may be truncated down to
* 4 or 8 bytes, for specific applications that can tolerate it. It must
* also be noted that successful forgeries leak information on the
* authentication key, making subsequent forgeries easier. Therefore,
* tag truncation, and in particular truncation to sizes lower than 12
* bytes, shall be envisioned only with great care.
*
* The tag is written in the provided `tag` buffer. This call terminates
* the EAX run: no data may be processed with that EAX context
* afterwards, until `br_eax_reset()` is called to initiate a new EAX
* run.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_eax_check_tag_trunc()` function can be used to
* compute and check the tag value.
*
* \param ctx EAX context structure.
* \param tag destination buffer for the tag.
* \param len tag length (16 bytes or less).
*/
void br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len);
/**
* \brief Compute and check EAX authentication tag (with truncation).
*
* This function is an alternative to `br_eax_get_tag_trunc()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* Tag length MUST be 16 bytes or less. The normal EAX tag length is 16
* bytes. See `br_check_tag_trunc()` for some discussion on the potential
* perils of truncating authentication tags.
*
* \param ctx EAX context structure.
* \param tag tag value to compare with.
* \param len tag length (in bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_eax_check_tag_trunc(br_eax_context *ctx,
const void *tag, size_t len);
/**
* \brief Class instance for EAX.
*/
extern const br_aead_class br_eax_vtable;
/**
* \brief Context structure for CCM.
*
* CCM is an AEAD mode that combines a block cipher in CTR mode with
* CBC-MAC using the same block cipher and the same key, to provide
* authenticated encryption:
*
* - Any block cipher with 16-byte blocks can be used with CCM
* (technically, other block sizes are defined as well, but this
* is not implemented by these functions; shorter blocks also
* imply numerous security issues).
*
* - The authentication tag length, and plaintext length, MUST be
* known when starting processing data. Plaintext and ciphertext
* can still be provided by chunks, but the total size must match
* the value provided upon initialisation.
*
* - The nonce length is constrained between 7 and 13 bytes (inclusive).
* Furthermore, the plaintext length, when encoded, must fit over
* 15-nonceLen bytes; thus, if the nonce has length 13 bytes, then
* the plaintext length cannot exceed 65535 bytes.
*
* - Additional authenticated data length is practically unlimited
* (formal limit is at 2^64 bytes).
*
* - The authentication tag has length 4 to 16 bytes (even values only).
*
* The CCM initialisation function receives as parameter an
* _initialised_ block cipher implementation context, with the secret
* key already set. A pointer to that context will be kept within the
* CCM context structure. It is up to the caller to allocate and
* initialise that block cipher context.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
const br_block_ctrcbc_class **bctx;
unsigned char ctr[16];
unsigned char cbcmac[16];
unsigned char tagmask[16];
unsigned char buf[16];
size_t ptr;
size_t tag_len;
#endif
} br_ccm_context;
/**
* \brief Initialize a CCM context.
*
* A block cipher implementation, with its initialised context
* structure, is provided. The block cipher MUST use 16-byte blocks in
* CTR + CBC-MAC mode, and its secret key MUST have been already set in
* the provided context. The parameters are linked in the CCM context.
*
* After this function has been called, the `br_ccm_reset()` function must
* be called, to provide the nonce for CCM computation.
*
* \param ctx CCM context structure.
* \param bctx block cipher context (already initialised with secret key).
*/
void br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx);
/**
* \brief Reset a CCM context.
*
* This function resets an already initialised CCM context for a new
* computation run. Implementations and keys are conserved. This function
* can be called at any time; it cancels any ongoing CCM computation that
* uses the provided context structure.
*
* The `aad_len` parameter contains the total length, in bytes, of the
* additional authenticated data. It may be zero. That length MUST be
* exact.
*
* The `data_len` parameter contains the total length, in bytes, of the
* data that will be injected (plaintext or ciphertext). That length MUST
* be exact. Moreover, that length MUST be less than 2^(8*(15-nonce_len)).
*
* The nonce length (`nonce_len`), in bytes, must be in the 7..13 range
* (inclusive).
*
* The tag length (`tag_len`), in bytes, must be in the 4..16 range, and
* be an even integer. Short tags mechanically allow for higher forgery
* probabilities; hence, tag sizes smaller than 12 bytes shall be used only
* with care.
*
* It is critical to CCM security that nonce values are not repeated for
* the same encryption key. Random generation of nonces is not generally
* recommended, due to the relatively small maximum nonce value.
*
* Returned value is 1 on success, 0 on error. An error is reported if
* the tag or nonce length is out of range, or if the
* plaintext/ciphertext length cannot be encoded with the specified
* nonce length.
*
* \param ctx CCM context structure.
* \param nonce CCM nonce to use.
* \param nonce_len CCM nonce length (in bytes, 7 to 13).
* \param aad_len additional authenticated data length (in bytes).
* \param data_len plaintext/ciphertext length (in bytes).
* \param tag_len tag length (in bytes).
* \return 1 on success, 0 on error.
*/
int br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len,
uint64_t aad_len, uint64_t data_len, size_t tag_len);
/**
* \brief Inject additional authenticated data into CCM.
*
* The provided data is injected into a running CCM computation. Additional
* data must be injected _before_ the call to `br_ccm_flip()`.
* Additional data can be injected in several chunks of arbitrary length,
* but the total amount MUST exactly match the value which was provided
* to `br_ccm_reset()`.
*
* \param ctx CCM context structure.
* \param data pointer to additional authenticated data.
* \param len length of additional authenticated data (in bytes).
*/
void br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len);
/**
* \brief Finish injection of additional authenticated data into CCM.
*
* This function MUST be called before beginning the actual encryption
* or decryption (with `br_ccm_run()`), even if no additional authenticated
* data was injected. No additional authenticated data may be injected
* after this function call.
*
* \param ctx CCM context structure.
*/
void br_ccm_flip(br_ccm_context *ctx);
/**
* \brief Encrypt or decrypt some data with CCM.
*
* Data encryption or decryption can be done after `br_ccm_flip()`
* has been called on the context. If `encrypt` is non-zero, then the
* provided data shall be plaintext, and it is encrypted in place.
* Otherwise, the data shall be ciphertext, and it is decrypted in place.
*
* Data may be provided in several chunks of arbitrary length, provided
* that the total length exactly matches the length provided to the
* `br_ccm_reset()` call.
*
* \param ctx CCM context structure.
* \param encrypt non-zero for encryption, zero for decryption.
* \param data data to encrypt or decrypt.
* \param len data length (in bytes).
*/
void br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len);
/**
* \brief Compute CCM authentication tag.
*
* Compute the CCM authentication tag. This call terminates the CCM
* run: all data must have been injected with `br_ccm_run()` (in zero,
* one or more successive calls). After this function has been called,
* no more data can br processed; a `br_ccm_reset()` call is required
* to start a new message.
*
* The tag length was provided upon context initialisation (last call
* to `br_ccm_reset()`); it is returned by this function.
*
* The tag value must normally be sent along with the encrypted data.
* When decrypting, the tag value must be recomputed and compared with
* the received tag: if the two tag values differ, then either the tag
* or the encrypted data was altered in transit. As an alternative to
* this function, the `br_ccm_check_tag()` function can be used to
* compute and check the tag value.
*
* \param ctx CCM context structure.
* \param tag destination buffer for the tag (up to 16 bytes).
* \return the tag length (in bytes).
*/
size_t br_ccm_get_tag(br_ccm_context *ctx, void *tag);
/**
* \brief Compute and check CCM authentication tag.
*
* This function is an alternative to `br_ccm_get_tag()`, normally used
* on the receiving end (i.e. when decrypting value). The tag value is
* recomputed and compared with the provided tag value. If they match, 1
* is returned; on mismatch, 0 is returned. A returned value of 0 means
* that the data or the tag was altered in transit, normally leading to
* wholesale rejection of the complete message.
*
* \param ctx CCM context structure.
* \param tag tag value to compare with (up to 16 bytes).
* \return 1 on success (exact match of tag value), 0 otherwise.
*/
uint32_t br_ccm_check_tag(br_ccm_context *ctx, const void *tag);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_RSA_H__
#define BR_BEARSSL_RSA_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_rsa.h
*
* # RSA
*
* This file documents the RSA implementations provided with BearSSL.
* Note that the SSL engine accesses these implementations through a
* configurable API, so it is possible to, for instance, run a SSL
* server which uses a RSA engine which is not based on this code.
*
* ## Key Elements
*
* RSA public and private keys consist in lists of big integers. All
* such integers are represented with big-endian unsigned notation:
* first byte is the most significant, and the value is positive (so
* there is no dedicated "sign bit"). Public and private key structures
* thus contain, for each such integer, a pointer to the first value byte
* (`unsigned char *`), and a length (`size_t`) which is the number of
* relevant bytes. As a general rule, minimal-length encoding is not
* enforced: values may have extra leading bytes of value 0.
*
* RSA public keys consist in two integers:
*
* - the modulus (`n`);
* - the public exponent (`e`).
*
* RSA private keys, as defined in
* [PKCS#1](https://tools.ietf.org/html/rfc3447), contain eight integers:
*
* - the modulus (`n`);
* - the public exponent (`e`);
* - the private exponent (`d`);
* - the first prime factor (`p`);
* - the second prime factor (`q`);
* - the first reduced exponent (`dp`, which is `d` modulo `p-1`);
* - the second reduced exponent (`dq`, which is `d` modulo `q-1`);
* - the CRT coefficient (`iq`, the inverse of `q` modulo `p`).
*
* However, the implementations defined in BearSSL use only five of
* these integers: `p`, `q`, `dp`, `dq` and `iq`.
*
* ## Security Features and Limitations
*
* The implementations contained in BearSSL have the following limitations
* and features:
*
* - They are constant-time. This means that the execution time and
* memory access pattern may depend on the _lengths_ of the private
* key components, but not on their value, nor on the value of
* the operand. Note that this property is not achieved through
* random masking, but "true" constant-time code.
*
* - They support only private keys with two prime factors. RSA private
* keys with three or more prime factors are nominally supported, but
* rarely used; they may offer faster operations, at the expense of
* more code and potentially a reduction in security if there are
* "too many" prime factors.
*
* - The public exponent may have arbitrary length. Of course, it is
* a good idea to keep public exponents small, so that public key
* operations are fast; but, contrary to some widely deployed
* implementations, BearSSL has no problem with public exponents
* longer than 32 bits.
*
* - The two prime factors of the modulus need not have the same length
* (but severely imbalanced factor lengths might reduce security).
* Similarly, there is no requirement that the first factor (`p`)
* be greater than the second factor (`q`).
*
* - Prime factors and modulus must be smaller than a compile-time limit.
* This is made necessary by the use of fixed-size stack buffers, and
* the limit has been adjusted to keep stack usage under 2 kB for the
* RSA operations. Currently, the maximum modulus size is 4096 bits,
* and the maximum prime factor size is 2080 bits.
*
* - The RSA functions themselves do not enforce lower size limits,
* except that which is absolutely necessary for the operation to
* mathematically make sense (e.g. a PKCS#1 v1.5 signature with
* SHA-1 requires a modulus of at least 361 bits). It is up to users
* of this code to enforce size limitations when appropriate (e.g.
* the X.509 validation engine, by default, rejects RSA keys of
* less than 1017 bits).
*
* - Within the size constraints expressed above, arbitrary bit lengths
* are supported. There is no requirement that prime factors or
* modulus have a size multiple of 8 or 16.
*
* - When verifying PKCS#1 v1.5 signatures, both variants of the hash
* function identifying header (with and without the ASN.1 NULL) are
* supported. When producing such signatures, the variant with the
* ASN.1 NULL is used.
*
* ## Implementations
*
* Three RSA implementations are included:
*
* - The **i32** implementation internally represents big integers
* as arrays of 32-bit integers. It is perfunctory and portable,
* but not very efficient.
*
* - The **i31** implementation uses 32-bit integers, each containing
* 31 bits worth of integer data. The i31 implementation is somewhat
* faster than the i32 implementation (the reduced integer size makes
* carry propagation easier) for a similar code footprint, but uses
* very slightly larger stack buffers (about 4% bigger).
*
* - The **i62** implementation is similar to the i31 implementation,
* except that it internally leverages the 64x64->128 multiplication
* opcode. This implementation is available only on architectures
* where such an opcode exists. It is much faster than i31.
*
* - The **i15** implementation uses 16-bit integers, each containing
* 15 bits worth of integer data. Multiplication results fit on
* 32 bits, so this won't use the "widening" multiplication routine
* on ARM Cortex M0/M0+, for much better performance and constant-time
* execution.
*/
/**
* \brief RSA public key.
*
* The structure references the modulus and the public exponent. Both
* integers use unsigned big-endian representation; extra leading bytes
* of value 0 are allowed.
*/
typedef struct {
/** \brief Modulus. */
unsigned char *n;
/** \brief Modulus length (in bytes). */
size_t nlen;
/** \brief Public exponent. */
unsigned char *e;
/** \brief Public exponent length (in bytes). */
size_t elen;
} br_rsa_public_key;
/**
* \brief RSA private key.
*
* The structure references the private factors, reduced private
* exponents, and CRT coefficient. It also contains the bit length of
* the modulus. The big integers use unsigned big-endian representation;
* extra leading bytes of value 0 are allowed. However, the modulus bit
* length (`n_bitlen`) MUST be exact.
*/
typedef struct {
/** \brief Modulus bit length (in bits, exact value). */
uint32_t n_bitlen;
/** \brief First prime factor. */
unsigned char *p;
/** \brief First prime factor length (in bytes). */
size_t plen;
/** \brief Second prime factor. */
unsigned char *q;
/** \brief Second prime factor length (in bytes). */
size_t qlen;
/** \brief First reduced private exponent. */
unsigned char *dp;
/** \brief First reduced private exponent length (in bytes). */
size_t dplen;
/** \brief Second reduced private exponent. */
unsigned char *dq;
/** \brief Second reduced private exponent length (in bytes). */
size_t dqlen;
/** \brief CRT coefficient. */
unsigned char *iq;
/** \brief CRT coefficient length (in bytes). */
size_t iqlen;
} br_rsa_private_key;
/**
* \brief Type for a RSA public key engine.
*
* The public key engine performs the modular exponentiation of the
* provided value with the public exponent. The value is modified in
* place.
*
* The value length (`xlen`) is verified to have _exactly_ the same
* length as the modulus (actual modulus length, without extra leading
* zeros in the modulus representation in memory). If the length does
* not match, then this function returns 0 and `x[]` is unmodified.
*
* It `xlen` is correct, then `x[]` is modified. Returned value is 1
* on success, 0 on error. Error conditions include an oversized `x[]`
* (the array has the same length as the modulus, but the numerical value
* is not lower than the modulus) and an invalid modulus (e.g. an even
* integer). If an error is reported, then the new contents of `x[]` are
* unspecified.
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_public)(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief Type for a RSA signature verification engine (PKCS#1 v1.5).
*
* Parameters are:
*
* - The signature itself. The provided array is NOT modified.
*
* - The encoded OID for the hash function. The provided array must begin
* with a single byte that contains the length of the OID value (in
* bytes), followed by exactly that many bytes. This parameter may
* also be `NULL`, in which case the raw hash value should be used
* with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up
* to TLS-1.1, with a 36-byte hash value).
*
* - The hash output length, in bytes.
*
* - The public key.
*
* - An output buffer for the hash value. The caller must still compare
* it with the hash of the data over which the signature is computed.
*
* **Constraints:**
*
* - Hash length MUST be no more than 64 bytes.
*
* - OID value length MUST be no more than 32 bytes (i.e. `hash_oid[0]`
* must have a value in the 0..32 range, inclusive).
*
* This function verifies that the signature length (`xlen`) matches the
* modulus length (this function returns 0 on mismatch). If the modulus
* size exceeds the maximum supported RSA size, then the function also
* returns 0.
*
* Returned value is 1 on success, 0 on error.
*
* Implementations of this type need not be constant-time.
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pkcs1_vrfy)(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief Type for a RSA signature verification engine (PSS).
*
* Parameters are:
*
* - The signature itself. The provided array is NOT modified.
*
* - The hash function which was used to hash the message.
*
* - The hash function to use with MGF1 within the PSS padding. This
* is not necessarily the same hash function as the one which was
* used to hash the signed message.
*
* - The hashed message (as an array of bytes).
*
* - The PSS salt length (in bytes).
*
* - The public key.
*
* **Constraints:**
*
* - Hash message length MUST be no more than 64 bytes.
*
* Note that, contrary to PKCS#1 v1.5 signature, the hash value of the
* signed data cannot be extracted from the signature; it must be
* provided to the verification function.
*
* This function verifies that the signature length (`xlen`) matches the
* modulus length (this function returns 0 on mismatch). If the modulus
* size exceeds the maximum supported RSA size, then the function also
* returns 0.
*
* Returned value is 1 on success, 0 on error.
*
* Implementations of this type need not be constant-time.
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pss_vrfy)(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief Type for a RSA encryption engine (OAEP).
*
* Parameters are:
*
* - A source of random bytes. The source must be already initialized.
*
* - A hash function, used internally with the mask generation function
* (MGF1).
*
* - A label. The `label` pointer may be `NULL` if `label_len` is zero
* (an empty label, which is the default in PKCS#1 v2.2).
*
* - The public key.
*
* - The destination buffer. Its maximum length (in bytes) is provided;
* if that length is lower than the public key length, then an error
* is reported.
*
* - The source message.
*
* The encrypted message output has exactly the same length as the modulus
* (mathematical length, in bytes, not counting extra leading zeros in the
* modulus representation in the public key).
*
* The source message (`src`, length `src_len`) may overlap with the
* destination buffer (`dst`, length `dst_max_len`).
*
* This function returns the actual encrypted message length, in bytes;
* on error, zero is returned. An error is reported if the output buffer
* is not large enough, or the public is invalid, or the public key
* modulus exceeds the maximum supported RSA size.
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
typedef size_t (*br_rsa_oaep_encrypt)(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief Type for a RSA private key engine.
*
* The `x[]` buffer is modified in place, and its length is inferred from
* the modulus length (`x[]` is assumed to have a length of
* `(sk->n_bitlen+7)/8` bytes).
*
* Returned value is 1 on success, 0 on error.
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_private)(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief Type for a RSA signature generation engine (PKCS#1 v1.5).
*
* Parameters are:
*
* - The encoded OID for the hash function. The provided array must begin
* with a single byte that contains the length of the OID value (in
* bytes), followed by exactly that many bytes. This parameter may
* also be `NULL`, in which case the raw hash value should be used
* with the PKCS#1 v1.5 "type 1" padding (as used in SSL/TLS up
* to TLS-1.1, with a 36-byte hash value).
*
* - The hash value computes over the data to sign (its length is
* expressed in bytes).
*
* - The RSA private key.
*
* - The output buffer, that receives the signature.
*
* Returned value is 1 on success, 0 on error. Error conditions include
* a too small modulus for the provided hash OID and value, or some
* invalid key parameters. The signature length is exactly
* `(sk->n_bitlen+7)/8` bytes.
*
* This function is expected to be constant-time with regards to the
* private key bytes (lengths of the modulus and the individual factors
* may leak, though) and to the hashed data.
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pkcs1_sign)(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Type for a RSA signature generation engine (PSS).
*
* Parameters are:
*
* - An initialized PRNG for salt generation. If the salt length is
* zero (`salt_len` parameter), then the PRNG is optional (this is
* not the typical case, as the security proof of RSA/PSS is
* tighter when a non-empty salt is used).
*
* - The hash function which was used to hash the message.
*
* - The hash function to use with MGF1 within the PSS padding. This
* is not necessarily the same function as the one used to hash the
* message.
*
* - The hashed message.
*
* - The salt length, in bytes.
*
* - The RSA private key.
*
* - The output buffer, that receives the signature.
*
* Returned value is 1 on success, 0 on error. Error conditions include
* a too small modulus for the provided hash and salt lengths, or some
* invalid key parameters. The signature length is exactly
* `(sk->n_bitlen+7)/8` bytes.
*
* This function is expected to be constant-time with regards to the
* private key bytes (lengths of the modulus and the individual factors
* may leak, though) and to the hashed data.
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_pss_sign)(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Encoded OID for SHA-1 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA1 \
((const unsigned char *)"\x05\x2B\x0E\x03\x02\x1A")
/**
* \brief Encoded OID for SHA-224 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA224 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04")
/**
* \brief Encoded OID for SHA-256 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA256 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
/**
* \brief Encoded OID for SHA-384 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA384 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02")
/**
* \brief Encoded OID for SHA-512 (in RSA PKCS#1 signatures).
*/
#define BR_HASH_OID_SHA512 \
((const unsigned char *)"\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
/**
* \brief Type for a RSA decryption engine (OAEP).
*
* Parameters are:
*
* - A hash function, used internally with the mask generation function
* (MGF1).
*
* - A label. The `label` pointer may be `NULL` if `label_len` is zero
* (an empty label, which is the default in PKCS#1 v2.2).
*
* - The private key.
*
* - The source and destination buffer. The buffer initially contains
* the encrypted message; the buffer contents are altered, and the
* decrypted message is written at the start of that buffer
* (decrypted message is always shorter than the encrypted message).
*
* If decryption fails in any way, then `*len` is unmodified, and the
* function returns 0. Otherwise, `*len` is set to the decrypted message
* length, and 1 is returned. The implementation is responsible for
* checking that the input message length matches the key modulus length,
* and that the padding is correct.
*
* Implementations MUST use constant-time check of the validity of the
* OAEP padding, at least until the leading byte and hash value have
* been checked. Whether overall decryption worked, and the length of
* the decrypted message, may leak.
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_rsa_oaep_decrypt)(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/*
* RSA "i32" engine. Integers are internally represented as arrays of
* 32-bit integers, and the core multiplication primitive is the
* 32x32->64 multiplication.
*/
/**
* \brief RSA public key engine "i32".
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i32" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i32" (PSS signatures).
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i32".
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i32" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i32" (PSS signatures).
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/*
* RSA "i31" engine. Similar to i32, but only 31 bits are used per 32-bit
* word. This uses slightly more stack space (about 4% more) and code
* space, but it quite faster.
*/
/**
* \brief RSA public key engine "i31".
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i31" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i31" (PSS signatures).
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i31".
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i31" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i31" (PSS signatures).
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/*
* RSA "i62" engine. Similar to i31, but internal multiplication use
* 64x64->128 multiplications. This is available only on architecture
* that offer such an opcode.
*/
/**
* \brief RSA public key engine "i62".
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_public_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i62" (PKCS#1 v1.5 signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pkcs1_vrfy_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i62" (PSS signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pss_vrfy_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i62".
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_private_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i62" (PKCS#1 v1.5 signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pkcs1_sign_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i62" (PSS signatures).
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_pss_sign_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Get the RSA "i62" implementation (public key operations),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_public br_rsa_i62_public_get(void);
/**
* \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature verification),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pkcs1_vrfy br_rsa_i62_pkcs1_vrfy_get(void);
/**
* \brief Get the RSA "i62" implementation (PSS signature verification),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pss_vrfy br_rsa_i62_pss_vrfy_get(void);
/**
* \brief Get the RSA "i62" implementation (private key operations),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_private br_rsa_i62_private_get(void);
/**
* \brief Get the RSA "i62" implementation (PKCS#1 v1.5 signature generation),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pkcs1_sign br_rsa_i62_pkcs1_sign_get(void);
/**
* \brief Get the RSA "i62" implementation (PSS signature generation),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_pss_sign br_rsa_i62_pss_sign_get(void);
/**
* \brief Get the RSA "i62" implementation (OAEP encryption),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_oaep_encrypt br_rsa_i62_oaep_encrypt_get(void);
/**
* \brief Get the RSA "i62" implementation (OAEP decryption),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_oaep_decrypt br_rsa_i62_oaep_decrypt_get(void);
/*
* RSA "i15" engine. Integers are represented as 15-bit integers, so
* the code uses only 32-bit multiplication (no 64-bit result), which
* is vastly faster (and constant-time) on the ARM Cortex M0/M0+.
*/
/**
* \brief RSA public key engine "i15".
*
* \see br_rsa_public
*
* \param x operand to exponentiate.
* \param xlen length of the operand (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_public(unsigned char *x, size_t xlen,
const br_rsa_public_key *pk);
/**
* \brief RSA signature verification engine "i15" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash_len expected hash value length (in bytes).
* \param pk RSA public key.
* \param hash_out output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pkcs1_vrfy(const unsigned char *x, size_t xlen,
const unsigned char *hash_oid, size_t hash_len,
const br_rsa_public_key *pk, unsigned char *hash_out);
/**
* \brief RSA signature verification engine "i15" (PSS signatures).
*
* \see br_rsa_pss_vrfy
*
* \param x signature buffer.
* \param xlen signature length (in bytes).
* \param hf_data hash function applied on the message.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hash value of the signed message.
* \param salt_len PSS salt length (in bytes).
* \param pk RSA public key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pss_vrfy(const unsigned char *x, size_t xlen,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const void *hash, size_t salt_len, const br_rsa_public_key *pk);
/**
* \brief RSA private key engine "i15".
*
* \see br_rsa_private
*
* \param x operand to exponentiate.
* \param sk RSA private key.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_private(unsigned char *x,
const br_rsa_private_key *sk);
/**
* \brief RSA signature generation engine "i15" (PKCS#1 v1.5 signatures).
*
* \see br_rsa_pkcs1_sign
*
* \param hash_oid encoded hash algorithm OID (or `NULL`).
* \param hash hash value.
* \param hash_len hash value length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the hash value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pkcs1_sign(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief RSA signature generation engine "i15" (PSS signatures).
*
* \see br_rsa_pss_sign
*
* \param rng PRNG for salt generation (`NULL` if `salt_len` is zero).
* \param hf_data hash function used to hash the signed data.
* \param hf_mgf1 hash function to use with MGF1.
* \param hash hashed message.
* \param salt_len salt length (in bytes).
* \param sk RSA private key.
* \param x output buffer for the signature value.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_pss_sign(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash_value, size_t salt_len,
const br_rsa_private_key *sk, unsigned char *x);
/**
* \brief Get "default" RSA implementation (public-key operations).
*
* This returns the preferred implementation of RSA (public-key operations)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_public br_rsa_public_get_default(void);
/**
* \brief Get "default" RSA implementation (private-key operations).
*
* This returns the preferred implementation of RSA (private-key operations)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_private br_rsa_private_get_default(void);
/**
* \brief Get "default" RSA implementation (PKCS#1 v1.5 signature verification).
*
* This returns the preferred implementation of RSA (signature verification)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pkcs1_vrfy br_rsa_pkcs1_vrfy_get_default(void);
/**
* \brief Get "default" RSA implementation (PSS signature verification).
*
* This returns the preferred implementation of RSA (signature verification)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pss_vrfy br_rsa_pss_vrfy_get_default(void);
/**
* \brief Get "default" RSA implementation (PKCS#1 v1.5 signature generation).
*
* This returns the preferred implementation of RSA (signature generation)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pkcs1_sign br_rsa_pkcs1_sign_get_default(void);
/**
* \brief Get "default" RSA implementation (PSS signature generation).
*
* This returns the preferred implementation of RSA (signature generation)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_pss_sign br_rsa_pss_sign_get_default(void);
/**
* \brief Get "default" RSA implementation (OAEP encryption).
*
* This returns the preferred implementation of RSA (OAEP encryption)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_oaep_encrypt br_rsa_oaep_encrypt_get_default(void);
/**
* \brief Get "default" RSA implementation (OAEP decryption).
*
* This returns the preferred implementation of RSA (OAEP decryption)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_oaep_decrypt br_rsa_oaep_decrypt_get_default(void);
/**
* \brief RSA decryption helper, for SSL/TLS.
*
* This function performs the RSA decryption for a RSA-based key exchange
* in a SSL/TLS server. The provided RSA engine is used. The `data`
* parameter points to the value to decrypt, of length `len` bytes. On
* success, the 48-byte pre-master secret is copied into `data`, starting
* at the first byte of that buffer; on error, the contents of `data`
* become indeterminate.
*
* This function first checks that the provided value length (`len`) is
* not lower than 59 bytes, and matches the RSA modulus length; if neither
* of this property is met, then this function returns 0 and the buffer
* is unmodified.
*
* Otherwise, decryption and then padding verification are performed, both
* in constant-time. A decryption error, or a bad padding, or an
* incorrect decrypted value length are reported with a returned value of
* 0; on success, 1 is returned. The caller (SSL server engine) is supposed
* to proceed with a random pre-master secret in case of error.
*
* \param core RSA private key engine.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len length (in bytes) of the data to decrypt.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_ssl_decrypt(br_rsa_private core, const br_rsa_private_key *sk,
unsigned char *data, size_t len);
/**
* \brief RSA encryption (OAEP) with the "i15" engine.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i15_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i15" engine.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i15_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief RSA encryption (OAEP) with the "i31" engine.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i31_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i31" engine.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i31_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief RSA encryption (OAEP) with the "i32" engine.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i32_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i32" engine.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i32_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief RSA encryption (OAEP) with the "i62" engine.
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_oaep_encrypt_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_oaep_encrypt
*
* \param rnd source of random bytes.
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param pk RSA public key.
* \param dst destination buffer.
* \param dst_max_len destination buffer length (maximum encrypted data size).
* \param src message to encrypt.
* \param src_len source message length (in bytes).
* \return encrypted message length (in bytes), or 0 on error.
*/
size_t br_rsa_i62_oaep_encrypt(
const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len,
const br_rsa_public_key *pk,
void *dst, size_t dst_max_len,
const void *src, size_t src_len);
/**
* \brief RSA decryption (OAEP) with the "i62" engine.
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_oaep_decrypt_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_oaep_decrypt
*
* \param dig hash function to use with MGF1.
* \param label label value (may be `NULL` if `label_len` is zero).
* \param label_len label length, in bytes.
* \param sk RSA private key.
* \param data input/output buffer.
* \param len encrypted/decrypted message length.
* \return 1 on success, 0 on error.
*/
uint32_t br_rsa_i62_oaep_decrypt(
const br_hash_class *dig, const void *label, size_t label_len,
const br_rsa_private_key *sk, void *data, size_t *len);
/**
* \brief Get buffer size to hold RSA private key elements.
*
* This macro returns the length (in bytes) of the buffer needed to
* receive the elements of a RSA private key, as generated by one of
* the `br_rsa_*_keygen()` functions. If the provided size is a constant
* expression, then the whole macro evaluates to a constant expression.
*
* \param size target key size (modulus size, in bits)
* \return the length of the private key buffer, in bytes.
*/
#define BR_RSA_KBUF_PRIV_SIZE(size) (5 * (((size) + 15) >> 4))
/**
* \brief Get buffer size to hold RSA public key elements.
*
* This macro returns the length (in bytes) of the buffer needed to
* receive the elements of a RSA public key, as generated by one of
* the `br_rsa_*_keygen()` functions. If the provided size is a constant
* expression, then the whole macro evaluates to a constant expression.
*
* \param size target key size (modulus size, in bits)
* \return the length of the public key buffer, in bytes.
*/
#define BR_RSA_KBUF_PUB_SIZE(size) (4 + (((size) + 7) >> 3))
/**
* \brief Type for RSA key pair generator implementation.
*
* This function generates a new RSA key pair whose modulus has bit
* length `size` bits. The private key elements are written in the
* `kbuf_priv` buffer, and pointer values and length fields to these
* elements are populated in the provided private key structure `sk`.
* Similarly, the public key elements are written in `kbuf_pub`, with
* pointers and lengths set in `pk`.
*
* If `pk` is `NULL`, then `kbuf_pub` may be `NULL`, and only the
* private key is set.
*
* If `pubexp` is not zero, then its value will be used as public
* exponent. Valid RSA public exponent values are odd integers
* greater than 1. If `pubexp` is zero, then the public exponent will
* have value 3.
*
* The provided PRNG (`rng_ctx`) must have already been initialized
* and seeded.
*
* Returned value is 1 on success, 0 on error. An error is reported
* if the requested range is outside of the supported key sizes, or
* if an invalid non-zero public exponent value is provided. Supported
* range starts at 512 bits, and up to an implementation-defined
* maximum (by default 4096 bits). Note that key sizes up to 768 bits
* have been broken in practice, and sizes lower than 2048 bits are
* usually considered to be weak and should not be used.
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
typedef uint32_t (*br_rsa_keygen)(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief RSA key pair generation with the "i15" engine.
*
* \see br_rsa_keygen
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
uint32_t br_rsa_i15_keygen(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief RSA key pair generation with the "i31" engine.
*
* \see br_rsa_keygen
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
uint32_t br_rsa_i31_keygen(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief RSA key pair generation with the "i62" engine.
*
* This function is defined only on architecture that offer a 64x64->128
* opcode. Use `br_rsa_i62_keygen_get()` to dynamically obtain a pointer
* to that function.
*
* \see br_rsa_keygen
*
* \param rng_ctx source PRNG context (already initialized)
* \param sk RSA private key structure (destination)
* \param kbuf_priv buffer for private key elements
* \param pk RSA public key structure (destination), or `NULL`
* \param kbuf_pub buffer for public key elements, or `NULL`
* \param size target RSA modulus size (in bits)
* \param pubexp public exponent to use, or zero
* \return 1 on success, 0 on error (invalid parameters)
*/
uint32_t br_rsa_i62_keygen(
const br_prng_class **rng_ctx,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp);
/**
* \brief Get the RSA "i62" implementation (key pair generation),
* if available.
*
* \return the implementation, or 0.
*/
br_rsa_keygen br_rsa_i62_keygen_get(void);
/**
* \brief Get "default" RSA implementation (key pair generation).
*
* This returns the preferred implementation of RSA (key pair generation)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_keygen br_rsa_keygen_get_default(void);
/**
* \brief Type for a modulus computing function.
*
* Such a function computes the public modulus from the private key. The
* encoded modulus (unsigned big-endian) is written on `n`, and the size
* (in bytes) is returned. If `n` is `NULL`, then the size is returned but
* the modulus itself is not computed.
*
* If the key size exceeds an internal limit, 0 is returned.
*
* \param n destination buffer (or `NULL`).
* \param sk RSA private key.
* \return the modulus length (in bytes), or 0.
*/
typedef size_t (*br_rsa_compute_modulus)(void *n, const br_rsa_private_key *sk);
/**
* \brief Recompute RSA modulus ("i15" engine).
*
* \see br_rsa_compute_modulus
*
* \param n destination buffer (or `NULL`).
* \param sk RSA private key.
* \return the modulus length (in bytes), or 0.
*/
size_t br_rsa_i15_compute_modulus(void *n, const br_rsa_private_key *sk);
/**
* \brief Recompute RSA modulus ("i31" engine).
*
* \see br_rsa_compute_modulus
*
* \param n destination buffer (or `NULL`).
* \param sk RSA private key.
* \return the modulus length (in bytes), or 0.
*/
size_t br_rsa_i31_compute_modulus(void *n, const br_rsa_private_key *sk);
/**
* \brief Get "default" RSA implementation (recompute modulus).
*
* This returns the preferred implementation of RSA (recompute modulus)
* on the current system.
*
* \return the default implementation.
*/
br_rsa_compute_modulus br_rsa_compute_modulus_get_default(void);
/**
* \brief Type for a public exponent computing function.
*
* Such a function recomputes the public exponent from the private key.
* 0 is returned if any of the following occurs:
*
* - Either `p` or `q` is not equal to 3 modulo 4.
*
* - The public exponent does not fit on 32 bits.
*
* - An internal limit is exceeded.
*
* - The private key is invalid in some way.
*
* For all private keys produced by the key generator functions
* (`br_rsa_keygen` type), this function succeeds and returns the true
* public exponent. The public exponent is always an odd integer greater
* than 1.
*
* \return the public exponent, or 0.
*/
typedef uint32_t (*br_rsa_compute_pubexp)(const br_rsa_private_key *sk);
/**
* \brief Recompute RSA public exponent ("i15" engine).
*
* \see br_rsa_compute_pubexp
*
* \return the public exponent, or 0.
*/
uint32_t br_rsa_i15_compute_pubexp(const br_rsa_private_key *sk);
/**
* \brief Recompute RSA public exponent ("i31" engine).
*
* \see br_rsa_compute_pubexp
*
* \return the public exponent, or 0.
*/
uint32_t br_rsa_i31_compute_pubexp(const br_rsa_private_key *sk);
/**
* \brief Get "default" RSA implementation (recompute public exponent).
*
* This returns the preferred implementation of RSA (recompute public
* exponent) on the current system.
*
* \return the default implementation.
*/
br_rsa_compute_pubexp br_rsa_compute_pubexp_get_default(void);
/**
* \brief Type for a private exponent computing function.
*
* An RSA private key (`br_rsa_private_key`) contains two reduced
* private exponents, which are sufficient to perform private key
* operations. However, standard encoding formats for RSA private keys
* require also a copy of the complete private exponent (non-reduced),
* which this function recomputes.
*
* This function suceeds if all the following conditions hold:
*
* - Both private factors `p` and `q` are equal to 3 modulo 4.
*
* - The provided public exponent `pubexp` is correct, and, in particular,
* is odd, relatively prime to `p-1` and `q-1`, and greater than 1.
*
* - No internal storage limit is exceeded.
*
* For all private keys produced by the key generator functions
* (`br_rsa_keygen` type), this function succeeds. Note that the API
* restricts the public exponent to a maximum size of 32 bits.
*
* The encoded private exponent is written in `d` (unsigned big-endian
* convention), and the length (in bytes) is returned. If `d` is `NULL`,
* then the exponent is not written anywhere, but the length is still
* returned. On error, 0 is returned.
*
* Not all error conditions are detected when `d` is `NULL`; therefore, the
* returned value shall be checked also when actually producing the value.
*
* \param d destination buffer (or `NULL`).
* \param sk RSA private key.
* \param pubexp the public exponent.
* \return the private exponent length (in bytes), or 0.
*/
typedef size_t (*br_rsa_compute_privexp)(void *d,
const br_rsa_private_key *sk, uint32_t pubexp);
/**
* \brief Recompute RSA private exponent ("i15" engine).
*
* \see br_rsa_compute_privexp
*
* \param d destination buffer (or `NULL`).
* \param sk RSA private key.
* \param pubexp the public exponent.
* \return the private exponent length (in bytes), or 0.
*/
size_t br_rsa_i15_compute_privexp(void *d,
const br_rsa_private_key *sk, uint32_t pubexp);
/**
* \brief Recompute RSA private exponent ("i31" engine).
*
* \see br_rsa_compute_privexp
*
* \param d destination buffer (or `NULL`).
* \param sk RSA private key.
* \param pubexp the public exponent.
* \return the private exponent length (in bytes), or 0.
*/
size_t br_rsa_i31_compute_privexp(void *d,
const br_rsa_private_key *sk, uint32_t pubexp);
/**
* \brief Get "default" RSA implementation (recompute private exponent).
*
* This returns the preferred implementation of RSA (recompute private
* exponent) on the current system.
*
* \return the default implementation.
*/
br_rsa_compute_privexp br_rsa_compute_privexp_get_default(void);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_EC_H__
#define BR_BEARSSL_EC_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_ec.h
*
* # Elliptic Curves
*
* This file documents the EC implementations provided with BearSSL, and
* ECDSA.
*
* ## Elliptic Curve API
*
* Only "named curves" are supported. Each EC implementation supports
* one or several named curves, identified by symbolic identifiers.
* These identifiers are small integers, that correspond to the values
* registered by the
* [IANA](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8).
*
* Since all currently defined elliptic curve identifiers are in the 0..31
* range, it is convenient to encode support of some curves in a 32-bit
* word, such that bit x corresponds to curve of identifier x.
*
* An EC implementation is incarnated by a `br_ec_impl` instance, that
* offers the following fields:
*
* - `supported_curves`
*
* A 32-bit word that documents the identifiers of the curves supported
* by this implementation.
*
* - `generator()`
*
* Callback method that returns a pointer to the conventional generator
* point for that curve.
*
* - `order()`
*
* Callback method that returns a pointer to the subgroup order for
* that curve. That value uses unsigned big-endian encoding.
*
* - `xoff()`
*
* Callback method that returns the offset and length of the X
* coordinate in an encoded point.
*
* - `mul()`
*
* Multiply a curve point with an integer.
*
* - `mulgen()`
*
* Multiply the curve generator with an integer. This may be faster
* than the generic `mul()`.
*
* - `muladd()`
*
* Multiply two curve points by two integers, and return the sum of
* the two products.
*
* All curve points are represented in uncompressed format. The `mul()`
* and `muladd()` methods take care to validate that the provided points
* are really part of the relevant curve subgroup.
*
* For all point multiplication functions, the following holds:
*
* - Functions validate that the provided points are valid members
* of the relevant curve subgroup. An error is reported if that is
* not the case.
*
* - Processing is constant-time, even if the point operands are not
* valid. This holds for both the source and resulting points, and
* the multipliers (integers). Only the byte length of the provided
* multiplier arrays (not their actual value length in bits) may
* leak through timing-based side channels.
*
* - The multipliers (integers) MUST be lower than the subgroup order.
* If this property is not met, then the result is indeterminate,
* but an error value is not necessarily returned.
*
*
* ## ECDSA
*
* ECDSA signatures have two standard formats, called "raw" and "asn1".
* Internally, such a signature is a pair of modular integers `(r,s)`.
* The "raw" format is the concatenation of the unsigned big-endian
* encodings of these two integers, possibly left-padded with zeros so
* that they have the same encoded length. The "asn1" format is the
* DER encoding of an ASN.1 structure that contains the two integer
* values:
*
* ECDSASignature ::= SEQUENCE {
* r INTEGER,
* s INTEGER
* }
*
* In general, in all of X.509 and SSL/TLS, the "asn1" format is used.
* BearSSL offers ECDSA implementations for both formats; conversion
* functions between the two formats are also provided. Conversion of a
* "raw" format signature into "asn1" may enlarge a signature by no more
* than 9 bytes for all supported curves; conversely, conversion of an
* "asn1" signature to "raw" may expand the signature but the "raw"
* length will never be more than twice the length of the "asn1" length
* (and usually it will be shorter).
*
* Note that for a given signature, the "raw" format is not fully
* deterministic, in that it does not enforce a minimal common length.
*/
/*
* Standard curve ID. These ID are equal to the assigned numerical
* identifiers assigned to these curves for TLS:
* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
*/
/** \brief Identifier for named curve sect163k1. */
#define BR_EC_sect163k1 1
/** \brief Identifier for named curve sect163r1. */
#define BR_EC_sect163r1 2
/** \brief Identifier for named curve sect163r2. */
#define BR_EC_sect163r2 3
/** \brief Identifier for named curve sect193r1. */
#define BR_EC_sect193r1 4
/** \brief Identifier for named curve sect193r2. */
#define BR_EC_sect193r2 5
/** \brief Identifier for named curve sect233k1. */
#define BR_EC_sect233k1 6
/** \brief Identifier for named curve sect233r1. */
#define BR_EC_sect233r1 7
/** \brief Identifier for named curve sect239k1. */
#define BR_EC_sect239k1 8
/** \brief Identifier for named curve sect283k1. */
#define BR_EC_sect283k1 9
/** \brief Identifier for named curve sect283r1. */
#define BR_EC_sect283r1 10
/** \brief Identifier for named curve sect409k1. */
#define BR_EC_sect409k1 11
/** \brief Identifier for named curve sect409r1. */
#define BR_EC_sect409r1 12
/** \brief Identifier for named curve sect571k1. */
#define BR_EC_sect571k1 13
/** \brief Identifier for named curve sect571r1. */
#define BR_EC_sect571r1 14
/** \brief Identifier for named curve secp160k1. */
#define BR_EC_secp160k1 15
/** \brief Identifier for named curve secp160r1. */
#define BR_EC_secp160r1 16
/** \brief Identifier for named curve secp160r2. */
#define BR_EC_secp160r2 17
/** \brief Identifier for named curve secp192k1. */
#define BR_EC_secp192k1 18
/** \brief Identifier for named curve secp192r1. */
#define BR_EC_secp192r1 19
/** \brief Identifier for named curve secp224k1. */
#define BR_EC_secp224k1 20
/** \brief Identifier for named curve secp224r1. */
#define BR_EC_secp224r1 21
/** \brief Identifier for named curve secp256k1. */
#define BR_EC_secp256k1 22
/** \brief Identifier for named curve secp256r1. */
#define BR_EC_secp256r1 23
/** \brief Identifier for named curve secp384r1. */
#define BR_EC_secp384r1 24
/** \brief Identifier for named curve secp521r1. */
#define BR_EC_secp521r1 25
/** \brief Identifier for named curve brainpoolP256r1. */
#define BR_EC_brainpoolP256r1 26
/** \brief Identifier for named curve brainpoolP384r1. */
#define BR_EC_brainpoolP384r1 27
/** \brief Identifier for named curve brainpoolP512r1. */
#define BR_EC_brainpoolP512r1 28
/** \brief Identifier for named curve Curve25519. */
#define BR_EC_curve25519 29
/** \brief Identifier for named curve Curve448. */
#define BR_EC_curve448 30
/**
* \brief Structure for an EC public key.
*/
typedef struct {
/** \brief Identifier for the curve used by this key. */
int curve;
/** \brief Public curve point (uncompressed format). */
unsigned char *q;
/** \brief Length of public curve point (in bytes). */
size_t qlen;
} br_ec_public_key;
/**
* \brief Structure for an EC private key.
*
* The private key is an integer modulo the curve subgroup order. The
* encoding below tolerates extra leading zeros. In general, it is
* recommended that the private key has the same length as the curve
* subgroup order.
*/
typedef struct {
/** \brief Identifier for the curve used by this key. */
int curve;
/** \brief Private key (integer, unsigned big-endian encoding). */
unsigned char *x;
/** \brief Private key length (in bytes). */
size_t xlen;
} br_ec_private_key;
/**
* \brief Type for an EC implementation.
*/
typedef struct {
/**
* \brief Supported curves.
*
* This word is a bitfield: bit `x` is set if the curve of ID `x`
* is supported. E.g. an implementation supporting both NIST P-256
* (secp256r1, ID 23) and NIST P-384 (secp384r1, ID 24) will have
* value `0x01800000` in this field.
*/
uint32_t supported_curves;
/**
* \brief Get the conventional generator.
*
* This function returns the conventional generator (encoded
* curve point) for the specified curve. This function MUST NOT
* be called if the curve is not supported.
*
* \param curve curve identifier.
* \param len receiver for the encoded generator length (in bytes).
* \return the encoded generator.
*/
const unsigned char *(*generator)(int curve, size_t *len);
/**
* \brief Get the subgroup order.
*
* This function returns the order of the subgroup generated by
* the conventional generator, for the specified curve. Unsigned
* big-endian encoding is used. This function MUST NOT be called
* if the curve is not supported.
*
* \param curve curve identifier.
* \param len receiver for the encoded order length (in bytes).
* \return the encoded order.
*/
const unsigned char *(*order)(int curve, size_t *len);
/**
* \brief Get the offset and length for the X coordinate.
*
* This function returns the offset and length (in bytes) of
* the X coordinate in an encoded non-zero point.
*
* \param curve curve identifier.
* \param len receiver for the X coordinate length (in bytes).
* \return the offset for the X coordinate (in bytes).
*/
size_t (*xoff)(int curve, size_t *len);
/**
* \brief Multiply a curve point by an integer.
*
* The source point is provided in array `G` (of size `Glen` bytes);
* the multiplication result is written over it. The multiplier
* `x` (of size `xlen` bytes) uses unsigned big-endian encoding.
*
* Rules:
*
* - The specified curve MUST be supported.
*
* - The source point must be a valid point on the relevant curve
* subgroup (and not the "point at infinity" either). If this is
* not the case, then this function returns an error (0).
*
* - The multiplier integer MUST be non-zero and less than the
* curve subgroup order. If this property does not hold, then
* the result is indeterminate and an error code is not
* guaranteed.
*
* Returned value is 1 on success, 0 on error. On error, the
* contents of `G` are indeterminate.
*
* \param G point to multiply.
* \param Glen length of the encoded point (in bytes).
* \param x multiplier (unsigned big-endian).
* \param xlen multiplier length (in bytes).
* \param curve curve identifier.
* \return 1 on success, 0 on error.
*/
uint32_t (*mul)(unsigned char *G, size_t Glen,
const unsigned char *x, size_t xlen, int curve);
/**
* \brief Multiply the generator by an integer.
*
* The multiplier MUST be non-zero and less than the curve
* subgroup order. Results are indeterminate if this property
* does not hold.
*
* \param R output buffer for the point.
* \param x multiplier (unsigned big-endian).
* \param xlen multiplier length (in bytes).
* \param curve curve identifier.
* \return encoded result point length (in bytes).
*/
size_t (*mulgen)(unsigned char *R,
const unsigned char *x, size_t xlen, int curve);
/**
* \brief Multiply two points by two integers and add the
* results.
*
* The point `x*A + y*B` is computed and written back in the `A`
* array.
*
* Rules:
*
* - The specified curve MUST be supported.
*
* - The source points (`A` and `B`) must be valid points on
* the relevant curve subgroup (and not the "point at
* infinity" either). If this is not the case, then this
* function returns an error (0).
*
* - If the `B` pointer is `NULL`, then the conventional
* subgroup generator is used. With some implementations,
* this may be faster than providing a pointer to the
* generator.
*
* - The multiplier integers (`x` and `y`) MUST be non-zero
* and less than the curve subgroup order. If either integer
* is zero, then an error is reported, but if one of them is
* not lower than the subgroup order, then the result is
* indeterminate and an error code is not guaranteed.
*
* - If the final result is the point at infinity, then an
* error is returned.
*
* Returned value is 1 on success, 0 on error. On error, the
* contents of `A` are indeterminate.
*
* \param A first point to multiply.
* \param B second point to multiply (`NULL` for the generator).
* \param len common length of the encoded points (in bytes).
* \param x multiplier for `A` (unsigned big-endian).
* \param xlen length of multiplier for `A` (in bytes).
* \param y multiplier for `A` (unsigned big-endian).
* \param ylen length of multiplier for `A` (in bytes).
* \param curve curve identifier.
* \return 1 on success, 0 on error.
*/
uint32_t (*muladd)(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve);
} br_ec_impl;
/**
* \brief EC implementation "i31".
*
* This implementation internally uses generic code for modular integers,
* with a representation as sequences of 31-bit words. It supports secp256r1,
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
*/
extern const br_ec_impl br_ec_prime_i31;
/**
* \brief EC implementation "i15".
*
* This implementation internally uses generic code for modular integers,
* with a representation as sequences of 15-bit words. It supports secp256r1,
* secp384r1 and secp521r1 (aka NIST curves P-256, P-384 and P-521).
*/
extern const br_ec_impl br_ec_prime_i15;
/**
* \brief EC implementation "m15" for P-256.
*
* This implementation uses specialised code for curve secp256r1 (also
* known as NIST P-256), with optional Karatsuba decomposition, and fast
* modular reduction thanks to the field modulus special format. Only
* 32-bit multiplications are used (with 32-bit results, not 64-bit).
*/
extern const br_ec_impl br_ec_p256_m15;
/**
* \brief EC implementation "m31" for P-256.
*
* This implementation uses specialised code for curve secp256r1 (also
* known as NIST P-256), relying on multiplications of 31-bit values
* (MUL31).
*/
extern const br_ec_impl br_ec_p256_m31;
/**
* \brief EC implementation "m62" (specialised code) for P-256.
*
* This implementation uses custom code relying on multiplication of
* integers up to 64 bits, with a 128-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_p256_m62_get()` to dynamically obtain a pointer
* to that implementation.
*/
extern const br_ec_impl br_ec_p256_m62;
/**
* \brief Get the "m62" implementation of P-256, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_p256_m62_get(void);
/**
* \brief EC implementation "m64" (specialised code) for P-256.
*
* This implementation uses custom code relying on multiplication of
* integers up to 64 bits, with a 128-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_p256_m64_get()` to dynamically obtain a pointer
* to that implementation.
*/
extern const br_ec_impl br_ec_p256_m64;
/**
* \brief Get the "m64" implementation of P-256, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_p256_m64_get(void);
/**
* \brief EC implementation "i15" (generic code) for Curve25519.
*
* This implementation uses the generic code for modular integers (with
* 15-bit words) to support Curve25519. Due to the specificities of the
* curve definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_i15;
/**
* \brief EC implementation "i31" (generic code) for Curve25519.
*
* This implementation uses the generic code for modular integers (with
* 31-bit words) to support Curve25519. Due to the specificities of the
* curve definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_i31;
/**
* \brief EC implementation "m15" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 15 bits. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m15;
/**
* \brief EC implementation "m31" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 31 bits. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m31;
/**
* \brief EC implementation "m62" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 62 bits, with a 124-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_c25519_m62_get()` to dynamically obtain a pointer
* to that implementation. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m62;
/**
* \brief Get the "m62" implementation of Curve25519, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_c25519_m62_get(void);
/**
* \brief EC implementation "m64" (specialised code) for Curve25519.
*
* This implementation uses custom code relying on multiplication of
* integers up to 64 bits, with a 128-bit result. This implementation is
* defined only on platforms that offer the 64x64->128 multiplication
* support; use `br_ec_c25519_m64_get()` to dynamically obtain a pointer
* to that implementation. Due to the specificities of the curve
* definition, the following applies:
*
* - `muladd()` is not implemented (the function returns 0 systematically).
* - `order()` returns 2^255-1, since the point multiplication algorithm
* accepts any 32-bit integer as input (it clears the top bit and low
* three bits systematically).
*/
extern const br_ec_impl br_ec_c25519_m64;
/**
* \brief Get the "m64" implementation of Curve25519, if available.
*
* \return the implementation, or 0.
*/
const br_ec_impl *br_ec_c25519_m64_get(void);
/**
* \brief Aggregate EC implementation "m15".
*
* This implementation is a wrapper for:
*
* - `br_ec_c25519_m15` for Curve25519
* - `br_ec_p256_m15` for NIST P-256
* - `br_ec_prime_i15` for other curves (NIST P-384 and NIST-P512)
*/
extern const br_ec_impl br_ec_all_m15;
/**
* \brief Aggregate EC implementation "m31".
*
* This implementation is a wrapper for:
*
* - `br_ec_c25519_m31` for Curve25519
* - `br_ec_p256_m31` for NIST P-256
* - `br_ec_prime_i31` for other curves (NIST P-384 and NIST-P512)
*/
extern const br_ec_impl br_ec_all_m31;
/**
* \brief Get the "default" EC implementation for the current system.
*
* This returns a pointer to the preferred implementation on the
* current system.
*
* \return the default EC implementation.
*/
const br_ec_impl *br_ec_get_default(void);
/**
* \brief Convert a signature from "raw" to "asn1".
*
* Conversion is done "in place" and the new length is returned.
* Conversion may enlarge the signature, but by no more than 9 bytes at
* most. On error, 0 is returned (error conditions include an odd raw
* signature length, or an oversized integer).
*
* \param sig signature to convert.
* \param sig_len signature length (in bytes).
* \return the new signature length, or 0 on error.
*/
size_t br_ecdsa_raw_to_asn1(void *sig, size_t sig_len);
/**
* \brief Convert a signature from "asn1" to "raw".
*
* Conversion is done "in place" and the new length is returned.
* Conversion may enlarge the signature, but the new signature length
* will be less than twice the source length at most. On error, 0 is
* returned (error conditions include an invalid ASN.1 structure or an
* oversized integer).
*
* \param sig signature to convert.
* \param sig_len signature length (in bytes).
* \return the new signature length, or 0 on error.
*/
size_t br_ecdsa_asn1_to_raw(void *sig, size_t sig_len);
/**
* \brief Type for an ECDSA signer function.
*
* A pointer to the EC implementation is provided. The hash value is
* assumed to have the length inferred from the designated hash function
* class.
*
* Signature is written in the buffer pointed to by `sig`, and the length
* (in bytes) is returned. On error, nothing is written in the buffer,
* and 0 is returned. This function returns 0 if the specified curve is
* not supported by the provided EC implementation.
*
* The signature format is either "raw" or "asn1", depending on the
* implementation; maximum length is predictable from the implemented
* curve:
*
* | curve | raw | asn1 |
* | :--------- | --: | ---: |
* | NIST P-256 | 64 | 72 |
* | NIST P-384 | 96 | 104 |
* | NIST P-521 | 132 | 139 |
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
typedef size_t (*br_ecdsa_sign)(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief Type for an ECDSA signature verification function.
*
* A pointer to the EC implementation is provided. The hashed value,
* computed over the purportedly signed data, is also provided with
* its length.
*
* The signature format is either "raw" or "asn1", depending on the
* implementation.
*
* Returned value is 1 on success (valid signature), 0 on error. This
* function returns 0 if the specified curve is not supported by the
* provided EC implementation.
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
typedef uint32_t (*br_ecdsa_vrfy)(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature generator, "i31" implementation, "asn1" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature generator, "i31" implementation, "raw" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature verifier, "i31" implementation, "asn1" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature verifier, "i31" implementation, "raw" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature generator, "i15" implementation, "asn1" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature generator, "i15" implementation, "raw" format.
*
* \see br_ecdsa_sign()
*
* \param impl EC implementation to use.
* \param hf hash function used to process the data.
* \param hash_value signed data (hashed).
* \param sk EC private key.
* \param sig destination buffer.
* \return the signature length (in bytes), or 0 on error.
*/
size_t br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig);
/**
* \brief ECDSA signature verifier, "i15" implementation, "asn1" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief ECDSA signature verifier, "i15" implementation, "raw" format.
*
* \see br_ecdsa_vrfy()
*
* \param impl EC implementation to use.
* \param hash signed data (hashed).
* \param hash_len hash value length (in bytes).
* \param pk EC public key.
* \param sig signature.
* \param sig_len signature length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk, const void *sig, size_t sig_len);
/**
* \brief Get "default" ECDSA implementation (signer, asn1 format).
*
* This returns the preferred implementation of ECDSA signature generation
* ("asn1" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_sign br_ecdsa_sign_asn1_get_default(void);
/**
* \brief Get "default" ECDSA implementation (signer, raw format).
*
* This returns the preferred implementation of ECDSA signature generation
* ("raw" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_sign br_ecdsa_sign_raw_get_default(void);
/**
* \brief Get "default" ECDSA implementation (verifier, asn1 format).
*
* This returns the preferred implementation of ECDSA signature verification
* ("asn1" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_vrfy br_ecdsa_vrfy_asn1_get_default(void);
/**
* \brief Get "default" ECDSA implementation (verifier, raw format).
*
* This returns the preferred implementation of ECDSA signature verification
* ("raw" output format) on the current system.
*
* \return the default implementation.
*/
br_ecdsa_vrfy br_ecdsa_vrfy_raw_get_default(void);
/**
* \brief Maximum size for EC private key element buffer.
*
* This is the largest number of bytes that `br_ec_keygen()` may need or
* ever return.
*/
#define BR_EC_KBUF_PRIV_MAX_SIZE 72
/**
* \brief Maximum size for EC public key element buffer.
*
* This is the largest number of bytes that `br_ec_compute_public()` may
* need or ever return.
*/
#define BR_EC_KBUF_PUB_MAX_SIZE 145
/**
* \brief Generate a new EC private key.
*
* If the specified `curve` is not supported by the elliptic curve
* implementation (`impl`), then this function returns zero.
*
* The `sk` structure fields are set to the new private key data. In
* particular, `sk.x` is made to point to the provided key buffer (`kbuf`),
* in which the actual private key data is written. That buffer is assumed
* to be large enough. The `BR_EC_KBUF_PRIV_MAX_SIZE` defines the maximum
* size for all supported curves.
*
* The number of bytes used in `kbuf` is returned. If `kbuf` is `NULL`, then
* the private key is not actually generated, and `sk` may also be `NULL`;
* the minimum length for `kbuf` is still computed and returned.
*
* If `sk` is `NULL` but `kbuf` is not `NULL`, then the private key is
* still generated and stored in `kbuf`.
*
* \param rng_ctx source PRNG context (already initialized).
* \param impl the elliptic curve implementation.
* \param sk the private key structure to fill, or `NULL`.
* \param kbuf the key element buffer, or `NULL`.
* \param curve the curve identifier.
* \return the key data length (in bytes), or zero.
*/
size_t br_ec_keygen(const br_prng_class **rng_ctx,
const br_ec_impl *impl, br_ec_private_key *sk,
void *kbuf, int curve);
/**
* \brief Compute EC public key from EC private key.
*
* This function uses the provided elliptic curve implementation (`impl`)
* to compute the public key corresponding to the private key held in `sk`.
* The public key point is written into `kbuf`, which is then linked from
* the `*pk` structure. The size of the public key point, i.e. the number
* of bytes used in `kbuf`, is returned.
*
* If `kbuf` is `NULL`, then the public key point is NOT computed, and
* the public key structure `*pk` is unmodified (`pk` may be `NULL` in
* that case). The size of the public key point is still returned.
*
* If `pk` is `NULL` but `kbuf` is not `NULL`, then the public key
* point is computed and stored in `kbuf`, and its size is returned.
*
* If the curve used by the private key is not supported by the curve
* implementation, then this function returns zero.
*
* The private key MUST be valid. An off-range private key value is not
* necessarily detected, and leads to unpredictable results.
*
* \param impl the elliptic curve implementation.
* \param pk the public key structure to fill (or `NULL`).
* \param kbuf the public key point buffer (or `NULL`).
* \param sk the source private key.
* \return the public key point length (in bytes), or zero.
*/
size_t br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
void *kbuf, const br_ec_private_key *sk);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_SSL_H__
#define BR_BEARSSL_SSL_H__
#include
#include
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_X509_H__
#define BR_BEARSSL_X509_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_x509.h
*
* # X.509 Certificate Chain Processing
*
* An X.509 processing engine receives an X.509 chain, chunk by chunk,
* as received from a SSL/TLS client or server (the client receives the
* server's certificate chain, and the server receives the client's
* certificate chain if it requested a client certificate). The chain
* is thus injected in the engine in SSL order (end-entity first).
*
* The engine's job is to return the public key to use for SSL/TLS.
* How exactly that key is obtained and verified is entirely up to the
* engine.
*
* **The "known key" engine** returns a public key which is already known
* from out-of-band information (e.g. the client _remembers_ the key from
* a previous connection, as in the usual SSH model). This is the simplest
* engine since it simply ignores the chain, thereby avoiding the need
* for any decoding logic.
*
* **The "minimal" engine** implements minimal X.509 decoding and chain
* validation:
*
* - The provided chain should validate "as is". There is no attempt
* at reordering, skipping or downloading extra certificates.
*
* - X.509 v1, v2 and v3 certificates are supported.
*
* - Trust anchors are a DN and a public key. Each anchor is either a
* "CA" anchor, or a non-CA.
*
* - If the end-entity certificate matches a non-CA anchor (subject DN
* is equal to the non-CA name, and public key is also identical to
* the anchor key), then this is a _direct trust_ case and the
* remaining certificates are ignored.
*
* - Unless direct trust is applied, the chain must be verifiable up to
* a certificate whose issuer DN matches the DN from a "CA" trust anchor,
* and whose signature is verifiable against that anchor's public key.
* Subsequent certificates in the chain are ignored.
*
* - The engine verifies subject/issuer DN matching, and enforces
* processing of Basic Constraints and Key Usage extensions. The
* Authority Key Identifier, Subject Key Identifier, Issuer Alt Name,
* Subject Directory Attribute, CRL Distribution Points, Freshest CRL,
* Authority Info Access and Subject Info Access extensions are
* ignored. The Subject Alt Name is decoded for the end-entity
* certificate under some conditions (see below). Other extensions
* are ignored if non-critical, or imply chain rejection if critical.
*
* - The Subject Alt Name extension is parsed for names of type `dNSName`
* when decoding the end-entity certificate, and only if there is a
* server name to match. If there is no SAN extension, then the
* Common Name from the subjectDN is used. That name matching is
* case-insensitive and honours a single starting wildcard (i.e. if
* the name in the certificate starts with "`*.`" then this matches
* any word as first element). Note: this name matching is performed
* also in the "direct trust" model.
*
* - DN matching is byte-to-byte equality (a future version might
* include some limited processing for case-insensitive matching and
* whitespace normalisation).
*
* - Successful validation produces a public key type but also a set
* of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
* The caller is responsible for checking that the key type and
* usages are compatible with the expected values (e.g. with the
* selected cipher suite, when the client validates the server's
* certificate).
*
* **Important caveats:**
*
* - The "minimal" engine does not check revocation status. The relevant
* extensions are ignored, and CRL or OCSP responses are not gathered
* or checked.
*
* - The "minimal" engine does not currently support Name Constraints
* (some basic functionality to handle sub-domains may be added in a
* later version).
*
* - The decoder is not "validating" in the sense that it won't reject
* some certificates with invalid field values when these fields are
* not actually processed.
*/
/*
* X.509 error codes are in the 32..63 range.
*/
/** \brief X.509 status: validation was successful; this is not actually
an error. */
#define BR_ERR_X509_OK 32
/** \brief X.509 status: invalid value in an ASN.1 structure. */
#define BR_ERR_X509_INVALID_VALUE 33
/** \brief X.509 status: truncated certificate. */
#define BR_ERR_X509_TRUNCATED 34
/** \brief X.509 status: empty certificate chain (no certificate at all). */
#define BR_ERR_X509_EMPTY_CHAIN 35
/** \brief X.509 status: decoding error: inner element extends beyond
outer element size. */
#define BR_ERR_X509_INNER_TRUNC 36
/** \brief X.509 status: decoding error: unsupported tag class (application
or private). */
#define BR_ERR_X509_BAD_TAG_CLASS 37
/** \brief X.509 status: decoding error: unsupported tag value. */
#define BR_ERR_X509_BAD_TAG_VALUE 38
/** \brief X.509 status: decoding error: indefinite length. */
#define BR_ERR_X509_INDEFINITE_LENGTH 39
/** \brief X.509 status: decoding error: extraneous element. */
#define BR_ERR_X509_EXTRA_ELEMENT 40
/** \brief X.509 status: decoding error: unexpected element. */
#define BR_ERR_X509_UNEXPECTED 41
/** \brief X.509 status: decoding error: expected constructed element, but
is primitive. */
#define BR_ERR_X509_NOT_CONSTRUCTED 42
/** \brief X.509 status: decoding error: expected primitive element, but
is constructed. */
#define BR_ERR_X509_NOT_PRIMITIVE 43
/** \brief X.509 status: decoding error: BIT STRING length is not multiple
of 8. */
#define BR_ERR_X509_PARTIAL_BYTE 44
/** \brief X.509 status: decoding error: BOOLEAN value has invalid length. */
#define BR_ERR_X509_BAD_BOOLEAN 45
/** \brief X.509 status: decoding error: value is off-limits. */
#define BR_ERR_X509_OVERFLOW 46
/** \brief X.509 status: invalid distinguished name. */
#define BR_ERR_X509_BAD_DN 47
/** \brief X.509 status: invalid date/time representation. */
#define BR_ERR_X509_BAD_TIME 48
/** \brief X.509 status: certificate contains unsupported features that
cannot be ignored. */
#define BR_ERR_X509_UNSUPPORTED 49
/** \brief X.509 status: key or signature size exceeds internal limits. */
#define BR_ERR_X509_LIMIT_EXCEEDED 50
/** \brief X.509 status: key type does not match that which was expected. */
#define BR_ERR_X509_WRONG_KEY_TYPE 51
/** \brief X.509 status: signature is invalid. */
#define BR_ERR_X509_BAD_SIGNATURE 52
/** \brief X.509 status: validation time is unknown. */
#define BR_ERR_X509_TIME_UNKNOWN 53
/** \brief X.509 status: certificate is expired or not yet valid. */
#define BR_ERR_X509_EXPIRED 54
/** \brief X.509 status: issuer/subject DN mismatch in the chain. */
#define BR_ERR_X509_DN_MISMATCH 55
/** \brief X.509 status: expected server name was not found in the chain. */
#define BR_ERR_X509_BAD_SERVER_NAME 56
/** \brief X.509 status: unknown critical extension in certificate. */
#define BR_ERR_X509_CRITICAL_EXTENSION 57
/** \brief X.509 status: not a CA, or path length constraint violation */
#define BR_ERR_X509_NOT_CA 58
/** \brief X.509 status: Key Usage extension prohibits intended usage. */
#define BR_ERR_X509_FORBIDDEN_KEY_USAGE 59
/** \brief X.509 status: public key found in certificate is too small. */
#define BR_ERR_X509_WEAK_PUBLIC_KEY 60
/** \brief X.509 status: chain could not be linked to a trust anchor. */
#define BR_ERR_X509_NOT_TRUSTED 62
/**
* \brief Aggregate structure for public keys.
*/
typedef struct {
/** \brief Key type: `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC` */
unsigned char key_type;
/** \brief Actual public key. */
union {
/** \brief RSA public key. */
br_rsa_public_key rsa;
/** \brief EC public key. */
br_ec_public_key ec;
} key;
} br_x509_pkey;
/**
* \brief Distinguished Name (X.500) structure.
*
* The DN is DER-encoded.
*/
typedef struct {
/** \brief Encoded DN data. */
unsigned char *data;
/** \brief Encoded DN length (in bytes). */
size_t len;
} br_x500_name;
/**
* \brief Trust anchor structure.
*/
typedef struct {
/** \brief Encoded DN (X.500 name). */
br_x500_name dn;
/** \brief Anchor flags (e.g. `BR_X509_TA_CA`). */
unsigned flags;
/** \brief Anchor public key. */
br_x509_pkey pkey;
} br_x509_trust_anchor;
/**
* \brief Trust anchor flag: CA.
*
* A "CA" anchor is deemed fit to verify signatures on certificates.
* A "non-CA" anchor is accepted only for direct trust (server's
* certificate name and key match the anchor).
*/
#define BR_X509_TA_CA 0x0001
/*
* Key type: combination of a basic key type (low 4 bits) and some
* optional flags.
*
* For a public key, the basic key type only is set.
*
* For an expected key type, the flags indicate the intended purpose(s)
* for the key; the basic key type may be set to 0 to indicate that any
* key type compatible with the indicated purpose is acceptable.
*/
/** \brief Key type: algorithm is RSA. */
#define BR_KEYTYPE_RSA 1
/** \brief Key type: algorithm is EC. */
#define BR_KEYTYPE_EC 2
/**
* \brief Key type: usage is "key exchange".
*
* This value is combined (with bitwise OR) with the algorithm
* (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509
* validation engine that it should find a public key of that type,
* fit for key exchanges (e.g. `TLS_RSA_*` and `TLS_ECDH_*` cipher
* suites).
*/
#define BR_KEYTYPE_KEYX 0x10
/**
* \brief Key type: usage is "signature".
*
* This value is combined (with bitwise OR) with the algorithm
* (`BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`) when informing the X.509
* validation engine that it should find a public key of that type,
* fit for signatures (e.g. `TLS_ECDHE_*` cipher suites).
*/
#define BR_KEYTYPE_SIGN 0x20
/*
* start_chain Called when a new chain is started. If 'server_name'
* is not NULL and non-empty, then it is a name that
* should be looked for in the EE certificate (in the
* SAN extension as dNSName, or in the subjectDN's CN
* if there is no SAN extension).
* The caller ensures that the provided 'server_name'
* pointer remains valid throughout validation.
*
* start_cert Begins a new certificate in the chain. The provided
* length is in bytes; this is the total certificate length.
*
* append Get some additional bytes for the current certificate.
*
* end_cert Ends the current certificate.
*
* end_chain Called at the end of the chain. Returned value is
* 0 on success, or a non-zero error code.
*
* get_pkey Returns the EE certificate public key.
*
* For a complete chain, start_chain() and end_chain() are always
* called. For each certificate, start_cert(), some append() calls, then
* end_cert() are called, in that order. There may be no append() call
* at all if the certificate is empty (which is not valid but may happen
* if the peer sends exactly that).
*
* get_pkey() shall return a pointer to a structure that is valid as
* long as a new chain is not started. This may be a sub-structure
* within the context for the engine. This function MAY return a valid
* pointer to a public key even in some cases of validation failure,
* depending on the validation engine.
*/
/**
* \brief Class type for an X.509 engine.
*
* A certificate chain validation uses a caller-allocated context, which
* contains the running state for that validation. Methods are called
* in due order:
*
* - `start_chain()` is called at the start of the validation.
* - Certificates are processed one by one, in SSL order (end-entity
* comes first). For each certificate, the following methods are
* called:
*
* - `start_cert()` at the beginning of the certificate.
* - `append()` is called zero, one or more times, to provide
* the certificate (possibly in chunks).
* - `end_cert()` at the end of the certificate.
*
* - `end_chain()` is called when the last certificate in the chain
* was processed.
* - `get_pkey()` is called after chain processing, if the chain
* validation was successful.
*
* A context structure may be reused; the `start_chain()` method shall
* ensure (re)initialisation.
*/
typedef struct br_x509_class_ br_x509_class;
struct br_x509_class_ {
/**
* \brief X.509 context size, in bytes.
*/
size_t context_size;
/**
* \brief Start a new chain.
*
* This method shall set the vtable (first field) of the context
* structure.
*
* The `server_name`, if not `NULL`, will be considered as a
* fully qualified domain name, to be matched against the `dNSName`
* elements of the end-entity certificate's SAN extension (if there
* is no SAN, then the Common Name from the subjectDN will be used).
* If `server_name` is `NULL` then no such matching is performed.
*
* \param ctx validation context.
* \param server_name server name to match (or `NULL`).
*/
void (*start_chain)(const br_x509_class **ctx,
const char *server_name);
/**
* \brief Start a new certificate.
*
* \param ctx validation context.
* \param length new certificate length (in bytes).
*/
void (*start_cert)(const br_x509_class **ctx, uint32_t length);
/**
* \brief Receive some bytes for the current certificate.
*
* This function may be called several times in succession for
* a given certificate. The caller guarantees that for each
* call, `len` is not zero, and the sum of all chunk lengths
* for a certificate matches the total certificate length which
* was provided in the previous `start_cert()` call.
*
* If the new certificate is empty (no byte at all) then this
* function won't be called at all.
*
* \param ctx validation context.
* \param buf certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void (*append)(const br_x509_class **ctx,
const unsigned char *buf, size_t len);
/**
* \brief Finish the current certificate.
*
* This function is called when the end of the current certificate
* is reached.
*
* \param ctx validation context.
*/
void (*end_cert)(const br_x509_class **ctx);
/**
* \brief Finish the chain.
*
* This function is called at the end of the chain. It shall
* return either 0 if the validation was successful, or a
* non-zero error code. The `BR_ERR_X509_*` constants are
* error codes, though other values may be possible.
*
* \param ctx validation context.
* \return 0 on success, or a non-zero error code.
*/
unsigned (*end_chain)(const br_x509_class **ctx);
/**
* \brief Get the resulting end-entity public key.
*
* The decoded public key is returned. The returned pointer
* may be valid only as long as the context structure is
* unmodified, i.e. it may cease to be valid if the context
* is released or reused.
*
* This function _may_ return `NULL` if the validation failed.
* However, returning a public key does not mean that the
* validation was wholly successful; some engines may return
* a decoded public key even if the chain did not end on a
* trusted anchor.
*
* If validation succeeded and `usage` is not `NULL`, then
* `*usage` is filled with a combination of `BR_KEYTYPE_SIGN`
* and/or `BR_KEYTYPE_KEYX` that specifies the validated key
* usage types. It is the caller's responsibility to check
* that value against the intended use of the public key.
*
* \param ctx validation context.
* \return the end-entity public key, or `NULL`.
*/
const br_x509_pkey *(*get_pkey)(
const br_x509_class *const *ctx, unsigned *usages);
};
/**
* \brief The "known key" X.509 engine structure.
*
* The structure contents are opaque (they shall not be accessed directly),
* except for the first field (the vtable).
*
* The "known key" engine returns an externally configured public key,
* and totally ignores the certificate contents.
*/
typedef struct {
/** \brief Reference to the context vtable. */
const br_x509_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
br_x509_pkey pkey;
unsigned usages;
#endif
} br_x509_knownkey_context;
/**
* \brief Class instance for the "known key" X.509 engine.
*/
extern const br_x509_class br_x509_knownkey_vtable;
/**
* \brief Initialize a "known key" X.509 engine with a known RSA public key.
*
* The `usages` parameter indicates the allowed key usages for that key
* (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
*
* The provided pointers are linked in, not copied, so they must remain
* valid while the public key may be in usage.
*
* \param ctx context to initialise.
* \param pk known public key.
* \param usages allowed key usages.
*/
void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
const br_rsa_public_key *pk, unsigned usages);
/**
* \brief Initialize a "known key" X.509 engine with a known EC public key.
*
* The `usages` parameter indicates the allowed key usages for that key
* (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
*
* The provided pointers are linked in, not copied, so they must remain
* valid while the public key may be in usage.
*
* \param ctx context to initialise.
* \param pk known public key.
* \param usages allowed key usages.
*/
void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx,
const br_ec_public_key *pk, unsigned usages);
#ifndef BR_DOXYGEN_IGNORE
/*
* The minimal X.509 engine has some state buffers which must be large
* enough to simultaneously accommodate:
* -- the public key extracted from the current certificate;
* -- the signature on the current certificate or on the previous
* certificate;
* -- the public key extracted from the EE certificate.
*
* We store public key elements in their raw unsigned big-endian
* encoding. We want to support up to RSA-4096 with a short (up to 64
* bits) public exponent, thus a buffer for a public key must have
* length at least 520 bytes. Similarly, a RSA-4096 signature has length
* 512 bytes.
*
* Though RSA public exponents can formally be as large as the modulus
* (mathematically, even larger exponents would work, but PKCS#1 forbids
* them), exponents that do not fit on 32 bits are extremely rare,
* notably because some widespread implementations (e.g. Microsoft's
* CryptoAPI) don't support them. Moreover, large public exponent do not
* seem to imply any tangible security benefit, and they increase the
* cost of public key operations. The X.509 "minimal" engine will tolerate
* public exponents of arbitrary size as long as the modulus and the
* exponent can fit together in the dedicated buffer.
*
* EC public keys are shorter than RSA public keys; even with curve
* NIST P-521 (the largest curve we care to support), a public key is
* encoded over 133 bytes only.
*/
#define BR_X509_BUFSIZE_KEY 520
#define BR_X509_BUFSIZE_SIG 512
#endif
/**
* \brief Type for receiving a name element.
*
* An array of such structures can be provided to the X.509 decoding
* engines. If the specified elements are found in the certificate
* subject DN or the SAN extension, then the name contents are copied
* as zero-terminated strings into the buffer.
*
* The decoder converts TeletexString and BMPString to UTF8String, and
* ensures that the resulting string is zero-terminated. If the string
* does not fit in the provided buffer, then the copy is aborted and an
* error is reported.
*/
typedef struct {
/**
* \brief Element OID.
*
* For X.500 name elements (to be extracted from the subject DN),
* this is the encoded OID for the requested name element; the
* first byte shall contain the length of the DER-encoded OID
* value, followed by the OID value (for instance, OID 2.5.4.3,
* for id-at-commonName, will be `03 55 04 03`). This is
* equivalent to full DER encoding with the length but without
* the tag.
*
* For SAN name elements, the first byte (`oid[0]`) has value 0,
* followed by another byte that matches the expected GeneralName
* tag. Allowed second byte values are then:
*
* - 1: `rfc822Name`
*
* - 2: `dNSName`
*
* - 6: `uniformResourceIdentifier`
*
* - 0: `otherName`
*
* If first and second byte are 0, then this is a SAN element of
* type `otherName`; the `oid[]` array should then contain, right
* after the two bytes of value 0, an encoded OID (with the same
* conventions as for X.500 name elements). If a match is found
* for that OID, then the corresponding name element will be
* extracted, as long as it is a supported string type.
*/
const unsigned char *oid;
/**
* \brief Destination buffer.
*/
char *buf;
/**
* \brief Length (in bytes) of the destination buffer.
*
* The buffer MUST NOT be smaller than 1 byte.
*/
size_t len;
/**
* \brief Decoding status.
*
* Status is 0 if the name element was not found, 1 if it was
* found and decoded, or -1 on error. Error conditions include
* an unrecognised encoding, an invalid encoding, or a string
* too large for the destination buffer.
*/
int status;
} br_name_element;
/**
* \brief Callback for validity date checks.
*
* The function receives as parameter an arbitrary user-provided context,
* and the notBefore and notAfter dates specified in an X.509 certificate,
* both expressed as a number of days and a number of seconds:
*
* - Days are counted in a proleptic Gregorian calendar since
* January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD";
* it is also traditionally known as "1 BC".
*
* - Seconds are counted since midnight, from 0 to 86400 (a count of
* 86400 is possible only if a leap second happened).
*
* Each date and time is understood in the UTC time zone. The "Unix
* Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and
* seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is
* days=584754, seconds=0.
*
* This function must return -1 if the current date is strictly before
* the "notBefore" time, or +1 if the current date is strictly after the
* "notAfter" time. If neither condition holds, then the function returns
* 0, which means that the current date falls within the validity range of
* the certificate. If the function returns a value distinct from -1, 0
* and +1, then this is interpreted as an unavailability of the current
* time, which normally ends the validation process with a
* `BR_ERR_X509_TIME_UNKNOWN` error.
*
* During path validation, this callback will be invoked for each
* considered X.509 certificate. Validation fails if any of the calls
* returns a non-zero value.
*
* The context value is an abritrary pointer set by the caller when
* configuring this callback.
*
* \param tctx context pointer.
* \param not_before_days notBefore date (days since Jan 1st, 0 AD).
* \param not_before_seconds notBefore time (seconds, at most 86400).
* \param not_after_days notAfter date (days since Jan 1st, 0 AD).
* \param not_after_seconds notAfter time (seconds, at most 86400).
* \return -1, 0 or +1.
*/
typedef int (*br_x509_time_check)(void *tctx,
uint32_t not_before_days, uint32_t not_before_seconds,
uint32_t not_after_days, uint32_t not_after_seconds);
/**
* \brief The "minimal" X.509 engine structure.
*
* The structure contents are opaque (they shall not be accessed directly),
* except for the first field (the vtable).
*
* The "minimal" engine performs a rudimentary but serviceable X.509 path
* validation.
*/
typedef struct {
const br_x509_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the EE public key. */
br_x509_pkey pkey;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[31];
uint32_t rp_stack[31];
int err;
/* Server name to match with the SAN / CN of the EE certificate. */
const char *server_name;
/* Validated key usages. */
unsigned char key_usages;
/* Explicitly set date and time. */
uint32_t days, seconds;
/* Current certificate length (in bytes). Set to 0 when the
certificate has been fully processed. */
uint32_t cert_length;
/* Number of certificates processed so far in the current chain.
It is incremented at the end of the processing of a certificate,
so it is 0 for the EE. */
uint32_t num_certs;
/* Certificate data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Buffer for EE public key data. */
unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY];
/* Buffer for currently decoded public key. */
unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
/* Signature type: signer key type, offset to the hash
function OID (in the T0 data block) and hash function
output length (TBS hash length). */
unsigned char cert_signer_key_type;
uint16_t cert_sig_hash_oid;
unsigned char cert_sig_hash_len;
/* Current/last certificate signature. */
unsigned char cert_sig[BR_X509_BUFSIZE_SIG];
uint16_t cert_sig_len;
/* Minimum RSA key length (difference in bytes from 128). */
int16_t min_rsa_size;
/* Configured trust anchors. */
const br_x509_trust_anchor *trust_anchors;
size_t trust_anchors_num;
/*
* Multi-hasher for the TBS.
*/
unsigned char do_mhash;
br_multihash_context mhash;
unsigned char tbs_hash[64];
/*
* Simple hasher for the subject/issuer DN.
*/
unsigned char do_dn_hash;
const br_hash_class *dn_hash_impl;
br_hash_compat_context dn_hash;
unsigned char current_dn_hash[64];
unsigned char next_dn_hash[64];
unsigned char saved_dn_hash[64];
/*
* Name elements to gather.
*/
br_name_element *name_elts;
size_t num_name_elts;
/*
* Callback function (and context) to get the current date.
*/
void *itime_ctx;
br_x509_time_check itime;
/*
* Public key cryptography implementations (signature verification).
*/
br_rsa_pkcs1_vrfy irsa;
br_ecdsa_vrfy iecdsa;
const br_ec_impl *iec;
#endif
} br_x509_minimal_context;
/**
* \brief Class instance for the "minimal" X.509 engine.
*/
extern const br_x509_class br_x509_minimal_vtable;
/**
* \brief Initialise a "minimal" X.509 engine.
*
* The `dn_hash_impl` parameter shall be a hash function internally used
* to match X.500 names (subject/issuer DN, and anchor names). Any standard
* hash function may be used, but a collision-resistant hash function is
* advised.
*
* After initialization, some implementations for signature verification
* (hash functions and signature algorithms) MUST be added.
*
* \param ctx context to initialise.
* \param dn_hash_impl hash function for DN comparisons.
* \param trust_anchors trust anchors.
* \param trust_anchors_num number of trust anchors.
*/
void br_x509_minimal_init(br_x509_minimal_context *ctx,
const br_hash_class *dn_hash_impl,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
/**
* \brief Set a supported hash function in an X.509 "minimal" engine.
*
* Hash functions are used with signature verification algorithms.
* Once initialised (with `br_x509_minimal_init()`), the context must
* be configured with the hash functions it shall support for that
* purpose. The hash function identifier MUST be one of the standard
* hash function identifiers (1 to 6, for MD5, SHA-1, SHA-224, SHA-256,
* SHA-384 and SHA-512).
*
* If `impl` is `NULL`, this _removes_ support for the designated
* hash function.
*
* \param ctx validation context.
* \param id hash function identifier (from 1 to 6).
* \param impl hash function implementation (or `NULL`).
*/
static inline void
br_x509_minimal_set_hash(br_x509_minimal_context *ctx,
int id, const br_hash_class *impl)
{
br_multihash_setimpl(&ctx->mhash, id, impl);
}
/**
* \brief Set a RSA signature verification implementation in the X.509
* "minimal" engine.
*
* Once initialised (with `br_x509_minimal_init()`), the context must
* be configured with the signature verification implementations that
* it is supposed to support. If `irsa` is `0`, then the RSA support
* is disabled.
*
* \param ctx validation context.
* \param irsa RSA signature verification implementation (or `0`).
*/
static inline void
br_x509_minimal_set_rsa(br_x509_minimal_context *ctx,
br_rsa_pkcs1_vrfy irsa)
{
ctx->irsa = irsa;
}
/**
* \brief Set a ECDSA signature verification implementation in the X.509
* "minimal" engine.
*
* Once initialised (with `br_x509_minimal_init()`), the context must
* be configured with the signature verification implementations that
* it is supposed to support.
*
* If `iecdsa` is `0`, then this call disables ECDSA support; in that
* case, `iec` may be `NULL`. Otherwise, `iecdsa` MUST point to a function
* that verifies ECDSA signatures with format "asn1", and it will use
* `iec` as underlying elliptic curve support.
*
* \param ctx validation context.
* \param iec elliptic curve implementation (or `NULL`).
* \param iecdsa ECDSA implementation (or `0`).
*/
static inline void
br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx,
const br_ec_impl *iec, br_ecdsa_vrfy iecdsa)
{
ctx->iecdsa = iecdsa;
ctx->iec = iec;
}
/**
* \brief Initialise a "minimal" X.509 engine with default algorithms.
*
* This function performs the same job as `br_x509_minimal_init()`, but
* also sets implementations for RSA, ECDSA, and the standard hash
* functions.
*
* \param ctx context to initialise.
* \param trust_anchors trust anchors.
* \param trust_anchors_num number of trust anchors.
*/
void br_x509_minimal_init_full(br_x509_minimal_context *ctx,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
/**
* \brief Set the validation time for the X.509 "minimal" engine.
*
* The validation time is set as two 32-bit integers, for days and
* seconds since a fixed epoch:
*
* - Days are counted in a proleptic Gregorian calendar since
* January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD";
* it is also traditionally known as "1 BC".
*
* - Seconds are counted since midnight, from 0 to 86400 (a count of
* 86400 is possible only if a leap second happened).
*
* The validation date and time is understood in the UTC time zone. The
* "Unix Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528
* and seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is
* days=584754, seconds=0.
*
* If the validation date and time are not explicitly set, but BearSSL
* was compiled with support for the system clock on the underlying
* platform, then the current time will automatically be used. Otherwise,
* not setting the validation date and time implies a validation
* failure (except in case of direct trust of the EE key).
*
* \param ctx validation context.
* \param days days since January 1st, 0 AD (Gregorian calendar).
* \param seconds seconds since midnight (0 to 86400).
*/
static inline void
br_x509_minimal_set_time(br_x509_minimal_context *ctx,
uint32_t days, uint32_t seconds)
{
ctx->days = days;
ctx->seconds = seconds;
ctx->itime = 0;
}
/**
* \brief Set the validity range callback function for the X.509
* "minimal" engine.
*
* The provided function will be invoked to check whether the validation
* date is within the validity range for a given X.509 certificate; a
* call will be issued for each considered certificate. The provided
* context pointer (itime_ctx) will be passed as first parameter to the
* callback.
*
* \param tctx context for callback invocation.
* \param cb callback function.
*/
static inline void
br_x509_minimal_set_time_callback(br_x509_minimal_context *ctx,
void *itime_ctx, br_x509_time_check itime)
{
ctx->itime_ctx = itime_ctx;
ctx->itime = itime;
}
/**
* \brief Set the minimal acceptable length for RSA keys (X.509 "minimal"
* engine).
*
* The RSA key length is expressed in bytes. The default minimum key
* length is 128 bytes, corresponding to 1017 bits. RSA keys shorter
* than the configured length will be rejected, implying validation
* failure. This setting applies to keys extracted from certificates
* (both end-entity, and intermediate CA) but not to "CA" trust anchors.
*
* \param ctx validation context.
* \param byte_length minimum RSA key length, **in bytes** (not bits).
*/
static inline void
br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length)
{
ctx->min_rsa_size = (int16_t)(byte_length - 128);
}
/**
* \brief Set the name elements to gather.
*
* The provided array is linked in the context. The elements are
* gathered from the EE certificate. If the same element type is
* requested several times, then the relevant structures will be filled
* in the order the matching values are encountered in the certificate.
*
* \param ctx validation context.
* \param elts array of name element structures to fill.
* \param num_elts number of name element structures to fill.
*/
static inline void
br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx,
br_name_element *elts, size_t num_elts)
{
ctx->name_elts = elts;
ctx->num_name_elts = num_elts;
}
/**
* \brief X.509 decoder context.
*
* This structure is _not_ for X.509 validation, but for extracting
* names and public keys from encoded certificates. Intended usage is
* to use (self-signed) certificates as trust anchors.
*
* Contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the public key. */
br_x509_pkey pkey;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Flag set when decoding succeeds. */
unsigned char decoded;
/* Validity dates. */
uint32_t notbefore_days, notbefore_seconds;
uint32_t notafter_days, notafter_seconds;
/* The "CA" flag. This is set to true if the certificate contains
a Basic Constraints extension that asserts CA status. */
unsigned char isCA;
/* DN processing: the subject DN is extracted and pushed to the
provided callback. */
unsigned char copy_dn;
void *append_dn_ctx;
void (*append_dn)(void *ctx, const void *buf, size_t len);
/* Certificate data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* Buffer for decoded public key. */
unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
/* Type of key and hash function used in the certificate signature. */
unsigned char signer_key_type;
unsigned char signer_hash_id;
#endif
} br_x509_decoder_context;
/**
* \brief Initialise an X.509 decoder context for processing a new
* certificate.
*
* The `append_dn()` callback (with opaque context `append_dn_ctx`)
* will be invoked to receive, chunk by chunk, the certificate's
* subject DN. If `append_dn` is `0` then the subject DN will be
* ignored.
*
* \param ctx X.509 decoder context to initialise.
* \param append_dn DN receiver callback (or `0`).
* \param append_dn_ctx context for the DN receiver callback.
*/
void br_x509_decoder_init(br_x509_decoder_context *ctx,
void (*append_dn)(void *ctx, const void *buf, size_t len),
void *append_dn_ctx);
/**
* \brief Push some certificate bytes into a decoder context.
*
* If `len` is non-zero, then that many bytes are pushed, from address
* `data`, into the provided decoder context.
*
* \param ctx X.509 decoder context.
* \param data certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void br_x509_decoder_push(br_x509_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Obtain the decoded public key.
*
* Returned value is a pointer to a structure internal to the decoder
* context; releasing or reusing the decoder context invalidates that
* structure.
*
* If decoding was not finished, or failed, then `NULL` is returned.
*
* \param ctx X.509 decoder context.
* \return the public key, or `NULL` on unfinished/error.
*/
static inline br_x509_pkey *
br_x509_decoder_get_pkey(br_x509_decoder_context *ctx)
{
if (ctx->decoded && ctx->err == 0) {
return &ctx->pkey;
} else {
return NULL;
}
}
/**
* \brief Get decoder error status.
*
* If no error was reported yet but the certificate decoding is not
* finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding
* was successful, then 0 is returned.
*
* \param ctx X.509 decoder context.
* \return 0 on successful decoding, or a non-zero error code.
*/
static inline int
br_x509_decoder_last_error(br_x509_decoder_context *ctx)
{
if (ctx->err != 0) {
return ctx->err;
}
if (!ctx->decoded) {
return BR_ERR_X509_TRUNCATED;
}
return 0;
}
/**
* \brief Get the "isCA" flag from an X.509 decoder context.
*
* This flag is set if the decoded certificate claims to be a CA through
* a Basic Constraints extension. This flag should not be read before
* decoding completed successfully.
*
* \param ctx X.509 decoder context.
* \return the "isCA" flag.
*/
static inline int
br_x509_decoder_isCA(br_x509_decoder_context *ctx)
{
return ctx->isCA;
}
/**
* \brief Get the issuing CA key type (type of algorithm used to sign the
* decoded certificate).
*
* This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned
* if the signature type was not recognised.
*
* \param ctx X.509 decoder context.
* \return the issuing CA key type.
*/
static inline int
br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx)
{
return ctx->signer_key_type;
}
/**
* \brief Get the identifier for the hash function used to sign the decoded
* certificate.
*
* This is 0 if the hash function was not recognised.
*
* \param ctx X.509 decoder context.
* \return the signature hash function identifier.
*/
static inline int
br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx)
{
return ctx->signer_hash_id;
}
/**
* \brief Type for an X.509 certificate (DER-encoded).
*/
typedef struct {
/** \brief The DER-encoded certificate data. */
unsigned char *data;
/** \brief The DER-encoded certificate length (in bytes). */
size_t data_len;
} br_x509_certificate;
/**
* \brief Private key decoder context.
*
* The private key decoder recognises RSA and EC private keys, either in
* their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8
* archive (again DER-encoded).
*
* Structure contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the private key. */
union {
br_rsa_private_key rsa;
br_ec_private_key ec;
} key;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
/* Private key data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Decoded key type; 0 until decoding is complete. */
unsigned char key_type;
/* Buffer for the private key elements. It shall be large enough
to accommodate all elements for a RSA-4096 private key (roughly
five 2048-bit integers, possibly a bit more). */
unsigned char key_data[3 * BR_X509_BUFSIZE_SIG];
#endif
} br_skey_decoder_context;
/**
* \brief Initialise a private key decoder context.
*
* \param ctx key decoder context to initialise.
*/
void br_skey_decoder_init(br_skey_decoder_context *ctx);
/**
* \brief Push some data bytes into a private key decoder context.
*
* If `len` is non-zero, then that many data bytes, starting at address
* `data`, are pushed into the decoder.
*
* \param ctx key decoder context.
* \param data private key data chunk.
* \param len private key data chunk length (in bytes).
*/
void br_skey_decoder_push(br_skey_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Get the decoding status for a private key.
*
* Decoding status is 0 on success, or a non-zero error code. If the
* decoding is unfinished when this function is called, then the
* status code `BR_ERR_X509_TRUNCATED` is returned.
*
* \param ctx key decoder context.
* \return 0 on successful decoding, or a non-zero error code.
*/
static inline int
br_skey_decoder_last_error(const br_skey_decoder_context *ctx)
{
if (ctx->err != 0) {
return ctx->err;
}
if (ctx->key_type == 0) {
return BR_ERR_X509_TRUNCATED;
}
return 0;
}
/**
* \brief Get the decoded private key type.
*
* Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is
* not finished or failed, then 0 is returned.
*
* \param ctx key decoder context.
* \return decoded private key type, or 0.
*/
static inline int
br_skey_decoder_key_type(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0) {
return ctx->key_type;
} else {
return 0;
}
}
/**
* \brief Get the decoded RSA private key.
*
* This function returns `NULL` if the decoding failed, or is not
* finished, or the key is not RSA. The returned pointer references
* structures within the context that can become invalid if the context
* is reused or released.
*
* \param ctx key decoder context.
* \return decoded RSA private key, or `NULL`.
*/
static inline const br_rsa_private_key *
br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) {
return &ctx->key.rsa;
} else {
return NULL;
}
}
/**
* \brief Get the decoded EC private key.
*
* This function returns `NULL` if the decoding failed, or is not
* finished, or the key is not EC. The returned pointer references
* structures within the context that can become invalid if the context
* is reused or released.
*
* \param ctx key decoder context.
* \return decoded EC private key, or `NULL`.
*/
static inline const br_ec_private_key *
br_skey_decoder_get_ec(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) {
return &ctx->key.ec;
} else {
return NULL;
}
}
/**
* \brief Encode an RSA private key (raw DER format).
*
* This function encodes the provided key into the "raw" format specified
* in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER
* encoding rules.
*
* The key elements are:
*
* - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`)
*
* - `pk`: the public key (`n` and `e`)
*
* - `d` (size: `dlen` bytes): the private exponent
*
* The public key elements, and the private exponent `d`, can be
* recomputed from the private key (see `br_rsa_compute_modulus()`,
* `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the RSA private key.
* \param pk the RSA public key.
* \param d the RSA private exponent.
* \param dlen the RSA private exponent length (in bytes).
* \return the encoded key length (in bytes).
*/
size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk,
const br_rsa_public_key *pk, const void *d, size_t dlen);
/**
* \brief Encode an RSA private key (PKCS#8 DER format).
*
* This function encodes the provided key into the PKCS#8 format
* (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER"
* format for the RSA key, as implemented by `br_encode_rsa_raw_der()`.
*
* The key elements are:
*
* - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`)
*
* - `pk`: the public key (`n` and `e`)
*
* - `d` (size: `dlen` bytes): the private exponent
*
* The public key elements, and the private exponent `d`, can be
* recomputed from the private key (see `br_rsa_compute_modulus()`,
* `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the RSA private key.
* \param pk the RSA public key.
* \param d the RSA private exponent.
* \param dlen the RSA private exponent length (in bytes).
* \return the encoded key length (in bytes).
*/
size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk,
const br_rsa_public_key *pk, const void *d, size_t dlen);
/**
* \brief Encode an EC private key (raw DER format).
*
* This function encodes the provided key into the "raw" format specified
* in RFC 5915 (type `ECPrivateKey`), with DER encoding rules.
*
* The private key is provided in `sk`, the public key being `pk`. If
* `pk` is `NULL`, then the encoded key will not include the public key
* in its `publicKey` field (which is nominally optional).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* If the key cannot be encoded (e.g. because there is no known OBJECT
* IDENTIFIER for the used curve), then 0 is returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the EC private key.
* \param pk the EC public key (or `NULL`).
* \return the encoded key length (in bytes), or 0.
*/
size_t br_encode_ec_raw_der(void *dest,
const br_ec_private_key *sk, const br_ec_public_key *pk);
/**
* \brief Encode an EC private key (PKCS#8 DER format).
*
* This function encodes the provided key into the PKCS#8 format
* (RFC 5958, type `OneAsymmetricKey`). The curve is identified
* by an OID provided as parameters to the `privateKeyAlgorithm`
* field. The private key value (contents of the `privateKey` field)
* contains the DER encoding of the `ECPrivateKey` type defined in
* RFC 5915, without the `parameters` field (since they would be
* redundant with the information in `privateKeyAlgorithm`).
*
* The private key is provided in `sk`, the public key being `pk`. If
* `pk` is not `NULL`, then the encoded public key is included in the
* `publicKey` field of the private key value (but not in the `publicKey`
* field of the PKCS#8 `OneAsymmetricKey` wrapper).
*
* If `dest` is not `NULL`, then the encoded key is written at that
* address, and the encoded length (in bytes) is returned. If `dest` is
* `NULL`, then nothing is written, but the encoded length is still
* computed and returned.
*
* If the key cannot be encoded (e.g. because there is no known OBJECT
* IDENTIFIER for the used curve), then 0 is returned.
*
* \param dest the destination buffer (or `NULL`).
* \param sk the EC private key.
* \param pk the EC public key (or `NULL`).
* \return the encoded key length (in bytes), or 0.
*/
size_t br_encode_ec_pkcs8_der(void *dest,
const br_ec_private_key *sk, const br_ec_public_key *pk);
/**
* \brief PEM banner for RSA private key (raw).
*/
#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY"
/**
* \brief PEM banner for EC private key (raw).
*/
#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY"
/**
* \brief PEM banner for an RSA or EC private key in PKCS#8 format.
*/
#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY"
#ifdef __cplusplus
}
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_ssl.h
*
* # SSL
*
* For an overview of the SSL/TLS API, see [the BearSSL Web
* site](https://www.bearssl.org/api1.html).
*
* The `BR_TLS_*` constants correspond to the standard cipher suites and
* their values in the [IANA
* registry](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4).
*
* The `BR_ALERT_*` constants are for standard TLS alert messages. When
* a fatal alert message is sent of received, then the SSL engine context
* status is set to the sum of that alert value (an integer in the 0..255
* range) and a fixed offset (`BR_ERR_SEND_FATAL_ALERT` for a sent alert,
* `BR_ERR_RECV_FATAL_ALERT` for a received alert).
*/
/** \brief Optimal input buffer size. */
#define BR_SSL_BUFSIZE_INPUT (16384 + 325)
/** \brief Optimal output buffer size. */
#define BR_SSL_BUFSIZE_OUTPUT (16384 + 85)
/** \brief Optimal buffer size for monodirectional engine
(shared input/output buffer). */
#define BR_SSL_BUFSIZE_MONO BR_SSL_BUFSIZE_INPUT
/** \brief Optimal buffer size for bidirectional engine
(single buffer split into two separate input/output buffers). */
#define BR_SSL_BUFSIZE_BIDI (BR_SSL_BUFSIZE_INPUT + BR_SSL_BUFSIZE_OUTPUT)
/*
* Constants for known SSL/TLS protocol versions (SSL 3.0, TLS 1.0, TLS 1.1
* and TLS 1.2). Note that though there is a constant for SSL 3.0, that
* protocol version is not actually supported.
*/
/** \brief Protocol version: SSL 3.0 (unsupported). */
#define BR_SSL30 0x0300
/** \brief Protocol version: TLS 1.0. */
#define BR_TLS10 0x0301
/** \brief Protocol version: TLS 1.1. */
#define BR_TLS11 0x0302
/** \brief Protocol version: TLS 1.2. */
#define BR_TLS12 0x0303
/*
* Error constants. They are used to report the reason why a context has
* been marked as failed.
*
* Implementation note: SSL-level error codes should be in the 1..31
* range. The 32..63 range is for certificate decoding and validation
* errors. Received fatal alerts imply an error code in the 256..511 range.
*/
/** \brief SSL status: no error so far (0). */
#define BR_ERR_OK 0
/** \brief SSL status: caller-provided parameter is incorrect. */
#define BR_ERR_BAD_PARAM 1
/** \brief SSL status: operation requested by the caller cannot be applied
with the current context state (e.g. reading data while outgoing data
is waiting to be sent). */
#define BR_ERR_BAD_STATE 2
/** \brief SSL status: incoming protocol or record version is unsupported. */
#define BR_ERR_UNSUPPORTED_VERSION 3
/** \brief SSL status: incoming record version does not match the expected
version. */
#define BR_ERR_BAD_VERSION 4
/** \brief SSL status: incoming record length is invalid. */
#define BR_ERR_BAD_LENGTH 5
/** \brief SSL status: incoming record is too large to be processed, or
buffer is too small for the handshake message to send. */
#define BR_ERR_TOO_LARGE 6
/** \brief SSL status: decryption found an invalid padding, or the record
MAC is not correct. */
#define BR_ERR_BAD_MAC 7
/** \brief SSL status: no initial entropy was provided, and none can be
obtained from the OS. */
#define BR_ERR_NO_RANDOM 8
/** \brief SSL status: incoming record type is unknown. */
#define BR_ERR_UNKNOWN_TYPE 9
/** \brief SSL status: incoming record or message has wrong type with
regards to the current engine state. */
#define BR_ERR_UNEXPECTED 10
/** \brief SSL status: ChangeCipherSpec message from the peer has invalid
contents. */
#define BR_ERR_BAD_CCS 12
/** \brief SSL status: alert message from the peer has invalid contents
(odd length). */
#define BR_ERR_BAD_ALERT 13
/** \brief SSL status: incoming handshake message decoding failed. */
#define BR_ERR_BAD_HANDSHAKE 14
/** \brief SSL status: ServerHello contains a session ID which is larger
than 32 bytes. */
#define BR_ERR_OVERSIZED_ID 15
/** \brief SSL status: server wants to use a cipher suite that we did
not claim to support. This is also reported if we tried to advertise
a cipher suite that we do not support. */
#define BR_ERR_BAD_CIPHER_SUITE 16
/** \brief SSL status: server wants to use a compression that we did not
claim to support. */
#define BR_ERR_BAD_COMPRESSION 17
/** \brief SSL status: server's max fragment length does not match
client's. */
#define BR_ERR_BAD_FRAGLEN 18
/** \brief SSL status: secure renegotiation failed. */
#define BR_ERR_BAD_SECRENEG 19
/** \brief SSL status: server sent an extension type that we did not
announce, or used the same extension type several times in a single
ServerHello. */
#define BR_ERR_EXTRA_EXTENSION 20
/** \brief SSL status: invalid Server Name Indication contents (when
used by the server, this extension shall be empty). */
#define BR_ERR_BAD_SNI 21
/** \brief SSL status: invalid ServerHelloDone from the server (length
is not 0). */
#define BR_ERR_BAD_HELLO_DONE 22
/** \brief SSL status: internal limit exceeded (e.g. server's public key
is too large). */
#define BR_ERR_LIMIT_EXCEEDED 23
/** \brief SSL status: Finished message from peer does not match the
expected value. */
#define BR_ERR_BAD_FINISHED 24
/** \brief SSL status: session resumption attempt with distinct version
or cipher suite. */
#define BR_ERR_RESUME_MISMATCH 25
/** \brief SSL status: unsupported or invalid algorithm (ECDHE curve,
signature algorithm, hash function). */
#define BR_ERR_INVALID_ALGORITHM 26
/** \brief SSL status: invalid signature (on ServerKeyExchange from
server, or in CertificateVerify from client). */
#define BR_ERR_BAD_SIGNATURE 27
/** \brief SSL status: peer's public key does not have the proper type
or is not allowed for requested operation. */
#define BR_ERR_WRONG_KEY_USAGE 28
/** \brief SSL status: client did not send a certificate upon request,
or the client certificate could not be validated. */
#define BR_ERR_NO_CLIENT_AUTH 29
/** \brief SSL status: I/O error or premature close on underlying
transport stream. This error code is set only by the simplified
I/O API ("br_sslio_*"). */
#define BR_ERR_IO 31
/** \brief SSL status: base value for a received fatal alert.
When a fatal alert is received from the peer, the alert value
is added to this constant. */
#define BR_ERR_RECV_FATAL_ALERT 256
/** \brief SSL status: base value for a sent fatal alert.
When a fatal alert is sent to the peer, the alert value is added
to this constant. */
#define BR_ERR_SEND_FATAL_ALERT 512
/* ===================================================================== */
/**
* \brief Decryption engine for SSL.
*
* When processing incoming records, the SSL engine will use a decryption
* engine that uses a specific context structure, and has a set of
* methods (a vtable) that follows this template.
*
* The decryption engine is responsible for applying decryption, verifying
* MAC, and keeping track of the record sequence number.
*/
typedef struct br_sslrec_in_class_ br_sslrec_in_class;
struct br_sslrec_in_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Test validity of the incoming record length.
*
* This function returns 1 if the announced length for an
* incoming record is valid, 0 otherwise,
*
* \param ctx decryption engine context.
* \param record_len incoming record length.
* \return 1 of a valid length, 0 otherwise.
*/
int (*check_length)(const br_sslrec_in_class *const *ctx,
size_t record_len);
/**
* \brief Decrypt the incoming record.
*
* This function may assume that the record length is valid
* (it has been previously tested with `check_length()`).
* Decryption is done in place; `*len` is updated with the
* cleartext length, and the address of the first plaintext
* byte is returned. If the record is correct but empty, then
* `*len` is set to 0 and a non-`NULL` pointer is returned.
*
* On decryption/MAC error, `NULL` is returned.
*
* \param ctx decryption engine context.
* \param record_type record type (23 for application data, etc).
* \param version record version.
* \param payload address of encrypted payload.
* \param len pointer to payload length (updated).
* \return pointer to plaintext, or `NULL` on error.
*/
unsigned char *(*decrypt)(const br_sslrec_in_class **ctx,
int record_type, unsigned version,
void *payload, size_t *len);
};
/**
* \brief Encryption engine for SSL.
*
* When building outgoing records, the SSL engine will use an encryption
* engine that uses a specific context structure, and has a set of
* methods (a vtable) that follows this template.
*
* The encryption engine is responsible for applying encryption and MAC,
* and keeping track of the record sequence number.
*/
typedef struct br_sslrec_out_class_ br_sslrec_out_class;
struct br_sslrec_out_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Compute maximum plaintext sizes and offsets.
*
* When this function is called, the `*start` and `*end`
* values contain offsets designating the free area in the
* outgoing buffer for plaintext data; that free area is
* preceded by a 5-byte space which will receive the record
* header.
*
* The `max_plaintext()` function is responsible for adjusting
* both `*start` and `*end` to make room for any record-specific
* header, MAC, padding, and possible split.
*
* \param ctx encryption engine context.
* \param start pointer to start of plaintext offset (updated).
* \param end pointer to start of plaintext offset (updated).
*/
void (*max_plaintext)(const br_sslrec_out_class *const *ctx,
size_t *start, size_t *end);
/**
* \brief Perform record encryption.
*
* This function encrypts the record. The plaintext address and
* length are provided. Returned value is the start of the
* encrypted record (or sequence of records, if a split was
* performed), _including_ the 5-byte header, and `*len` is
* adjusted to the total size of the record(s), there again
* including the header(s).
*
* \param ctx decryption engine context.
* \param record_type record type (23 for application data, etc).
* \param version record version.
* \param plaintext address of plaintext.
* \param len pointer to plaintext length (updated).
* \return pointer to start of built record.
*/
unsigned char *(*encrypt)(const br_sslrec_out_class **ctx,
int record_type, unsigned version,
void *plaintext, size_t *len);
};
/**
* \brief Context for a no-encryption engine.
*
* The no-encryption engine processes outgoing records during the initial
* handshake, before encryption is applied.
*/
typedef struct {
/** \brief No-encryption engine vtable. */
const br_sslrec_out_class *vtable;
} br_sslrec_out_clear_context;
/** \brief Static, constant vtable for the no-encryption engine. */
extern const br_sslrec_out_class br_sslrec_out_clear_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for CBC mode.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for CBC processing: block cipher implementation, block cipher key,
* HMAC parameters (hash function, key, MAC length), and IV. If the
* IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
*/
typedef struct br_sslrec_in_cbc_class_ br_sslrec_in_cbc_class;
struct br_sslrec_in_cbc_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CBC decryption).
* \param bc_key block cipher key.
* \param bc_key_len block cipher key length (in bytes).
* \param dig_impl hash function for HMAC.
* \param mac_key HMAC key.
* \param mac_key_len HMAC key length (in bytes).
* \param mac_out_len HMAC output length (in bytes).
* \param iv initial IV (or `NULL`).
*/
void (*init)(const br_sslrec_in_cbc_class **ctx,
const br_block_cbcdec_class *bc_impl,
const void *bc_key, size_t bc_key_len,
const br_hash_class *dig_impl,
const void *mac_key, size_t mac_key_len, size_t mac_out_len,
const void *iv);
};
/**
* \brief Record encryption engine class, for CBC mode.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for CBC processing: block cipher implementation, block cipher key,
* HMAC parameters (hash function, key, MAC length), and IV. If the
* IV is `NULL`, then a per-record IV will be used (TLS 1.1+).
*/
typedef struct br_sslrec_out_cbc_class_ br_sslrec_out_cbc_class;
struct br_sslrec_out_cbc_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CBC encryption).
* \param bc_key block cipher key.
* \param bc_key_len block cipher key length (in bytes).
* \param dig_impl hash function for HMAC.
* \param mac_key HMAC key.
* \param mac_key_len HMAC key length (in bytes).
* \param mac_out_len HMAC output length (in bytes).
* \param iv initial IV (or `NULL`).
*/
void (*init)(const br_sslrec_out_cbc_class **ctx,
const br_block_cbcenc_class *bc_impl,
const void *bc_key, size_t bc_key_len,
const br_hash_class *dig_impl,
const void *mac_key, size_t mac_key_len, size_t mac_out_len,
const void *iv);
};
/**
* \brief Context structure for decrypting incoming records with
* CBC + HMAC.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_sslrec_in_cbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_cbcdec_class *vtable;
br_aes_gen_cbcdec_keys aes;
br_des_gen_cbcdec_keys des;
} bc;
br_hmac_key_context mac;
size_t mac_len;
unsigned char iv[16];
int explicit_IV;
#endif
} br_sslrec_in_cbc_context;
/**
* \brief Static, constant vtable for record decryption with CBC.
*/
extern const br_sslrec_in_cbc_class br_sslrec_in_cbc_vtable;
/**
* \brief Context structure for encrypting outgoing records with
* CBC + HMAC.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_sslrec_out_cbc_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_cbcenc_class *vtable;
br_aes_gen_cbcenc_keys aes;
br_des_gen_cbcenc_keys des;
} bc;
br_hmac_key_context mac;
size_t mac_len;
unsigned char iv[16];
int explicit_IV;
#endif
} br_sslrec_out_cbc_context;
/**
* \brief Static, constant vtable for record encryption with CBC.
*/
extern const br_sslrec_out_cbc_class br_sslrec_out_cbc_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for GCM mode.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for GCM processing: block cipher implementation, block cipher key,
* GHASH implementation, and 4-byte IV.
*/
typedef struct br_sslrec_in_gcm_class_ br_sslrec_in_gcm_class;
struct br_sslrec_in_gcm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param gh_impl GHASH implementation.
* \param iv static IV (4 bytes).
*/
void (*init)(const br_sslrec_in_gcm_class **ctx,
const br_block_ctr_class *bc_impl,
const void *key, size_t key_len,
br_ghash gh_impl,
const void *iv);
};
/**
* \brief Record encryption engine class, for GCM mode.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for GCM processing: block cipher implementation, block cipher key,
* GHASH implementation, and 4-byte IV.
*/
typedef struct br_sslrec_out_gcm_class_ br_sslrec_out_gcm_class;
struct br_sslrec_out_gcm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param gh_impl GHASH implementation.
* \param iv static IV (4 bytes).
*/
void (*init)(const br_sslrec_out_gcm_class **ctx,
const br_block_ctr_class *bc_impl,
const void *key, size_t key_len,
br_ghash gh_impl,
const void *iv);
};
/**
* \brief Context structure for processing records with GCM.
*
* The same context structure is used for encrypting and decrypting.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
union {
const void *gen;
const br_sslrec_in_gcm_class *in;
const br_sslrec_out_gcm_class *out;
} vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_ctr_class *vtable;
br_aes_gen_ctr_keys aes;
} bc;
br_ghash gh;
unsigned char iv[4];
unsigned char h[16];
#endif
} br_sslrec_gcm_context;
/**
* \brief Static, constant vtable for record decryption with GCM.
*/
extern const br_sslrec_in_gcm_class br_sslrec_in_gcm_vtable;
/**
* \brief Static, constant vtable for record encryption with GCM.
*/
extern const br_sslrec_out_gcm_class br_sslrec_out_gcm_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for ChaCha20+Poly1305.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for ChaCha20+Poly1305 processing: ChaCha20 implementation,
* Poly1305 implementation, key, and 12-byte IV.
*/
typedef struct br_sslrec_in_chapol_class_ br_sslrec_in_chapol_class;
struct br_sslrec_in_chapol_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param ichacha ChaCha20 implementation.
* \param ipoly Poly1305 implementation.
* \param key secret key (32 bytes).
* \param iv static IV (12 bytes).
*/
void (*init)(const br_sslrec_in_chapol_class **ctx,
br_chacha20_run ichacha,
br_poly1305_run ipoly,
const void *key, const void *iv);
};
/**
* \brief Record encryption engine class, for ChaCha20+Poly1305.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for ChaCha20+Poly1305 processing: ChaCha20 implementation,
* Poly1305 implementation, key, and 12-byte IV.
*/
typedef struct br_sslrec_out_chapol_class_ br_sslrec_out_chapol_class;
struct br_sslrec_out_chapol_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param ichacha ChaCha20 implementation.
* \param ipoly Poly1305 implementation.
* \param key secret key (32 bytes).
* \param iv static IV (12 bytes).
*/
void (*init)(const br_sslrec_out_chapol_class **ctx,
br_chacha20_run ichacha,
br_poly1305_run ipoly,
const void *key, const void *iv);
};
/**
* \brief Context structure for processing records with ChaCha20+Poly1305.
*
* The same context structure is used for encrypting and decrypting.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
union {
const void *gen;
const br_sslrec_in_chapol_class *in;
const br_sslrec_out_chapol_class *out;
} vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
unsigned char key[32];
unsigned char iv[12];
br_chacha20_run ichacha;
br_poly1305_run ipoly;
#endif
} br_sslrec_chapol_context;
/**
* \brief Static, constant vtable for record decryption with ChaCha20+Poly1305.
*/
extern const br_sslrec_in_chapol_class br_sslrec_in_chapol_vtable;
/**
* \brief Static, constant vtable for record encryption with ChaCha20+Poly1305.
*/
extern const br_sslrec_out_chapol_class br_sslrec_out_chapol_vtable;
/* ===================================================================== */
/**
* \brief Record decryption engine class, for CCM mode.
*
* This class type extends the decryption engine class with an
* initialisation method that receives the parameters needed
* for CCM processing: block cipher implementation, block cipher key,
* and 4-byte IV.
*/
typedef struct br_sslrec_in_ccm_class_ br_sslrec_in_ccm_class;
struct br_sslrec_in_ccm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_in_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR+CBC).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param iv static IV (4 bytes).
* \param tag_len tag length (in bytes)
*/
void (*init)(const br_sslrec_in_ccm_class **ctx,
const br_block_ctrcbc_class *bc_impl,
const void *key, size_t key_len,
const void *iv, size_t tag_len);
};
/**
* \brief Record encryption engine class, for CCM mode.
*
* This class type extends the encryption engine class with an
* initialisation method that receives the parameters needed
* for CCM processing: block cipher implementation, block cipher key,
* and 4-byte IV.
*/
typedef struct br_sslrec_out_ccm_class_ br_sslrec_out_ccm_class;
struct br_sslrec_out_ccm_class_ {
/**
* \brief Superclass, as first vtable field.
*/
br_sslrec_out_class inner;
/**
* \brief Engine initialisation method.
*
* This method sets the vtable field in the context.
*
* \param ctx context to initialise.
* \param bc_impl block cipher implementation (CTR+CBC).
* \param key block cipher key.
* \param key_len block cipher key length (in bytes).
* \param iv static IV (4 bytes).
* \param tag_len tag length (in bytes)
*/
void (*init)(const br_sslrec_out_ccm_class **ctx,
const br_block_ctrcbc_class *bc_impl,
const void *key, size_t key_len,
const void *iv, size_t tag_len);
};
/**
* \brief Context structure for processing records with CCM.
*
* The same context structure is used for encrypting and decrypting.
*
* The first field points to the vtable. The other fields are opaque
* and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
union {
const void *gen;
const br_sslrec_in_ccm_class *in;
const br_sslrec_out_ccm_class *out;
} vtable;
#ifndef BR_DOXYGEN_IGNORE
uint64_t seq;
union {
const br_block_ctrcbc_class *vtable;
br_aes_gen_ctrcbc_keys aes;
} bc;
unsigned char iv[4];
size_t tag_len;
#endif
} br_sslrec_ccm_context;
/**
* \brief Static, constant vtable for record decryption with CCM.
*/
extern const br_sslrec_in_ccm_class br_sslrec_in_ccm_vtable;
/**
* \brief Static, constant vtable for record encryption with CCM.
*/
extern const br_sslrec_out_ccm_class br_sslrec_out_ccm_vtable;
/* ===================================================================== */
/**
* \brief Type for session parameters, to be saved for session resumption.
*/
typedef struct {
/** \brief Session ID buffer. */
unsigned char session_id[32];
/** \brief Session ID length (in bytes, at most 32). */
unsigned char session_id_len;
/** \brief Protocol version. */
uint16_t version;
/** \brief Cipher suite. */
uint16_t cipher_suite;
/** \brief Master secret. */
unsigned char master_secret[48];
} br_ssl_session_parameters;
#ifndef BR_DOXYGEN_IGNORE
/*
* Maximum number of cipher suites supported by a client or server.
*/
#define BR_MAX_CIPHER_SUITES 48
#endif
/**
* \brief Context structure for SSL engine.
*
* This strucuture is common to the client and server; both the client
* context (`br_ssl_client_context`) and the server context
* (`br_ssl_server_context`) include a `br_ssl_engine_context` as their
* first field.
*
* The engine context manages records, including alerts, closures, and
* transitions to new encryption/MAC algorithms. Processing of handshake
* records is delegated to externally provided code. This structure
* should not be used directly.
*
* Structure contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/*
* The error code. When non-zero, then the state is "failed" and
* no I/O may occur until reset.
*/
int err;
/*
* Configured I/O buffers. They are either disjoint, or identical.
*/
unsigned char *ibuf, *obuf;
size_t ibuf_len, obuf_len;
/*
* Maximum fragment length applies to outgoing records; incoming
* records can be processed as long as they fit in the input
* buffer. It is guaranteed that incoming records at least as big
* as max_frag_len can be processed.
*/
uint16_t max_frag_len;
unsigned char log_max_frag_len;
unsigned char peer_log_max_frag_len;
/*
* Buffering management registers.
*/
size_t ixa, ixb, ixc;
size_t oxa, oxb, oxc;
unsigned char iomode;
unsigned char incrypt;
/*
* Shutdown flag: when set to non-zero, incoming record bytes
* will not be accepted anymore. This is used after a close_notify
* has been received: afterwards, the engine no longer claims that
* it could receive bytes from the transport medium.
*/
unsigned char shutdown_recv;
/*
* 'record_type_in' is set to the incoming record type when the
* record header has been received.
* 'record_type_out' is used to make the next outgoing record
* header when it is ready to go.
*/
unsigned char record_type_in, record_type_out;
/*
* When a record is received, its version is extracted:
* -- if 'version_in' is 0, then it is set to the received version;
* -- otherwise, if the received version is not identical to
* the 'version_in' contents, then a failure is reported.
*
* This implements the SSL requirement that all records shall
* use the negotiated protocol version, once decided (in the
* ServerHello). It is up to the handshake handler to adjust this
* field when necessary.
*/
uint16_t version_in;
/*
* 'version_out' is used when the next outgoing record is ready
* to go.
*/
uint16_t version_out;
/*
* Record handler contexts.
*/
union {
const br_sslrec_in_class *vtable;
br_sslrec_in_cbc_context cbc;
br_sslrec_gcm_context gcm;
br_sslrec_chapol_context chapol;
br_sslrec_ccm_context ccm;
} in;
union {
const br_sslrec_out_class *vtable;
br_sslrec_out_clear_context clear;
br_sslrec_out_cbc_context cbc;
br_sslrec_gcm_context gcm;
br_sslrec_chapol_context chapol;
br_sslrec_ccm_context ccm;
} out;
/*
* The "application data" flag. Value:
* 0 handshake is in process, no application data acceptable
* 1 application data can be sent and received
* 2 closing, no application data can be sent, but some
* can still be received (and discarded)
*/
unsigned char application_data;
/*
* Context RNG.
*
* rng_init_done is initially 0. It is set to 1 when the
* basic structure of the RNG is set, and 2 when some
* entropy has been pushed in. The value 2 marks the RNG
* as "properly seeded".
*
* rng_os_rand_done is initially 0. It is set to 1 when
* some seeding from the OS or hardware has been attempted.
*/
br_hmac_drbg_context rng;
int rng_init_done;
int rng_os_rand_done;
/*
* Supported minimum and maximum versions, and cipher suites.
*/
uint16_t version_min;
uint16_t version_max;
uint16_t suites_buf[BR_MAX_CIPHER_SUITES];
unsigned char suites_num;
/*
* For clients, the server name to send as a SNI extension. For
* servers, the name received in the SNI extension (if any).
*/
char server_name[256];
/*
* "Security parameters". These are filled by the handshake
* handler, and used when switching encryption state.
*/
unsigned char client_random[32];
unsigned char server_random[32];
br_ssl_session_parameters session;
/*
* ECDHE elements: curve and point from the peer. The server also
* uses that buffer for the point to send to the client.
*/
unsigned char ecdhe_curve;
unsigned char ecdhe_point[133];
unsigned char ecdhe_point_len;
/*
* Secure renegotiation (RFC 5746): 'reneg' can be:
* 0 first handshake (server support is not known)
* 1 peer does not support secure renegotiation
* 2 peer supports secure renegotiation
*
* The saved_finished buffer contains the client and the
* server "Finished" values from the last handshake, in
* that order (12 bytes each).
*/
unsigned char reneg;
unsigned char saved_finished[24];
/*
* Behavioural flags.
*/
uint32_t flags;
/*
* Context variables for the handshake processor. The 'pad' must
* be large enough to accommodate an RSA-encrypted pre-master
* secret, or an RSA signature; since we want to support up to
* RSA-4096, this means at least 512 bytes. (Other pad usages
* require its length to be at least 256.)
*/
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
unsigned char pad[512];
unsigned char *hbuf_in, *hbuf_out, *saved_hbuf_out;
size_t hlen_in, hlen_out;
void (*hsrun)(void *ctx);
/*
* The 'action' value communicates OOB information between the
* engine and the handshake processor.
*
* From the engine:
* 0 invocation triggered by I/O
* 1 invocation triggered by explicit close
* 2 invocation triggered by explicit renegotiation
*/
unsigned char action;
/*
* State for alert messages. Value is either 0, or the value of
* the alert level byte (level is either 1 for warning, or 2 for
* fatal; we convert all other values to 'fatal').
*/
unsigned char alert;
/*
* Closure flags. This flag is set when a close_notify has been
* received from the peer.
*/
unsigned char close_received;
/*
* Multi-hasher for the handshake messages. The handshake handler
* is responsible for resetting it when appropriate.
*/
br_multihash_context mhash;
/*
* Pointer to the X.509 engine. The engine is supposed to be
* already initialized. It is used to validate the peer's
* certificate.
*/
const br_x509_class **x509ctx;
/*
* Certificate chain to send. This is used by both client and
* server, when they send their respective Certificate messages.
* If chain_len is 0, then chain may be NULL.
*/
const br_x509_certificate *chain;
size_t chain_len;
const unsigned char *cert_cur;
size_t cert_len;
/*
* List of supported protocol names (ALPN extension). If unset,
* (number of names is 0), then:
* - the client sends no ALPN extension;
* - the server ignores any incoming ALPN extension.
*
* Otherwise:
* - the client sends an ALPN extension with all the names;
* - the server selects the first protocol in its list that
* the client also supports, or fails (fatal alert 120)
* if the client sends an ALPN extension and there is no
* match.
*
* The 'selected_protocol' field contains 1+n if the matching
* name has index n in the list (the value is 0 if no match was
* performed, e.g. the peer did not send an ALPN extension).
*/
const char **protocol_names;
uint16_t protocol_names_num;
uint16_t selected_protocol;
/*
* Pointers to implementations; left to NULL for unsupported
* functions. For the raw hash functions, implementations are
* referenced from the multihasher (mhash field).
*/
br_tls_prf_impl prf10;
br_tls_prf_impl prf_sha256;
br_tls_prf_impl prf_sha384;
const br_block_cbcenc_class *iaes_cbcenc;
const br_block_cbcdec_class *iaes_cbcdec;
const br_block_ctr_class *iaes_ctr;
const br_block_ctrcbc_class *iaes_ctrcbc;
const br_block_cbcenc_class *ides_cbcenc;
const br_block_cbcdec_class *ides_cbcdec;
br_ghash ighash;
br_chacha20_run ichacha;
br_poly1305_run ipoly;
const br_sslrec_in_cbc_class *icbc_in;
const br_sslrec_out_cbc_class *icbc_out;
const br_sslrec_in_gcm_class *igcm_in;
const br_sslrec_out_gcm_class *igcm_out;
const br_sslrec_in_chapol_class *ichapol_in;
const br_sslrec_out_chapol_class *ichapol_out;
const br_sslrec_in_ccm_class *iccm_in;
const br_sslrec_out_ccm_class *iccm_out;
const br_ec_impl *iec;
br_rsa_pkcs1_vrfy irsavrfy;
br_ecdsa_vrfy iecdsa;
#endif
} br_ssl_engine_context;
/**
* \brief Get currently defined engine behavioural flags.
*
* \param cc SSL engine context.
* \return the flags.
*/
static inline uint32_t
br_ssl_engine_get_flags(br_ssl_engine_context *cc)
{
return cc->flags;
}
/**
* \brief Set all engine behavioural flags.
*
* \param cc SSL engine context.
* \param flags new value for all flags.
*/
static inline void
br_ssl_engine_set_all_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags = flags;
}
/**
* \brief Set some engine behavioural flags.
*
* The flags set in the `flags` parameter are set in the context; other
* flags are untouched.
*
* \param cc SSL engine context.
* \param flags additional set flags.
*/
static inline void
br_ssl_engine_add_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags |= flags;
}
/**
* \brief Clear some engine behavioural flags.
*
* The flags set in the `flags` parameter are cleared from the context; other
* flags are untouched.
*
* \param cc SSL engine context.
* \param flags flags to remove.
*/
static inline void
br_ssl_engine_remove_flags(br_ssl_engine_context *cc, uint32_t flags)
{
cc->flags &= ~flags;
}
/**
* \brief Behavioural flag: enforce server preferences.
*
* If this flag is set, then the server will enforce its own cipher suite
* preference order; otherwise, it follows the client preferences.
*/
#define BR_OPT_ENFORCE_SERVER_PREFERENCES ((uint32_t)1 << 0)
/**
* \brief Behavioural flag: disable renegotiation.
*
* If this flag is set, then renegotiations are rejected unconditionally:
* they won't be honoured if asked for programmatically, and requests from
* the peer are rejected.
*/
#define BR_OPT_NO_RENEGOTIATION ((uint32_t)1 << 1)
/**
* \brief Behavioural flag: tolerate lack of client authentication.
*
* If this flag is set in a server and the server requests a client
* certificate, but the authentication fails (the client does not send
* a certificate, or the client's certificate chain cannot be validated),
* then the connection keeps on. Without this flag, a failed client
* authentication terminates the connection.
*
* Notes:
*
* - If the client's certificate can be validated and its public key is
* supported, then a wrong signature value terminates the connection
* regardless of that flag.
*
* - If using full-static ECDH, then a failure to validate the client's
* certificate prevents the handshake from succeeding.
*/
#define BR_OPT_TOLERATE_NO_CLIENT_AUTH ((uint32_t)1 << 2)
/**
* \brief Behavioural flag: fail on application protocol mismatch.
*
* The ALPN extension ([RFC 7301](https://tools.ietf.org/html/rfc7301))
* allows the client to send a list of application protocol names, and
* the server to select one. A mismatch is one of the following occurrences:
*
* - On the client: the client sends a list of names, the server
* responds with a protocol name which is _not_ part of the list of
* names sent by the client.
*
* - On the server: the client sends a list of names, and the server
* is also configured with a list of names, but there is no common
* protocol name between the two lists.
*
* Normal behaviour in case of mismatch is to report no matching name
* (`br_ssl_engine_get_selected_protocol()` returns `NULL`) and carry on.
* If the flag is set, then a mismatch implies a protocol failure (if
* the mismatch is detected by the server, it will send a fatal alert).
*
* Note: even with this flag, `br_ssl_engine_get_selected_protocol()`
* may still return `NULL` if the client or the server does not send an
* ALPN extension at all.
*/
#define BR_OPT_FAIL_ON_ALPN_MISMATCH ((uint32_t)1 << 3)
/**
* \brief Set the minimum and maximum supported protocol versions.
*
* The two provided versions MUST be supported by the implementation
* (i.e. TLS 1.0, 1.1 and 1.2), and `version_max` MUST NOT be lower
* than `version_min`.
*
* \param cc SSL engine context.
* \param version_min minimum supported TLS version.
* \param version_max maximum supported TLS version.
*/
static inline void
br_ssl_engine_set_versions(br_ssl_engine_context *cc,
unsigned version_min, unsigned version_max)
{
cc->version_min = (uint16_t)version_min;
cc->version_max = (uint16_t)version_max;
}
/**
* \brief Set the list of cipher suites advertised by this context.
*
* The provided array is copied into the context. It is the caller
* responsibility to ensure that all provided suites will be supported
* by the context. The engine context has enough room to receive _all_
* suites supported by the implementation. The provided array MUST NOT
* contain duplicates.
*
* If the engine is for a client, the "signaling" pseudo-cipher suite
* `TLS_FALLBACK_SCSV` can be added at the end of the list, if the
* calling application is performing a voluntary downgrade (voluntary
* downgrades are not recommended, but if such a downgrade is done, then
* adding the fallback pseudo-suite is a good idea).
*
* \param cc SSL engine context.
* \param suites cipher suites.
* \param suites_num number of cipher suites.
*/
void br_ssl_engine_set_suites(br_ssl_engine_context *cc,
const uint16_t *suites, size_t suites_num);
/**
* \brief Set the X.509 engine.
*
* The caller shall ensure that the X.509 engine is properly initialised.
*
* \param cc SSL engine context.
* \param x509ctx X.509 certificate validation context.
*/
static inline void
br_ssl_engine_set_x509(br_ssl_engine_context *cc, const br_x509_class **x509ctx)
{
cc->x509ctx = x509ctx;
}
/**
* \brief Set the supported protocol names.
*
* Protocol names are part of the ALPN extension ([RFC
* 7301](https://tools.ietf.org/html/rfc7301)). Each protocol name is a
* character string, containing no more than 255 characters (256 with the
* terminating zero). When names are set, then:
*
* - The client will send an ALPN extension, containing the names. If
* the server responds with an ALPN extension, the client will verify
* that the response contains one of its name, and report that name
* through `br_ssl_engine_get_selected_protocol()`.
*
* - The server will parse incoming ALPN extension (from clients), and
* try to find a common protocol; if none is found, the connection
* is aborted with a fatal alert. On match, a response ALPN extension
* is sent, and name is reported through
* `br_ssl_engine_get_selected_protocol()`.
*
* The provided array is linked in, and must remain valid while the
* connection is live.
*
* Names MUST NOT be empty. Names MUST NOT be longer than 255 characters
* (excluding the terminating 0).
*
* \param ctx SSL engine context.
* \param names list of protocol names (zero-terminated).
* \param num number of protocol names (MUST be 1 or more).
*/
static inline void
br_ssl_engine_set_protocol_names(br_ssl_engine_context *ctx,
const char **names, size_t num)
{
ctx->protocol_names = names;
ctx->protocol_names_num = (uint16_t)num;
}
/**
* \brief Get the selected protocol.
*
* If this context was initialised with a non-empty list of protocol
* names, and both client and server sent ALPN extensions during the
* handshake, and a common name was found, then that name is returned.
* Otherwise, `NULL` is returned.
*
* The returned pointer is one of the pointers provided to the context
* with `br_ssl_engine_set_protocol_names()`.
*
* \return the selected protocol, or `NULL`.
*/
static inline const char *
br_ssl_engine_get_selected_protocol(br_ssl_engine_context *ctx)
{
unsigned k;
k = ctx->selected_protocol;
return (k == 0 || k == 0xFFFF) ? NULL : ctx->protocol_names[k - 1];
}
/**
* \brief Set a hash function implementation (by ID).
*
* Hash functions set with this call will be used for SSL/TLS specific
* usages, not X.509 certificate validation. Only "standard" hash functions
* may be set (MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512). If `impl`
* is `NULL`, then the hash function support is removed, not added.
*
* \param ctx SSL engine context.
* \param id hash function identifier.
* \param impl hash function implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_hash(br_ssl_engine_context *ctx,
int id, const br_hash_class *impl)
{
br_multihash_setimpl(&ctx->mhash, id, impl);
}
/**
* \brief Get a hash function implementation (by ID).
*
* This function retrieves a hash function implementation which was
* set with `br_ssl_engine_set_hash()`.
*
* \param ctx SSL engine context.
* \param id hash function identifier.
* \return the hash function implementation (or `NULL`).
*/
static inline const br_hash_class *
br_ssl_engine_get_hash(br_ssl_engine_context *ctx, int id)
{
return br_multihash_getimpl(&ctx->mhash, id);
}
/**
* \brief Set the PRF implementation (for TLS 1.0 and 1.1).
*
* This function sets (or removes, if `impl` is `NULL`) the implementation
* for the PRF used in TLS 1.0 and 1.1.
*
* \param cc SSL engine context.
* \param impl PRF implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_prf10(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf10 = impl;
}
/**
* \brief Set the PRF implementation with SHA-256 (for TLS 1.2).
*
* This function sets (or removes, if `impl` is `NULL`) the implementation
* for the SHA-256 variant of the PRF used in TLS 1.2.
*
* \param cc SSL engine context.
* \param impl PRF implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_prf_sha256(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf_sha256 = impl;
}
/**
* \brief Set the PRF implementation with SHA-384 (for TLS 1.2).
*
* This function sets (or removes, if `impl` is `NULL`) the implementation
* for the SHA-384 variant of the PRF used in TLS 1.2.
*
* \param cc SSL engine context.
* \param impl PRF implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_prf_sha384(br_ssl_engine_context *cc, br_tls_prf_impl impl)
{
cc->prf_sha384 = impl;
}
/**
* \brief Set the AES/CBC implementations.
*
* \param cc SSL engine context.
* \param impl_enc AES/CBC encryption implementation (or `NULL`).
* \param impl_dec AES/CBC decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_aes_cbc(br_ssl_engine_context *cc,
const br_block_cbcenc_class *impl_enc,
const br_block_cbcdec_class *impl_dec)
{
cc->iaes_cbcenc = impl_enc;
cc->iaes_cbcdec = impl_dec;
}
/**
* \brief Set the "default" AES/CBC implementations.
*
* This function configures in the engine the AES implementations that
* should provide best runtime performance on the local system, while
* still being safe (in particular, constant-time). It also sets the
* handlers for CBC records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc);
/**
* \brief Set the AES/CTR implementation.
*
* \param cc SSL engine context.
* \param impl AES/CTR encryption/decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_aes_ctr(br_ssl_engine_context *cc,
const br_block_ctr_class *impl)
{
cc->iaes_ctr = impl;
}
/**
* \brief Set the "default" implementations for AES/GCM (AES/CTR + GHASH).
*
* This function configures in the engine the AES/CTR and GHASH
* implementation that should provide best runtime performance on the local
* system, while still being safe (in particular, constant-time). It also
* sets the handlers for GCM records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc);
/**
* \brief Set the DES/CBC implementations.
*
* \param cc SSL engine context.
* \param impl_enc DES/CBC encryption implementation (or `NULL`).
* \param impl_dec DES/CBC decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_des_cbc(br_ssl_engine_context *cc,
const br_block_cbcenc_class *impl_enc,
const br_block_cbcdec_class *impl_dec)
{
cc->ides_cbcenc = impl_enc;
cc->ides_cbcdec = impl_dec;
}
/**
* \brief Set the "default" DES/CBC implementations.
*
* This function configures in the engine the DES implementations that
* should provide best runtime performance on the local system, while
* still being safe (in particular, constant-time). It also sets the
* handlers for CBC records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc);
/**
* \brief Set the GHASH implementation (used in GCM mode).
*
* \param cc SSL engine context.
* \param impl GHASH implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_ghash(br_ssl_engine_context *cc, br_ghash impl)
{
cc->ighash = impl;
}
/**
* \brief Set the ChaCha20 implementation.
*
* \param cc SSL engine context.
* \param ichacha ChaCha20 implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_chacha20(br_ssl_engine_context *cc,
br_chacha20_run ichacha)
{
cc->ichacha = ichacha;
}
/**
* \brief Set the Poly1305 implementation.
*
* \param cc SSL engine context.
* \param ipoly Poly1305 implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_poly1305(br_ssl_engine_context *cc,
br_poly1305_run ipoly)
{
cc->ipoly = ipoly;
}
/**
* \brief Set the "default" ChaCha20 and Poly1305 implementations.
*
* This function configures in the engine the ChaCha20 and Poly1305
* implementations that should provide best runtime performance on the
* local system, while still being safe (in particular, constant-time).
* It also sets the handlers for ChaCha20+Poly1305 records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc);
/**
* \brief Set the AES/CTR+CBC implementation.
*
* \param cc SSL engine context.
* \param impl AES/CTR+CBC encryption/decryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_aes_ctrcbc(br_ssl_engine_context *cc,
const br_block_ctrcbc_class *impl)
{
cc->iaes_ctrcbc = impl;
}
/**
* \brief Set the "default" implementations for AES/CCM.
*
* This function configures in the engine the AES/CTR+CBC
* implementation that should provide best runtime performance on the local
* system, while still being safe (in particular, constant-time). It also
* sets the handlers for CCM records.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_aes_ccm(br_ssl_engine_context *cc);
/**
* \brief Set the record encryption and decryption engines for CBC + HMAC.
*
* \param cc SSL engine context.
* \param impl_in record CBC decryption implementation (or `NULL`).
* \param impl_out record CBC encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_cbc(br_ssl_engine_context *cc,
const br_sslrec_in_cbc_class *impl_in,
const br_sslrec_out_cbc_class *impl_out)
{
cc->icbc_in = impl_in;
cc->icbc_out = impl_out;
}
/**
* \brief Set the record encryption and decryption engines for GCM.
*
* \param cc SSL engine context.
* \param impl_in record GCM decryption implementation (or `NULL`).
* \param impl_out record GCM encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_gcm(br_ssl_engine_context *cc,
const br_sslrec_in_gcm_class *impl_in,
const br_sslrec_out_gcm_class *impl_out)
{
cc->igcm_in = impl_in;
cc->igcm_out = impl_out;
}
/**
* \brief Set the record encryption and decryption engines for CCM.
*
* \param cc SSL engine context.
* \param impl_in record CCM decryption implementation (or `NULL`).
* \param impl_out record CCM encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_ccm(br_ssl_engine_context *cc,
const br_sslrec_in_ccm_class *impl_in,
const br_sslrec_out_ccm_class *impl_out)
{
cc->iccm_in = impl_in;
cc->iccm_out = impl_out;
}
/**
* \brief Set the record encryption and decryption engines for
* ChaCha20+Poly1305.
*
* \param cc SSL engine context.
* \param impl_in record ChaCha20 decryption implementation (or `NULL`).
* \param impl_out record ChaCha20 encryption implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_chapol(br_ssl_engine_context *cc,
const br_sslrec_in_chapol_class *impl_in,
const br_sslrec_out_chapol_class *impl_out)
{
cc->ichapol_in = impl_in;
cc->ichapol_out = impl_out;
}
/**
* \brief Set the EC implementation.
*
* The elliptic curve implementation will be used for ECDH and ECDHE
* cipher suites, and for ECDSA support.
*
* \param cc SSL engine context.
* \param iec EC implementation (or `NULL`).
*/
static inline void
br_ssl_engine_set_ec(br_ssl_engine_context *cc, const br_ec_impl *iec)
{
cc->iec = iec;
}
/**
* \brief Set the "default" EC implementation.
*
* This function sets the elliptic curve implementation for ECDH and
* ECDHE cipher suites, and for ECDSA support. It selects the fastest
* implementation on the current system.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_ec(br_ssl_engine_context *cc);
/**
* \brief Get the EC implementation configured in the provided engine.
*
* \param cc SSL engine context.
* \return the EC implementation.
*/
static inline const br_ec_impl *
br_ssl_engine_get_ec(br_ssl_engine_context *cc)
{
return cc->iec;
}
/**
* \brief Set the RSA signature verification implementation.
*
* On the client, this is used to verify the server's signature on its
* ServerKeyExchange message (for ECDHE_RSA cipher suites). On the server,
* this is used to verify the client's CertificateVerify message (if a
* client certificate is requested, and that certificate contains a RSA key).
*
* \param cc SSL engine context.
* \param irsavrfy RSA signature verification implementation.
*/
static inline void
br_ssl_engine_set_rsavrfy(br_ssl_engine_context *cc, br_rsa_pkcs1_vrfy irsavrfy)
{
cc->irsavrfy = irsavrfy;
}
/**
* \brief Set the "default" RSA implementation (signature verification).
*
* This function sets the RSA implementation (signature verification)
* to the fastest implementation available on the current platform.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc);
/**
* \brief Get the RSA implementation (signature verification) configured
* in the provided engine.
*
* \param cc SSL engine context.
* \return the RSA signature verification implementation.
*/
static inline br_rsa_pkcs1_vrfy
br_ssl_engine_get_rsavrfy(br_ssl_engine_context *cc)
{
return cc->irsavrfy;
}
/*
* \brief Set the ECDSA implementation (signature verification).
*
* On the client, this is used to verify the server's signature on its
* ServerKeyExchange message (for ECDHE_ECDSA cipher suites). On the server,
* this is used to verify the client's CertificateVerify message (if a
* client certificate is requested, that certificate contains an EC key,
* and full-static ECDH is not used).
*
* The ECDSA implementation will use the EC core implementation configured
* in the engine context.
*
* \param cc client context.
* \param iecdsa ECDSA verification implementation.
*/
static inline void
br_ssl_engine_set_ecdsa(br_ssl_engine_context *cc, br_ecdsa_vrfy iecdsa)
{
cc->iecdsa = iecdsa;
}
/**
* \brief Set the "default" ECDSA implementation (signature verification).
*
* This function sets the ECDSA implementation (signature verification)
* to the fastest implementation available on the current platform. This
* call also sets the elliptic curve implementation itself, there again
* to the fastest EC implementation available.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc);
/**
* \brief Get the ECDSA implementation (signature verification) configured
* in the provided engine.
*
* \param cc SSL engine context.
* \return the ECDSA signature verification implementation.
*/
static inline br_ecdsa_vrfy
br_ssl_engine_get_ecdsa(br_ssl_engine_context *cc)
{
return cc->iecdsa;
}
/**
* \brief Set the I/O buffer for the SSL engine.
*
* Once this call has been made, `br_ssl_client_reset()` or
* `br_ssl_server_reset()` MUST be called before using the context.
*
* The provided buffer will be used as long as the engine context is
* used. The caller is responsible for keeping it available.
*
* If `bidi` is 0, then the engine will operate in half-duplex mode
* (it won't be able to send data while there is unprocessed incoming
* data in the buffer, and it won't be able to receive data while there
* is unsent data in the buffer). The optimal buffer size in half-duplex
* mode is `BR_SSL_BUFSIZE_MONO`; if the buffer is larger, then extra
* bytes are ignored. If the buffer is smaller, then this limits the
* capacity of the engine to support all allowed record sizes.
*
* If `bidi` is 1, then the engine will split the buffer into two
* parts, for separate handling of outgoing and incoming data. This
* enables full-duplex processing, but requires more RAM. The optimal
* buffer size in full-duplex mode is `BR_SSL_BUFSIZE_BIDI`; if the
* buffer is larger, then extra bytes are ignored. If the buffer is
* smaller, then the split will favour the incoming part, so that
* interoperability is maximised.
*
* \param cc SSL engine context
* \param iobuf I/O buffer.
* \param iobuf_len I/O buffer length (in bytes).
* \param bidi non-zero for full-duplex mode.
*/
void br_ssl_engine_set_buffer(br_ssl_engine_context *cc,
void *iobuf, size_t iobuf_len, int bidi);
/**
* \brief Set the I/O buffers for the SSL engine.
*
* Once this call has been made, `br_ssl_client_reset()` or
* `br_ssl_server_reset()` MUST be called before using the context.
*
* This function is similar to `br_ssl_engine_set_buffer()`, except
* that it enforces full-duplex mode, and the two I/O buffers are
* provided as separate chunks.
*
* The macros `BR_SSL_BUFSIZE_INPUT` and `BR_SSL_BUFSIZE_OUTPUT`
* evaluate to the optimal (maximum) sizes for the input and output
* buffer, respectively.
*
* \param cc SSL engine context
* \param ibuf input buffer.
* \param ibuf_len input buffer length (in bytes).
* \param obuf output buffer.
* \param obuf_len output buffer length (in bytes).
*/
void br_ssl_engine_set_buffers_bidi(br_ssl_engine_context *cc,
void *ibuf, size_t ibuf_len, void *obuf, size_t obuf_len);
/**
* \brief Inject some "initial entropy" in the context.
*
* This entropy will be added to what can be obtained from the
* underlying operating system, if that OS is supported.
*
* This function may be called several times; all injected entropy chunks
* are cumulatively mixed.
*
* If entropy gathering from the OS is supported and compiled in, then this
* step is optional. Otherwise, it is mandatory to inject randomness, and
* the caller MUST take care to push (as one or several successive calls)
* enough entropy to achieve cryptographic resistance (at least 80 bits,
* preferably 128 or more). The engine will report an error if no entropy
* was provided and none can be obtained from the OS.
*
* Take care that this function cannot assess the cryptographic quality of
* the provided bytes.
*
* In all generality, "entropy" must here be considered to mean "that
* which the attacker cannot predict". If your OS/architecture does not
* have a suitable source of randomness, then you can make do with the
* combination of a large enough secret value (possibly a copy of an
* asymmetric private key that you also store on the system) AND a
* non-repeating value (e.g. current time, provided that the local clock
* cannot be reset or altered by the attacker).
*
* \param cc SSL engine context.
* \param data extra entropy to inject.
* \param len length of the extra data (in bytes).
*/
void br_ssl_engine_inject_entropy(br_ssl_engine_context *cc,
const void *data, size_t len);
/**
* \brief Get the "server name" in this engine.
*
* For clients, this is the name provided with `br_ssl_client_reset()`;
* for servers, this is the name received from the client as part of the
* ClientHello message. If there is no such name (e.g. the client did
* not send an SNI extension) then the returned string is empty
* (returned pointer points to a byte of value 0).
*
* The returned pointer refers to a buffer inside the context, which may
* be overwritten as part of normal SSL activity (even within the same
* connection, if a renegotiation occurs).
*
* \param cc SSL engine context.
* \return the server name (possibly empty).
*/
static inline const char *
br_ssl_engine_get_server_name(const br_ssl_engine_context *cc)
{
return cc->server_name;
}
/**
* \brief Get the protocol version.
*
* This function returns the protocol version that is used by the
* engine. That value is set after sending (for a server) or receiving
* (for a client) the ServerHello message.
*
* \param cc SSL engine context.
* \return the protocol version.
*/
static inline unsigned
br_ssl_engine_get_version(const br_ssl_engine_context *cc)
{
return cc->session.version;
}
/**
* \brief Get a copy of the session parameters.
*
* The session parameters are filled during the handshake, so this
* function shall not be called before completion of the handshake.
* The initial handshake is completed when the context first allows
* application data to be injected.
*
* This function copies the current session parameters into the provided
* structure. Beware that the session parameters include the master
* secret, which is sensitive data, to handle with great care.
*
* \param cc SSL engine context.
* \param pp destination structure for the session parameters.
*/
static inline void
br_ssl_engine_get_session_parameters(const br_ssl_engine_context *cc,
br_ssl_session_parameters *pp)
{
memcpy(pp, &cc->session, sizeof *pp);
}
/**
* \brief Set the session parameters to the provided values.
*
* This function is meant to be used in the client, before doing a new
* handshake; a session resumption will be attempted with these
* parameters. In the server, this function has no effect.
*
* \param cc SSL engine context.
* \param pp source structure for the session parameters.
*/
static inline void
br_ssl_engine_set_session_parameters(br_ssl_engine_context *cc,
const br_ssl_session_parameters *pp)
{
memcpy(&cc->session, pp, sizeof *pp);
}
/**
* \brief Get identifier for the curve used for key exchange.
*
* If the cipher suite uses ECDHE, then this function returns the
* identifier for the curve used for transient parameters. This is
* defined during the course of the handshake, when the ServerKeyExchange
* is sent (on the server) or received (on the client). If the
* cipher suite does not use ECDHE (e.g. static ECDH, or RSA key
* exchange), then this value is indeterminate.
*
* @param cc SSL engine context.
* @return the ECDHE curve identifier.
*/
static inline int
br_ssl_engine_get_ecdhe_curve(br_ssl_engine_context *cc)
{
return cc->ecdhe_curve;
}
/**
* \brief Get the current engine state.
*
* An SSL engine (client or server) has, at any time, a state which is
* the combination of zero, one or more of these flags:
*
* - `BR_SSL_CLOSED`
*
* Engine is finished, no more I/O (until next reset).
*
* - `BR_SSL_SENDREC`
*
* Engine has some bytes to send to the peer.
*
* - `BR_SSL_RECVREC`
*
* Engine expects some bytes from the peer.
*
* - `BR_SSL_SENDAPP`
*
* Engine may receive application data to send (or flush).
*
* - `BR_SSL_RECVAPP`
*
* Engine has obtained some application data from the peer,
* that should be read by the caller.
*
* If no flag at all is set (state value is 0), then the engine is not
* fully initialised yet.
*
* The `BR_SSL_CLOSED` flag is exclusive; when it is set, no other flag
* is set. To distinguish between a normal closure and an error, use
* `br_ssl_engine_last_error()`.
*
* Generally speaking, `BR_SSL_SENDREC` and `BR_SSL_SENDAPP` are mutually
* exclusive: the input buffer, at any point, either accumulates
* plaintext data, or contains an assembled record that is being sent.
* Similarly, `BR_SSL_RECVREC` and `BR_SSL_RECVAPP` are mutually exclusive.
* This may change in a future library version.
*
* \param cc SSL engine context.
* \return the current engine state.
*/
unsigned br_ssl_engine_current_state(const br_ssl_engine_context *cc);
/** \brief SSL engine state: closed or failed. */
#define BR_SSL_CLOSED 0x0001
/** \brief SSL engine state: record data is ready to be sent to the peer. */
#define BR_SSL_SENDREC 0x0002
/** \brief SSL engine state: engine may receive records from the peer. */
#define BR_SSL_RECVREC 0x0004
/** \brief SSL engine state: engine may accept application data to send. */
#define BR_SSL_SENDAPP 0x0008
/** \brief SSL engine state: engine has received application data. */
#define BR_SSL_RECVAPP 0x0010
/**
* \brief Get the engine error indicator.
*
* The error indicator is `BR_ERR_OK` (0) if no error was encountered
* since the last call to `br_ssl_client_reset()` or
* `br_ssl_server_reset()`. Other status values are "sticky": they
* remain set, and prevent all I/O activity, until cleared. Only the
* reset calls clear the error indicator.
*
* \param cc SSL engine context.
* \return 0, or a non-zero error code.
*/
static inline int
br_ssl_engine_last_error(const br_ssl_engine_context *cc)
{
return cc->err;
}
/*
* There are four I/O operations, each identified by a symbolic name:
*
* sendapp inject application data in the engine
* recvapp retrieving application data from the engine
* sendrec sending records on the transport medium
* recvrec receiving records from the transport medium
*
* Terminology works thus: in a layered model where the SSL engine sits
* between the application and the network, "send" designates operations
* where bytes flow from application to network, and "recv" for the
* reverse operation. Application data (the plaintext that is to be
* conveyed through SSL) is "app", while encrypted records are "rec".
* Note that from the SSL engine point of view, "sendapp" and "recvrec"
* designate bytes that enter the engine ("inject" operation), while
* "recvapp" and "sendrec" designate bytes that exit the engine
* ("extract" operation).
*
* For the operation 'xxx', two functions are defined:
*
* br_ssl_engine_xxx_buf
* Returns a pointer and length to the buffer to use for that
* operation. '*len' is set to the number of bytes that may be read
* from the buffer (extract operation) or written to the buffer
* (inject operation). If no byte may be exchanged for that operation
* at that point, then '*len' is set to zero, and NULL is returned.
* The engine state is unmodified by this call.
*
* br_ssl_engine_xxx_ack
* Informs the engine that 'len' bytes have been read from the buffer
* (extract operation) or written to the buffer (inject operation).
* The 'len' value MUST NOT be zero. The 'len' value MUST NOT exceed
* that which was obtained from a preceding br_ssl_engine_xxx_buf()
* call.
*/
/**
* \brief Get buffer for application data to send.
*
* If the engine is ready to accept application data to send to the
* peer, then this call returns a pointer to the buffer where such
* data shall be written, and its length is written in `*len`.
* Otherwise, `*len` is set to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the application data output buffer length, or 0.
* \return the application data output buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_sendapp_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Inform the engine of some new application data.
*
* After writing `len` bytes in the buffer returned by
* `br_ssl_engine_sendapp_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_sendapp_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes pushed (not zero).
*/
void br_ssl_engine_sendapp_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Get buffer for received application data.
*
* If the engine has received application data from the peer, then this
* call returns a pointer to the buffer from where such data shall be
* read, and its length is written in `*len`. Otherwise, `*len` is set
* to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the application data input buffer length, or 0.
* \return the application data input buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_recvapp_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Acknowledge some received application data.
*
* After reading `len` bytes from the buffer returned by
* `br_ssl_engine_recvapp_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_recvapp_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes read (not zero).
*/
void br_ssl_engine_recvapp_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Get buffer for record data to send.
*
* If the engine has prepared some records to send to the peer, then this
* call returns a pointer to the buffer from where such data shall be
* read, and its length is written in `*len`. Otherwise, `*len` is set
* to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the record data output buffer length, or 0.
* \return the record data output buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_sendrec_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Acknowledge some sent record data.
*
* After reading `len` bytes from the buffer returned by
* `br_ssl_engine_sendrec_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_sendrec_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes read (not zero).
*/
void br_ssl_engine_sendrec_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Get buffer for incoming records.
*
* If the engine is ready to accept records from the peer, then this
* call returns a pointer to the buffer where such data shall be
* written, and its length is written in `*len`. Otherwise, `*len` is
* set to 0 and `NULL` is returned.
*
* \param cc SSL engine context.
* \param len receives the record data input buffer length, or 0.
* \return the record data input buffer, or `NULL`.
*/
unsigned char *br_ssl_engine_recvrec_buf(
const br_ssl_engine_context *cc, size_t *len);
/**
* \brief Inform the engine of some new record data.
*
* After writing `len` bytes in the buffer returned by
* `br_ssl_engine_recvrec_buf()`, the application shall call this
* function to trigger any relevant processing. The `len` parameter
* MUST NOT be 0, and MUST NOT exceed the value obtained in the
* `br_ssl_engine_recvrec_buf()` call.
*
* \param cc SSL engine context.
* \param len number of bytes pushed (not zero).
*/
void br_ssl_engine_recvrec_ack(br_ssl_engine_context *cc, size_t len);
/**
* \brief Flush buffered application data.
*
* If some application data has been buffered in the engine, then wrap
* it into a record and mark it for sending. If no application data has
* been buffered but the engine would be ready to accept some, AND the
* `force` parameter is non-zero, then an empty record is assembled and
* marked for sending. In all other cases, this function does nothing.
*
* Empty records are technically legal, but not all existing SSL/TLS
* implementations support them. Empty records can be useful as a
* transparent "keep-alive" mechanism to maintain some low-level
* network activity.
*
* \param cc SSL engine context.
* \param force non-zero to force sending an empty record.
*/
void br_ssl_engine_flush(br_ssl_engine_context *cc, int force);
/**
* \brief Initiate a closure.
*
* If, at that point, the context is open and in ready state, then a
* `close_notify` alert is assembled and marked for sending; this
* triggers the closure protocol. Otherwise, no such alert is assembled.
*
* \param cc SSL engine context.
*/
void br_ssl_engine_close(br_ssl_engine_context *cc);
/**
* \brief Initiate a renegotiation.
*
* If the engine is failed or closed, or if the peer is known not to
* support secure renegotiation (RFC 5746), or if renegotiations have
* been disabled with the `BR_OPT_NO_RENEGOTIATION` flag, or if there
* is buffered incoming application data, then this function returns 0
* and nothing else happens.
*
* Otherwise, this function returns 1, and a renegotiation attempt is
* triggered (if a handshake is already ongoing at that point, then
* no new handshake is triggered).
*
* \param cc SSL engine context.
* \return 1 on success, 0 on error.
*/
int br_ssl_engine_renegotiate(br_ssl_engine_context *cc);
/**
* \brief Export key material from a connected SSL engine (RFC 5705).
*
* This calls compute a secret key of arbitrary length from the master
* secret of a connected SSL engine. If the provided context is not
* currently in "application data" state (initial handshake is not
* finished, another handshake is ongoing, or the connection failed or
* was closed), then this function returns 0. Otherwise, a secret key of
* length `len` bytes is computed and written in the buffer pointed to
* by `dst`, and 1 is returned.
*
* The computed key follows the specification described in RFC 5705.
* That RFC includes two key computations, with and without a "context
* value". If `context` is `NULL`, then the variant without context is
* used; otherwise, the `context_len` bytes located at the address
* pointed to by `context` are used in the computation. Note that it
* is possible to have a "with context" key with a context length of
* zero bytes, by setting `context` to a non-`NULL` value but
* `context_len` to 0.
*
* When context bytes are used, the context length MUST NOT exceed
* 65535 bytes.
*
* \param cc SSL engine context.
* \param dst destination buffer for exported key.
* \param len exported key length (in bytes).
* \param label disambiguation label.
* \param context context value (or `NULL`).
* \param context_len context length (in bytes).
* \return 1 on success, 0 on error.
*/
int br_ssl_key_export(br_ssl_engine_context *cc,
void *dst, size_t len, const char *label,
const void *context, size_t context_len);
/*
* Pre-declaration for the SSL client context.
*/
typedef struct br_ssl_client_context_ br_ssl_client_context;
/**
* \brief Type for the client certificate, if requested by the server.
*/
typedef struct {
/**
* \brief Authentication type.
*
* This is either `BR_AUTH_RSA` (RSA signature), `BR_AUTH_ECDSA`
* (ECDSA signature), or `BR_AUTH_ECDH` (static ECDH key exchange).
*/
int auth_type;
/**
* \brief Hash function for computing the CertificateVerify.
*
* This is the symbolic identifier for the hash function that
* will be used to produce the hash of handshake messages, to
* be signed into the CertificateVerify. For full static ECDH
* (client and server certificates are both EC in the same
* curve, and static ECDH is used), this value is set to -1.
*
* Take care that with TLS 1.0 and 1.1, that value MUST match
* the protocol requirements: value must be 0 (MD5+SHA-1) for
* a RSA signature, or 2 (SHA-1) for an ECDSA signature. Only
* TLS 1.2 allows for other hash functions.
*/
int hash_id;
/**
* \brief Certificate chain to send to the server.
*
* This is an array of `br_x509_certificate` objects, each
* normally containing a DER-encoded certificate. The client
* code does not try to decode these elements. If there is no
* chain to send to the server, then this pointer shall be
* set to `NULL`.
*/
const br_x509_certificate *chain;
/**
* \brief Certificate chain length (number of certificates).
*
* If there is no chain to send to the server, then this value
* shall be set to 0.
*/
size_t chain_len;
} br_ssl_client_certificate;
/*
* Note: the constants below for signatures match the TLS constants.
*/
/** \brief Client authentication type: static ECDH. */
#define BR_AUTH_ECDH 0
/** \brief Client authentication type: RSA signature. */
#define BR_AUTH_RSA 1
/** \brief Client authentication type: ECDSA signature. */
#define BR_AUTH_ECDSA 3
/**
* \brief Class type for a certificate handler (client side).
*
* A certificate handler selects a client certificate chain to send to
* the server, upon explicit request from that server. It receives
* the list of trust anchor DN from the server, and supported types
* of certificates and signatures, and returns the chain to use. It
* is also invoked to perform the corresponding private key operation
* (a signature, or an ECDH computation).
*
* The SSL client engine will first push the trust anchor DN with
* `start_name_list()`, `start_name()`, `append_name()`, `end_name()`
* and `end_name_list()`. Then it will call `choose()`, to select the
* actual chain (and signature/hash algorithms). Finally, it will call
* either `do_sign()` or `do_keyx()`, depending on the algorithm choices.
*/
typedef struct br_ssl_client_certificate_class_ br_ssl_client_certificate_class;
struct br_ssl_client_certificate_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Begin reception of a list of trust anchor names. This
* is called while parsing the incoming CertificateRequest.
*
* \param pctx certificate handler context.
*/
void (*start_name_list)(const br_ssl_client_certificate_class **pctx);
/**
* \brief Begin reception of a new trust anchor name.
*
* The total encoded name length is provided; it is less than
* 65535 bytes.
*
* \param pctx certificate handler context.
* \param len encoded name length (in bytes).
*/
void (*start_name)(const br_ssl_client_certificate_class **pctx,
size_t len);
/**
* \brief Receive some more bytes for the current trust anchor name.
*
* The provided reference (`data`) points to a transient buffer
* they may be reused as soon as this function returns. The chunk
* length (`len`) is never zero.
*
* \param pctx certificate handler context.
* \param data anchor name chunk.
* \param len anchor name chunk length (in bytes).
*/
void (*append_name)(const br_ssl_client_certificate_class **pctx,
const unsigned char *data, size_t len);
/**
* \brief End current trust anchor name.
*
* This function is called when all the encoded anchor name data
* has been provided.
*
* \param pctx certificate handler context.
*/
void (*end_name)(const br_ssl_client_certificate_class **pctx);
/**
* \brief End list of trust anchor names.
*
* This function is called when all the anchor names in the
* CertificateRequest message have been obtained.
*
* \param pctx certificate handler context.
*/
void (*end_name_list)(const br_ssl_client_certificate_class **pctx);
/**
* \brief Select client certificate and algorithms.
*
* This callback function shall fill the provided `choices`
* structure with the selected algorithms and certificate chain.
* The `hash_id`, `chain` and `chain_len` fields must be set. If
* the client cannot or does not wish to send a certificate,
* then it shall set `chain` to `NULL` and `chain_len` to 0.
*
* The `auth_types` parameter describes the authentication types,
* signature algorithms and hash functions that are supported by
* both the client context and the server, and compatible with
* the current protocol version. This is a bit field with the
* following contents:
*
* - If RSA signatures with hash function x are supported, then
* bit x is set.
*
* - If ECDSA signatures with hash function x are supported,
* then bit 8+x is set.
*
* - If static ECDH is supported, with a RSA-signed certificate,
* then bit 16 is set.
*
* - If static ECDH is supported, with an ECDSA-signed certificate,
* then bit 17 is set.
*
* Notes:
*
* - When using TLS 1.0 or 1.1, the hash function for RSA
* signatures is always the special MD5+SHA-1 (id 0), and the
* hash function for ECDSA signatures is always SHA-1 (id 2).
*
* - When using TLS 1.2, the list of hash functions is trimmed
* down to include only hash functions that the client context
* can support. The actual server list can be obtained with
* `br_ssl_client_get_server_hashes()`; that list may be used
* to select the certificate chain to send to the server.
*
* \param pctx certificate handler context.
* \param cc SSL client context.
* \param auth_types supported authentication types and algorithms.
* \param choices destination structure for the policy choices.
*/
void (*choose)(const br_ssl_client_certificate_class **pctx,
const br_ssl_client_context *cc, uint32_t auth_types,
br_ssl_client_certificate *choices);
/**
* \brief Perform key exchange (client part).
*
* This callback is invoked in case of a full static ECDH key
* exchange:
*
* - the cipher suite uses `ECDH_RSA` or `ECDH_ECDSA`;
*
* - the server requests a client certificate;
*
* - the client has, and sends, a client certificate that
* uses an EC key in the same curve as the server's key,
* and chooses static ECDH (the `hash_id` field in the choice
* structure was set to -1).
*
* In that situation, this callback is invoked to compute the
* client-side ECDH: the provided `data` (of length `*len` bytes)
* is the server's public key point (as decoded from its
* certificate), and the client shall multiply that point with
* its own private key, and write back the X coordinate of the
* resulting point in the same buffer, starting at offset 0.
* The `*len` value shall be modified to designate the actual
* length of the X coordinate.
*
* The callback must uphold the following:
*
* - If the input array does not have the proper length for
* an encoded curve point, then an error (0) shall be reported.
*
* - If the input array has the proper length, then processing
* MUST be constant-time, even if the data is not a valid
* encoded point.
*
* - This callback MUST check that the input point is valid.
*
* Returned value is 1 on success, 0 on error.
*
* \param pctx certificate handler context.
* \param data server public key point.
* \param len public key point length / X coordinate length.
* \return 1 on success, 0 on error.
*/
uint32_t (*do_keyx)(const br_ssl_client_certificate_class **pctx,
unsigned char *data, size_t *len);
/**
* \brief Perform a signature (client authentication).
*
* This callback is invoked when a client certificate was sent,
* and static ECDH is not used. It shall compute a signature,
* using the client's private key, over the provided hash value
* (which is the hash of all previous handshake messages).
*
* On input, the hash value to sign is in `data`, of size
* `hv_len`; the involved hash function is identified by
* `hash_id`. The signature shall be computed and written
* back into `data`; the total size of that buffer is `len`
* bytes.
*
* This callback shall verify that the signature length does not
* exceed `len` bytes, and abstain from writing the signature if
* it does not fit.
*
* For RSA signatures, the `hash_id` may be 0, in which case
* this is the special header-less signature specified in TLS 1.0
* and 1.1, with a 36-byte hash value. Otherwise, normal PKCS#1
* v1.5 signatures shall be computed.
*
* For ECDSA signatures, the signature value shall use the ASN.1
* based encoding.
*
* Returned value is the signature length (in bytes), or 0 on error.
*
* \param pctx certificate handler context.
* \param hash_id hash function identifier.
* \param hv_len hash value length (in bytes).
* \param data input/output buffer (hash value, then signature).
* \param len total buffer length (in bytes).
* \return signature length (in bytes) on success, or 0 on error.
*/
size_t (*do_sign)(const br_ssl_client_certificate_class **pctx,
int hash_id, size_t hv_len, unsigned char *data, size_t len);
};
/**
* \brief A single-chain RSA client certificate handler.
*
* This handler uses a single certificate chain, with a RSA
* signature. The list of trust anchor DN is ignored.
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_client_certificate_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_rsa_private_key *sk;
br_rsa_pkcs1_sign irsasign;
#endif
} br_ssl_client_certificate_rsa_context;
/**
* \brief A single-chain EC client certificate handler.
*
* This handler uses a single certificate chain, with a RSA
* signature. The list of trust anchor DN is ignored.
*
* This handler may support both static ECDH, and ECDSA signatures
* (either usage may be selectively disabled).
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_client_certificate_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_ec_private_key *sk;
unsigned allowed_usages;
unsigned issuer_key_type;
const br_multihash_context *mhash;
const br_ec_impl *iec;
br_ecdsa_sign iecdsa;
#endif
} br_ssl_client_certificate_ec_context;
/**
* \brief Context structure for a SSL client.
*
* The first field (called `eng`) is the SSL engine; all functions that
* work on a `br_ssl_engine_context` structure shall take as parameter
* a pointer to that field. The other structure fields are opaque and
* must not be accessed directly.
*/
struct br_ssl_client_context_ {
/**
* \brief The encapsulated engine context.
*/
br_ssl_engine_context eng;
#ifndef BR_DOXYGEN_IGNORE
/*
* Minimum ClientHello length; padding with an extension (RFC
* 7685) is added if necessary to match at least that length.
* Such padding is nominally unnecessary, but it has been used
* to work around some server implementation bugs.
*/
uint16_t min_clienthello_len;
/*
* Bit field for algoithms (hash + signature) supported by the
* server when requesting a client certificate.
*/
uint32_t hashes;
/*
* Server's public key curve.
*/
int server_curve;
/*
* Context for certificate handler.
*/
const br_ssl_client_certificate_class **client_auth_vtable;
/*
* Client authentication type.
*/
unsigned char auth_type;
/*
* Hash function to use for the client signature. This is 0xFF
* if static ECDH is used.
*/
unsigned char hash_id;
/*
* For the core certificate handlers, thus avoiding (in most
* cases) the need for an externally provided policy context.
*/
union {
const br_ssl_client_certificate_class *vtable;
br_ssl_client_certificate_rsa_context single_rsa;
br_ssl_client_certificate_ec_context single_ec;
} client_auth;
/*
* Implementations.
*/
br_rsa_public irsapub;
#endif
};
/**
* \brief Get the hash functions and signature algorithms supported by
* the server.
*
* This value is a bit field:
*
* - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`,
* then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1,
* or 2 to 6 for the SHA family).
*
* - If ECDSA is supported with hash function of ID `x`, then bit `8+x`
* is set.
*
* - Newer algorithms are symbolic 16-bit identifiers that do not
* represent signature algorithm and hash function separately. If
* the TLS-level identifier is `0x0800+x` for a `x` in the 0..15
* range, then bit `16+x` is set.
*
* "New algorithms" are currently defined only in draft documents, so
* this support is subject to possible change. Right now (early 2017),
* this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA
* on Curve448) to bit 24. If the identifiers on the wire change in
* future document, then the decoding mechanism in BearSSL will be
* amended to keep mapping ed25519 and ed448 on bits 23 and 24,
* respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not
* guaranteed yet.
*
* \param cc client context.
* \return the server-supported hash functions and signature algorithms.
*/
static inline uint32_t
br_ssl_client_get_server_hashes(const br_ssl_client_context *cc)
{
return cc->hashes;
}
/**
* \brief Get the server key curve.
*
* This function returns the ID for the curve used by the server's public
* key. This is set when the server's certificate chain is processed;
* this value is 0 if the server's key is not an EC key.
*
* \return the server's public key curve ID, or 0.
*/
static inline int
br_ssl_client_get_server_curve(const br_ssl_client_context *cc)
{
return cc->server_curve;
}
/*
* Each br_ssl_client_init_xxx() function sets the list of supported
* cipher suites and used implementations, as specified by the profile
* name 'xxx'. Defined profile names are:
*
* full all supported versions and suites; constant-time implementations
* TODO: add other profiles
*/
/**
* \brief SSL client profile: full.
*
* This function initialises the provided SSL client context with
* all supported algorithms and cipher suites. It also initialises
* a companion X.509 validation engine with all supported algorithms,
* and the provided trust anchors; the X.509 engine will be used by
* the client context to validate the server's certificate.
*
* \param cc client context to initialise.
* \param xc X.509 validation context to initialise.
* \param trust_anchors trust anchors to use.
* \param trust_anchors_num number of trust anchors.
*/
void br_ssl_client_init_full(br_ssl_client_context *cc,
br_x509_minimal_context *xc,
const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num);
/**
* \brief Clear the complete contents of a SSL client context.
*
* Everything is cleared, including the reference to the configured buffer,
* implementations, cipher suites and state. This is a preparatory step
* to assembling a custom profile.
*
* \param cc client context to clear.
*/
void br_ssl_client_zero(br_ssl_client_context *cc);
/**
* \brief Set an externally provided client certificate handler context.
*
* The handler's methods are invoked when the server requests a client
* certificate.
*
* \param cc client context.
* \param pctx certificate handler context (pointer to its vtable field).
*/
static inline void
br_ssl_client_set_client_certificate(br_ssl_client_context *cc,
const br_ssl_client_certificate_class **pctx)
{
cc->client_auth_vtable = pctx;
}
/**
* \brief Set the RSA public-key operations implementation.
*
* This will be used to encrypt the pre-master secret with the server's
* RSA public key (RSA-encryption cipher suites only).
*
* \param cc client context.
* \param irsapub RSA public-key encryption implementation.
*/
static inline void
br_ssl_client_set_rsapub(br_ssl_client_context *cc, br_rsa_public irsapub)
{
cc->irsapub = irsapub;
}
/**
* \brief Set the "default" RSA implementation for public-key operations.
*
* This sets the RSA implementation in the client context (for encrypting
* the pre-master secret, in `TLS_RSA_*` cipher suites) to the fastest
* available on the current platform.
*
* \param cc client context.
*/
void br_ssl_client_set_default_rsapub(br_ssl_client_context *cc);
/**
* \brief Set the minimum ClientHello length (RFC 7685 padding).
*
* If this value is set and the ClientHello would be shorter, then
* the Pad ClientHello extension will be added with enough padding bytes
* to reach the target size. Because of the extension header, the resulting
* size will sometimes be slightly more than `len` bytes if the target
* size cannot be exactly met.
*
* The target length relates to the _contents_ of the ClientHello, not
* counting its 4-byte header. For instance, if `len` is set to 512,
* then the padding will bring the ClientHello size to 516 bytes with its
* header, and 521 bytes when counting the 5-byte record header.
*
* \param cc client context.
* \param len minimum ClientHello length (in bytes).
*/
static inline void
br_ssl_client_set_min_clienthello_len(br_ssl_client_context *cc, uint16_t len)
{
cc->min_clienthello_len = len;
}
/**
* \brief Prepare or reset a client context for a new connection.
*
* The `server_name` parameter is used to fill the SNI extension; the
* X.509 "minimal" engine will also match that name against the server
* names included in the server's certificate. If the parameter is
* `NULL` then no SNI extension will be sent, and the X.509 "minimal"
* engine (if used for server certificate validation) will not check
* presence of any specific name in the received certificate.
*
* Therefore, setting the `server_name` to `NULL` shall be reserved
* to cases where alternate or additional methods are used to ascertain
* that the right server public key is used (e.g. a "known key" model).
*
* If `resume_session` is non-zero and the context was previously used
* then the session parameters may be reused (depending on whether the
* server previously sent a non-empty session ID, and accepts the session
* resumption). The session parameters for session resumption can also
* be set explicitly with `br_ssl_engine_set_session_parameters()`.
*
* On failure, the context is marked as failed, and this function
* returns 0. A possible failure condition is when no initial entropy
* was injected, and none could be obtained from the OS (either OS
* randomness gathering is not supported, or it failed).
*
* \param cc client context.
* \param server_name target server name, or `NULL`.
* \param resume_session non-zero to try session resumption.
* \return 0 on failure, 1 on success.
*/
int br_ssl_client_reset(br_ssl_client_context *cc,
const char *server_name, int resume_session);
/**
* \brief Forget any session in the context.
*
* This means that the next handshake that uses this context will
* necessarily be a full handshake (this applies both to new connections
* and to renegotiations).
*
* \param cc client context.
*/
static inline void
br_ssl_client_forget_session(br_ssl_client_context *cc)
{
cc->eng.session.session_id_len = 0;
}
/**
* \brief Set client certificate chain and key (single RSA case).
*
* This function sets a client certificate chain, that the client will
* send to the server whenever a client certificate is requested. This
* certificate uses an RSA public key; the corresponding private key is
* invoked for authentication. Trust anchor names sent by the server are
* ignored.
*
* The provided chain and private key are linked in the client context;
* they must remain valid as long as they may be used, i.e. normally
* for the duration of the connection, since they might be invoked
* again upon renegotiations.
*
* \param cc SSL client context.
* \param chain client certificate chain (SSL order: EE comes first).
* \param chain_len client chain length (number of certificates).
* \param sk client private key.
* \param irsasign RSA signature implementation (PKCS#1 v1.5).
*/
void br_ssl_client_set_single_rsa(br_ssl_client_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk, br_rsa_pkcs1_sign irsasign);
/*
* \brief Set the client certificate chain and key (single EC case).
*
* This function sets a client certificate chain, that the client will
* send to the server whenever a client certificate is requested. This
* certificate uses an EC public key; the corresponding private key is
* invoked for authentication. Trust anchor names sent by the server are
* ignored.
*
* The provided chain and private key are linked in the client context;
* they must remain valid as long as they may be used, i.e. normally
* for the duration of the connection, since they might be invoked
* again upon renegotiations.
*
* The `allowed_usages` is a combination of usages, namely
* `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`. The `BR_KEYTYPE_KEYX`
* value allows full static ECDH, while the `BR_KEYTYPE_SIGN` value
* allows ECDSA signatures. If ECDSA signatures are used, then an ECDSA
* signature implementation must be provided; otherwise, the `iecdsa`
* parameter may be 0.
*
* The `cert_issuer_key_type` value is either `BR_KEYTYPE_RSA` or
* `BR_KEYTYPE_EC`; it is the type of the public key used the the CA
* that issued (signed) the client certificate. That value is used with
* full static ECDH: support of the certificate by the server depends
* on how the certificate was signed. (Note: when using TLS 1.2, this
* parameter is ignored; but its value matters for TLS 1.0 and 1.1.)
*
* \param cc server context.
* \param chain server certificate chain to send.
* \param chain_len chain length (number of certificates).
* \param sk server private key (EC).
* \param allowed_usages allowed private key usages.
* \param cert_issuer_key_type issuing CA's key type.
* \param iec EC core implementation.
* \param iecdsa ECDSA signature implementation ("asn1" format).
*/
void br_ssl_client_set_single_ec(br_ssl_client_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk, unsigned allowed_usages,
unsigned cert_issuer_key_type,
const br_ec_impl *iec, br_ecdsa_sign iecdsa);
/**
* \brief Type for a "translated cipher suite", as an array of two
* 16-bit integers.
*
* The first element is the cipher suite identifier (as used on the wire).
* The second element is the concatenation of four 4-bit elements which
* characterise the cipher suite contents. In most to least significant
* order, these 4-bit elements are:
*
* - Bits 12 to 15: key exchange + server key type
*
* | val | symbolic constant | suite type | details |
* | :-- | :----------------------- | :---------- | :----------------------------------------------- |
* | 0 | `BR_SSLKEYX_RSA` | RSA | RSA key exchange, key is RSA (encryption) |
* | 1 | `BR_SSLKEYX_ECDHE_RSA` | ECDHE_RSA | ECDHE key exchange, key is RSA (signature) |
* | 2 | `BR_SSLKEYX_ECDHE_ECDSA` | ECDHE_ECDSA | ECDHE key exchange, key is EC (signature) |
* | 3 | `BR_SSLKEYX_ECDH_RSA` | ECDH_RSA | Key is EC (key exchange), cert signed with RSA |
* | 4 | `BR_SSLKEYX_ECDH_ECDSA` | ECDH_ECDSA | Key is EC (key exchange), cert signed with ECDSA |
*
* - Bits 8 to 11: symmetric encryption algorithm
*
* | val | symbolic constant | symmetric encryption | key strength (bits) |
* | :-- | :--------------------- | :------------------- | :------------------ |
* | 0 | `BR_SSLENC_3DES_CBC` | 3DES/CBC | 168 |
* | 1 | `BR_SSLENC_AES128_CBC` | AES-128/CBC | 128 |
* | 2 | `BR_SSLENC_AES256_CBC` | AES-256/CBC | 256 |
* | 3 | `BR_SSLENC_AES128_GCM` | AES-128/GCM | 128 |
* | 4 | `BR_SSLENC_AES256_GCM` | AES-256/GCM | 256 |
* | 5 | `BR_SSLENC_CHACHA20` | ChaCha20/Poly1305 | 256 |
*
* - Bits 4 to 7: MAC algorithm
*
* | val | symbolic constant | MAC type | details |
* | :-- | :----------------- | :----------- | :------------------------------------ |
* | 0 | `BR_SSLMAC_AEAD` | AEAD | No dedicated MAC (encryption is AEAD) |
* | 2 | `BR_SSLMAC_SHA1` | HMAC/SHA-1 | Value matches `br_sha1_ID` |
* | 4 | `BR_SSLMAC_SHA256` | HMAC/SHA-256 | Value matches `br_sha256_ID` |
* | 5 | `BR_SSLMAC_SHA384` | HMAC/SHA-384 | Value matches `br_sha384_ID` |
*
* - Bits 0 to 3: hash function for PRF when used with TLS-1.2
*
* | val | symbolic constant | hash function | details |
* | :-- | :----------------- | :------------ | :----------------------------------- |
* | 4 | `BR_SSLPRF_SHA256` | SHA-256 | Value matches `br_sha256_ID` |
* | 5 | `BR_SSLPRF_SHA384` | SHA-384 | Value matches `br_sha384_ID` |
*
* For instance, cipher suite `TLS_RSA_WITH_AES_128_GCM_SHA256` has
* standard identifier 0x009C, and is translated to 0x0304, for, in
* that order: RSA key exchange (0), AES-128/GCM (3), AEAD integrity (0),
* SHA-256 in the TLS PRF (4).
*/
typedef uint16_t br_suite_translated[2];
#ifndef BR_DOXYGEN_IGNORE
/*
* Constants are already documented in the br_suite_translated type.
*/
#define BR_SSLKEYX_RSA 0
#define BR_SSLKEYX_ECDHE_RSA 1
#define BR_SSLKEYX_ECDHE_ECDSA 2
#define BR_SSLKEYX_ECDH_RSA 3
#define BR_SSLKEYX_ECDH_ECDSA 4
#define BR_SSLENC_3DES_CBC 0
#define BR_SSLENC_AES128_CBC 1
#define BR_SSLENC_AES256_CBC 2
#define BR_SSLENC_AES128_GCM 3
#define BR_SSLENC_AES256_GCM 4
#define BR_SSLENC_CHACHA20 5
#define BR_SSLMAC_AEAD 0
#define BR_SSLMAC_SHA1 br_sha1_ID
#define BR_SSLMAC_SHA256 br_sha256_ID
#define BR_SSLMAC_SHA384 br_sha384_ID
#define BR_SSLPRF_SHA256 br_sha256_ID
#define BR_SSLPRF_SHA384 br_sha384_ID
#endif
/*
* Pre-declaration for the SSL server context.
*/
typedef struct br_ssl_server_context_ br_ssl_server_context;
/**
* \brief Type for the server policy choices, taken after analysis of
* the client message (ClientHello).
*/
typedef struct {
/**
* \brief Cipher suite to use with that client.
*/
uint16_t cipher_suite;
/**
* \brief Hash function or algorithm for signing the ServerKeyExchange.
*
* This parameter is ignored for `TLS_RSA_*` and `TLS_ECDH_*`
* cipher suites; it is used only for `TLS_ECDHE_*` suites, in
* which the server _signs_ the ephemeral EC Diffie-Hellman
* parameters sent to the client.
*
* This identifier must be one of the following values:
*
* - `0xFF00 + id`, where `id` is a hash function identifier
* (0 for MD5+SHA-1, or 2 to 6 for one of the SHA functions);
*
* - a full 16-bit identifier, lower than `0xFF00`.
*
* If the first option is used, then the SSL engine will
* compute the hash of the data that is to be signed, with the
* designated hash function. The `do_sign()` method will be
* invoked with that hash value provided in the the `data`
* buffer.
*
* If the second option is used, then the SSL engine will NOT
* compute a hash on the data; instead, it will provide the
* to-be-signed data itself in `data`, i.e. the concatenation of
* the client random, server random, and encoded ECDH
* parameters. Furthermore, with TLS-1.2 and later, the 16-bit
* identifier will be used "as is" in the protocol, in the
* SignatureAndHashAlgorithm; for instance, `0x0401` stands for
* RSA PKCS#1 v1.5 signature (the `01`) with SHA-256 as hash
* function (the `04`).
*
* Take care that with TLS 1.0 and 1.1, the hash function is
* constrainted by the protocol: RSA signature must use
* MD5+SHA-1 (so use `0xFF00`), while ECDSA must use SHA-1
* (`0xFF02`). Since TLS 1.0 and 1.1 don't include a
* SignatureAndHashAlgorithm field in their ServerKeyExchange
* messages, any value below `0xFF00` will be usable to send the
* raw ServerKeyExchange data to the `do_sign()` callback, but
* that callback must still follow the protocol requirements
* when generating the signature.
*/
unsigned algo_id;
/**
* \brief Certificate chain to send to the client.
*
* This is an array of `br_x509_certificate` objects, each
* normally containing a DER-encoded certificate. The server
* code does not try to decode these elements.
*/
const br_x509_certificate *chain;
/**
* \brief Certificate chain length (number of certificates).
*/
size_t chain_len;
} br_ssl_server_choices;
/**
* \brief Class type for a policy handler (server side).
*
* A policy handler selects the policy parameters for a connection
* (cipher suite and other algorithms, and certificate chain to send to
* the client); it also performs the server-side computations involving
* its permanent private key.
*
* The SSL server engine will invoke first `choose()`, once the
* ClientHello message has been received, then either `do_keyx()`
* `do_sign()`, depending on the cipher suite.
*/
typedef struct br_ssl_server_policy_class_ br_ssl_server_policy_class;
struct br_ssl_server_policy_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Select algorithms and certificates for this connection.
*
* This callback function shall fill the provided `choices`
* structure with the policy choices for this connection. This
* entails selecting the cipher suite, hash function for signing
* the ServerKeyExchange (applicable only to ECDHE cipher suites),
* and certificate chain to send.
*
* The callback receives a pointer to the server context that
* contains the relevant data. In particular, the functions
* `br_ssl_server_get_client_suites()`,
* `br_ssl_server_get_client_hashes()` and
* `br_ssl_server_get_client_curves()` can be used to obtain
* the cipher suites, hash functions and elliptic curves
* supported by both the client and server, respectively. The
* `br_ssl_engine_get_version()` and `br_ssl_engine_get_server_name()`
* functions yield the protocol version and requested server name
* (SNI), respectively.
*
* This function may modify its context structure (`pctx`) in
* arbitrary ways to keep track of its own choices.
*
* This function shall return 1 if appropriate policy choices
* could be made, or 0 if this connection cannot be pursued.
*
* \param pctx policy context.
* \param cc SSL server context.
* \param choices destination structure for the policy choices.
* \return 1 on success, 0 on error.
*/
int (*choose)(const br_ssl_server_policy_class **pctx,
const br_ssl_server_context *cc,
br_ssl_server_choices *choices);
/**
* \brief Perform key exchange (server part).
*
* This callback is invoked to perform the server-side cryptographic
* operation for a key exchange that is not ECDHE. This callback
* uses the private key.
*
* **For RSA key exchange**, the provided `data` (of length `*len`
* bytes) shall be decrypted with the server's private key, and
* the 48-byte premaster secret copied back to the first 48 bytes
* of `data`.
*
* - The caller makes sure that `*len` is at least 59 bytes.
*
* - This callback MUST check that the provided length matches
* that of the key modulus; it shall report an error otherwise.
*
* - If the length matches that of the RSA key modulus, then
* processing MUST be constant-time, even if decryption fails,
* or the padding is incorrect, or the plaintext message length
* is not exactly 48 bytes.
*
* - This callback needs not check the two first bytes of the
* obtained pre-master secret (the caller will do that).
*
* - If an error is reported (0), then what the callback put
* in the first 48 bytes of `data` is unimportant (the caller
* will use random bytes instead).
*
* **For ECDH key exchange**, the provided `data` (of length `*len`
* bytes) is the elliptic curve point from the client. The
* callback shall multiply it with its private key, and store
* the resulting X coordinate in `data`, starting at offset 0,
* and set `*len` to the length of the X coordinate.
*
* - If the input array does not have the proper length for
* an encoded curve point, then an error (0) shall be reported.
*
* - If the input array has the proper length, then processing
* MUST be constant-time, even if the data is not a valid
* encoded point.
*
* - This callback MUST check that the input point is valid.
*
* Returned value is 1 on success, 0 on error.
*
* \param pctx policy context.
* \param data key exchange data from the client.
* \param len key exchange data length (in bytes).
* \return 1 on success, 0 on error.
*/
uint32_t (*do_keyx)(const br_ssl_server_policy_class **pctx,
unsigned char *data, size_t *len);
/**
* \brief Perform a signature (for a ServerKeyExchange message).
*
* This callback function is invoked for ECDHE cipher suites. On
* input, the hash value or message to sign is in `data`, of
* size `hv_len`; the involved hash function or algorithm is
* identified by `algo_id`. The signature shall be computed and
* written back into `data`; the total size of that buffer is
* `len` bytes.
*
* This callback shall verify that the signature length does not
* exceed `len` bytes, and abstain from writing the signature if
* it does not fit.
*
* The `algo_id` value matches that which was written in the
* `choices` structures by the `choose()` callback. This will be
* one of the following:
*
* - `0xFF00 + id` for a hash function identifier `id`. In
* that case, the `data` buffer contains a hash value
* already computed over the data that is to be signed,
* of length `hv_len`. The `id` may be 0 to designate the
* special MD5+SHA-1 concatenation (old-style RSA signing).
*
* - Another value, lower than `0xFF00`. The `data` buffer
* then contains the raw, non-hashed data to be signed
* (concatenation of the client and server randoms and
* ECDH parameters). The callback is responsible to apply
* any relevant hashing as part of the signing process.
*
* Returned value is the signature length (in bytes), or 0 on error.
*
* \param pctx policy context.
* \param algo_id hash function / algorithm identifier.
* \param data input/output buffer (message/hash, then signature).
* \param hv_len hash value or message length (in bytes).
* \param len total buffer length (in bytes).
* \return signature length (in bytes) on success, or 0 on error.
*/
size_t (*do_sign)(const br_ssl_server_policy_class **pctx,
unsigned algo_id,
unsigned char *data, size_t hv_len, size_t len);
};
/**
* \brief A single-chain RSA policy handler.
*
* This policy context uses a single certificate chain, and a RSA
* private key. The context can be restricted to only signatures or
* only key exchange.
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_server_policy_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_rsa_private_key *sk;
unsigned allowed_usages;
br_rsa_private irsacore;
br_rsa_pkcs1_sign irsasign;
#endif
} br_ssl_server_policy_rsa_context;
/**
* \brief A single-chain EC policy handler.
*
* This policy context uses a single certificate chain, and an EC
* private key. The context can be restricted to only signatures or
* only key exchange.
*
* Due to how TLS is defined, this context must be made aware whether
* the server certificate was itself signed with RSA or ECDSA. The code
* does not try to decode the certificate to obtain that information.
*
* Apart from the first field (vtable pointer), its contents are
* opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_server_policy_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
const br_x509_certificate *chain;
size_t chain_len;
const br_ec_private_key *sk;
unsigned allowed_usages;
unsigned cert_issuer_key_type;
const br_multihash_context *mhash;
const br_ec_impl *iec;
br_ecdsa_sign iecdsa;
#endif
} br_ssl_server_policy_ec_context;
/**
* \brief Class type for a session parameter cache.
*
* Session parameters are saved in the cache with `save()`, and
* retrieved with `load()`. The cache implementation can apply any
* storage and eviction strategy that it sees fit. The SSL server
* context that performs the request is provided, so that its
* functionalities may be used by the implementation (e.g. hash
* functions or random number generation).
*/
typedef struct br_ssl_session_cache_class_ br_ssl_session_cache_class;
struct br_ssl_session_cache_class_ {
/**
* \brief Context size (in bytes).
*/
size_t context_size;
/**
* \brief Record a session.
*
* This callback should record the provided session parameters.
* The `params` structure is transient, so its contents shall
* be copied into the cache. The session ID has been randomly
* generated and always has length exactly 32 bytes.
*
* \param ctx session cache context.
* \param server_ctx SSL server context.
* \param params session parameters to save.
*/
void (*save)(const br_ssl_session_cache_class **ctx,
br_ssl_server_context *server_ctx,
const br_ssl_session_parameters *params);
/**
* \brief Lookup a session in the cache.
*
* The session ID to lookup is in `params` and always has length
* exactly 32 bytes. If the session parameters are found in the
* cache, then the parameters shall be copied into the `params`
* structure. Returned value is 1 on successful lookup, 0
* otherwise.
*
* \param ctx session cache context.
* \param server_ctx SSL server context.
* \param params destination for session parameters.
* \return 1 if found, 0 otherwise.
*/
int (*load)(const br_ssl_session_cache_class **ctx,
br_ssl_server_context *server_ctx,
br_ssl_session_parameters *params);
};
/**
* \brief Context for a basic cache system.
*
* The system stores session parameters in a buffer provided at
* initialisation time. Each entry uses exactly 100 bytes, and
* buffer sizes up to 4294967295 bytes are supported.
*
* Entries are evicted with a LRU (Least Recently Used) policy. A
* search tree is maintained to keep lookups fast even with large
* caches.
*
* Apart from the first field (vtable pointer), the structure
* contents are opaque and shall not be accessed directly.
*/
typedef struct {
/** \brief Pointer to vtable. */
const br_ssl_session_cache_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
unsigned char *store;
size_t store_len, store_ptr;
unsigned char index_key[32];
const br_hash_class *hash;
int init_done;
uint32_t head, tail, root;
#endif
} br_ssl_session_cache_lru;
/**
* \brief Initialise a LRU session cache with the provided storage space.
*
* The provided storage space must remain valid as long as the cache
* is used. Arbitrary lengths are supported, up to 4294967295 bytes;
* each entry uses up exactly 100 bytes.
*
* \param cc session cache context.
* \param store storage space for cached entries.
* \param store_len storage space length (in bytes).
*/
void br_ssl_session_cache_lru_init(br_ssl_session_cache_lru *cc,
unsigned char *store, size_t store_len);
/**
* \brief Forget an entry in an LRU session cache.
*
* The session cache context must have been initialised. The entry
* with the provided session ID (of exactly 32 bytes) is looked for
* in the cache; if located, it is disabled.
*
* \param cc session cache context.
* \param id session ID to forget.
*/
void br_ssl_session_cache_lru_forget(
br_ssl_session_cache_lru *cc, const unsigned char *id);
/**
* \brief Context structure for a SSL server.
*
* The first field (called `eng`) is the SSL engine; all functions that
* work on a `br_ssl_engine_context` structure shall take as parameter
* a pointer to that field. The other structure fields are opaque and
* must not be accessed directly.
*/
struct br_ssl_server_context_ {
/**
* \brief The encapsulated engine context.
*/
br_ssl_engine_context eng;
#ifndef BR_DOXYGEN_IGNORE
/*
* Maximum version from the client.
*/
uint16_t client_max_version;
/*
* Session cache.
*/
const br_ssl_session_cache_class **cache_vtable;
/*
* Translated cipher suites supported by the client. The list
* is trimmed to include only the cipher suites that the
* server also supports; they are in the same order as in the
* client message.
*/
br_suite_translated client_suites[BR_MAX_CIPHER_SUITES];
unsigned char client_suites_num;
/*
* Hash functions supported by the client, with ECDSA and RSA
* (bit mask). For hash function with id 'x', set bit index is
* x for RSA, x+8 for ECDSA. For newer algorithms, with ID
* 0x08**, bit 16+k is set for algorithm 0x0800+k.
*/
uint32_t hashes;
/*
* Curves supported by the client (bit mask, for named curves).
*/
uint32_t curves;
/*
* Context for chain handler.
*/
const br_ssl_server_policy_class **policy_vtable;
uint16_t sign_hash_id;
/*
* For the core handlers, thus avoiding (in most cases) the
* need for an externally provided policy context.
*/
union {
const br_ssl_server_policy_class *vtable;
br_ssl_server_policy_rsa_context single_rsa;
br_ssl_server_policy_ec_context single_ec;
} chain_handler;
/*
* Buffer for the ECDHE private key.
*/
unsigned char ecdhe_key[70];
size_t ecdhe_key_len;
/*
* Trust anchor names for client authentication. "ta_names" and
* "tas" cannot be both non-NULL.
*/
const br_x500_name *ta_names;
const br_x509_trust_anchor *tas;
size_t num_tas;
size_t cur_dn_index;
const unsigned char *cur_dn;
size_t cur_dn_len;
/*
* Buffer for the hash value computed over all handshake messages
* prior to CertificateVerify, and identifier for the hash function.
*/
unsigned char hash_CV[64];
size_t hash_CV_len;
int hash_CV_id;
/*
* Server-specific implementations.
* (none for now)
*/
#endif
};
/*
* Each br_ssl_server_init_xxx() function sets the list of supported
* cipher suites and used implementations, as specified by the profile
* name 'xxx'. Defined profile names are:
*
* full_rsa all supported algorithm, server key type is RSA
* full_ec all supported algorithm, server key type is EC
* TODO: add other profiles
*
* Naming scheme for "minimal" profiles: min123
*
* -- character 1: key exchange
* r = RSA
* e = ECDHE_RSA
* f = ECDHE_ECDSA
* u = ECDH_RSA
* v = ECDH_ECDSA
* -- character 2: version / PRF
* 0 = TLS 1.0 / 1.1 with MD5+SHA-1
* 2 = TLS 1.2 with SHA-256
* 3 = TLS 1.2 with SHA-384
* -- character 3: encryption
* a = AES/CBC
* d = 3DES/CBC
* g = AES/GCM
* c = ChaCha20+Poly1305
*/
/**
* \brief SSL server profile: full_rsa.
*
* This function initialises the provided SSL server context with
* all supported algorithms and cipher suites that rely on a RSA
* key pair.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: full_ec.
*
* This function initialises the provided SSL server context with
* all supported algorithms and cipher suites that rely on an EC
* key pair.
*
* The key type of the CA that issued the server's certificate must
* be provided, since it matters for ECDH cipher suites (ECDH_RSA
* suites require a RSA-powered CA). The key type is either
* `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len chain length (number of certificates).
* \param cert_issuer_key_type certificate issuer's key type.
* \param sk EC private key.
*/
void br_ssl_server_init_full_ec(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
unsigned cert_issuer_key_type, const br_ec_private_key *sk);
/**
* \brief SSL server profile: minr2g.
*
* This profile uses only TLS_RSA_WITH_AES_128_GCM_SHA256. Server key is
* RSA, and RSA key exchange is used (not forward secure, but uses little
* CPU in the client).
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_minr2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: mine2g.
*
* This profile uses only TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256. Server key
* is RSA, and ECDHE key exchange is used. This suite provides forward
* security, with a higher CPU expense on the client, and a somewhat
* larger code footprint (compared to "minr2g").
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_mine2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: minf2g.
*
* This profile uses only TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
* Server key is EC, and ECDHE key exchange is used. This suite provides
* forward security, with a higher CPU expense on the client and server
* (by a factor of about 3 to 4), and a somewhat larger code footprint
* (compared to "minu2g" and "minv2g").
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minf2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief SSL server profile: minu2g.
*
* This profile uses only TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256.
* Server key is EC, and ECDH key exchange is used; the issuing CA used
* a RSA key.
*
* The "minu2g" and "minv2g" profiles do not provide forward secrecy,
* but are the lightest on the server (for CPU usage), and are rather
* inexpensive on the client as well.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minu2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief SSL server profile: minv2g.
*
* This profile uses only TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256.
* Server key is EC, and ECDH key exchange is used; the issuing CA used
* an EC key.
*
* The "minu2g" and "minv2g" profiles do not provide forward secrecy,
* but are the lightest on the server (for CPU usage), and are rather
* inexpensive on the client as well.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minv2g(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief SSL server profile: mine2c.
*
* This profile uses only TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
* Server key is RSA, and ECDHE key exchange is used. This suite
* provides forward security.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk RSA private key.
*/
void br_ssl_server_init_mine2c(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk);
/**
* \brief SSL server profile: minf2c.
*
* This profile uses only TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256.
* Server key is EC, and ECDHE key exchange is used. This suite provides
* forward security.
*
* \param cc server context to initialise.
* \param chain server certificate chain.
* \param chain_len certificate chain length (number of certificate).
* \param sk EC private key.
*/
void br_ssl_server_init_minf2c(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk);
/**
* \brief Get the supported client suites.
*
* This function shall be called only after the ClientHello has been
* processed, typically from the policy engine. The returned array
* contains the cipher suites that are supported by both the client
* and the server; these suites are in client preference order, unless
* the `BR_OPT_ENFORCE_SERVER_PREFERENCES` flag was set, in which case
* they are in server preference order.
*
* The suites are _translated_, which means that each suite is given
* as two 16-bit integers: the standard suite identifier, and its
* translated version, broken down into its individual components,
* as explained with the `br_suite_translated` type.
*
* The returned array is allocated in the context and will be rewritten
* by each handshake.
*
* \param cc server context.
* \param num receives the array size (number of suites).
* \return the translated common cipher suites, in preference order.
*/
static inline const br_suite_translated *
br_ssl_server_get_client_suites(const br_ssl_server_context *cc, size_t *num)
{
*num = cc->client_suites_num;
return cc->client_suites;
}
/**
* \brief Get the hash functions and signature algorithms supported by
* the client.
*
* This value is a bit field:
*
* - If RSA (PKCS#1 v1.5) is supported with hash function of ID `x`,
* then bit `x` is set (hash function ID is 0 for the special MD5+SHA-1,
* or 2 to 6 for the SHA family).
*
* - If ECDSA is supported with hash function of ID `x`, then bit `8+x`
* is set.
*
* - Newer algorithms are symbolic 16-bit identifiers that do not
* represent signature algorithm and hash function separately. If
* the TLS-level identifier is `0x0800+x` for a `x` in the 0..15
* range, then bit `16+x` is set.
*
* "New algorithms" are currently defined only in draft documents, so
* this support is subject to possible change. Right now (early 2017),
* this maps ed25519 (EdDSA on Curve25519) to bit 23, and ed448 (EdDSA
* on Curve448) to bit 24. If the identifiers on the wire change in
* future document, then the decoding mechanism in BearSSL will be
* amended to keep mapping ed25519 and ed448 on bits 23 and 24,
* respectively. Mapping of other new algorithms (e.g. RSA/PSS) is not
* guaranteed yet.
*
* \param cc server context.
* \return the client-supported hash functions and signature algorithms.
*/
static inline uint32_t
br_ssl_server_get_client_hashes(const br_ssl_server_context *cc)
{
return cc->hashes;
}
/**
* \brief Get the elliptic curves supported by the client.
*
* This is a bit field (bit x is set if curve of ID x is supported).
*
* \param cc server context.
* \return the client-supported elliptic curves.
*/
static inline uint32_t
br_ssl_server_get_client_curves(const br_ssl_server_context *cc)
{
return cc->curves;
}
/**
* \brief Clear the complete contents of a SSL server context.
*
* Everything is cleared, including the reference to the configured buffer,
* implementations, cipher suites and state. This is a preparatory step
* to assembling a custom profile.
*
* \param cc server context to clear.
*/
void br_ssl_server_zero(br_ssl_server_context *cc);
/**
* \brief Set an externally provided policy context.
*
* The policy context's methods are invoked to decide the cipher suite
* and certificate chain, and to perform operations involving the server's
* private key.
*
* \param cc server context.
* \param pctx policy context (pointer to its vtable field).
*/
static inline void
br_ssl_server_set_policy(br_ssl_server_context *cc,
const br_ssl_server_policy_class **pctx)
{
cc->policy_vtable = pctx;
}
/**
* \brief Set the server certificate chain and key (single RSA case).
*
* This function uses a policy context included in the server context.
* It configures use of a single server certificate chain with a RSA
* private key. The `allowed_usages` is a combination of usages, namely
* `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
* the corresponding cipher suites (i.e. `TLS_RSA_*` use the RSA key for
* key exchange, while `TLS_ECDHE_RSA_*` use the RSA key for signatures).
*
* \param cc server context.
* \param chain server certificate chain to send to the client.
* \param chain_len chain length (number of certificates).
* \param sk server private key (RSA).
* \param allowed_usages allowed private key usages.
* \param irsacore RSA core implementation.
* \param irsasign RSA signature implementation (PKCS#1 v1.5).
*/
void br_ssl_server_set_single_rsa(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_rsa_private_key *sk, unsigned allowed_usages,
br_rsa_private irsacore, br_rsa_pkcs1_sign irsasign);
/**
* \brief Set the server certificate chain and key (single EC case).
*
* This function uses a policy context included in the server context.
* It configures use of a single server certificate chain with an EC
* private key. The `allowed_usages` is a combination of usages, namely
* `BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`; this enables or disables
* the corresponding cipher suites (i.e. `TLS_ECDH_*` use the EC key for
* key exchange, while `TLS_ECDHE_ECDSA_*` use the EC key for signatures).
*
* In order to support `TLS_ECDH_*` cipher suites (non-ephemeral ECDH),
* the algorithm type of the key used by the issuing CA to sign the
* server's certificate must be provided, as `cert_issuer_key_type`
* parameter (this value is either `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`).
*
* \param cc server context.
* \param chain server certificate chain to send.
* \param chain_len chain length (number of certificates).
* \param sk server private key (EC).
* \param allowed_usages allowed private key usages.
* \param cert_issuer_key_type issuing CA's key type.
* \param iec EC core implementation.
* \param iecdsa ECDSA signature implementation ("asn1" format).
*/
void br_ssl_server_set_single_ec(br_ssl_server_context *cc,
const br_x509_certificate *chain, size_t chain_len,
const br_ec_private_key *sk, unsigned allowed_usages,
unsigned cert_issuer_key_type,
const br_ec_impl *iec, br_ecdsa_sign iecdsa);
/**
* \brief Activate client certificate authentication.
*
* The trust anchor encoded X.500 names (DN) to send to the client are
* provided. A client certificate will be requested and validated through
* the X.509 validator configured in the SSL engine. If `num` is 0, then
* client certificate authentication is disabled.
*
* If the client does not send a certificate, or on validation failure,
* the handshake aborts. Unauthenticated clients can be tolerated by
* setting the `BR_OPT_TOLERATE_NO_CLIENT_AUTH` flag.
*
* The provided array is linked in, not copied, so that pointer must
* remain valid as long as anchor names may be used.
*
* \param cc server context.
* \param ta_names encoded trust anchor names.
* \param num number of encoded trust anchor names.
*/
static inline void
br_ssl_server_set_trust_anchor_names(br_ssl_server_context *cc,
const br_x500_name *ta_names, size_t num)
{
cc->ta_names = ta_names;
cc->tas = NULL;
cc->num_tas = num;
}
/**
* \brief Activate client certificate authentication.
*
* This is a variant for `br_ssl_server_set_trust_anchor_names()`: the
* trust anchor names are provided not as an array of stand-alone names
* (`br_x500_name` structures), but as an array of trust anchors
* (`br_x509_trust_anchor` structures). The server engine itself will
* only use the `dn` field of each trust anchor. This is meant to allow
* defining a single array of trust anchors, to be used here and in the
* X.509 validation engine itself.
*
* The provided array is linked in, not copied, so that pointer must
* remain valid as long as anchor names may be used.
*
* \param cc server context.
* \param tas trust anchors (only names are used).
* \param num number of trust anchors.
*/
static inline void
br_ssl_server_set_trust_anchor_names_alt(br_ssl_server_context *cc,
const br_x509_trust_anchor *tas, size_t num)
{
cc->ta_names = NULL;
cc->tas = tas;
cc->num_tas = num;
}
/**
* \brief Configure the cache for session parameters.
*
* The cache context is provided as a pointer to its first field (vtable
* pointer).
*
* \param cc server context.
* \param vtable session cache context.
*/
static inline void
br_ssl_server_set_cache(br_ssl_server_context *cc,
const br_ssl_session_cache_class **vtable)
{
cc->cache_vtable = vtable;
}
/**
* \brief Prepare or reset a server context for handling an incoming client.
*
* \param cc server context.
* \return 1 on success, 0 on error.
*/
int br_ssl_server_reset(br_ssl_server_context *cc);
/* ===================================================================== */
/*
* Context for the simplified I/O context. The transport medium is accessed
* through the low_read() and low_write() callback functions, each with
* its own opaque context pointer.
*
* low_read() read some bytes, at most 'len' bytes, into data[]. The
* returned value is the number of read bytes, or -1 on error.
* The 'len' parameter is guaranteed never to exceed 20000,
* so the length always fits in an 'int' on all platforms.
*
* low_write() write up to 'len' bytes, to be read from data[]. The
* returned value is the number of written bytes, or -1 on
* error. The 'len' parameter is guaranteed never to exceed
* 20000, so the length always fits in an 'int' on all
* parameters.
*
* A socket closure (if the transport medium is a socket) should be reported
* as an error (-1). The callbacks shall endeavour to block until at least
* one byte can be read or written; a callback returning 0 at times is
* acceptable, but this normally leads to the callback being immediately
* called again, so the callback should at least always try to block for
* some time if no I/O can take place.
*
* The SSL engine naturally applies some buffering, so the callbacks need
* not apply buffers of their own.
*/
/**
* \brief Context structure for the simplified SSL I/O wrapper.
*
* This structure is initialised with `br_sslio_init()`. Its contents
* are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
br_ssl_engine_context *engine;
int (*low_read)(void *read_context,
unsigned char *data, size_t len);
void *read_context;
int (*low_write)(void *write_context,
const unsigned char *data, size_t len);
void *write_context;
#endif
} br_sslio_context;
/**
* \brief Initialise a simplified I/O wrapper context.
*
* The simplified I/O wrapper offers a simpler read/write API for a SSL
* engine (client or server), using the provided callback functions for
* reading data from, or writing data to, the transport medium.
*
* The callback functions have the following semantics:
*
* - Each callback receives an opaque context value (of type `void *`)
* that the callback may use arbitrarily (or possibly ignore).
*
* - `low_read()` reads at least one byte, at most `len` bytes, from
* the transport medium. Read bytes shall be written in `data`.
*
* - `low_write()` writes at least one byte, at most `len` bytes, unto
* the transport medium. The bytes to write are read from `data`.
*
* - The `len` parameter is never zero, and is always lower than 20000.
*
* - The number of processed bytes (read or written) is returned. Since
* that number is less than 20000, it always fits on an `int`.
*
* - On error, the callbacks return -1. Reaching end-of-stream is an
* error. Errors are permanent: the SSL connection is terminated.
*
* - Callbacks SHOULD NOT return 0. This is tolerated, as long as
* callbacks endeavour to block for some non-negligible amount of
* time until at least one byte can be sent or received (if a
* callback returns 0, then the wrapper invokes it again
* immediately).
*
* - Callbacks MAY return as soon as at least one byte is processed;
* they MAY also insist on reading or writing _all_ requested bytes.
* Since SSL is a self-terminated protocol (each record has a length
* header), this does not change semantics.
*
* - Callbacks need not apply any buffering (for performance) since SSL
* itself uses buffers.
*
* \param ctx wrapper context to initialise.
* \param engine SSL engine to wrap.
* \param low_read callback for reading data from the transport.
* \param read_context context pointer for `low_read()`.
* \param low_write callback for writing data on the transport.
* \param write_context context pointer for `low_write()`.
*/
void br_sslio_init(br_sslio_context *ctx,
br_ssl_engine_context *engine,
int (*low_read)(void *read_context,
unsigned char *data, size_t len),
void *read_context,
int (*low_write)(void *write_context,
const unsigned char *data, size_t len),
void *write_context);
/**
* \brief Read some application data from a SSL connection.
*
* If `len` is zero, then this function returns 0 immediately. In
* all other cases, it never returns 0.
*
* This call returns only when at least one byte has been obtained.
* Returned value is the number of bytes read, or -1 on error. The
* number of bytes always fits on an 'int' (data from a single SSL/TLS
* record is returned).
*
* On error or SSL closure, this function returns -1. The caller should
* inspect the error status on the SSL engine to distinguish between
* normal closure and error.
*
* \param cc SSL wrapper context.
* \param dst destination buffer for application data.
* \param len maximum number of bytes to obtain.
* \return number of bytes obtained, or -1 on error.
*/
int br_sslio_read(br_sslio_context *cc, void *dst, size_t len);
/**
* \brief Read application data from a SSL connection.
*
* This calls returns only when _all_ requested `len` bytes are read,
* or an error is reached. Returned value is 0 on success, -1 on error.
* A normal (verified) SSL closure before that many bytes are obtained
* is reported as an error by this function.
*
* \param cc SSL wrapper context.
* \param dst destination buffer for application data.
* \param len number of bytes to obtain.
* \return 0 on success, or -1 on error.
*/
int br_sslio_read_all(br_sslio_context *cc, void *dst, size_t len);
/**
* \brief Write some application data unto a SSL connection.
*
* If `len` is zero, then this function returns 0 immediately. In
* all other cases, it never returns 0.
*
* This call returns only when at least one byte has been written.
* Returned value is the number of bytes written, or -1 on error. The
* number of bytes always fits on an 'int' (less than 20000).
*
* On error or SSL closure, this function returns -1. The caller should
* inspect the error status on the SSL engine to distinguish between
* normal closure and error.
*
* **Important:** SSL is buffered; a "written" byte is a byte that was
* injected into the wrapped SSL engine, but this does not necessarily mean
* that it has been scheduled for sending. Use `br_sslio_flush()` to
* ensure that all pending data has been sent to the transport medium.
*
* \param cc SSL wrapper context.
* \param src source buffer for application data.
* \param len maximum number of bytes to write.
* \return number of bytes written, or -1 on error.
*/
int br_sslio_write(br_sslio_context *cc, const void *src, size_t len);
/**
* \brief Write application data unto a SSL connection.
*
* This calls returns only when _all_ requested `len` bytes have been
* written, or an error is reached. Returned value is 0 on success, -1
* on error. A normal (verified) SSL closure before that many bytes are
* written is reported as an error by this function.
*
* **Important:** SSL is buffered; a "written" byte is a byte that was
* injected into the wrapped SSL engine, but this does not necessarily mean
* that it has been scheduled for sending. Use `br_sslio_flush()` to
* ensure that all pending data has been sent to the transport medium.
*
* \param cc SSL wrapper context.
* \param src source buffer for application data.
* \param len number of bytes to write.
* \return 0 on success, or -1 on error.
*/
int br_sslio_write_all(br_sslio_context *cc, const void *src, size_t len);
/**
* \brief Flush pending data.
*
* This call makes sure that any buffered application data in the
* provided context (including the wrapped SSL engine) has been sent
* to the transport medium (i.e. accepted by the `low_write()` callback
* method). If there is no such pending data, then this function does
* nothing (and returns a success, i.e. 0).
*
* If the underlying transport medium has its own buffers, then it is
* up to the caller to ensure the corresponding flushing.
*
* Returned value is 0 on success, -1 on error.
*
* \param cc SSL wrapper context.
* \return 0 on success, or -1 on error.
*/
int br_sslio_flush(br_sslio_context *cc);
/**
* \brief Close the SSL connection.
*
* This call runs the SSL closure protocol (sending a `close_notify`,
* receiving the response `close_notify`). When it returns, the SSL
* connection is finished. It is still up to the caller to manage the
* possible transport-level termination, if applicable (alternatively,
* the underlying transport stream may be reused for non-SSL messages).
*
* Returned value is 0 on success, -1 on error. A failure by the peer
* to process the complete closure protocol (i.e. sending back the
* `close_notify`) is an error.
*
* \param cc SSL wrapper context.
* \return 0 on success, or -1 on error.
*/
int br_sslio_close(br_sslio_context *cc);
/* ===================================================================== */
/*
* Symbolic constants for cipher suites.
*/
/* From RFC 5246 */
#define BR_TLS_NULL_WITH_NULL_NULL 0x0000
#define BR_TLS_RSA_WITH_NULL_MD5 0x0001
#define BR_TLS_RSA_WITH_NULL_SHA 0x0002
#define BR_TLS_RSA_WITH_NULL_SHA256 0x003B
#define BR_TLS_RSA_WITH_RC4_128_MD5 0x0004
#define BR_TLS_RSA_WITH_RC4_128_SHA 0x0005
#define BR_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A
#define BR_TLS_RSA_WITH_AES_128_CBC_SHA 0x002F
#define BR_TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
#define BR_TLS_RSA_WITH_AES_128_CBC_SHA256 0x003C
#define BR_TLS_RSA_WITH_AES_256_CBC_SHA256 0x003D
#define BR_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D
#define BR_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010
#define BR_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013
#define BR_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016
#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030
#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031
#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032
#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033
#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036
#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037
#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038
#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039
#define BR_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 0x003E
#define BR_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 0x003F
#define BR_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 0x0040
#define BR_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x0067
#define BR_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 0x0068
#define BR_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 0x0069
#define BR_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 0x006A
#define BR_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x006B
#define BR_TLS_DH_anon_WITH_RC4_128_MD5 0x0018
#define BR_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B
#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034
#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A
#define BR_TLS_DH_anon_WITH_AES_128_CBC_SHA256 0x006C
#define BR_TLS_DH_anon_WITH_AES_256_CBC_SHA256 0x006D
/* From RFC 4492 */
#define BR_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001
#define BR_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002
#define BR_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005
#define BR_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006
#define BR_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007
#define BR_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A
#define BR_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B
#define BR_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C
#define BR_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D
#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E
#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F
#define BR_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010
#define BR_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011
#define BR_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012
#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013
#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014
#define BR_TLS_ECDH_anon_WITH_NULL_SHA 0xC015
#define BR_TLS_ECDH_anon_WITH_RC4_128_SHA 0xC016
#define BR_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA 0xC017
#define BR_TLS_ECDH_anon_WITH_AES_128_CBC_SHA 0xC018
#define BR_TLS_ECDH_anon_WITH_AES_256_CBC_SHA 0xC019
/* From RFC 5288 */
#define BR_TLS_RSA_WITH_AES_128_GCM_SHA256 0x009C
#define BR_TLS_RSA_WITH_AES_256_GCM_SHA384 0x009D
#define BR_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x009E
#define BR_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x009F
#define BR_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 0x00A0
#define BR_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 0x00A1
#define BR_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 0x00A2
#define BR_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 0x00A3
#define BR_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 0x00A4
#define BR_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 0x00A5
#define BR_TLS_DH_anon_WITH_AES_128_GCM_SHA256 0x00A6
#define BR_TLS_DH_anon_WITH_AES_256_GCM_SHA384 0x00A7
/* From RFC 5289 */
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026
#define BR_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027
#define BR_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028
#define BR_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029
#define BR_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C
#define BR_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D
#define BR_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E
#define BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F
#define BR_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030
#define BR_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031
#define BR_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032
/* From RFC 6655 and 7251 */
#define BR_TLS_RSA_WITH_AES_128_CCM 0xC09C
#define BR_TLS_RSA_WITH_AES_256_CCM 0xC09D
#define BR_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0
#define BR_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD
#define BR_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
#define BR_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF
/* From RFC 7905 */
#define BR_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8
#define BR_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9
#define BR_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA
#define BR_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB
#define BR_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC
#define BR_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD
#define BR_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE
/* From RFC 7507 */
#define BR_TLS_FALLBACK_SCSV 0x5600
/*
* Symbolic constants for alerts.
*/
#define BR_ALERT_CLOSE_NOTIFY 0
#define BR_ALERT_UNEXPECTED_MESSAGE 10
#define BR_ALERT_BAD_RECORD_MAC 20
#define BR_ALERT_RECORD_OVERFLOW 22
#define BR_ALERT_DECOMPRESSION_FAILURE 30
#define BR_ALERT_HANDSHAKE_FAILURE 40
#define BR_ALERT_BAD_CERTIFICATE 42
#define BR_ALERT_UNSUPPORTED_CERTIFICATE 43
#define BR_ALERT_CERTIFICATE_REVOKED 44
#define BR_ALERT_CERTIFICATE_EXPIRED 45
#define BR_ALERT_CERTIFICATE_UNKNOWN 46
#define BR_ALERT_ILLEGAL_PARAMETER 47
#define BR_ALERT_UNKNOWN_CA 48
#define BR_ALERT_ACCESS_DENIED 49
#define BR_ALERT_DECODE_ERROR 50
#define BR_ALERT_DECRYPT_ERROR 51
#define BR_ALERT_PROTOCOL_VERSION 70
#define BR_ALERT_INSUFFICIENT_SECURITY 71
#define BR_ALERT_INTERNAL_ERROR 80
#define BR_ALERT_USER_CANCELED 90
#define BR_ALERT_NO_RENEGOTIATION 100
#define BR_ALERT_UNSUPPORTED_EXTENSION 110
#define BR_ALERT_NO_APPLICATION_PROTOCOL 120
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef BR_BEARSSL_PEM_H__
#define BR_BEARSSL_PEM_H__
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_pem.h
*
* # PEM Support
*
* PEM is a traditional encoding layer use to store binary objects (in
* particular X.509 certificates, and private keys) in text files. While
* the acronym comes from an old, defunct standard ("Privacy Enhanced
* Mail"), the format has been reused, with some variations, by many
* systems, and is a _de facto_ standard, even though it is not, actually,
* specified in all clarity anywhere.
*
* ## Format Details
*
* BearSSL contains a generic, streamed PEM decoder, which handles the
* following format:
*
* - The input source (a sequence of bytes) is assumed to be the
* encoding of a text file in an ASCII-compatible charset. This
* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each
* line ends on a newline character (U+000A LINE FEED). The
* U+000D CARRIAGE RETURN characters are ignored, so the code
* accepts both Windows-style and Unix-style line endings.
*
* - Each object begins with a banner that occurs at the start of
* a line; the first banner characters are "`-----BEGIN `" (five
* dashes, the word "BEGIN", and a space). The banner matching is
* not case-sensitive.
*
* - The _object name_ consists in the characters that follow the
* banner start sequence, up to the end of the line, but without
* trailing dashes (in "normal" PEM, there are five trailing
* dashes, but this implementation is not picky about these dashes).
* The BearSSL decoder normalises the name characters to uppercase
* (for ASCII letters only) and accepts names up to 127 characters.
*
* - The object ends with a banner that again occurs at the start of
* a line, and starts with "`-----END `" (again case-insensitive).
*
* - Between that start and end banner, only Base64 data shall occur.
* Base64 converts each sequence of three bytes into four
* characters; the four characters are ASCII letters, digits, "`+`"
* or "`-`" signs, and one or two "`=`" signs may occur in the last
* quartet. Whitespace is ignored (whitespace is any ASCII character
* of code 32 or less, so control characters are whitespace) and
* lines may have arbitrary length; the only restriction is that the
* four characters of a quartet must appear on the same line (no
* line break inside a quartet).
*
* - A single file may contain more than one PEM object. Bytes that
* occur between objects are ignored.
*
*
* ## PEM Decoder API
*
* The PEM decoder offers a state-machine API. The caller allocates a
* decoder context, then injects source bytes. Source bytes are pushed
* with `br_pem_decoder_push()`. The decoder stops accepting bytes when
* it reaches an "event", which is either the start of an object, the
* end of an object, or a decoding error within an object.
*
* The `br_pem_decoder_event()` function is used to obtain the current
* event; it also clears it, thus allowing the decoder to accept more
* bytes. When a object start event is raised, the decoder context
* offers the found object name (normalised to ASCII uppercase).
*
* When an object is reached, the caller must set an appropriate callback
* function, which will receive (by chunks) the decoded object data.
*
* Since the decoder context makes no dynamic allocation, it requires
* no explicit deallocation.
*/
/**
* \brief PEM decoder context.
*
* Contents are opaque (they should not be accessed directly).
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
const unsigned char *hbuf;
size_t hlen;
void (*dest)(void *dest_ctx, const void *src, size_t len);
void *dest_ctx;
unsigned char event;
char name[128];
unsigned char buf[255];
size_t ptr;
#endif
} br_pem_decoder_context;
/**
* \brief Initialise a PEM decoder structure.
*
* \param ctx decoder context to initialise.
*/
void br_pem_decoder_init(br_pem_decoder_context *ctx);
/**
* \brief Push some bytes into the decoder.
*
* Returned value is the number of bytes actually consumed; this may be
* less than the number of provided bytes if an event is raised. When an
* event is raised, it must be read (with `br_pem_decoder_event()`);
* until the event is read, this function will return 0.
*
* \param ctx decoder context.
* \param data new data bytes.
* \param len number of new data bytes.
* \return the number of bytes actually received (may be less than `len`).
*/
size_t br_pem_decoder_push(br_pem_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Set the receiver for decoded data.
*
* When an object is entered, the provided function (with opaque context
* pointer) will be called repeatedly with successive chunks of decoded
* data for that object. If `dest` is set to 0, then decoded data is
* simply ignored. The receiver can be set at any time, but, in practice,
* it should be called immediately after receiving a "start of object"
* event.
*
* \param ctx decoder context.
* \param dest callback for receiving decoded data.
* \param dest_ctx opaque context pointer for the `dest` callback.
*/
static inline void
br_pem_decoder_setdest(br_pem_decoder_context *ctx,
void (*dest)(void *dest_ctx, const void *src, size_t len),
void *dest_ctx)
{
ctx->dest = dest;
ctx->dest_ctx = dest_ctx;
}
/**
* \brief Get the last event.
*
* If an event was raised, then this function returns the event value, and
* also clears it, thereby allowing the decoder to proceed. If no event
* was raised since the last call to `br_pem_decoder_event()`, then this
* function returns 0.
*
* \param ctx decoder context.
* \return the raised event, or 0.
*/
int br_pem_decoder_event(br_pem_decoder_context *ctx);
/**
* \brief Event: start of object.
*
* This event is raised when the start of a new object has been detected.
* The object name (normalised to uppercase) can be accessed with
* `br_pem_decoder_name()`.
*/
#define BR_PEM_BEGIN_OBJ 1
/**
* \brief Event: end of object.
*
* This event is raised when the end of the current object is reached
* (normally, i.e. with no decoding error).
*/
#define BR_PEM_END_OBJ 2
/**
* \brief Event: decoding error.
*
* This event is raised when decoding fails within an object.
* This formally closes the current object and brings the decoder back
* to the "out of any object" state. The offending line in the source
* is consumed.
*/
#define BR_PEM_ERROR 3
/**
* \brief Get the name of the encountered object.
*
* The encountered object name is defined only when the "start of object"
* event is raised. That name is normalised to uppercase (for ASCII letters
* only) and does not include trailing dashes.
*
* \param ctx decoder context.
* \return the current object name.
*/
static inline const char *
br_pem_decoder_name(br_pem_decoder_context *ctx)
{
return ctx->name;
}
/**
* \brief Encode an object in PEM.
*
* This function encodes the provided binary object (`data`, of length `len`
* bytes) into PEM. The `banner` text will be included in the header and
* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).
*
* The length (in characters) of the PEM output is returned; that length
* does NOT include the terminating zero, that this function nevertheless
* adds. If using the returned value for allocation purposes, the allocated
* buffer size MUST be at least one byte larger than the returned size.
*
* If `dest` is `NULL`, then the encoding does not happen; however, the
* length of the encoded object is still computed and returned.
*
* The `data` pointer may be `NULL` only if `len` is zero (when encoding
* an object of length zero, which is not very useful), or when `dest`
* is `NULL` (in that case, source data bytes are ignored).
*
* Some `flags` can be specified to alter the encoding behaviour:
*
* - If `BR_PEM_LINE64` is set, then line-breaking will occur after
* every 64 characters of output, instead of the default of 76.
*
* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use
* CR+LF instead of a single LF.
*
* The `data` and `dest` buffers may overlap, in which case the source
* binary data is destroyed in the process. Note that the PEM-encoded output
* is always larger than the source binary.
*
* \param dest the destination buffer (or `NULL`).
* \param data the source buffer (can be `NULL` in some cases).
* \param len the source length (in bytes).
* \param banner the PEM banner expression.
* \param flags the behavioural flags.
* \return the PEM object length (in characters), EXCLUDING the final zero.
*/
size_t br_pem_encode(void *dest, const void *data, size_t len,
const char *banner, unsigned flags);
/**
* \brief PEM encoding flag: split lines at 64 characters.
*/
#define BR_PEM_LINE64 0x0001
/**
* \brief PEM encoding flag: use CR+LF line endings.
*/
#define BR_PEM_CRLF 0x0002
#ifdef __cplusplus
}
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \brief Type for a configuration option.
*
* A "configuration option" is a value that is selected when the BearSSL
* library itself is compiled. Most options are boolean; their value is
* then either 1 (option is enabled) or 0 (option is disabled). Some
* values have other integer values. Option names correspond to macro
* names. Some of the options can be explicitly set in the internal
* `"config.h"` file.
*/
typedef struct {
/** \brief Configurable option name. */
const char *name;
/** \brief Configurable option value. */
long value;
} br_config_option;
/** \brief Get configuration report.
*
* This function returns compiled configuration options, each as a
* 'long' value. Names match internal macro names, in particular those
* that can be set in the `"config.h"` inner file. For boolean options,
* the numerical value is 1 if enabled, 0 if disabled. For maximum
* key sizes, values are expressed in bits.
*
* The returned array is terminated by an entry whose `name` is `NULL`.
*
* \return the configuration report.
*/
const br_config_option *br_get_config(void);
/* ======================================================================= */
/** \brief Version feature: support for time callback. */
#define BR_FEATURE_X509_TIME_CALLBACK 1
#ifdef __cplusplus
}
#endif
#endif
/*
* On MSVC, disable the warning about applying unary minus on an
* unsigned type: it is standard, we do it all the time, and for
* good reasons.
*/
#if _MSC_VER
#pragma warning( disable : 4146 )
#endif
/*
* Maximum size for a RSA modulus (in bits). Allocated stack buffers
* depend on that size, so this value should be kept small. Currently,
* 2048-bit RSA keys offer adequate security, and should still do so for
* the next few decades; however, a number of widespread PKI have
* already set their root keys to RSA-4096, so we should be able to
* process such keys.
*
* This value MUST be a multiple of 64. This value MUST NOT exceed 47666
* (some computations in RSA key generation rely on the factor size being
* no more than 23833 bits). RSA key sizes beyond 3072 bits don't make a
* lot of sense anyway.
*/
#define BR_MAX_RSA_SIZE 4096
/*
* Minimum size for a RSA modulus (in bits); this value is used only to
* filter out invalid parameters for key pair generation. Normally,
* applications should not use RSA keys smaller than 2048 bits; but some
* specific cases might need shorter keys, for legacy or research
* purposes.
*/
#define BR_MIN_RSA_SIZE 512
/*
* Maximum size for a RSA factor (in bits). This is for RSA private-key
* operations. Default is to support factors up to a bit more than half
* the maximum modulus size.
*
* This value MUST be a multiple of 32.
*/
#define BR_MAX_RSA_FACTOR ((BR_MAX_RSA_SIZE + 64) >> 1)
/*
* Maximum size for an EC curve (modulus or order), in bits. Size of
* stack buffers depends on that parameter. This size MUST be a multiple
* of 8 (so that decoding an integer with that many bytes does not
* overflow).
*/
#define BR_MAX_EC_SIZE 528
/*
* Some macros to recognize the current architecture. Right now, we are
* interested into automatically recognizing architecture with efficient
* 64-bit types so that we may automatically use implementations that
* use 64-bit registers in that case. Future versions may detect, e.g.,
* availability of SSE2 intrinsics.
*
* If 'unsigned long' is a 64-bit type, then we assume that 64-bit types
* are efficient. Otherwise, we rely on macros that depend on compiler,
* OS and architecture. In any case, failure to detect the architecture
* as 64-bit means that the 32-bit code will be used, and that code
* works also on 64-bit architectures (the 64-bit code may simply be
* more efficient).
*
* The test on 'unsigned long' should already catch most cases, the one
* notable exception being Windows code where 'unsigned long' is kept to
* 32-bit for compatibility with all the legacy code that liberally uses
* the 'DWORD' type for 32-bit values.
*
* Macro names are taken from: https://nadeausoftware.com/articles/2012/02/c_c_tip_how_detect_processor_type_using_compiler_predefined_macros
*/
#ifndef BR_64
#if ((ULONG_MAX >> 31) >> 31) == 3
#define BR_64 1
#elif defined(__ia64) || defined(__itanium__) || defined(_M_IA64)
#define BR_64 1
#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \
|| defined(__64BIT__) || defined(_LP64) || defined(__LP64__)
#define BR_64 1
#elif defined(__sparc64__)
#define BR_64 1
#elif defined(__x86_64__) || defined(_M_X64)
#define BR_64 1
#elif defined(__aarch64__) || defined(_M_ARM64)
#define BR_64 1
#elif defined(__mips64)
#define BR_64 1
#endif
#endif
/*
* Set BR_LOMUL on platforms where it makes sense.
*/
#ifndef BR_LOMUL
#if BR_ARMEL_CORTEXM_GCC
#define BR_LOMUL 1
#endif
#endif
/*
* Architecture detection.
*/
#ifndef BR_i386
#if __i386__ || _M_IX86
#define BR_i386 1
#endif
#endif
#ifndef BR_amd64
#if __x86_64__ || _M_X64
#define BR_amd64 1
#endif
#endif
/*
* Compiler brand and version.
*
* Implementations that use intrinsics need to detect the compiler type
* and version because some specific actions may be needed to activate
* the corresponding opcodes, both for header inclusion, and when using
* them in a function.
*
* BR_GCC, BR_CLANG and BR_MSC will be set to 1 for, respectively, GCC,
* Clang and MS Visual C. For each of them, sub-macros will be defined
* for versions; each sub-macro is set whenever the compiler version is
* at least as recent as the one corresponding to the macro.
*/
/*
* GCC thresholds are on versions 4.4 to 4.9 and 5.0.
*/
#ifndef BR_GCC
#if __GNUC__ && !__clang__
#define BR_GCC 1
#if __GNUC__ > 4
#define BR_GCC_5_0 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
#define BR_GCC_4_9 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8
#define BR_GCC_4_8 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7
#define BR_GCC_4_7 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6
#define BR_GCC_4_6 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 5
#define BR_GCC_4_5 1
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 4
#define BR_GCC_4_4 1
#endif
#if BR_GCC_5_0
#define BR_GCC_4_9 1
#endif
#if BR_GCC_4_9
#define BR_GCC_4_8 1
#endif
#if BR_GCC_4_8
#define BR_GCC_4_7 1
#endif
#if BR_GCC_4_7
#define BR_GCC_4_6 1
#endif
#if BR_GCC_4_6
#define BR_GCC_4_5 1
#endif
#if BR_GCC_4_5
#define BR_GCC_4_4 1
#endif
#endif
#endif
/*
* Clang thresholds are on versions 3.7.0 and 3.8.0.
*/
#ifndef BR_CLANG
#if __clang__
#define BR_CLANG 1
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 8)
#define BR_CLANG_3_8 1
#elif __clang_major__ == 3 && __clang_minor__ >= 7
#define BR_CLANG_3_7 1
#endif
#if BR_CLANG_3_8
#define BR_CLANG_3_7 1
#endif
#endif
#endif
/*
* MS Visual C thresholds are on Visual Studio 2005 to 2015.
*/
#ifndef BR_MSC
#if _MSC_VER
#define BR_MSC 1
#if _MSC_VER >= 1900
#define BR_MSC_2015 1
#elif _MSC_VER >= 1800
#define BR_MSC_2013 1
#elif _MSC_VER >= 1700
#define BR_MSC_2012 1
#elif _MSC_VER >= 1600
#define BR_MSC_2010 1
#elif _MSC_VER >= 1500
#define BR_MSC_2008 1
#elif _MSC_VER >= 1400
#define BR_MSC_2005 1
#endif
#if BR_MSC_2015
#define BR_MSC_2013 1
#endif
#if BR_MSC_2013
#define BR_MSC_2012 1
#endif
#if BR_MSC_2012
#define BR_MSC_2010 1
#endif
#if BR_MSC_2010
#define BR_MSC_2008 1
#endif
#if BR_MSC_2008
#define BR_MSC_2005 1
#endif
#endif
#endif
/*
* GCC 4.4+ and Clang 3.7+ allow tagging specific functions with a
* 'target' attribute that activates support for specific opcodes.
*/
#if BR_GCC_4_4 || BR_CLANG_3_7
#define BR_TARGET(x) __attribute__((target(x)))
#else
#define BR_TARGET(x)
#endif
/*
* AES-NI intrinsics are available on x86 (32-bit and 64-bit) with
* GCC 4.8+, Clang 3.7+ and MSC 2012+.
*/
#ifndef BR_AES_X86NI
#if (BR_i386 || BR_amd64) && (BR_GCC_4_8 || BR_CLANG_3_7 || BR_MSC_2012)
#define BR_AES_X86NI 1
#endif
#endif
/*
* SSE2 intrinsics are available on x86 (32-bit and 64-bit) with
* GCC 4.4+, Clang 3.7+ and MSC 2005+.
*/
#ifndef BR_SSE2
#if (BR_i386 || BR_amd64) && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005)
#define BR_SSE2 1
#endif
#endif
/*
* RDRAND intrinsics are available on x86 (32-bit and 64-bit) with
* GCC 4.6+, Clang 3.7+ and MSC 2012+.
*/
#ifndef BR_RDRAND
#if (BR_i386 || BR_amd64) && (BR_GCC_4_6 || BR_CLANG_3_7 || BR_MSC_2012)
#define BR_RDRAND 1
#endif
#endif
/*
* Determine type of OS for random number generation. Macro names and
* values are documented on:
* https://sourceforge.net/p/predef/wiki/OperatingSystems/
*
* Win32's CryptGenRandom() should be available on Windows systems.
*
* /dev/urandom should work on all Unix-like systems (including macOS X).
*
* getentropy() is present on Linux (Glibc 2.25+), FreeBSD (12.0+) and
* OpenBSD (5.6+). For OpenBSD, there does not seem to be easy to use
* macros to test the minimum version, so we just assume that it is
* recent enough (last version without getentropy() has gone out of
* support in May 2015).
*
* Ideally we should use getentropy() on macOS (10.12+) too, but I don't
* know how to test the exact OS version with preprocessor macros.
*
* TODO: enrich the list of detected system.
*/
#ifndef BR_USE_URANDOM
#if defined _AIX \
|| defined __ANDROID__ \
|| defined __FreeBSD__ \
|| defined __NetBSD__ \
|| defined __OpenBSD__ \
|| defined __DragonFly__ \
|| defined __linux__ \
|| (defined __sun && (defined __SVR4 || defined __svr4__)) \
|| (defined __APPLE__ && defined __MACH__)
#define BR_USE_URANDOM 1
#endif
#endif
#ifndef BR_USE_GETENTROPY
#if (defined __linux__ \
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) \
|| (defined __FreeBSD__ && __FreeBSD__ >= 12) \
|| defined __OpenBSD__
#define BR_USE_GETENTROPY 1
#endif
#endif
#ifndef BR_USE_WIN32_RAND
#if defined _WIN32 || defined _WIN64
#define BR_USE_WIN32_RAND 1
#endif
#endif
/*
* POWER8 crypto support. We rely on compiler macros for the
* architecture, since we do not have a reliable, simple way to detect
* the required support at runtime (we could try running an opcode, and
* trapping the exception or signal on illegal instruction, but this
* induces some non-trivial OS dependencies that we would prefer to
* avoid if possible).
*/
#ifndef BR_POWER8
#if __GNUC__ && ((_ARCH_PWR8 || _ARCH_PPC) && __CRYPTO__)
#define BR_POWER8 1
#endif
#endif
/*
* Detect endinanness on POWER8.
*/
#if BR_POWER8
#if defined BR_POWER8_LE
#undef BR_POWER8_BE
#if BR_POWER8_LE
#define BR_POWER8_BE 0
#else
#define BR_POWER8_BE 1
#endif
#elif defined BR_POWER8_BE
#undef BR_POWER8_LE
#if BR_POWER8_BE
#define BR_POWER8_LE 0
#else
#define BR_POWER8_LE 1
#endif
#else
#if __LITTLE_ENDIAN__
#define BR_POWER8_LE 1
#define BR_POWER8_BE 0
#else
#define BR_POWER8_LE 0
#define BR_POWER8_BE 1
#endif
#endif
#endif
/*
* Detect support for 128-bit integers.
*/
#if !defined BR_INT128 && !defined BR_UMUL128
#ifdef __SIZEOF_INT128__
#define BR_INT128 1
#elif _M_X64
#define BR_UMUL128 1
#endif
#endif
/*
* Detect support for unaligned accesses with known endianness.
*
* x86 (both 32-bit and 64-bit) is little-endian and allows unaligned
* accesses.
*
* POWER/PowerPC allows unaligned accesses when big-endian. POWER8 and
* later also allow unaligned accesses when little-endian.
*/
#if !defined BR_LE_UNALIGNED && !defined BR_BE_UNALIGNED
#if __i386 || __i386__ || __x86_64__ || _M_IX86 || _M_X64
#define BR_LE_UNALIGNED 1
#elif BR_POWER8_BE
#define BR_BE_UNALIGNED 1
#elif BR_POWER8_LE
#define BR_LE_UNALIGNED 1
#elif (__powerpc__ || __powerpc64__ || _M_PPC || _ARCH_PPC || _ARCH_PPC64) \
&& __BIG_ENDIAN__
#define BR_BE_UNALIGNED 1
#endif
#endif
/*
* Detect support for an OS-provided time source.
*/
#ifndef BR_USE_UNIX_TIME
#if defined __unix__ || defined __linux__ \
|| defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \
|| (defined __APPLE__ && defined __MACH__)
#define BR_USE_UNIX_TIME 1
#endif
#endif
#ifndef BR_USE_WIN32_TIME
#if defined _WIN32 || defined _WIN64
#define BR_USE_WIN32_TIME 1
#endif
#endif
/* ==================================================================== */
/*
* Encoding/decoding functions.
*
* 32-bit and 64-bit decoding, both little-endian and big-endian, is
* implemented with the inline functions below.
*
* When allowed by some compile-time options (autodetected or provided),
* optimised code is used, to perform direct memory access when the
* underlying architecture supports it, both for endianness and
* alignment. This, however, may trigger strict aliasing issues; the
* code below uses unions to perform (supposedly) safe type punning.
* Since the C aliasing rules are relatively complex and were amended,
* or at least re-explained with different phrasing, in all successive
* versions of the C standard, it is always a bit risky to bet that any
* specific version of a C compiler got it right, for some notion of
* "right".
*/
typedef union {
uint16_t u;
unsigned char b[sizeof(uint16_t)];
} br_union_u16;
typedef union {
uint32_t u;
unsigned char b[sizeof(uint32_t)];
} br_union_u32;
typedef union {
uint64_t u;
unsigned char b[sizeof(uint64_t)];
} br_union_u64;
static inline void
br_enc16le(void *dst, unsigned x)
{
#if BR_LE_UNALIGNED
((br_union_u16 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)x;
buf[1] = (unsigned char)(x >> 8);
#endif
}
static inline void
br_enc16be(void *dst, unsigned x)
{
#if BR_BE_UNALIGNED
((br_union_u16 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)(x >> 8);
buf[1] = (unsigned char)x;
#endif
}
static inline unsigned
br_dec16le(const void *src)
{
#if BR_LE_UNALIGNED
return ((const br_union_u16 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return (unsigned)buf[0] | ((unsigned)buf[1] << 8);
#endif
}
static inline unsigned
br_dec16be(const void *src)
{
#if BR_BE_UNALIGNED
return ((const br_union_u16 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return ((unsigned)buf[0] << 8) | (unsigned)buf[1];
#endif
}
static inline void
br_enc32le(void *dst, uint32_t x)
{
#if BR_LE_UNALIGNED
((br_union_u32 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)x;
buf[1] = (unsigned char)(x >> 8);
buf[2] = (unsigned char)(x >> 16);
buf[3] = (unsigned char)(x >> 24);
#endif
}
static inline void
br_enc32be(void *dst, uint32_t x)
{
#if BR_BE_UNALIGNED
((br_union_u32 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = (unsigned char)(x >> 24);
buf[1] = (unsigned char)(x >> 16);
buf[2] = (unsigned char)(x >> 8);
buf[3] = (unsigned char)x;
#endif
}
static inline uint32_t
br_dec32le(const void *src)
{
#if BR_LE_UNALIGNED
return ((const br_union_u32 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return (uint32_t)buf[0]
| ((uint32_t)buf[1] << 8)
| ((uint32_t)buf[2] << 16)
| ((uint32_t)buf[3] << 24);
#endif
}
static inline uint32_t
br_dec32be(const void *src)
{
#if BR_BE_UNALIGNED
return ((const br_union_u32 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return ((uint32_t)buf[0] << 24)
| ((uint32_t)buf[1] << 16)
| ((uint32_t)buf[2] << 8)
| (uint32_t)buf[3];
#endif
}
static inline void
br_enc64le(void *dst, uint64_t x)
{
#if BR_LE_UNALIGNED
((br_union_u64 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
br_enc32le(buf, (uint32_t)x);
br_enc32le(buf + 4, (uint32_t)(x >> 32));
#endif
}
static inline void
br_enc64be(void *dst, uint64_t x)
{
#if BR_BE_UNALIGNED
((br_union_u64 *)dst)->u = x;
#else
unsigned char *buf;
buf = (unsigned char*)dst;
br_enc32be(buf, (uint32_t)(x >> 32));
br_enc32be(buf + 4, (uint32_t)x);
#endif
}
static inline uint64_t
br_dec64le(const void *src)
{
#if BR_LE_UNALIGNED
return ((const br_union_u64 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return (uint64_t)br_dec32le(buf)
| ((uint64_t)br_dec32le(buf + 4) << 32);
#endif
}
static inline uint64_t
br_dec64be(const void *src)
{
#if BR_BE_UNALIGNED
return ((const br_union_u64 *)src)->u;
#else
const unsigned char *buf;
buf = (const unsigned char*)src;
return ((uint64_t)br_dec32be(buf) << 32)
| (uint64_t)br_dec32be(buf + 4);
#endif
}
/*
* Range decoding and encoding (for several successive values).
*/
void br_range_dec16le(uint16_t *v, size_t num, const void *src);
void br_range_dec16be(uint16_t *v, size_t num, const void *src);
void br_range_enc16le(void *dst, const uint16_t *v, size_t num);
void br_range_enc16be(void *dst, const uint16_t *v, size_t num);
void br_range_dec32le(uint32_t *v, size_t num, const void *src);
void br_range_dec32be(uint32_t *v, size_t num, const void *src);
void br_range_enc32le(void *dst, const uint32_t *v, size_t num);
void br_range_enc32be(void *dst, const uint32_t *v, size_t num);
void br_range_dec64le(uint64_t *v, size_t num, const void *src);
void br_range_dec64be(uint64_t *v, size_t num, const void *src);
void br_range_enc64le(void *dst, const uint64_t *v, size_t num);
void br_range_enc64be(void *dst, const uint64_t *v, size_t num);
/*
* Byte-swap a 32-bit integer.
*/
static inline uint32_t
br_swap32(uint32_t x)
{
x = ((x & (uint32_t)0x00FF00FF) << 8)
| ((x >> 8) & (uint32_t)0x00FF00FF);
return (x << 16) | (x >> 16);
}
/* ==================================================================== */
/*
* Support code for hash functions.
*/
/*
* IV for MD5, SHA-1, SHA-224 and SHA-256.
*/
extern const uint32_t br_md5_IV[];
extern const uint32_t br_sha1_IV[];
extern const uint32_t br_sha224_IV[];
extern const uint32_t br_sha256_IV[];
/*
* Round functions for MD5, SHA-1, SHA-224 and SHA-256 (SHA-224 and
* SHA-256 use the same round function).
*/
void br_md5_round(const unsigned char *buf, uint32_t *val);
void br_sha1_round(const unsigned char *buf, uint32_t *val);
void br_sha2small_round(const unsigned char *buf, uint32_t *val);
/*
* The core function for the TLS PRF. It computes
* P_hash(secret, label + seed), and XORs the result into the dst buffer.
*/
void br_tls_phash(void *dst, size_t len,
const br_hash_class *dig,
const void *secret, size_t secret_len, const char *label,
size_t seed_num, const br_tls_prf_seed_chunk *seed);
/*
* Copy all configured hash implementations from a multihash context
* to another.
*/
static inline void
br_multihash_copyimpl(br_multihash_context *dst,
const br_multihash_context *src)
{
memcpy((void *)dst->impl, src->impl, sizeof src->impl);
}
/* ==================================================================== */
/*
* Constant-time primitives. These functions manipulate 32-bit values in
* order to provide constant-time comparisons and multiplexers.
*
* Boolean values (the "ctl" bits) MUST have value 0 or 1.
*
* Implementation notes:
* =====================
*
* The uintN_t types are unsigned and with width exactly N bits; the C
* standard guarantees that computations are performed modulo 2^N, and
* there can be no overflow. Negation (unary '-') works on unsigned types
* as well.
*
* The intN_t types are guaranteed to have width exactly N bits, with no
* padding bit, and using two's complement representation. Casting
* intN_t to uintN_t really is conversion modulo 2^N. Beware that intN_t
* types, being signed, trigger implementation-defined behaviour on
* overflow (including raising some signal): with GCC, while modular
* arithmetics are usually applied, the optimizer may assume that
* overflows don't occur (unless the -fwrapv command-line option is
* added); Clang has the additional -ftrapv option to explicitly trap on
* integer overflow or underflow.
*/
/*
* Negate a boolean.
*/
static inline uint32_t
NOT(uint32_t ctl)
{
return ctl ^ 1;
}
/*
* Multiplexer: returns x if ctl == 1, y if ctl == 0.
*/
static inline uint32_t
MUX(uint32_t ctl, uint32_t x, uint32_t y)
{
return y ^ (-ctl & (x ^ y));
}
/*
* Equality check: returns 1 if x == y, 0 otherwise.
*/
static inline uint32_t
EQ(uint32_t x, uint32_t y)
{
uint32_t q;
q = x ^ y;
return NOT((q | -q) >> 31);
}
/*
* Inequality check: returns 1 if x != y, 0 otherwise.
*/
static inline uint32_t
NEQ(uint32_t x, uint32_t y)
{
uint32_t q;
q = x ^ y;
return (q | -q) >> 31;
}
/*
* Comparison: returns 1 if x > y, 0 otherwise.
*/
static inline uint32_t
GT(uint32_t x, uint32_t y)
{
/*
* If both x < 2^31 and x < 2^31, then y-x will have its high
* bit set if x > y, cleared otherwise.
*
* If either x >= 2^31 or y >= 2^31 (but not both), then the
* result is the high bit of x.
*
* If both x >= 2^31 and y >= 2^31, then we can virtually
* subtract 2^31 from both, and we are back to the first case.
* Since (y-2^31)-(x-2^31) = y-x, the subtraction is already
* fine.
*/
uint32_t z;
z = y - x;
return (z ^ ((x ^ y) & (x ^ z))) >> 31;
}
/*
* Other comparisons (greater-or-equal, lower-than, lower-or-equal).
*/
#define GE(x, y) NOT(GT(y, x))
#define LT(x, y) GT(y, x)
#define LE(x, y) NOT(GT(x, y))
/*
* General comparison: returned value is -1, 0 or 1, depending on
* whether x is lower than, equal to, or greater than y.
*/
static inline int32_t
CMP(uint32_t x, uint32_t y)
{
return (int32_t)GT(x, y) | -(int32_t)GT(y, x);
}
/*
* Returns 1 if x == 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
EQ0(int32_t x)
{
uint32_t q;
q = (uint32_t)x;
return ~(q | -q) >> 31;
}
/*
* Returns 1 if x > 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
GT0(int32_t x)
{
/*
* High bit of -x is 0 if x == 0, but 1 if x > 0.
*/
uint32_t q;
q = (uint32_t)x;
return (~q & -q) >> 31;
}
/*
* Returns 1 if x >= 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
GE0(int32_t x)
{
return ~(uint32_t)x >> 31;
}
/*
* Returns 1 if x < 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
LT0(int32_t x)
{
return (uint32_t)x >> 31;
}
/*
* Returns 1 if x <= 0, 0 otherwise. Take care that the operand is signed.
*/
static inline uint32_t
LE0(int32_t x)
{
uint32_t q;
/*
* ~-x has its high bit set if and only if -x is nonnegative (as
* a signed int), i.e. x is in the -(2^31-1) to 0 range. We must
* do an OR with x itself to account for x = -2^31.
*/
q = (uint32_t)x;
return (q | ~-q) >> 31;
}
/*
* Conditional copy: src[] is copied into dst[] if and only if ctl is 1.
* dst[] and src[] may overlap completely (but not partially).
*/
void br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len);
#define CCOPY br_ccopy
/*
* Compute the bit length of a 32-bit integer. Returned value is between 0
* and 32 (inclusive).
*/
static inline uint32_t
BIT_LENGTH(uint32_t x)
{
uint32_t k, c;
k = NEQ(x, 0);
c = GT(x, 0xFFFF); x = MUX(c, x >> 16, x); k += c << 4;
c = GT(x, 0x00FF); x = MUX(c, x >> 8, x); k += c << 3;
c = GT(x, 0x000F); x = MUX(c, x >> 4, x); k += c << 2;
c = GT(x, 0x0003); x = MUX(c, x >> 2, x); k += c << 1;
k += GT(x, 0x0001);
return k;
}
/*
* Compute the minimum of x and y.
*/
static inline uint32_t
MIN(uint32_t x, uint32_t y)
{
return MUX(GT(x, y), y, x);
}
/*
* Compute the maximum of x and y.
*/
static inline uint32_t
MAX(uint32_t x, uint32_t y)
{
return MUX(GT(x, y), x, y);
}
/*
* Multiply two 32-bit integers, with a 64-bit result. This default
* implementation assumes that the basic multiplication operator
* yields constant-time code.
*/
#define MUL(x, y) ((uint64_t)(x) * (uint64_t)(y))
#if BR_CT_MUL31
/*
* Alternate implementation of MUL31, that will be constant-time on some
* (old) platforms where the default MUL31 is not. Unfortunately, it is
* also substantially slower, and yields larger code, on more modern
* platforms, which is why it is deactivated by default.
*
* MUL31_lo() must do some extra work because on some platforms, the
* _signed_ multiplication may return early if the top bits are 1.
* Simply truncating (casting) the output of MUL31() would not be
* sufficient, because the compiler may notice that we keep only the low
* word, and then replace automatically the unsigned multiplication with
* a signed multiplication opcode.
*/
#define MUL31(x, y) ((uint64_t)((x) | (uint32_t)0x80000000) \
* (uint64_t)((y) | (uint32_t)0x80000000) \
- ((uint64_t)(x) << 31) - ((uint64_t)(y) << 31) \
- ((uint64_t)1 << 62))
static inline uint32_t
MUL31_lo(uint32_t x, uint32_t y)
{
uint32_t xl, xh;
uint32_t yl, yh;
xl = (x & 0xFFFF) | (uint32_t)0x80000000;
xh = (x >> 16) | (uint32_t)0x80000000;
yl = (y & 0xFFFF) | (uint32_t)0x80000000;
yh = (y >> 16) | (uint32_t)0x80000000;
return (xl * yl + ((xl * yh + xh * yl) << 16)) & (uint32_t)0x7FFFFFFF;
}
#else
/*
* Multiply two 31-bit integers, with a 62-bit result. This default
* implementation assumes that the basic multiplication operator
* yields constant-time code.
* The MUL31_lo() macro returns only the low 31 bits of the product.
*/
#define MUL31(x, y) ((uint64_t)(x) * (uint64_t)(y))
#define MUL31_lo(x, y) (((uint32_t)(x) * (uint32_t)(y)) & (uint32_t)0x7FFFFFFF)
#endif
/*
* Multiply two words together; the sum of the lengths of the two
* operands must not exceed 31 (for instance, one operand may use 16
* bits if the other fits on 15). If BR_CT_MUL15 is non-zero, then the
* macro will contain some extra operations that help in making the
* operation constant-time on some platforms, where the basic 32-bit
* multiplication is not constant-time.
*/
#if BR_CT_MUL15
#define MUL15(x, y) (((uint32_t)(x) | (uint32_t)0x80000000) \
* ((uint32_t)(y) | (uint32_t)0x80000000) \
& (uint32_t)0x7FFFFFFF)
#else
#define MUL15(x, y) ((uint32_t)(x) * (uint32_t)(y))
#endif
/*
* Arithmetic right shift (sign bit is copied). What happens when
* right-shifting a negative value is _implementation-defined_, so it
* does not trigger undefined behaviour, but it is still up to each
* compiler to define (and document) what it does. Most/all compilers
* will do an arithmetic shift, the sign bit being used to fill the
* holes; this is a native operation on the underlying CPU, and it would
* make little sense for the compiler to do otherwise. GCC explicitly
* documents that it follows that convention.
*
* Still, if BR_NO_ARITH_SHIFT is defined (and non-zero), then an
* alternate version will be used, that does not rely on such
* implementation-defined behaviour. Unfortunately, it is also slower
* and yields bigger code, which is why it is deactivated by default.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#endif
/*
* Constant-time division. The dividend hi:lo is divided by the
* divisor d; the quotient is returned and the remainder is written
* in *r. If hi == d, then the quotient does not fit on 32 bits;
* returned value is thus truncated. If hi > d, returned values are
* indeterminate.
*/
uint32_t br_divrem(uint32_t hi, uint32_t lo, uint32_t d, uint32_t *r);
/*
* Wrapper for br_divrem(); the remainder is returned, and the quotient
* is discarded.
*/
static inline uint32_t
br_rem(uint32_t hi, uint32_t lo, uint32_t d)
{
uint32_t r;
br_divrem(hi, lo, d, &r);
return r;
}
/*
* Wrapper for br_divrem(); the quotient is returned, and the remainder
* is discarded.
*/
static inline uint32_t
br_div(uint32_t hi, uint32_t lo, uint32_t d)
{
uint32_t r;
return br_divrem(hi, lo, d, &r);
}
/* ==================================================================== */
/*
* Integers 'i32'
* --------------
*
* The 'i32' functions implement computations on big integers using
* an internal representation as an array of 32-bit integers. For
* an array x[]:
* -- x[0] contains the "announced bit length" of the integer
* -- x[1], x[2]... contain the value in little-endian order (x[1]
* contains the least significant 32 bits)
*
* Multiplications rely on the elementary 32x32->64 multiplication.
*
* The announced bit length specifies the number of bits that are
* significant in the subsequent 32-bit words. Unused bits in the
* last (most significant) word are set to 0; subsequent words are
* uninitialized and need not exist at all.
*
* The execution time and memory access patterns of all computations
* depend on the announced bit length, but not on the actual word
* values. For modular integers, the announced bit length of any integer
* modulo n is equal to the actual bit length of n; thus, computations
* on modular integers are "constant-time" (only the modulus length may
* leak).
*/
/*
* Compute the actual bit length of an integer. The argument x should
* point to the first (least significant) value word of the integer.
* The len 'xlen' contains the number of 32-bit words to access.
*
* CT: value or length of x does not leak.
*/
uint32_t br_i32_bit_length(uint32_t *x, size_t xlen);
/*
* Decode an integer from its big-endian unsigned representation. The
* "true" bit length of the integer is computed, but all words of x[]
* corresponding to the full 'len' bytes of the source are set.
*
* CT: value or length of x does not leak.
*/
void br_i32_decode(uint32_t *x, const void *src, size_t len);
/*
* Decode an integer from its big-endian unsigned representation. The
* integer MUST be lower than m[]; the announced bit length written in
* x[] will be equal to that of m[]. All 'len' bytes from the source are
* read.
*
* Returned value is 1 if the decode value fits within the modulus, 0
* otherwise. In the latter case, the x[] buffer will be set to 0 (but
* still with the announced bit length of m[]).
*
* CT: value or length of x does not leak. Memory access pattern depends
* only of 'len' and the announced bit length of m. Whether x fits or
* not does not leak either.
*/
uint32_t br_i32_decode_mod(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Reduce an integer (a[]) modulo another (m[]). The result is written
* in x[] and its announced bit length is set to be equal to that of m[].
*
* x[] MUST be distinct from a[] and m[].
*
* CT: only announced bit lengths leak, not values of x, a or m.
*/
void br_i32_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m);
/*
* Decode an integer from its big-endian unsigned representation, and
* reduce it modulo the provided modulus m[]. The announced bit length
* of the result is set to be equal to that of the modulus.
*
* x[] MUST be distinct from m[].
*/
void br_i32_decode_reduce(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Encode an integer into its big-endian unsigned representation. The
* output length in bytes is provided (parameter 'len'); if the length
* is too short then the integer is appropriately truncated; if it is
* too long then the extra bytes are set to 0.
*/
void br_i32_encode(void *dst, size_t len, const uint32_t *x);
/*
* Multiply x[] by 2^32 and then add integer z, modulo m[]. This
* function assumes that x[] and m[] have the same announced bit
* length, and the announced bit length of m[] matches its true
* bit length.
*
* x[] and m[] MUST be distinct arrays.
*
* CT: only the common announced bit length of x and m leaks, not
* the values of x, z or m.
*/
void br_i32_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
/*
* Extract one word from an integer. The offset is counted in bits.
* The word MUST entirely fit within the word elements corresponding
* to the announced bit length of a[].
*/
static inline uint32_t
br_i32_word(const uint32_t *a, uint32_t off)
{
size_t u;
unsigned j;
u = (size_t)(off >> 5) + 1;
j = (unsigned)off & 31;
if (j == 0) {
return a[u];
} else {
return (a[u] >> j) | (a[u + 1] << (32 - j));
}
}
/*
* Test whether an integer is zero.
*/
uint32_t br_i32_iszero(const uint32_t *x);
/*
* Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
* is unmodified, but the carry is still computed and returned. The
* arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i32_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
* then a[] is unmodified, but the carry is still computed and returned.
* The arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i32_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Compute d+a*b, result in d. The initial announced bit length of d[]
* MUST match that of a[]. The d[] array MUST be large enough to
* accommodate the full result, plus (possibly) an extra word. The
* resulting announced bit length of d[] will be the sum of the announced
* bit lengths of a[] and b[] (therefore, it may be larger than the actual
* bit length of the numerical result).
*
* a[] and b[] may be the same array. d[] must be disjoint from both a[]
* and b[].
*/
void br_i32_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
/*
* Zeroize an integer. The announced bit length is set to the provided
* value, and the corresponding words are set to 0.
*/
static inline void
br_i32_zero(uint32_t *x, uint32_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
}
/*
* Compute -(1/x) mod 2^32. If x is even, then this function returns 0.
*/
uint32_t br_i32_ninv32(uint32_t x);
/*
* Convert a modular integer to Montgomery representation. The integer x[]
* MUST be lower than m[], but with the same announced bit length.
*/
void br_i32_to_monty(uint32_t *x, const uint32_t *m);
/*
* Convert a modular integer back from Montgomery representation. The
* integer x[] MUST be lower than m[], but with the same announced bit
* length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is
* the least significant value word of m[] (this works only if m[] is
* an odd integer).
*/
void br_i32_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
/*
* Compute a modular Montgomery multiplication. d[] is filled with the
* value of x*y/R modulo m[] (where R is the Montgomery factor). The
* array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be
* numerically lower than m[]. x[] and y[] MAY be the same array. The
* "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer).
*/
void br_i32_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
const uint32_t *m, uint32_t m0i);
/*
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
* (same announced bit length, lower value). m[] MUST be odd. The
* exponent is in big-endian unsigned notation, over 'elen' bytes. The
* "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer). The t1[] and t2[] parameters must be temporary arrays,
* each large enough to accommodate an integer with the same size as m[].
*/
void br_i32_modpow(uint32_t *x, const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
/* ==================================================================== */
/*
* Integers 'i31'
* --------------
*
* The 'i31' functions implement computations on big integers using
* an internal representation as an array of 32-bit integers. For
* an array x[]:
* -- x[0] encodes the array length and the "announced bit length"
* of the integer: namely, if the announced bit length is k,
* then x[0] = ((k / 31) << 5) + (k % 31).
* -- x[1], x[2]... contain the value in little-endian order, 31
* bits per word (x[1] contains the least significant 31 bits).
* The upper bit of each word is 0.
*
* Multiplications rely on the elementary 32x32->64 multiplication.
*
* The announced bit length specifies the number of bits that are
* significant in the subsequent 32-bit words. Unused bits in the
* last (most significant) word are set to 0; subsequent words are
* uninitialized and need not exist at all.
*
* The execution time and memory access patterns of all computations
* depend on the announced bit length, but not on the actual word
* values. For modular integers, the announced bit length of any integer
* modulo n is equal to the actual bit length of n; thus, computations
* on modular integers are "constant-time" (only the modulus length may
* leak).
*/
/*
* Test whether an integer is zero.
*/
uint32_t br_i31_iszero(const uint32_t *x);
/*
* Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
* is unmodified, but the carry is still computed and returned. The
* arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i31_add(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
* then a[] is unmodified, but the carry is still computed and returned.
* The arrays a[] and b[] MUST have the same announced bit length.
*
* a[] and b[] MAY be the same array, but partial overlap is not allowed.
*/
uint32_t br_i31_sub(uint32_t *a, const uint32_t *b, uint32_t ctl);
/*
* Compute the ENCODED actual bit length of an integer. The argument x
* should point to the first (least significant) value word of the
* integer. The len 'xlen' contains the number of 32-bit words to
* access. The upper bit of each value word MUST be 0.
* Returned value is ((k / 31) << 5) + (k % 31) if the bit length is k.
*
* CT: value or length of x does not leak.
*/
uint32_t br_i31_bit_length(uint32_t *x, size_t xlen);
/*
* Decode an integer from its big-endian unsigned representation. The
* "true" bit length of the integer is computed and set in the encoded
* announced bit length (x[0]), but all words of x[] corresponding to
* the full 'len' bytes of the source are set.
*
* CT: value or length of x does not leak.
*/
void br_i31_decode(uint32_t *x, const void *src, size_t len);
/*
* Decode an integer from its big-endian unsigned representation. The
* integer MUST be lower than m[]; the (encoded) announced bit length
* written in x[] will be equal to that of m[]. All 'len' bytes from the
* source are read.
*
* Returned value is 1 if the decode value fits within the modulus, 0
* otherwise. In the latter case, the x[] buffer will be set to 0 (but
* still with the announced bit length of m[]).
*
* CT: value or length of x does not leak. Memory access pattern depends
* only of 'len' and the announced bit length of m. Whether x fits or
* not does not leak either.
*/
uint32_t br_i31_decode_mod(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Zeroize an integer. The announced bit length is set to the provided
* value, and the corresponding words are set to 0. The ENCODED bit length
* is expected here.
*/
static inline void
br_i31_zero(uint32_t *x, uint32_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 31) >> 5) * sizeof *x);
}
/*
* Right-shift an integer. The shift amount must be lower than 31
* bits.
*/
void br_i31_rshift(uint32_t *x, int count);
/*
* Reduce an integer (a[]) modulo another (m[]). The result is written
* in x[] and its announced bit length is set to be equal to that of m[].
*
* x[] MUST be distinct from a[] and m[].
*
* CT: only announced bit lengths leak, not values of x, a or m.
*/
void br_i31_reduce(uint32_t *x, const uint32_t *a, const uint32_t *m);
/*
* Decode an integer from its big-endian unsigned representation, and
* reduce it modulo the provided modulus m[]. The announced bit length
* of the result is set to be equal to that of the modulus.
*
* x[] MUST be distinct from m[].
*/
void br_i31_decode_reduce(uint32_t *x,
const void *src, size_t len, const uint32_t *m);
/*
* Multiply x[] by 2^31 and then add integer z, modulo m[]. This
* function assumes that x[] and m[] have the same announced bit
* length, the announced bit length of m[] matches its true
* bit length.
*
* x[] and m[] MUST be distinct arrays. z MUST fit in 31 bits (upper
* bit set to 0).
*
* CT: only the common announced bit length of x and m leaks, not
* the values of x, z or m.
*/
void br_i31_muladd_small(uint32_t *x, uint32_t z, const uint32_t *m);
/*
* Encode an integer into its big-endian unsigned representation. The
* output length in bytes is provided (parameter 'len'); if the length
* is too short then the integer is appropriately truncated; if it is
* too long then the extra bytes are set to 0.
*/
void br_i31_encode(void *dst, size_t len, const uint32_t *x);
/*
* Compute -(1/x) mod 2^31. If x is even, then this function returns 0.
*/
uint32_t br_i31_ninv31(uint32_t x);
/*
* Compute a modular Montgomery multiplication. d[] is filled with the
* value of x*y/R modulo m[] (where R is the Montgomery factor). The
* array d[] MUST be distinct from x[], y[] and m[]. x[] and y[] MUST be
* numerically lower than m[]. x[] and y[] MAY be the same array. The
* "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer).
*/
void br_i31_montymul(uint32_t *d, const uint32_t *x, const uint32_t *y,
const uint32_t *m, uint32_t m0i);
/*
* Convert a modular integer to Montgomery representation. The integer x[]
* MUST be lower than m[], but with the same announced bit length.
*/
void br_i31_to_monty(uint32_t *x, const uint32_t *m);
/*
* Convert a modular integer back from Montgomery representation. The
* integer x[] MUST be lower than m[], but with the same announced bit
* length. The "m0i" parameter is equal to -(1/m0) mod 2^32, where m0 is
* the least significant value word of m[] (this works only if m[] is
* an odd integer).
*/
void br_i31_from_monty(uint32_t *x, const uint32_t *m, uint32_t m0i);
/*
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
* (same announced bit length, lower value). m[] MUST be odd. The
* exponent is in big-endian unsigned notation, over 'elen' bytes. The
* "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer). The t1[] and t2[] parameters must be temporary arrays,
* each large enough to accommodate an integer with the same size as m[].
*/
void br_i31_modpow(uint32_t *x, const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *t1, uint32_t *t2);
/*
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
* (same announced bit length, lower value). m[] MUST be odd. The
* exponent is in big-endian unsigned notation, over 'elen' bytes. The
* "m0i" parameter is equal to -(1/m0) mod 2^31, where m0 is the least
* significant value word of m[] (this works only if m[] is an odd
* integer). The tmp[] array is used for temporaries, and has size
* 'twlen' words; it must be large enough to accommodate at least two
* temporary values with the same size as m[] (including the leading
* "bit length" word). If there is room for more temporaries, then this
* function may use the extra room for window-based optimisation,
* resulting in faster computations.
*
* Returned value is 1 on success, 0 on error. An error is reported if
* the provided tmp[] array is too short.
*/
uint32_t br_i31_modpow_opt(uint32_t *x, const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
/*
* Compute d+a*b, result in d. The initial announced bit length of d[]
* MUST match that of a[]. The d[] array MUST be large enough to
* accommodate the full result, plus (possibly) an extra word. The
* resulting announced bit length of d[] will be the sum of the announced
* bit lengths of a[] and b[] (therefore, it may be larger than the actual
* bit length of the numerical result).
*
* a[] and b[] may be the same array. d[] must be disjoint from both a[]
* and b[].
*/
void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
/*
* Compute x/y mod m, result in x. Values x and y must be between 0 and
* m-1, and have the same announced bit length as m. Modulus m must be
* odd. The "m0i" parameter is equal to -1/m mod 2^31. The array 't'
* must point to a temporary area that can hold at least three integers
* of the size of m.
*
* m may not overlap x and y. x and y may overlap each other (this can
* be useful to test whether a value is invertible modulo m). t must be
* disjoint from all other arrays.
*
* Returned value is 1 on success, 0 otherwise. Success is attained if
* y is invertible modulo m.
*/
uint32_t br_i31_moddiv(uint32_t *x, const uint32_t *y,
const uint32_t *m, uint32_t m0i, uint32_t *t);
/* ==================================================================== */
/*
* FIXME: document "i15" functions.
*/
static inline void
br_i15_zero(uint16_t *x, uint16_t bit_len)
{
*x ++ = bit_len;
memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x);
}
uint32_t br_i15_iszero(const uint16_t *x);
uint16_t br_i15_ninv15(uint16_t x);
uint32_t br_i15_add(uint16_t *a, const uint16_t *b, uint32_t ctl);
uint32_t br_i15_sub(uint16_t *a, const uint16_t *b, uint32_t ctl);
void br_i15_muladd_small(uint16_t *x, uint16_t z, const uint16_t *m);
void br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
const uint16_t *m, uint16_t m0i);
void br_i15_to_monty(uint16_t *x, const uint16_t *m);
void br_i15_modpow(uint16_t *x, const unsigned char *e, size_t elen,
const uint16_t *m, uint16_t m0i, uint16_t *t1, uint16_t *t2);
uint32_t br_i15_modpow_opt(uint16_t *x, const unsigned char *e, size_t elen,
const uint16_t *m, uint16_t m0i, uint16_t *tmp, size_t twlen);
void br_i15_encode(void *dst, size_t len, const uint16_t *x);
uint32_t br_i15_decode_mod(uint16_t *x,
const void *src, size_t len, const uint16_t *m);
void br_i15_rshift(uint16_t *x, int count);
uint32_t br_i15_bit_length(uint16_t *x, size_t xlen);
void br_i15_decode(uint16_t *x, const void *src, size_t len);
void br_i15_from_monty(uint16_t *x, const uint16_t *m, uint16_t m0i);
void br_i15_decode_reduce(uint16_t *x,
const void *src, size_t len, const uint16_t *m);
void br_i15_reduce(uint16_t *x, const uint16_t *a, const uint16_t *m);
void br_i15_mulacc(uint16_t *d, const uint16_t *a, const uint16_t *b);
uint32_t br_i15_moddiv(uint16_t *x, const uint16_t *y,
const uint16_t *m, uint16_t m0i, uint16_t *t);
/*
* Variant of br_i31_modpow_opt() that internally uses 64x64->128
* multiplications. It expects the same parameters as br_i31_modpow_opt(),
* except that the temporaries should be 64-bit integers, not 32-bit
* integers.
*/
uint32_t br_i62_modpow_opt(uint32_t *x31, const unsigned char *e, size_t elen,
const uint32_t *m31, uint32_t m0i31, uint64_t *tmp, size_t twlen);
/*
* Type for a function with the same API as br_i31_modpow_opt() (some
* implementations of this type may have stricter alignment requirements
* on the temporaries).
*/
typedef uint32_t (*br_i31_modpow_opt_type)(uint32_t *x,
const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
/*
* Wrapper for br_i62_modpow_opt() that uses the same type as
* br_i31_modpow_opt(); however, it requires its 'tmp' argument to the
* 64-bit aligned.
*/
uint32_t br_i62_modpow_opt_as_i31(uint32_t *x,
const unsigned char *e, size_t elen,
const uint32_t *m, uint32_t m0i, uint32_t *tmp, size_t twlen);
/* ==================================================================== */
static inline size_t
br_digest_size(const br_hash_class *digest_class)
{
return (size_t)(digest_class->desc >> BR_HASHDESC_OUT_OFF)
& BR_HASHDESC_OUT_MASK;
}
/*
* Get the output size (in bytes) of a hash function.
*/
size_t br_digest_size_by_ID(int digest_id);
/*
* Get the OID (encoded OBJECT IDENTIFIER value, without tag and length)
* for a hash function. If digest_id is not a supported digest identifier
* (in particular if it is equal to 0, i.e. br_md5sha1_ID), then NULL is
* returned and *len is set to 0.
*/
const unsigned char *br_digest_OID(int digest_id, size_t *len);
/* ==================================================================== */
/*
* DES support functions.
*/
/*
* Apply DES Initial Permutation.
*/
void br_des_do_IP(uint32_t *xl, uint32_t *xr);
/*
* Apply DES Final Permutation (inverse of IP).
*/
void br_des_do_invIP(uint32_t *xl, uint32_t *xr);
/*
* Key schedule unit: for a DES key (8 bytes), compute 16 subkeys. Each
* subkey is two 28-bit words represented as two 32-bit words; the PC-2
* bit extration is NOT applied.
*/
void br_des_keysched_unit(uint32_t *skey, const void *key);
/*
* Reversal of 16 DES sub-keys (for decryption).
*/
void br_des_rev_skey(uint32_t *skey);
/*
* DES/3DES key schedule for 'des_tab' (encryption direction). Returned
* value is the number of rounds.
*/
unsigned br_des_tab_keysched(uint32_t *skey, const void *key, size_t key_len);
/*
* DES/3DES key schedule for 'des_ct' (encryption direction). Returned
* value is the number of rounds.
*/
unsigned br_des_ct_keysched(uint32_t *skey, const void *key, size_t key_len);
/*
* DES/3DES subkey decompression (from the compressed bitsliced subkeys).
*/
void br_des_ct_skey_expand(uint32_t *sk_exp,
unsigned num_rounds, const uint32_t *skey);
/*
* DES/3DES block encryption/decryption ('des_tab').
*/
void br_des_tab_process_block(unsigned num_rounds,
const uint32_t *skey, void *block);
/*
* DES/3DES block encryption/decryption ('des_ct').
*/
void br_des_ct_process_block(unsigned num_rounds,
const uint32_t *skey, void *block);
/* ==================================================================== */
/*
* AES support functions.
*/
/*
* The AES S-box (256-byte table).
*/
extern const unsigned char br_aes_S[];
/*
* AES key schedule. skey[] is filled with n+1 128-bit subkeys, where n
* is the number of rounds (10 to 14, depending on key size). The number
* of rounds is returned. If the key size is invalid (not 16, 24 or 32),
* then 0 is returned.
*
* This implementation uses a 256-byte table and is NOT constant-time.
*/
unsigned br_aes_keysched(uint32_t *skey, const void *key, size_t key_len);
/*
* AES key schedule for decryption ('aes_big' implementation).
*/
unsigned br_aes_big_keysched_inv(uint32_t *skey,
const void *key, size_t key_len);
/*
* AES block encryption with the 'aes_big' implementation (fast, but
* not constant-time). This function encrypts a single block "in place".
*/
void br_aes_big_encrypt(unsigned num_rounds, const uint32_t *skey, void *data);
/*
* AES block decryption with the 'aes_big' implementation (fast, but
* not constant-time). This function decrypts a single block "in place".
*/
void br_aes_big_decrypt(unsigned num_rounds, const uint32_t *skey, void *data);
/*
* AES block encryption with the 'aes_small' implementation (small, but
* slow and not constant-time). This function encrypts a single block
* "in place".
*/
void br_aes_small_encrypt(unsigned num_rounds,
const uint32_t *skey, void *data);
/*
* AES block decryption with the 'aes_small' implementation (small, but
* slow and not constant-time). This function decrypts a single block
* "in place".
*/
void br_aes_small_decrypt(unsigned num_rounds,
const uint32_t *skey, void *data);
/*
* The constant-time implementation is "bitsliced": the 128-bit state is
* split over eight 32-bit words q* in the following way:
*
* -- Input block consists in 16 bytes:
* a00 a10 a20 a30 a01 a11 a21 a31 a02 a12 a22 a32 a03 a13 a23 a33
* In the terminology of FIPS 197, this is a 4x4 matrix which is read
* column by column.
*
* -- Each byte is split into eight bits which are distributed over the
* eight words, at the same rank. Thus, for a byte x at rank k, bit 0
* (least significant) of x will be at rank k in q0 (if that bit is b,
* then it contributes "b << k" to the value of q0), bit 1 of x will be
* at rank k in q1, and so on.
*
* -- Ranks given to bits are in "row order" and are either all even, or
* all odd. Two independent AES states are thus interleaved, one using
* the even ranks, the other the odd ranks. Row order means:
* a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 a30 a31 a32 a33
*
* Converting input bytes from two AES blocks to bitslice representation
* is done in the following way:
* -- Decode first block into the four words q0 q2 q4 q6, in that order,
* using little-endian convention.
* -- Decode second block into the four words q1 q3 q5 q7, in that order,
* using little-endian convention.
* -- Call br_aes_ct_ortho().
*
* Converting back to bytes is done by using the reverse operations. Note
* that br_aes_ct_ortho() is its own inverse.
*/
/*
* Perform bytewise orthogonalization of eight 32-bit words. Bytes
* of q0..q7 are spread over all words: for a byte x that occurs
* at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit
* of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.
*
* This operation is an involution.
*/
void br_aes_ct_ortho(uint32_t *q);
/*
* The AES S-box, as a bitsliced constant-time version. The input array
* consists in eight 32-bit words; 32 S-box instances are computed in
* parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)
* are spread over the words 0 to 7, at the same rank.
*/
void br_aes_ct_bitslice_Sbox(uint32_t *q);
/*
* Like br_aes_bitslice_Sbox(), but for the inverse S-box.
*/
void br_aes_ct_bitslice_invSbox(uint32_t *q);
/*
* Compute AES encryption on bitsliced data. Since input is stored on
* eight 32-bit words, two block encryptions are actually performed
* in parallel.
*/
void br_aes_ct_bitslice_encrypt(unsigned num_rounds,
const uint32_t *skey, uint32_t *q);
/*
* Compute AES decryption on bitsliced data. Since input is stored on
* eight 32-bit words, two block decryptions are actually performed
* in parallel.
*/
void br_aes_ct_bitslice_decrypt(unsigned num_rounds,
const uint32_t *skey, uint32_t *q);
/*
* AES key schedule, constant-time version. skey[] is filled with n+1
* 128-bit subkeys, where n is the number of rounds (10 to 14, depending
* on key size). The number of rounds is returned. If the key size is
* invalid (not 16, 24 or 32), then 0 is returned.
*/
unsigned br_aes_ct_keysched(uint32_t *comp_skey,
const void *key, size_t key_len);
/*
* Expand AES subkeys as produced by br_aes_ct_keysched(), into
* a larger array suitable for br_aes_ct_bitslice_encrypt() and
* br_aes_ct_bitslice_decrypt().
*/
void br_aes_ct_skey_expand(uint32_t *skey,
unsigned num_rounds, const uint32_t *comp_skey);
/*
* For the ct64 implementation, the same bitslicing technique is used,
* but four instances are interleaved. First instance uses bits 0, 4,
* 8, 12,... of each word; second instance uses bits 1, 5, 9, 13,...
* and so on.
*/
/*
* Perform bytewise orthogonalization of eight 64-bit words. Bytes
* of q0..q7 are spread over all words: for a byte x that occurs
* at rank i in q[j] (byte x uses bits 8*i to 8*i+7 in q[j]), the bit
* of rank k in x (0 <= k <= 7) goes to q[k] at rank 8*i+j.
*
* This operation is an involution.
*/
void br_aes_ct64_ortho(uint64_t *q);
/*
* Interleave bytes for an AES input block. If input bytes are
* denoted 0123456789ABCDEF, and have been decoded with little-endian
* convention (w[0] contains 0123, with '3' being most significant;
* w[1] contains 4567, and so on), then output word q0 will be
* set to 08192A3B (again little-endian convention) and q1 will
* be set to 4C5D6E7F.
*/
void br_aes_ct64_interleave_in(uint64_t *q0, uint64_t *q1, const uint32_t *w);
/*
* Perform the opposite of br_aes_ct64_interleave_in().
*/
void br_aes_ct64_interleave_out(uint32_t *w, uint64_t q0, uint64_t q1);
/*
* The AES S-box, as a bitsliced constant-time version. The input array
* consists in eight 64-bit words; 64 S-box instances are computed in
* parallel. Bits 0 to 7 of each S-box input (bit 0 is least significant)
* are spread over the words 0 to 7, at the same rank.
*/
void br_aes_ct64_bitslice_Sbox(uint64_t *q);
/*
* Like br_aes_bitslice_Sbox(), but for the inverse S-box.
*/
void br_aes_ct64_bitslice_invSbox(uint64_t *q);
/*
* Compute AES encryption on bitsliced data. Since input is stored on
* eight 64-bit words, four block encryptions are actually performed
* in parallel.
*/
void br_aes_ct64_bitslice_encrypt(unsigned num_rounds,
const uint64_t *skey, uint64_t *q);
/*
* Compute AES decryption on bitsliced data. Since input is stored on
* eight 64-bit words, four block decryptions are actually performed
* in parallel.
*/
void br_aes_ct64_bitslice_decrypt(unsigned num_rounds,
const uint64_t *skey, uint64_t *q);
/*
* AES key schedule, constant-time version. skey[] is filled with n+1
* 128-bit subkeys, where n is the number of rounds (10 to 14, depending
* on key size). The number of rounds is returned. If the key size is
* invalid (not 16, 24 or 32), then 0 is returned.
*/
unsigned br_aes_ct64_keysched(uint64_t *comp_skey,
const void *key, size_t key_len);
/*
* Expand AES subkeys as produced by br_aes_ct64_keysched(), into
* a larger array suitable for br_aes_ct64_bitslice_encrypt() and
* br_aes_ct64_bitslice_decrypt().
*/
void br_aes_ct64_skey_expand(uint64_t *skey,
unsigned num_rounds, const uint64_t *comp_skey);
/*
* Test support for AES-NI opcodes.
*/
int br_aes_x86ni_supported(void);
/*
* AES key schedule, using x86 AES-NI instructions. This yields the
* subkeys in the encryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_x86ni_keysched_enc(unsigned char *skni,
const void *key, size_t len);
/*
* AES key schedule, using x86 AES-NI instructions. This yields the
* subkeys in the decryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_x86ni_keysched_dec(unsigned char *skni,
const void *key, size_t len);
/*
* Test support for AES POWER8 opcodes.
*/
int br_aes_pwr8_supported(void);
/*
* AES key schedule, using POWER8 instructions. This yields the
* subkeys in the encryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_pwr8_keysched(unsigned char *skni,
const void *key, size_t len);
/* ==================================================================== */
/*
* RSA.
*/
/*
* Apply proper PKCS#1 v1.5 padding (for signatures). 'hash_oid' is
* the encoded hash function OID, or NULL.
*/
uint32_t br_rsa_pkcs1_sig_pad(const unsigned char *hash_oid,
const unsigned char *hash, size_t hash_len,
uint32_t n_bitlen, unsigned char *x);
/*
* Check PKCS#1 v1.5 padding (for signatures). 'hash_oid' is the encoded
* hash function OID, or NULL. The provided 'sig' value is _after_ the
* modular exponentiation, i.e. it should be the padded hash. On
* success, the hashed message is extracted.
*/
uint32_t br_rsa_pkcs1_sig_unpad(const unsigned char *sig, size_t sig_len,
const unsigned char *hash_oid, size_t hash_len,
unsigned char *hash_out);
/*
* Apply proper PSS padding. The 'x' buffer is output only: it
* receives the value that is to be exponentiated.
*/
uint32_t br_rsa_pss_sig_pad(const br_prng_class **rng,
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash, size_t salt_len,
uint32_t n_bitlen, unsigned char *x);
/*
* Check PSS padding. The provided value is the one _after_
* the modular exponentiation; it is modified by this function.
* This function infers the signature length from the public key
* size, i.e. it assumes that this has already been verified (as
* part of the exponentiation).
*/
uint32_t br_rsa_pss_sig_unpad(
const br_hash_class *hf_data, const br_hash_class *hf_mgf1,
const unsigned char *hash, size_t salt_len,
const br_rsa_public_key *pk, unsigned char *x);
/*
* Apply OAEP padding. Returned value is the actual padded string length,
* or zero on error.
*/
size_t br_rsa_oaep_pad(const br_prng_class **rnd, const br_hash_class *dig,
const void *label, size_t label_len, const br_rsa_public_key *pk,
void *dst, size_t dst_nax_len, const void *src, size_t src_len);
/*
* Unravel and check OAEP padding. If the padding is correct, then 1 is
* returned, '*len' is adjusted to the length of the message, and the
* data is moved to the start of the 'data' buffer. If the padding is
* incorrect, then 0 is returned and '*len' is untouched. Either way,
* the complete buffer contents are altered.
*/
uint32_t br_rsa_oaep_unpad(const br_hash_class *dig,
const void *label, size_t label_len, void *data, size_t *len);
/*
* Compute MGF1 for a given seed, and XOR the output into the provided
* buffer.
*/
void br_mgf1_xor(void *data, size_t len,
const br_hash_class *dig, const void *seed, size_t seed_len);
/*
* Inner function for RSA key generation; used by the "i31" and "i62"
* implementations.
*/
uint32_t br_rsa_i31_keygen_inner(const br_prng_class **rng,
br_rsa_private_key *sk, void *kbuf_priv,
br_rsa_public_key *pk, void *kbuf_pub,
unsigned size, uint32_t pubexp, br_i31_modpow_opt_type mp31);
/* ==================================================================== */
/*
* Elliptic curves.
*/
/*
* Type for generic EC parameters: curve order (unsigned big-endian
* encoding) and encoded conventional generator.
*/
typedef struct {
int curve;
const unsigned char *order;
size_t order_len;
const unsigned char *generator;
size_t generator_len;
} br_ec_curve_def;
extern const br_ec_curve_def br_secp256r1;
extern const br_ec_curve_def br_secp384r1;
extern const br_ec_curve_def br_secp521r1;
/*
* For Curve25519, the advertised "order" really is 2^255-1, since the
* point multipliction function really works over arbitrary 255-bit
* scalars. This value is only meant as a hint for ECDH key generation;
* only ECDSA uses the exact curve order, and ECDSA is not used with
* that specific curve.
*/
extern const br_ec_curve_def br_curve25519;
/*
* Decode some bytes as an i31 integer, with truncation (corresponding
* to the 'bits2int' operation in RFC 6979). The target ENCODED bit
* length is provided as last parameter. The resulting value will have
* this declared bit length, and consists the big-endian unsigned decoding
* of exactly that many bits in the source (capped at the source length).
*/
void br_ecdsa_i31_bits2int(uint32_t *x,
const void *src, size_t len, uint32_t ebitlen);
/*
* Decode some bytes as an i15 integer, with truncation (corresponding
* to the 'bits2int' operation in RFC 6979). The target ENCODED bit
* length is provided as last parameter. The resulting value will have
* this declared bit length, and consists the big-endian unsigned decoding
* of exactly that many bits in the source (capped at the source length).
*/
void br_ecdsa_i15_bits2int(uint16_t *x,
const void *src, size_t len, uint32_t ebitlen);
/* ==================================================================== */
/*
* ASN.1 support functions.
*/
/*
* A br_asn1_uint structure contains encoding information about an
* INTEGER nonnegative value: pointer to the integer contents (unsigned
* big-endian representation), length of the integer contents,
* and length of the encoded value. The data shall have minimal length:
* - If the integer value is zero, then 'len' must be zero.
* - If the integer value is not zero, then data[0] must be non-zero.
*
* Under these conditions, 'asn1len' is necessarily equal to either len
* or len+1.
*/
typedef struct {
const unsigned char *data;
size_t len;
size_t asn1len;
} br_asn1_uint;
/*
* Given an encoded integer (unsigned big-endian, with possible leading
* bytes of value 0), returned the "prepared INTEGER" structure.
*/
br_asn1_uint br_asn1_uint_prepare(const void *xdata, size_t xlen);
/*
* Encode an ASN.1 length. The length of the encoded length is returned.
* If 'dest' is NULL, then no encoding is performed, but the length of
* the encoded length is still computed and returned.
*/
size_t br_asn1_encode_length(void *dest, size_t len);
/*
* Convenient macro for computing lengths of lengths.
*/
#define len_of_len(len) br_asn1_encode_length(NULL, len)
/*
* Encode a (prepared) ASN.1 INTEGER. The encoded length is returned.
* If 'dest' is NULL, then no encoding is performed, but the length of
* the encoded integer is still computed and returned.
*/
size_t br_asn1_encode_uint(void *dest, br_asn1_uint pp);
/*
* Get the OID that identifies an elliptic curve. Returned value is
* the DER-encoded OID, with the length (always one byte) but without
* the tag. Thus, the first byte of the returned buffer contains the
* number of subsequent bytes in the value. If the curve is not
* recognised, NULL is returned.
*/
const unsigned char *br_get_curve_OID(int curve);
/*
* Inner function for EC private key encoding. This is equivalent to
* the API function br_encode_ec_raw_der(), except for an extra
* parameter: if 'include_curve_oid' is zero, then the curve OID is
* _not_ included in the output blob (this is for PKCS#8 support).
*/
size_t br_encode_ec_raw_der_inner(void *dest,
const br_ec_private_key *sk, const br_ec_public_key *pk,
int include_curve_oid);
/* ==================================================================== */
/*
* SSL/TLS support functions.
*/
/*
* Record types.
*/
#define BR_SSL_CHANGE_CIPHER_SPEC 20
#define BR_SSL_ALERT 21
#define BR_SSL_HANDSHAKE 22
#define BR_SSL_APPLICATION_DATA 23
/*
* Handshake message types.
*/
#define BR_SSL_HELLO_REQUEST 0
#define BR_SSL_CLIENT_HELLO 1
#define BR_SSL_SERVER_HELLO 2
#define BR_SSL_CERTIFICATE 11
#define BR_SSL_SERVER_KEY_EXCHANGE 12
#define BR_SSL_CERTIFICATE_REQUEST 13
#define BR_SSL_SERVER_HELLO_DONE 14
#define BR_SSL_CERTIFICATE_VERIFY 15
#define BR_SSL_CLIENT_KEY_EXCHANGE 16
#define BR_SSL_FINISHED 20
/*
* Alert levels.
*/
#define BR_LEVEL_WARNING 1
#define BR_LEVEL_FATAL 2
/*
* Low-level I/O state.
*/
#define BR_IO_FAILED 0
#define BR_IO_IN 1
#define BR_IO_OUT 2
#define BR_IO_INOUT 3
/*
* Mark a SSL engine as failed. The provided error code is recorded if
* the engine was not already marked as failed. If 'err' is 0, then the
* engine is marked as closed (without error).
*/
void br_ssl_engine_fail(br_ssl_engine_context *cc, int err);
/*
* Test whether the engine is closed (normally or as a failure).
*/
static inline int
br_ssl_engine_closed(const br_ssl_engine_context *cc)
{
return cc->iomode == BR_IO_FAILED;
}
/*
* Configure a new maximum fragment length. If possible, the maximum
* length for outgoing records is immediately adjusted (if there are
* not already too many buffered bytes for that).
*/
void br_ssl_engine_new_max_frag_len(
br_ssl_engine_context *rc, unsigned max_frag_len);
/*
* Test whether the current incoming record has been fully received
* or not. This functions returns 0 only if a complete record header
* has been received, but some of the (possibly encrypted) payload
* has not yet been obtained.
*/
int br_ssl_engine_recvrec_finished(const br_ssl_engine_context *rc);
/*
* Flush the current record (if not empty). This is meant to be called
* from the handshake processor only.
*/
void br_ssl_engine_flush_record(br_ssl_engine_context *cc);
/*
* Test whether there is some accumulated payload to send.
*/
static inline int
br_ssl_engine_has_pld_to_send(const br_ssl_engine_context *rc)
{
return rc->oxa != rc->oxb && rc->oxa != rc->oxc;
}
/*
* Initialize RNG in engine. Returned value is 1 on success, 0 on error.
* This function will try to use the OS-provided RNG, if available. If
* there is no OS-provided RNG, or if it failed, and no entropy was
* injected by the caller, then a failure will be reported. On error,
* the context error code is set.
*/
int br_ssl_engine_init_rand(br_ssl_engine_context *cc);
/*
* Reset the handshake-related parts of the engine.
*/
void br_ssl_engine_hs_reset(br_ssl_engine_context *cc,
void (*hsinit)(void *), void (*hsrun)(void *));
/*
* Get the PRF to use for this context, for the provided PRF hash
* function ID.
*/
br_tls_prf_impl br_ssl_engine_get_PRF(br_ssl_engine_context *cc, int prf_id);
/*
* Consume the provided pre-master secret and compute the corresponding
* master secret. The 'prf_id' is the ID of the hash function to use
* with the TLS 1.2 PRF (ignored if the version is TLS 1.0 or 1.1).
*/
void br_ssl_engine_compute_master(br_ssl_engine_context *cc,
int prf_id, const void *pms, size_t len);
/*
* Switch to CBC decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF (ignored if not TLS 1.2+)
* mac_id id of hash function for HMAC
* bc_impl block cipher implementation (CBC decryption)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_cbc_in(br_ssl_engine_context *cc,
int is_client, int prf_id, int mac_id,
const br_block_cbcdec_class *bc_impl, size_t cipher_key_len);
/*
* Switch to CBC encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF (ignored if not TLS 1.2+)
* mac_id id of hash function for HMAC
* bc_impl block cipher implementation (CBC encryption)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_cbc_out(br_ssl_engine_context *cc,
int is_client, int prf_id, int mac_id,
const br_block_cbcenc_class *bc_impl, size_t cipher_key_len);
/*
* Switch to GCM decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_gcm_in(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctr_class *bc_impl, size_t cipher_key_len);
/*
* Switch to GCM encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR)
* cipher_key_len block cipher key length (in bytes)
*/
void br_ssl_engine_switch_gcm_out(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctr_class *bc_impl, size_t cipher_key_len);
/*
* Switch to ChaCha20+Poly1305 decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
*/
void br_ssl_engine_switch_chapol_in(br_ssl_engine_context *cc,
int is_client, int prf_id);
/*
* Switch to ChaCha20+Poly1305 encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
*/
void br_ssl_engine_switch_chapol_out(br_ssl_engine_context *cc,
int is_client, int prf_id);
/*
* Switch to CCM decryption for incoming records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR+CBC)
* cipher_key_len block cipher key length (in bytes)
* tag_len tag length (in bytes)
*/
void br_ssl_engine_switch_ccm_in(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctrcbc_class *bc_impl,
size_t cipher_key_len, size_t tag_len);
/*
* Switch to GCM encryption for outgoing records.
* cc the engine context
* is_client non-zero for a client, zero for a server
* prf_id id of hash function for PRF
* bc_impl block cipher implementation (CTR+CBC)
* cipher_key_len block cipher key length (in bytes)
* tag_len tag length (in bytes)
*/
void br_ssl_engine_switch_ccm_out(br_ssl_engine_context *cc,
int is_client, int prf_id,
const br_block_ctrcbc_class *bc_impl,
size_t cipher_key_len, size_t tag_len);
/*
* Calls to T0-generated code.
*/
void br_ssl_hs_client_init_main(void *ctx);
void br_ssl_hs_client_run(void *ctx);
void br_ssl_hs_server_init_main(void *ctx);
void br_ssl_hs_server_run(void *ctx);
/*
* Get the hash function to use for signatures, given a bit mask of
* supported hash functions. This implements a strict choice order
* (namely SHA-256, SHA-384, SHA-512, SHA-224, SHA-1). If the mask
* does not document support of any of these hash functions, then this
* functions returns 0.
*/
int br_ssl_choose_hash(unsigned bf);
/* ==================================================================== */
/*
* PowerPC / POWER assembly stuff. The special BR_POWER_ASM_MACROS macro
* must be defined before including this file; this is done by source
* files that use some inline assembly for PowerPC / POWER machines.
*/
#if BR_POWER_ASM_MACROS
#define lxvw4x(xt, ra, rb) lxvw4x_(xt, ra, rb)
#define stxvw4x(xt, ra, rb) stxvw4x_(xt, ra, rb)
#define bdnz(foo) bdnz_(foo)
#define bdz(foo) bdz_(foo)
#define beq(foo) beq_(foo)
#define li(rx, value) li_(rx, value)
#define addi(rx, ra, imm) addi_(rx, ra, imm)
#define cmpldi(rx, imm) cmpldi_(rx, imm)
#define mtctr(rx) mtctr_(rx)
#define vspltb(vrt, vrb, uim) vspltb_(vrt, vrb, uim)
#define vspltw(vrt, vrb, uim) vspltw_(vrt, vrb, uim)
#define vspltisb(vrt, imm) vspltisb_(vrt, imm)
#define vspltisw(vrt, imm) vspltisw_(vrt, imm)
#define vrlw(vrt, vra, vrb) vrlw_(vrt, vra, vrb)
#define vsbox(vrt, vra) vsbox_(vrt, vra)
#define vxor(vrt, vra, vrb) vxor_(vrt, vra, vrb)
#define vand(vrt, vra, vrb) vand_(vrt, vra, vrb)
#define vsro(vrt, vra, vrb) vsro_(vrt, vra, vrb)
#define vsl(vrt, vra, vrb) vsl_(vrt, vra, vrb)
#define vsldoi(vt, va, vb, sh) vsldoi_(vt, va, vb, sh)
#define vsr(vrt, vra, vrb) vsr_(vrt, vra, vrb)
#define vaddcuw(vrt, vra, vrb) vaddcuw_(vrt, vra, vrb)
#define vadduwm(vrt, vra, vrb) vadduwm_(vrt, vra, vrb)
#define vsububm(vrt, vra, vrb) vsububm_(vrt, vra, vrb)
#define vsubuwm(vrt, vra, vrb) vsubuwm_(vrt, vra, vrb)
#define vsrw(vrt, vra, vrb) vsrw_(vrt, vra, vrb)
#define vcipher(vt, va, vb) vcipher_(vt, va, vb)
#define vcipherlast(vt, va, vb) vcipherlast_(vt, va, vb)
#define vncipher(vt, va, vb) vncipher_(vt, va, vb)
#define vncipherlast(vt, va, vb) vncipherlast_(vt, va, vb)
#define vperm(vt, va, vb, vc) vperm_(vt, va, vb, vc)
#define vpmsumd(vt, va, vb) vpmsumd_(vt, va, vb)
#define xxpermdi(vt, va, vb, d) xxpermdi_(vt, va, vb, d)
#define lxvw4x_(xt, ra, rb) "\tlxvw4x\t" #xt "," #ra "," #rb "\n"
#define stxvw4x_(xt, ra, rb) "\tstxvw4x\t" #xt "," #ra "," #rb "\n"
#define label(foo) #foo "%=:\n"
#define bdnz_(foo) "\tbdnz\t" #foo "%=\n"
#define bdz_(foo) "\tbdz\t" #foo "%=\n"
#define beq_(foo) "\tbeq\t" #foo "%=\n"
#define li_(rx, value) "\tli\t" #rx "," #value "\n"
#define addi_(rx, ra, imm) "\taddi\t" #rx "," #ra "," #imm "\n"
#define cmpldi_(rx, imm) "\tcmpldi\t" #rx "," #imm "\n"
#define mtctr_(rx) "\tmtctr\t" #rx "\n"
#define vspltb_(vrt, vrb, uim) "\tvspltb\t" #vrt "," #vrb "," #uim "\n"
#define vspltw_(vrt, vrb, uim) "\tvspltw\t" #vrt "," #vrb "," #uim "\n"
#define vspltisb_(vrt, imm) "\tvspltisb\t" #vrt "," #imm "\n"
#define vspltisw_(vrt, imm) "\tvspltisw\t" #vrt "," #imm "\n"
#define vrlw_(vrt, vra, vrb) "\tvrlw\t" #vrt "," #vra "," #vrb "\n"
#define vsbox_(vrt, vra) "\tvsbox\t" #vrt "," #vra "\n"
#define vxor_(vrt, vra, vrb) "\tvxor\t" #vrt "," #vra "," #vrb "\n"
#define vand_(vrt, vra, vrb) "\tvand\t" #vrt "," #vra "," #vrb "\n"
#define vsro_(vrt, vra, vrb) "\tvsro\t" #vrt "," #vra "," #vrb "\n"
#define vsl_(vrt, vra, vrb) "\tvsl\t" #vrt "," #vra "," #vrb "\n"
#define vsldoi_(vt, va, vb, sh) "\tvsldoi\t" #vt "," #va "," #vb "," #sh "\n"
#define vsr_(vrt, vra, vrb) "\tvsr\t" #vrt "," #vra "," #vrb "\n"
#define vaddcuw_(vrt, vra, vrb) "\tvaddcuw\t" #vrt "," #vra "," #vrb "\n"
#define vadduwm_(vrt, vra, vrb) "\tvadduwm\t" #vrt "," #vra "," #vrb "\n"
#define vsububm_(vrt, vra, vrb) "\tvsububm\t" #vrt "," #vra "," #vrb "\n"
#define vsubuwm_(vrt, vra, vrb) "\tvsubuwm\t" #vrt "," #vra "," #vrb "\n"
#define vsrw_(vrt, vra, vrb) "\tvsrw\t" #vrt "," #vra "," #vrb "\n"
#define vcipher_(vt, va, vb) "\tvcipher\t" #vt "," #va "," #vb "\n"
#define vcipherlast_(vt, va, vb) "\tvcipherlast\t" #vt "," #va "," #vb "\n"
#define vncipher_(vt, va, vb) "\tvncipher\t" #vt "," #va "," #vb "\n"
#define vncipherlast_(vt, va, vb) "\tvncipherlast\t" #vt "," #va "," #vb "\n"
#define vperm_(vt, va, vb, vc) "\tvperm\t" #vt "," #va "," #vb "," #vc "\n"
#define vpmsumd_(vt, va, vb) "\tvpmsumd\t" #vt "," #va "," #vb "\n"
#define xxpermdi_(vt, va, vb, d) "\txxpermdi\t" #vt "," #va "," #vb "," #d "\n"
#endif
/* ==================================================================== */
/*
* Special "activate intrinsics" code, needed for some compiler versions.
* This is defined at the end of this file, so that it won't impact any
* of the inline functions defined previously; and it is controlled by
* a specific macro defined in the caller code.
*
* Calling code conventions:
*
* - Caller must define BR_ENABLE_INTRINSICS before including "inner.h".
* - Functions that use intrinsics must be enclosed in an "enabled"
* region (between BR_TARGETS_X86_UP and BR_TARGETS_X86_DOWN).
* - Functions that use intrinsics must be tagged with the appropriate
* BR_TARGET().
*/
#if BR_ENABLE_INTRINSICS && (BR_GCC_4_4 || BR_CLANG_3_7 || BR_MSC_2005)
/*
* x86 intrinsics (both 32-bit and 64-bit).
*/
#if BR_i386 || BR_amd64
/*
* On GCC before version 5.0, we need to use the pragma to enable the
* target options globally, because the 'target' function attribute
* appears to be unreliable. Before 4.6 we must also avoid the
* push_options / pop_options mechanism, because it tends to trigger
* some internal compiler errors.
*/
#if BR_GCC && !BR_GCC_5_0
#if BR_GCC_4_6
#define BR_TARGETS_X86_UP \
_Pragma("GCC push_options") \
_Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul,rdrnd\")")
#define BR_TARGETS_X86_DOWN \
_Pragma("GCC pop_options")
#else
#define BR_TARGETS_X86_UP \
_Pragma("GCC target(\"sse2,ssse3,sse4.1,aes,pclmul\")")
#define BR_TARGETS_X86_DOWN
#endif
#pragma GCC diagnostic ignored "-Wpsabi"
#endif
#if BR_CLANG && !BR_CLANG_3_8
#undef __SSE2__
#undef __SSE3__
#undef __SSSE3__
#undef __SSE4_1__
#undef __AES__
#undef __PCLMUL__
#undef __RDRND__
#define __SSE2__ 1
#define __SSE3__ 1
#define __SSSE3__ 1
#define __SSE4_1__ 1
#define __AES__ 1
#define __PCLMUL__ 1
#define __RDRND__ 1
#endif
#ifndef BR_TARGETS_X86_UP
#define BR_TARGETS_X86_UP
#endif
#ifndef BR_TARGETS_X86_DOWN
#define BR_TARGETS_X86_DOWN
#endif
#if BR_GCC || BR_CLANG
BR_TARGETS_X86_UP
#include
#include
#define br_bswap32 __builtin_bswap32
BR_TARGETS_X86_DOWN
#endif
#if BR_MSC
#include
#include
#include
#define br_bswap32 __src_inner_hbyteswap_ulong
#endif
static inline int
br_cpuid(uint32_t mask_eax, uint32_t mask_ebx,
uint32_t mask_ecx, uint32_t mask_edx)
{
#if BR_GCC || BR_CLANG
unsigned eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
if ((eax & mask_eax) == mask_eax
&& (ebx & mask_ebx) == mask_ebx
&& (ecx & mask_ecx) == mask_ecx
&& (edx & mask_edx) == mask_edx)
{
return 1;
}
}
#elif BR_MSC
int info[4];
__cpuid(info, 1);
if (((uint32_t)info[0] & mask_eax) == mask_eax
&& ((uint32_t)info[1] & mask_ebx) == mask_ebx
&& ((uint32_t)info[2] & mask_ecx) == mask_ecx
&& ((uint32_t)info[3] & mask_edx) == mask_edx)
{
return 1;
}
#endif
return 0;
}
#endif
#endif
/* ==================================================================== */
#endif
#define BEARSSL_HTTPS_BEARSSL_DECLARATED
#endif
#if !defined(cJSON__h) && !defined(BEARSSL_HTTPS_MOCK_CJSON)
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#include
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif
#define BEARSSL_HTTPS_CJSON_DECLARATED
#endif
#endif
#ifndef LuaSilverChain_macros
#define LuaSilverChain_macros
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define PRIVATE_BEARSSL_NO_BODY 0
#define PRIVATE_BEARSSL_BODY_RAW 1
#define PRIVATE_BEARSSL_BODY_FILE 2
#define PRIVATE_BEARSSL_BODY_JSON 3
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define BEARSSL_HTTPS_FAILT_TO_START_UNISOCKET 1
#define BEARSSL_HTTPS_INVALID_URL 2
#define BEARSSL_HTTPS_IMPOSSIBLE_TO_OPEN_FILE 3
#define BEARSSL_HTTPS_MUST_BE_IPV4 4
#define BEARSSL_HTTPS_BODY_ITS_BINARY 5
#define BEARSSL_HTTPS_IMPOSSIBLE_TO_READ_BODY 6
#define BEARSSL_HTTPS_BODY_SIZE_ITS_BIGGER_THAN_LIMIT 7
#define BEARSSL_HTTPS_ALOCATION_FAILED 8
#define BEARSSL_HTTPS_BODY_ITS_NOT_A_VALID_JSON 9
#define BEARSSL_HTTPS_FAILT_TO_CREATE_DNS_REQUEST 10
#define BEARSSL_HTTPS_NO_DNS_PROVIDED 11
#define BEARSSL_HTTPS_FAILT_TO_CREATE_SOCKET 12
#define BEARSSL_HTTPS_INVALID_IPV4 12
#define BEARSSL_HTTPS_FAILT_TO_CONNECT 13
#define BEARSSL_HTTPS_UNKNOW_ERROR 14
#define BEARSSL_HTTPS_INVALID_READ_CODE 15
#define BEARSSL_HTTPS_INVALID_HTTP_RESPONSE 16
#define BEARSSL_HTTPS_IMPOSSIBLE_TO_SEND_DATA 17
#define BEARSSL_HTTPS_ERROR_FLUSHING 18
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define BEARSSL_HTTPS_REFERENCE 0
#define BEARSSL_HTTPS_GET_OWNERSHIP 1
#define BEARSSL_HTTPS_COPY 2
#define BEARSSL_DEFAULT_STRATEGY BEARSSL_HTTPS_COPY
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#define BEARSSL_HEADER_CHUNK 200
#define BEARSSL_HEADER_REALLOC_FACTOR 3
#define BEARSSL_MAX_REDIRECTIONS 10
#define BEARSSL_BODY_CHUNK_SIZE 1024
#define BEARSSL_BODY_REALLOC_FACTOR 1.5
#define BEARSSL_DNS_CACHE_HOST_SIZE 1000
#define BEARSSL_DNS_CACHE_IP_SIZE 200
#define BEARSSL_DNS_CACHE_SIZE 100
#endif
#ifndef LuaSilverChain_types
#define LuaSilverChain_types
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsKeyVal{
char *key;
bool key_owner;
char *value;
bool value_owner;
}private_BearHttpsKeyVal;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct privateBearHttpsDnsCache{
char host[BEARSSL_DNS_CACHE_HOST_SIZE];
char ip[BEARSSL_DNS_CACHE_IP_SIZE];
}privateBearHttpsDnsCache;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsBodyRawRequest{
unsigned char *value;
long size;
bool onwer;
}private_BearHttpsBodyRawRequest;
typedef struct private_BearHttpsBodyRequestFile{
char *path;
char content_type[100];
bool onwer;
}private_BearHttpsBodyRequestFile;
#ifndef BEARSSL_HTTPS_MOCK_CJSON
typedef struct private_BearHttpsBodyJsonRequest{
cJSON *json;
bool onwer;
}private_BearHttpsBodyJsonRequest;
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsClientDnsProvider {
const char *hostname;
const char *route;
const char *ip;
int port;
}BearHttpsClientDnsProvider;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsRequisitionProps{
char *hostname;
char *route;
bool is_ipv4;
bool is_ipv6;
bool is_https;
int port;
}private_BearHttpsRequisitionProps ;
#endif
#ifndef LuaSilverChain_typesB
#define LuaSilverChain_typesB
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct private_BearHttpsHeaders{
int size;
private_BearHttpsKeyVal **keyvals;
}private_BearHttpsHeaders;
#endif
#ifndef LuaSilverChain_typesC
#define LuaSilverChain_typesC
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsRequest{
char *url;
bool route_owner;
int max_redirections;
const char *custom_bear_dns;
const char **known_ips;
int known_ips_size;
BearHttpsClientDnsProvider *dns_providers;
int total_dns_providers;
bool must_be_ipv4;
private_BearHttpsHeaders *headers;
char method[30];
int port;
int header_chunk_read_size;
int header_chunk_reallocator_factor;
int response_max_headers_size;
br_x509_trust_anchor *trust_anchors;
size_t trusted_anchors_size;
short body_type;
union{
private_BearHttpsBodyRawRequest body_raw;
private_BearHttpsBodyRequestFile body_file;
#ifndef BEARSSL_HTTPS_MOCK_CJSON
private_BearHttpsBodyJsonRequest body_json;
#endif
};
}BearHttpsRequest ;
#endif
#ifndef LuaSilverChain_typesD
#define LuaSilverChain_typesD
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsResponse{
int connection_file_descriptor;
bool is_https;
br_sslio_context ssl_io;
br_ssl_client_context ssl_client;
unsigned char bear_buffer[BR_SSL_BUFSIZE_BIDI];
br_x509_minimal_context certification_context;
long max_body_size;
unsigned char *raw_content;
int error_code;
private_BearHttpsHeaders *headers;
long user_content_length;
long body_start_index;
unsigned char *body;
#ifndef BEARSSL_HTTPS_MOCK_CJSON
cJSON *json_body;
#endif
long body_size;
long body_readded;
long extra_body_remaning_to_send;
bool body_readed;
int body_chunk_size;
double body_realloc_factor;
char *error_msg;
int status_code;
}BearHttpsResponse ;
#endif
#ifndef LuaSilverChain_typesE
#define LuaSilverChain_typesE
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsRequestNamespace{
void (*send_any_with_ownership_control)(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode);
void (*send_any)(BearHttpsRequest *self,unsigned char *content, long size);
void (*send_body_str_with_ownership_control)(BearHttpsRequest *self, char *content,short ownership_mode);
void (*send_body_str)(BearHttpsRequest *self, char *content);
void (*send_file_with_ownership_control)(BearHttpsRequest *self, char *path,short ownership_mode,const char *content_type);
void (*send_file)(BearHttpsRequest *self,const char *path,const char *content_type);
void (*send_file_auto_detect_content_type)(BearHttpsRequest *self, const char *path);
BearHttpsResponse * (*fetch)(BearHttpsRequest *self);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
void (*send_cJSON_with_ownership_control)(BearHttpsRequest *self,cJSON *json,short ownership_mode);
void (*send_cJSON)(BearHttpsRequest *self,cJSON *json);
cJSON * (*create_cJSONPayloadObject)(BearHttpsRequest *self);
cJSON * (*create_cJSONPayloadArray)(BearHttpsRequest *self);
#endif
BearHttpsRequest * (*newBearHttpsRequest_with_url_ownership_config)(char *url,short url_ownership_mode);
BearHttpsRequest * (*newBearHttpsRequest)(const char *url);
BearHttpsRequest * (*newBearHttpsRequest_fmt)(const char *url,...);
void (*set_known_ips)(BearHttpsRequest *self ,const char *known_ips[],int known_ips_size);
void (*set_url_with_ownership_config)(BearHttpsRequest *self , char *url,short url_ownership_mode);
void (*set_url)(BearHttpsRequest *self ,const char *url);
void (*add_header_with_ownership_config)(BearHttpsRequest *self ,char *key,short key_ownership_mode,char *value,short value_owner);
void (*add_header)(BearHttpsRequest *self ,char *key,char *value);
void (*set_method)(BearHttpsRequest *self ,const char *method);
void (*set_max_redirections)(BearHttpsRequest *self ,int max_redirections);
void (*set_dns_providers)(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers);
void (*set_chunk_header_read_props)(BearHttpsRequest *self ,int chunk_size,int max_chunk_size);
void (*set_trusted_anchors)(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size);
void (*represent)(BearHttpsRequest *self);
void (*free)(BearHttpsRequest *self);
} BearHttpsRequestNamespace;
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsResponseNamespace{
int (*read_body_chunck)(BearHttpsResponse *self,unsigned char *bufer,long size);
unsigned char *(*read_body)(BearHttpsResponse *self);
const char *(*read_body_str)(BearHttpsResponse *self);
int (*get_status_code)(BearHttpsResponse*self);
int (*get_body_size)(BearHttpsResponse*self);
int (*get_headers_size)(BearHttpsResponse*self);
char* (*get_header_value_by_index)(BearHttpsResponse*self,int index);
char* (*get_header_value_by_key)(BearHttpsResponse*self,const char *key);
char* (*get_header_key_by_index)(BearHttpsResponse*self,int index);
char* (*get_header_value_by_sanitized_key)(BearHttpsResponse*self,const char *key);
void (*set_max_body_size)(BearHttpsResponse*self,long size);
void (*set_body_read_props)(BearHttpsResponse*self,int chunk_size,double realloc_factor);
bool (*error)(BearHttpsResponse*self);
char* (*get_error_msg)(BearHttpsResponse*self);
int (*get_error_code)(BearHttpsResponse*self);
void (*free)(BearHttpsResponse *self);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
cJSON * (*read_body_json)(BearHttpsResponse *self);
#endif
} BearHttpsResponseNamespace;
#endif
#ifndef LuaSilverChain_typesH
#define LuaSilverChain_typesH
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
typedef struct BearHttpsNamespace{
short REFERENCE;
short GET_OWNERSHIP;
short COPY;
BearHttpsRequestNamespace request;
BearHttpsResponseNamespace response;
} BearHttpsNamespace;
#endif
#ifndef LuaSilverChain_fdeclare
#define LuaSilverChain_fdeclare
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
bool private_BearHttps_is_sanitize_key(const char *key,const char *sanitized,int sanitized_size);
char * private_BearHttps_format_vaarg(const char *expresion, va_list args);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
private_BearHttpsHeaders *private_newBearHttpsHeaders();
void private_BearHttpsHeaders_add_keyval(private_BearHttpsHeaders *self, private_BearHttpsKeyVal *keyval);
void private_BearHttpsHeaders_free(private_BearHttpsHeaders *self);
private_BearHttpsKeyVal * private_BearHttpsHeaders_get_key_val_by_index(private_BearHttpsHeaders *self,int index);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
private_BearHttpsKeyVal *private_newBearHttpsKeyVal();
void private_BearHttpsKeyVal_set_key(private_BearHttpsKeyVal *self, char *key,short key_onwership_mode);
void private_BearHttpsKeyVal_set_value(private_BearHttpsKeyVal *self, char *value,short value_onwership_mode);
void private_BearHttpsKeyVal_free(private_BearHttpsKeyVal *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsNamespace newBearHttpsNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsRequestNamespace newBearHttpsRequestNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsResponseNamespace newBearHttpsResponseNamespace();
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
static int private_BearHttpsRequest_connect_ipv4(BearHttpsResponse *self, const char *ipv4_ip, int port);
static int private_BearHttpsRequest_connect_ipv4_no_error_raise( const char *ipv4_ip, int port);
static int private_BearHttps_connect_host(BearHttpsRequest *self, BearHttpsResponse *response, const char *host, int port);
static int private_BearHttps_sock_read(void *ctx, unsigned char *buf, size_t len);
static int private_BearHttps_sock_write(void *ctx, const unsigned char *buf, size_t len);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_BearsslHttps_free_considering_ownership(void **value,bool *owner);
void private_BearsslHttps_set_str_considering_ownership(char **dest, char *value, bool *owner, short ownership_mode);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
void private_BearHttpsRequest_free_body(BearHttpsRequest *self);
void BearHttpsRequest_send_any_with_ownership_control(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode);
void BearHttpsRequest_send_any(BearHttpsRequest *self,unsigned char *content, long size);
void BearHttpsRequest_send_body_str_with_ownership_control(BearHttpsRequest *self, char *content,short ownership_mode);
void BearHttpsRequest_send_body_str(BearHttpsRequest *self, char *content);
void BearHttpsRequest_send_file_with_ownership_control(BearHttpsRequest *self, char *path,short ownership_mode,const char *content_type);
void BearHttpsRequest_send_file(BearHttpsRequest *self,const char *path,const char *content_type);
void BearHttpsRequest_send_file_auto_detect_content_type(BearHttpsRequest *self, const char *path);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
void BearHttpsRequest_send_cJSON_with_ownership_control(BearHttpsRequest *self,cJSON *json,short ownership_mode);
void BearHttpsRequest_send_cJSON(BearHttpsRequest *self,cJSON *json);
cJSON * BearHttpsRequest_create_cJSONPayloadObject(BearHttpsRequest *self);
cJSON * BearHttpsRequest_create_cJSONPayloadArray(BearHttpsRequest *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsRequest * newBearHttpsRequest_with_url_ownership_config(char *url,short url_ownership_mode);
BearHttpsRequest * newBearHttpsRequest(const char *url);
BearHttpsRequest * newBearHttpsRequest_fmt(const char *url,...);
void BearHttpsRequest_set_url_with_ownership_config(BearHttpsRequest *self , char *url,short url_ownership_mode);
void BearHttpsRequest_set_url(BearHttpsRequest *self ,const char *url);
void BearHttpsRequest_add_header_with_ownership_config(BearHttpsRequest *self ,char *key,short key_ownership_mode,char *value,short value_owner);
void BearHttpsRequest_add_header(BearHttpsRequest *self ,char *key,char *value);
void BearHttpsRequest_add_header_fmt(BearHttpsRequest *self ,char *key,char *format,...);
void BearHttpsRequest_set_max_redirections(BearHttpsRequest *self ,int max_redirections);
void BearHttpsRequest_set_dns_providers(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers);
void BearHttpsRequest_set_known_ips(BearHttpsRequest *self , const char *known_ips[],int known_ips_size);
void BearHttpsRequest_set_chunk_header_read_props(BearHttpsRequest *self ,int chunk_size,int max_chunk_size);
void BearHttpsRequest_set_trusted_anchors(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size);
void BearHttpsRequest_set_method(BearHttpsRequest *self ,const char *method);
void BearHttpsRequest_represent(BearHttpsRequest *self);
void BearHttpsRequest_free(BearHttpsRequest *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
private_BearHttpsRequisitionProps * private_new_private_BearHttpsRequisitionProps(
const char *route,int default_port);
void private_BearHttpsRequisitionProps_free(private_BearHttpsRequisitionProps *self);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
BearHttpsResponse *private_newBearHttpsResponse();
int private_BearHttpsResponse_read_chunck_raw(BearHttpsResponse *self,unsigned char *bufer,long size);
int BearHttpsResponse_read_body_chunck(BearHttpsResponse *self,unsigned char *bufer,long size);
unsigned char *BearHttpsResponse_read_body(BearHttpsResponse *self);
const char *BearHttpsResponse_read_body_str(BearHttpsResponse *self);
int private_BearHttpsResponse_write(BearHttpsResponse *self,unsigned char *bufer,long size);
void private_BearHttpsResponse_read_til_end_of_headers_or_reach_limit(
BearHttpsResponse *self,
int chunk,
double factor_headers_growth
);
void private_BearHttpsResponse_start_bearssl_props(BearHttpsResponse *self, const char *hostname,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size);
int BearHttpsResponse_get_status_code(BearHttpsResponse*self);
int BearHttpsResponse_get_body_size(BearHttpsResponse*self);
int BearHttpsResponse_get_headers_size(BearHttpsResponse*self);
char* BearHttpsResponse_get_header_value_by_index(BearHttpsResponse*self,int index);
char* BearHttpsResponse_get_header_value_by_key(BearHttpsResponse*self,const char *key);
char* BearHttpsResponse_get_header_key_by_index(BearHttpsResponse*self,int index);
char* BearHttpsResponse_get_header_value_by_sanitized_key(BearHttpsResponse*self,const char *key);
bool BearHttpsResponse_error(BearHttpsResponse*self);
char* BearHttpsResponse_get_error_msg(BearHttpsResponse*self);
int BearHttpsResponse_get_error_code(BearHttpsResponse*self);
void BearHttpsResponse_set_error(BearHttpsResponse*self,const char *msg,int error_code);
void BearHttpsResponse_set_max_body_size(BearHttpsResponse*self,long size);
void BearHttpsResponse_set_body_read_props(BearHttpsResponse*self,int chunk_size,double realloc_factor);
void BearHttpsResponse_free(BearHttpsResponse *self);
#ifndef BEARSSL_HTTPS_MOCK_CJSON
cJSON * BearHttpsResponse_read_body_json(BearHttpsResponse *self);
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
long private_BearsslHttps_strlen(const char *str);
int private_BearsslHttp_strcmp(const char *str1,const char *str2);
bool private_BearsslHttps_startswith(const char *str,const char *prefix);
char * private_BearsslHttps_strdup(const char *str);
char * private_BearsslHttps_strcpy( char *dest,const char *str);
char * private_BearsslHttps_strndup(const char *str,int size);
int private_BearsslHttps_indexof_from_point(const char *str,char c,int start);
char private_BearsslHttps_parse_char_to_lower(char c);
#endif
//silver_chain_scope_end
BearHttpsClientDnsProvider privateBearHttpsProviders[] = {
{.hostname= "dns.google.com",.route="/resolve",.ip = "8.8.8.8",.port=443},
{.hostname= "dns.quad9.net",.route="/dns-query",.ip = "9.9.9.9",.port=5053},
{.hostname= "dns.nextdns.io",.route="/dns-query",.ip = "217.146.9.93",.port=443},
};
int privateBearHttpsProvidersSize = sizeof(privateBearHttpsProviders)/sizeof(BearHttpsClientDnsProvider);
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
privateBearHttpsDnsCache privateBearHttpsDnsCache_itens[BEARSSL_DNS_CACHE_SIZE] ={0};
int privateBearHttpsDnsCache_last_free_point = 0;
#endif
#ifndef LuaSilverChain_dep_define
#define LuaSilverChain_dep_define
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#ifdef _WIN32
typedef __m128i __m128i_u;
#endif
#if !defined(BEARSSL_HTTPS_MOCK_UNIVERSAL_SOCKET_DEFINE) && defined(BEARSSL_HTTPS_UNIVERSAL_SOCKET_DECLARATED)
/* MIT License
Copyright (c) 2024 Samuel Henrique
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef UniversalSocket_def
#define UniversalSocket_def
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern ssize_t Universal_send (int fd, const void *buf, size_t n, int flags){
return send(fd,(char*)buf,n,flags);
}
#if !defined(_DEFAULT_INET_PTON_AND_INET_NTOP_)
extern const char *Universal_inet_ntop(int af, const void *src, char *dst, Universal_socket_len size){
if (af == AF_INET) {
unsigned char *p = (unsigned char *)src;
snprintf(dst, size, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
return dst;
} else if (af == AF_INET6) {
unsigned char *p = (unsigned char *)src;
int i;
int offset = 0;
for (i = 0; i < 8; i++) {
if (offset < size) {
offset += snprintf(dst + offset, size - offset, "%x", (p[i * 2] << 8) | p[i * 2 + 1]);
}
if (i < 7 && offset < size) {
dst[offset++] = ':';
}
}
return dst;
}
return NULL;
}
extern int Universal_inet_pton(int af, const char *src, void *dst){
if (af == AF_INET) {
unsigned char *p = (unsigned char *)dst;
int values[4];
if (sscanf(src, "%d.%d.%d.%d", &values[0], &values[1], &values[2], &values[3]) != 4) {
return 0;
}
for (int i = 0; i < 4; i++) {
if (values[i] < 0 || values[i] > 255) {
return 0;
}
p[i] = (unsigned char)values[i];
}
return 1;
}
else if (af == AF_INET6) {
unsigned char *p = (unsigned char *)dst;
int values[8];
int count = 0;
const char *ptr = src;
int i;
while (*ptr) {
if (sscanf(ptr, "%x", &values[count]) != 1) {
return 0;
}
count++;
while (*ptr && isxdigit(*ptr)) {
ptr++;
}
if (*ptr == ':') {
ptr++;
}
if (count > 8) {
return 0;
}
}
if (count != 8) {
return 0;
}
for (i = 0; i < 8; i++) {
p[i * 2] = (unsigned char)(values[i] >> 8);
p[i * 2 + 1] = (unsigned char)(values[i] & 0xFF);
}
return 1;
}
return 0;
}
#else
extern const char *Universal_inet_ntop(int af, const void *src, char *dst, Universal_socket_len size){
return inet_ntop(af, src, dst, size);
}
extern int Universal_inet_pton(int af, const char *src, void *dst){
return inet_pton(af, src, dst);
}
#endif
extern uint32_t Universal_ntohl(uint32_t netlong){
return ntohl(netlong);
}
uint16_t Universal_htons(uint16_t value) {
return htons(value);
}
uint16_t Universal_ntohs(uint16_t value) {
return ntohs(value);
}
extern in_addr_t Universal_inet_addr(const char *ip) {
return inet_addr(ip);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
extern int Universal_bind (int fd, Universal_sockaddr_in *addrin , Universal_socket_len len){
return bind(fd,(const struct sockaddr *)addrin,len);
}
extern int Universal_accept (int fd, Universal_sockaddr_in *addrin, Universal_socket_len *adrr_len){
return accept(fd,( struct sockaddr *)addrin, adrr_len);
}
extern int Universal_listen (int fd, int n){
return listen(fd,n);
}
extern int Universal_connect(int sockfd, const Universal_sockaddr *addr, socklen_t addrlen){
return connect(sockfd, addr, addrlen);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
const char* Universal_gai_strerror(int e_code){
return gai_strerror(e_code);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
int Universal_socket (int domain, int type, int protocol){
return socket(domain,type,protocol);
}
int Universal_ZeroMemory(void *ptr, size_t num){
if (ptr == NULL || num <= 0) {
return -1;
}
memset(ptr, 0, (unsigned long long)num);
return 0;
}
int Universal_setsockopt(
Universal_socket_int sockfd,
int level,
int optname,
const void *optval,
Universal_socket_len optlen
){
return setsockopt(sockfd, level, optname, (const char *)optval, optlen);
}
int Universal_getsockopt(
Universal_socket_int sockfd,
int level,
int optname,
void *optval,
Universal_socket_len *optlen
){
return getsockopt(sockfd, level, optname, (char *)optval, optlen);
}
Universal_hostent *Universal_gethostbyname(const char *hostname){
return gethostbyname(hostname);
}
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
extern const char* Universal_inet_ntoa(Universal_in_addr addr) {
static char buffer[INET_ADDRSTRLEN];
return inet_ntop(UNI_AF_INET, &addr, buffer, INET_ADDRSTRLEN);
}
extern ssize_t Universal_recv (int fd, void *buf, size_t n, int flags){
return recv(fd, buf, n,flags);
}
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
extern char *Universal_GetLastError(){
return strerror(errno);
}
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(__linux__)
extern int Universal_start_all (){
return 0;
}
extern int Universal_end (){
return 0;
}
extern int Universal_close (int fd){
return close(fd);
}
//#if defined(_GET_ADDR_INFO_DEFAULT_)
int Universal_getaddrinfo(const char *node, const char *service, const Universal_addrinfo *hints, Universal_addrinfo **res){
return getaddrinfo(node, service, hints, res);
}
void Universal_freeaddrinfo(Universal_addrinfo *addrinfo_ptr){
freeaddrinfo(addrinfo_ptr);
}
//#endif
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
extern const char* Universal_inet_ntoa(Universal_in_addr addr) {
return inet_ntoa(addr);
}
ssize_t private_Universal_recv_all(int fd, void *buf, size_t n){
int max = 0;
int received;
while (max < n) {
unsigned char *ptr = (unsigned char*)buf + max;
received = recv(fd,(char*)ptr, n - max, 0);
if (received <= 0) {
return max;
}
max += received;
}
return max;
}
extern ssize_t Universal_recv (int fd, void *buf, size_t n, int flags){
if(flags == UNI_MSG_WAITALL){
return private_Universal_recv_all(fd, buf, n);
}
return recv(fd, (char*)buf, n, flags);
}
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
extern char *Universal_GetLastError(){
static char errorBuffer[256];
DWORD dwError = WSAGetLastError();
if (dwError == 0) {
return (char*)"Nenhum erro";
}
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
0,
errorBuffer,
sizeof(errorBuffer),
NULL
);
return errorBuffer;
}
#endif
//silver_chain_scope_start
//DONT MODIFY THIS COMMENT
//this import is computationally generated
//mannaged by SilverChain: https://github.com/OUIsolutions/SilverChain
//silver_chain_scope_end
#if defined(_WIN32)
extern int Universal_start_all (){
WSADATA wsa;
int error = WSAStartup(MAKEWORD(2, 2), &wsa);
return error;
}
extern int Universal_end (){
return WSACleanup();
}
extern int Universal_close (int fd){
return closesocket(fd);
}
//#if defined(_GET_ADDR_INFO_DEFAULT_)
int Universal_getaddrinfo(const char *node, const char *service, const Universal_addrinfo *hints, Universal_addrinfo **res){
Universal_hostent *he;
he = Universal_gethostbyname(node);
if(he == NULL){
return 1;
}
*res = (Universal_addrinfo *)malloc(sizeof(Universal_addrinfo));
if (*res == NULL) {
return 1;
}
(*res)->ai_flags = 0;
(*res)->ai_family = UNI_AF_INET;
(*res)->ai_socktype = UNI_SOCK_STREAM;
(*res)->ai_protocol = UNI_IPPROTO_TCP;
(*res)->ai_addrlen = sizeof(Universal_sockaddr_in);
Universal_sockaddr_in *sa_in = (Universal_sockaddr_in *)malloc(sizeof(Universal_sockaddr_in));
if (sa_in == NULL) {
free(*res);
return 1;
}
Universal_in_addr **addr_list;
sa_in->sin_family = UNI_AF_INET;
addr_list = (Universal_in_addr **)he->h_addr_list;
sa_in->sin_addr = *addr_list[0];
(*res)->ai_addr = (Universal_sockaddr *)sa_in;
(*res)->ai_canonname = strdup(he->h_name);
(*res)->ai_next = NULL;
return 0;
}
void Universal_freeaddrinfo(Universal_addrinfo *addrinfo_ptr){
free(addrinfo_ptr->ai_addr);
free(addrinfo_ptr->ai_canonname);
free(addrinfo_ptr);
}
//#endif
#endif
#endif
#endif
#if !defined(BEARSSL_HTTPS_MOCK_BEARSSL_DEFINE) && defined(BEARSSL_HTTPS_BEARSSL_DECLARATED)
static const unsigned char TA0_DN[] = {
0x30, 0x57, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E,
0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03,
0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41,
0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47,
0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA0_RSA_N[] = {
0xDA, 0x0E, 0xE6, 0x99, 0x8D, 0xCE, 0xA3, 0xE3, 0x4F, 0x8A, 0x7E, 0xFB,
0xF1, 0x8B, 0x83, 0x25, 0x6B, 0xEA, 0x48, 0x1F, 0xF1, 0x2A, 0xB0, 0xB9,
0x95, 0x11, 0x04, 0xBD, 0xF0, 0x63, 0xD1, 0xE2, 0x67, 0x66, 0xCF, 0x1C,
0xDD, 0xCF, 0x1B, 0x48, 0x2B, 0xEE, 0x8D, 0x89, 0x8E, 0x9A, 0xAF, 0x29,
0x80, 0x65, 0xAB, 0xE9, 0xC7, 0x2D, 0x12, 0xCB, 0xAB, 0x1C, 0x4C, 0x70,
0x07, 0xA1, 0x3D, 0x0A, 0x30, 0xCD, 0x15, 0x8D, 0x4F, 0xF8, 0xDD, 0xD4,
0x8C, 0x50, 0x15, 0x1C, 0xEF, 0x50, 0xEE, 0xC4, 0x2E, 0xF7, 0xFC, 0xE9,
0x52, 0xF2, 0x91, 0x7D, 0xE0, 0x6D, 0xD5, 0x35, 0x30, 0x8E, 0x5E, 0x43,
0x73, 0xF2, 0x41, 0xE9, 0xD5, 0x6A, 0xE3, 0xB2, 0x89, 0x3A, 0x56, 0x39,
0x38, 0x6F, 0x06, 0x3C, 0x88, 0x69, 0x5B, 0x2A, 0x4D, 0xC5, 0xA7, 0x54,
0xB8, 0x6C, 0x89, 0xCC, 0x9B, 0xF9, 0x3C, 0xCA, 0xE5, 0xFD, 0x89, 0xF5,
0x12, 0x3C, 0x92, 0x78, 0x96, 0xD6, 0xDC, 0x74, 0x6E, 0x93, 0x44, 0x61,
0xD1, 0x8D, 0xC7, 0x46, 0xB2, 0x75, 0x0E, 0x86, 0xE8, 0x19, 0x8A, 0xD5,
0x6D, 0x6C, 0xD5, 0x78, 0x16, 0x95, 0xA2, 0xE9, 0xC8, 0x0A, 0x38, 0xEB,
0xF2, 0x24, 0x13, 0x4F, 0x73, 0x54, 0x93, 0x13, 0x85, 0x3A, 0x1B, 0xBC,
0x1E, 0x34, 0xB5, 0x8B, 0x05, 0x8C, 0xB9, 0x77, 0x8B, 0xB1, 0xDB, 0x1F,
0x20, 0x91, 0xAB, 0x09, 0x53, 0x6E, 0x90, 0xCE, 0x7B, 0x37, 0x74, 0xB9,
0x70, 0x47, 0x91, 0x22, 0x51, 0x63, 0x16, 0x79, 0xAE, 0xB1, 0xAE, 0x41,
0x26, 0x08, 0xC8, 0x19, 0x2B, 0xD1, 0x46, 0xAA, 0x48, 0xD6, 0x64, 0x2A,
0xD7, 0x83, 0x34, 0xFF, 0x2C, 0x2A, 0xC1, 0x6C, 0x19, 0x43, 0x4A, 0x07,
0x85, 0xE7, 0xD3, 0x7C, 0xF6, 0x21, 0x68, 0xEF, 0xEA, 0xF2, 0x52, 0x9F,
0x7F, 0x93, 0x90, 0xCF
};
static const unsigned char TA0_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA1_DN[] = {
0x30, 0x81, 0xB4, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0B, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65,
0x74, 0x31, 0x40, 0x30, 0x3E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x14, 0x37,
0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E,
0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x5F, 0x32, 0x30, 0x34, 0x38,
0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x2E, 0x20, 0x62, 0x79, 0x20,
0x72, 0x65, 0x66, 0x2E, 0x20, 0x28, 0x6C, 0x69, 0x6D, 0x69, 0x74, 0x73,
0x20, 0x6C, 0x69, 0x61, 0x62, 0x2E, 0x29, 0x31, 0x25, 0x30, 0x23, 0x06,
0x03, 0x55, 0x04, 0x0B, 0x13, 0x1C, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39,
0x39, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E,
0x65, 0x74, 0x20, 0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x33,
0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74,
0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x28, 0x32, 0x30,
0x34, 0x38, 0x29
};
static const unsigned char TA1_RSA_N[] = {
0xAD, 0x4D, 0x4B, 0xA9, 0x12, 0x86, 0xB2, 0xEA, 0xA3, 0x20, 0x07, 0x15,
0x16, 0x64, 0x2A, 0x2B, 0x4B, 0xD1, 0xBF, 0x0B, 0x4A, 0x4D, 0x8E, 0xED,
0x80, 0x76, 0xA5, 0x67, 0xB7, 0x78, 0x40, 0xC0, 0x73, 0x42, 0xC8, 0x68,
0xC0, 0xDB, 0x53, 0x2B, 0xDD, 0x5E, 0xB8, 0x76, 0x98, 0x35, 0x93, 0x8B,
0x1A, 0x9D, 0x7C, 0x13, 0x3A, 0x0E, 0x1F, 0x5B, 0xB7, 0x1E, 0xCF, 0xE5,
0x24, 0x14, 0x1E, 0xB1, 0x81, 0xA9, 0x8D, 0x7D, 0xB8, 0xCC, 0x6B, 0x4B,
0x03, 0xF1, 0x02, 0x0C, 0xDC, 0xAB, 0xA5, 0x40, 0x24, 0x00, 0x7F, 0x74,
0x94, 0xA1, 0x9D, 0x08, 0x29, 0xB3, 0x88, 0x0B, 0xF5, 0x87, 0x77, 0x9D,
0x55, 0xCD, 0xE4, 0xC3, 0x7E, 0xD7, 0x6A, 0x64, 0xAB, 0x85, 0x14, 0x86,
0x95, 0x5B, 0x97, 0x32, 0x50, 0x6F, 0x3D, 0xC8, 0xBA, 0x66, 0x0C, 0xE3,
0xFC, 0xBD, 0xB8, 0x49, 0xC1, 0x76, 0x89, 0x49, 0x19, 0xFD, 0xC0, 0xA8,
0xBD, 0x89, 0xA3, 0x67, 0x2F, 0xC6, 0x9F, 0xBC, 0x71, 0x19, 0x60, 0xB8,
0x2D, 0xE9, 0x2C, 0xC9, 0x90, 0x76, 0x66, 0x7B, 0x94, 0xE2, 0xAF, 0x78,
0xD6, 0x65, 0x53, 0x5D, 0x3C, 0xD6, 0x9C, 0xB2, 0xCF, 0x29, 0x03, 0xF9,
0x2F, 0xA4, 0x50, 0xB2, 0xD4, 0x48, 0xCE, 0x05, 0x32, 0x55, 0x8A, 0xFD,
0xB2, 0x64, 0x4C, 0x0E, 0xE4, 0x98, 0x07, 0x75, 0xDB, 0x7F, 0xDF, 0xB9,
0x08, 0x55, 0x60, 0x85, 0x30, 0x29, 0xF9, 0x7B, 0x48, 0xA4, 0x69, 0x86,
0xE3, 0x35, 0x3F, 0x1E, 0x86, 0x5D, 0x7A, 0x7A, 0x15, 0xBD, 0xEF, 0x00,
0x8E, 0x15, 0x22, 0x54, 0x17, 0x00, 0x90, 0x26, 0x93, 0xBC, 0x0E, 0x49,
0x68, 0x91, 0xBF, 0xF8, 0x47, 0xD3, 0x9D, 0x95, 0x42, 0xC1, 0x0E, 0x4D,
0xDF, 0x6F, 0x26, 0xCF, 0xC3, 0x18, 0x21, 0x62, 0x66, 0x43, 0x70, 0xD6,
0xD5, 0xC0, 0x07, 0xE1
};
static const unsigned char TA1_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA2_DN[] = {
0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x49, 0x45, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x42, 0x61, 0x6C, 0x74, 0x69, 0x6D, 0x6F, 0x72, 0x65, 0x31,
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x0A, 0x43, 0x79,
0x62, 0x65, 0x72, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x22, 0x30, 0x20,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x42, 0x61, 0x6C, 0x74, 0x69,
0x6D, 0x6F, 0x72, 0x65, 0x20, 0x43, 0x79, 0x62, 0x65, 0x72, 0x54, 0x72,
0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74
};
static const unsigned char TA2_RSA_N[] = {
0xA3, 0x04, 0xBB, 0x22, 0xAB, 0x98, 0x3D, 0x57, 0xE8, 0x26, 0x72, 0x9A,
0xB5, 0x79, 0xD4, 0x29, 0xE2, 0xE1, 0xE8, 0x95, 0x80, 0xB1, 0xB0, 0xE3,
0x5B, 0x8E, 0x2B, 0x29, 0x9A, 0x64, 0xDF, 0xA1, 0x5D, 0xED, 0xB0, 0x09,
0x05, 0x6D, 0xDB, 0x28, 0x2E, 0xCE, 0x62, 0xA2, 0x62, 0xFE, 0xB4, 0x88,
0xDA, 0x12, 0xEB, 0x38, 0xEB, 0x21, 0x9D, 0xC0, 0x41, 0x2B, 0x01, 0x52,
0x7B, 0x88, 0x77, 0xD3, 0x1C, 0x8F, 0xC7, 0xBA, 0xB9, 0x88, 0xB5, 0x6A,
0x09, 0xE7, 0x73, 0xE8, 0x11, 0x40, 0xA7, 0xD1, 0xCC, 0xCA, 0x62, 0x8D,
0x2D, 0xE5, 0x8F, 0x0B, 0xA6, 0x50, 0xD2, 0xA8, 0x50, 0xC3, 0x28, 0xEA,
0xF5, 0xAB, 0x25, 0x87, 0x8A, 0x9A, 0x96, 0x1C, 0xA9, 0x67, 0xB8, 0x3F,
0x0C, 0xD5, 0xF7, 0xF9, 0x52, 0x13, 0x2F, 0xC2, 0x1B, 0xD5, 0x70, 0x70,
0xF0, 0x8F, 0xC0, 0x12, 0xCA, 0x06, 0xCB, 0x9A, 0xE1, 0xD9, 0xCA, 0x33,
0x7A, 0x77, 0xD6, 0xF8, 0xEC, 0xB9, 0xF1, 0x68, 0x44, 0x42, 0x48, 0x13,
0xD2, 0xC0, 0xC2, 0xA4, 0xAE, 0x5E, 0x60, 0xFE, 0xB6, 0xA6, 0x05, 0xFC,
0xB4, 0xDD, 0x07, 0x59, 0x02, 0xD4, 0x59, 0x18, 0x98, 0x63, 0xF5, 0xA5,
0x63, 0xE0, 0x90, 0x0C, 0x7D, 0x5D, 0xB2, 0x06, 0x7A, 0xF3, 0x85, 0xEA,
0xEB, 0xD4, 0x03, 0xAE, 0x5E, 0x84, 0x3E, 0x5F, 0xFF, 0x15, 0xED, 0x69,
0xBC, 0xF9, 0x39, 0x36, 0x72, 0x75, 0xCF, 0x77, 0x52, 0x4D, 0xF3, 0xC9,
0x90, 0x2C, 0xB9, 0x3D, 0xE5, 0xC9, 0x23, 0x53, 0x3F, 0x1F, 0x24, 0x98,
0x21, 0x5C, 0x07, 0x99, 0x29, 0xBD, 0xC6, 0x3A, 0xEC, 0xE7, 0x6E, 0x86,
0x3A, 0x6B, 0x97, 0x74, 0x63, 0x33, 0xBD, 0x68, 0x18, 0x31, 0xF0, 0x78,
0x8D, 0x76, 0xBF, 0xFC, 0x9E, 0x8E, 0x5D, 0x2A, 0x86, 0xA7, 0x4D, 0x90,
0xDC, 0x27, 0x1A, 0x39
};
static const unsigned char TA2_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA3_DN[] = {
0x30, 0x81, 0xB0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x39, 0x30, 0x37, 0x06, 0x03, 0x55, 0x04,
0x0B, 0x13, 0x30, 0x77, 0x77, 0x77, 0x2E, 0x65, 0x6E, 0x74, 0x72, 0x75,
0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x43, 0x50, 0x53, 0x20, 0x69,
0x73, 0x20, 0x69, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74,
0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65,
0x6E, 0x63, 0x65, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B,
0x13, 0x16, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x20, 0x45,
0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E,
0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x45,
0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F,
0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA3_RSA_N[] = {
0xB6, 0x95, 0xB6, 0x43, 0x42, 0xFA, 0xC6, 0x6D, 0x2A, 0x6F, 0x48, 0xDF,
0x94, 0x4C, 0x39, 0x57, 0x05, 0xEE, 0xC3, 0x79, 0x11, 0x41, 0x68, 0x36,
0xED, 0xEC, 0xFE, 0x9A, 0x01, 0x8F, 0xA1, 0x38, 0x28, 0xFC, 0xF7, 0x10,
0x46, 0x66, 0x2E, 0x4D, 0x1E, 0x1A, 0xB1, 0x1A, 0x4E, 0xC6, 0xD1, 0xC0,
0x95, 0x88, 0xB0, 0xC9, 0xFF, 0x31, 0x8B, 0x33, 0x03, 0xDB, 0xB7, 0x83,
0x7B, 0x3E, 0x20, 0x84, 0x5E, 0xED, 0xB2, 0x56, 0x28, 0xA7, 0xF8, 0xE0,
0xB9, 0x40, 0x71, 0x37, 0xC5, 0xCB, 0x47, 0x0E, 0x97, 0x2A, 0x68, 0xC0,
0x22, 0x95, 0x62, 0x15, 0xDB, 0x47, 0xD9, 0xF5, 0xD0, 0x2B, 0xFF, 0x82,
0x4B, 0xC9, 0xAD, 0x3E, 0xDE, 0x4C, 0xDB, 0x90, 0x80, 0x50, 0x3F, 0x09,
0x8A, 0x84, 0x00, 0xEC, 0x30, 0x0A, 0x3D, 0x18, 0xCD, 0xFB, 0xFD, 0x2A,
0x59, 0x9A, 0x23, 0x95, 0x17, 0x2C, 0x45, 0x9E, 0x1F, 0x6E, 0x43, 0x79,
0x6D, 0x0C, 0x5C, 0x98, 0xFE, 0x48, 0xA7, 0xC5, 0x23, 0x47, 0x5C, 0x5E,
0xFD, 0x6E, 0xE7, 0x1E, 0xB4, 0xF6, 0x68, 0x45, 0xD1, 0x86, 0x83, 0x5B,
0xA2, 0x8A, 0x8D, 0xB1, 0xE3, 0x29, 0x80, 0xFE, 0x25, 0x71, 0x88, 0xAD,
0xBE, 0xBC, 0x8F, 0xAC, 0x52, 0x96, 0x4B, 0xAA, 0x51, 0x8D, 0xE4, 0x13,
0x31, 0x19, 0xE8, 0x4E, 0x4D, 0x9F, 0xDB, 0xAC, 0xB3, 0x6A, 0xD5, 0xBC,
0x39, 0x54, 0x71, 0xCA, 0x7A, 0x7A, 0x7F, 0x90, 0xDD, 0x7D, 0x1D, 0x80,
0xD9, 0x81, 0xBB, 0x59, 0x26, 0xC2, 0x11, 0xFE, 0xE6, 0x93, 0xE2, 0xF7,
0x80, 0xE4, 0x65, 0xFB, 0x34, 0x37, 0x0E, 0x29, 0x80, 0x70, 0x4D, 0xAF,
0x38, 0x86, 0x2E, 0x9E, 0x7F, 0x57, 0xAF, 0x9E, 0x17, 0xAE, 0xEB, 0x1C,
0xCB, 0x28, 0x21, 0x5F, 0xB6, 0x1C, 0xD8, 0xE7, 0xA2, 0x04, 0x22, 0xF9,
0xD3, 0xDA, 0xD8, 0xCB
};
static const unsigned char TA3_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA4_DN[] = {
0x30, 0x7B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0C, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D, 0x61,
0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0E,
0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x61, 0x6C, 0x66, 0x6F,
0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C,
0x11, 0x43, 0x6F, 0x6D, 0x6F, 0x64, 0x6F, 0x20, 0x43, 0x41, 0x20, 0x4C,
0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x18, 0x41, 0x41, 0x41, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72,
0x76, 0x69, 0x63, 0x65, 0x73
};
static const unsigned char TA4_RSA_N[] = {
0xBE, 0x40, 0x9D, 0xF4, 0x6E, 0xE1, 0xEA, 0x76, 0x87, 0x1C, 0x4D, 0x45,
0x44, 0x8E, 0xBE, 0x46, 0xC8, 0x83, 0x06, 0x9D, 0xC1, 0x2A, 0xFE, 0x18,
0x1F, 0x8E, 0xE4, 0x02, 0xFA, 0xF3, 0xAB, 0x5D, 0x50, 0x8A, 0x16, 0x31,
0x0B, 0x9A, 0x06, 0xD0, 0xC5, 0x70, 0x22, 0xCD, 0x49, 0x2D, 0x54, 0x63,
0xCC, 0xB6, 0x6E, 0x68, 0x46, 0x0B, 0x53, 0xEA, 0xCB, 0x4C, 0x24, 0xC0,
0xBC, 0x72, 0x4E, 0xEA, 0xF1, 0x15, 0xAE, 0xF4, 0x54, 0x9A, 0x12, 0x0A,
0xC3, 0x7A, 0xB2, 0x33, 0x60, 0xE2, 0xDA, 0x89, 0x55, 0xF3, 0x22, 0x58,
0xF3, 0xDE, 0xDC, 0xCF, 0xEF, 0x83, 0x86, 0xA2, 0x8C, 0x94, 0x4F, 0x9F,
0x68, 0xF2, 0x98, 0x90, 0x46, 0x84, 0x27, 0xC7, 0x76, 0xBF, 0xE3, 0xCC,
0x35, 0x2C, 0x8B, 0x5E, 0x07, 0x64, 0x65, 0x82, 0xC0, 0x48, 0xB0, 0xA8,
0x91, 0xF9, 0x61, 0x9F, 0x76, 0x20, 0x50, 0xA8, 0x91, 0xC7, 0x66, 0xB5,
0xEB, 0x78, 0x62, 0x03, 0x56, 0xF0, 0x8A, 0x1A, 0x13, 0xEA, 0x31, 0xA3,
0x1E, 0xA0, 0x99, 0xFD, 0x38, 0xF6, 0xF6, 0x27, 0x32, 0x58, 0x6F, 0x07,
0xF5, 0x6B, 0xB8, 0xFB, 0x14, 0x2B, 0xAF, 0xB7, 0xAA, 0xCC, 0xD6, 0x63,
0x5F, 0x73, 0x8C, 0xDA, 0x05, 0x99, 0xA8, 0x38, 0xA8, 0xCB, 0x17, 0x78,
0x36, 0x51, 0xAC, 0xE9, 0x9E, 0xF4, 0x78, 0x3A, 0x8D, 0xCF, 0x0F, 0xD9,
0x42, 0xE2, 0x98, 0x0C, 0xAB, 0x2F, 0x9F, 0x0E, 0x01, 0xDE, 0xEF, 0x9F,
0x99, 0x49, 0xF1, 0x2D, 0xDF, 0xAC, 0x74, 0x4D, 0x1B, 0x98, 0xB5, 0x47,
0xC5, 0xE5, 0x29, 0xD1, 0xF9, 0x90, 0x18, 0xC7, 0x62, 0x9C, 0xBE, 0x83,
0xC7, 0x26, 0x7B, 0x3E, 0x8A, 0x25, 0xC7, 0xC0, 0xDD, 0x9D, 0xE6, 0x35,
0x68, 0x10, 0x20, 0x9D, 0x8F, 0xD8, 0xDE, 0xD2, 0xC3, 0x84, 0x9C, 0x0D,
0x5E, 0xE8, 0x2F, 0xC9
};
static const unsigned char TA4_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA5_DN[] = {
0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C,
0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32
};
static const unsigned char TA5_RSA_N[] = {
0x9A, 0x18, 0xCA, 0x4B, 0x94, 0x0D, 0x00, 0x2D, 0xAF, 0x03, 0x29, 0x8A,
0xF0, 0x0F, 0x81, 0xC8, 0xAE, 0x4C, 0x19, 0x85, 0x1D, 0x08, 0x9F, 0xAB,
0x29, 0x44, 0x85, 0xF3, 0x2F, 0x81, 0xAD, 0x32, 0x1E, 0x90, 0x46, 0xBF,
0xA3, 0x86, 0x26, 0x1A, 0x1E, 0xFE, 0x7E, 0x1C, 0x18, 0x3A, 0x5C, 0x9C,
0x60, 0x17, 0x2A, 0x3A, 0x74, 0x83, 0x33, 0x30, 0x7D, 0x61, 0x54, 0x11,
0xCB, 0xED, 0xAB, 0xE0, 0xE6, 0xD2, 0xA2, 0x7E, 0xF5, 0x6B, 0x6F, 0x18,
0xB7, 0x0A, 0x0B, 0x2D, 0xFD, 0xE9, 0x3E, 0xEF, 0x0A, 0xC6, 0xB3, 0x10,
0xE9, 0xDC, 0xC2, 0x46, 0x17, 0xF8, 0x5D, 0xFD, 0xA4, 0xDA, 0xFF, 0x9E,
0x49, 0x5A, 0x9C, 0xE6, 0x33, 0xE6, 0x24, 0x96, 0xF7, 0x3F, 0xBA, 0x5B,
0x2B, 0x1C, 0x7A, 0x35, 0xC2, 0xD6, 0x67, 0xFE, 0xAB, 0x66, 0x50, 0x8B,
0x6D, 0x28, 0x60, 0x2B, 0xEF, 0xD7, 0x60, 0xC3, 0xC7, 0x93, 0xBC, 0x8D,
0x36, 0x91, 0xF3, 0x7F, 0xF8, 0xDB, 0x11, 0x13, 0xC4, 0x9C, 0x77, 0x76,
0xC1, 0xAE, 0xB7, 0x02, 0x6A, 0x81, 0x7A, 0xA9, 0x45, 0x83, 0xE2, 0x05,
0xE6, 0xB9, 0x56, 0xC1, 0x94, 0x37, 0x8F, 0x48, 0x71, 0x63, 0x22, 0xEC,
0x17, 0x65, 0x07, 0x95, 0x8A, 0x4B, 0xDF, 0x8F, 0xC6, 0x5A, 0x0A, 0xE5,
0xB0, 0xE3, 0x5F, 0x5E, 0x6B, 0x11, 0xAB, 0x0C, 0xF9, 0x85, 0xEB, 0x44,
0xE9, 0xF8, 0x04, 0x73, 0xF2, 0xE9, 0xFE, 0x5C, 0x98, 0x8C, 0xF5, 0x73,
0xAF, 0x6B, 0xB4, 0x7E, 0xCD, 0xD4, 0x5C, 0x02, 0x2B, 0x4C, 0x39, 0xE1,
0xB2, 0x95, 0x95, 0x2D, 0x42, 0x87, 0xD7, 0xD5, 0xB3, 0x90, 0x43, 0xB7,
0x6C, 0x13, 0xF1, 0xDE, 0xDD, 0xF6, 0xC4, 0xF8, 0x89, 0x3F, 0xD1, 0x75,
0xF5, 0x92, 0xC3, 0x91, 0xD5, 0x8A, 0x88, 0xD0, 0x90, 0xEC, 0xDC, 0x6D,
0xDE, 0x89, 0xC2, 0x65, 0x71, 0x96, 0x8B, 0x0D, 0x03, 0xFD, 0x9C, 0xBF,
0x5B, 0x16, 0xAC, 0x92, 0xDB, 0xEA, 0xFE, 0x79, 0x7C, 0xAD, 0xEB, 0xAF,
0xF7, 0x16, 0xCB, 0xDB, 0xCD, 0x25, 0x2B, 0xE5, 0x1F, 0xFB, 0x9A, 0x9F,
0xE2, 0x51, 0xCC, 0x3A, 0x53, 0x0C, 0x48, 0xE6, 0x0E, 0xBD, 0xC9, 0xB4,
0x76, 0x06, 0x52, 0xE6, 0x11, 0x13, 0x85, 0x72, 0x63, 0x03, 0x04, 0xE0,
0x04, 0x36, 0x2B, 0x20, 0x19, 0x02, 0xE8, 0x74, 0xA7, 0x1F, 0xB6, 0xC9,
0x56, 0x66, 0xF0, 0x75, 0x25, 0xDC, 0x67, 0xC1, 0x0E, 0x61, 0x60, 0x88,
0xB3, 0x3E, 0xD1, 0xA8, 0xFC, 0xA3, 0xDA, 0x1D, 0xB0, 0xD1, 0xB1, 0x23,
0x54, 0xDF, 0x44, 0x76, 0x6D, 0xED, 0x41, 0xD8, 0xC1, 0xB2, 0x22, 0xB6,
0x53, 0x1C, 0xDF, 0x35, 0x1D, 0xDC, 0xA1, 0x77, 0x2A, 0x31, 0xE4, 0x2D,
0xF5, 0xE5, 0xE5, 0xDB, 0xC8, 0xE0, 0xFF, 0xE5, 0x80, 0xD7, 0x0B, 0x63,
0xA0, 0xFF, 0x33, 0xA1, 0x0F, 0xBA, 0x2C, 0x15, 0x15, 0xEA, 0x97, 0xB3,
0xD2, 0xA2, 0xB5, 0xBE, 0xF2, 0x8C, 0x96, 0x1E, 0x1A, 0x8F, 0x1D, 0x6C,
0xA4, 0x61, 0x37, 0xB9, 0x86, 0x73, 0x33, 0xD7, 0x97, 0x96, 0x9E, 0x23,
0x7D, 0x82, 0xA4, 0x4C, 0x81, 0xE2, 0xA1, 0xD1, 0xBA, 0x67, 0x5F, 0x95,
0x07, 0xA3, 0x27, 0x11, 0xEE, 0x16, 0x10, 0x7B, 0xBC, 0x45, 0x4A, 0x4C,
0xB2, 0x04, 0xD2, 0xAB, 0xEF, 0xD5, 0xFD, 0x0C, 0x51, 0xCE, 0x50, 0x6A,
0x08, 0x31, 0xF9, 0x91, 0xDA, 0x0C, 0x8F, 0x64, 0x5C, 0x03, 0xC3, 0x3A,
0x8B, 0x20, 0x3F, 0x6E, 0x8D, 0x67, 0x3D, 0x3A, 0xD6, 0xFE, 0x7D, 0x5B,
0x88, 0xC9, 0x5E, 0xFB, 0xCC, 0x61, 0xDC, 0x8B, 0x33, 0x77, 0xD3, 0x44,
0x32, 0x35, 0x09, 0x62, 0x04, 0x92, 0x16, 0x10, 0xD8, 0x9E, 0x27, 0x47,
0xFB, 0x3B, 0x21, 0xE3, 0xF8, 0xEB, 0x1D, 0x5B
};
static const unsigned char TA5_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA6_DN[] = {
0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C,
0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x12, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33
};
static const unsigned char TA6_RSA_N[] = {
0xCC, 0x57, 0x42, 0x16, 0x54, 0x9C, 0xE6, 0x98, 0xD3, 0xD3, 0x4D, 0xEE,
0xFE, 0xED, 0xC7, 0x9F, 0x43, 0x39, 0x4A, 0x65, 0xB3, 0xE8, 0x16, 0x88,
0x34, 0xDB, 0x0D, 0x59, 0x91, 0x74, 0xCF, 0x92, 0xB8, 0x04, 0x40, 0xAD,
0x02, 0x4B, 0x31, 0xAB, 0xBC, 0x8D, 0x91, 0x68, 0xD8, 0x20, 0x0E, 0x1A,
0x01, 0xE2, 0x1A, 0x7B, 0x4E, 0x17, 0x5D, 0xE2, 0x8A, 0xB7, 0x3F, 0x99,
0x1A, 0xCD, 0xEB, 0x61, 0xAB, 0xC2, 0x65, 0xA6, 0x1F, 0xB7, 0xB7, 0xBD,
0xB7, 0x8F, 0xFC, 0xFD, 0x70, 0x8F, 0x0B, 0xA0, 0x67, 0xBE, 0x01, 0xA2,
0x59, 0xCF, 0x71, 0xE6, 0x0F, 0x29, 0x76, 0xFF, 0xB1, 0x56, 0x79, 0x45,
0x2B, 0x1F, 0x9E, 0x7A, 0x54, 0xE8, 0xA3, 0x29, 0x35, 0x68, 0xA4, 0x01,
0x4F, 0x0F, 0xA4, 0x2E, 0x37, 0xEF, 0x1B, 0xBF, 0xE3, 0x8F, 0x10, 0xA8,
0x72, 0xAB, 0x58, 0x57, 0xE7, 0x54, 0x86, 0xC8, 0xC9, 0xF3, 0x5B, 0xDA,
0x2C, 0xDA, 0x5D, 0x8E, 0x6E, 0x3C, 0xA3, 0x3E, 0xDA, 0xFB, 0x82, 0xE5,
0xDD, 0xF2, 0x5C, 0xB2, 0x05, 0x33, 0x6F, 0x8A, 0x36, 0xCE, 0xD0, 0x13,
0x4E, 0xFF, 0xBF, 0x4A, 0x0C, 0x34, 0x4C, 0xA6, 0xC3, 0x21, 0xBD, 0x50,
0x04, 0x55, 0xEB, 0xB1, 0xBB, 0x9D, 0xFB, 0x45, 0x1E, 0x64, 0x15, 0xDE,
0x55, 0x01, 0x8C, 0x02, 0x76, 0xB5, 0xCB, 0xA1, 0x3F, 0x42, 0x69, 0xBC,
0x2F, 0xBD, 0x68, 0x43, 0x16, 0x56, 0x89, 0x2A, 0x37, 0x61, 0x91, 0xFD,
0xA6, 0xAE, 0x4E, 0xC0, 0xCB, 0x14, 0x65, 0x94, 0x37, 0x4B, 0x92, 0x06,
0xEF, 0x04, 0xD0, 0xC8, 0x9C, 0x88, 0xDB, 0x0B, 0x7B, 0x81, 0xAF, 0xB1,
0x3D, 0x2A, 0xC4, 0x65, 0x3A, 0x78, 0xB6, 0xEE, 0xDC, 0x80, 0xB1, 0xD2,
0xD3, 0x99, 0x9C, 0x3A, 0xEE, 0x6B, 0x5A, 0x6B, 0xB3, 0x8D, 0xB7, 0xD5,
0xCE, 0x9C, 0xC2, 0xBE, 0xA5, 0x4B, 0x2F, 0x16, 0xB1, 0x9E, 0x68, 0x3B,
0x06, 0x6F, 0xAE, 0x7D, 0x9F, 0xF8, 0xDE, 0xEC, 0xCC, 0x29, 0xA7, 0x98,
0xA3, 0x25, 0x43, 0x2F, 0xEF, 0xF1, 0x5F, 0x26, 0xE1, 0x88, 0x4D, 0xF8,
0x5E, 0x6E, 0xD7, 0xD9, 0x14, 0x6E, 0x19, 0x33, 0x69, 0xA7, 0x3B, 0x84,
0x89, 0x93, 0xC4, 0x53, 0x55, 0x13, 0xA1, 0x51, 0x78, 0x40, 0xF8, 0xB8,
0xC9, 0xA2, 0xEE, 0x7B, 0xBA, 0x52, 0x42, 0x83, 0x9E, 0x14, 0xED, 0x05,
0x52, 0x5A, 0x59, 0x56, 0xA7, 0x97, 0xFC, 0x9D, 0x3F, 0x0A, 0x29, 0xD8,
0xDC, 0x4F, 0x91, 0x0E, 0x13, 0xBC, 0xDE, 0x95, 0xA4, 0xDF, 0x8B, 0x99,
0xBE, 0xAC, 0x9B, 0x33, 0x88, 0xEF, 0xB5, 0x81, 0xAF, 0x1B, 0xC6, 0x22,
0x53, 0xC8, 0xF6, 0xC7, 0xEE, 0x97, 0x14, 0xB0, 0xC5, 0x7C, 0x78, 0x52,
0xC8, 0xF0, 0xCE, 0x6E, 0x77, 0x60, 0x84, 0xA6, 0xE9, 0x2A, 0x76, 0x20,
0xED, 0x58, 0x01, 0x17, 0x30, 0x93, 0xE9, 0x1A, 0x8B, 0xE0, 0x73, 0x63,
0xD9, 0x6A, 0x92, 0x94, 0x49, 0x4E, 0xB4, 0xAD, 0x4A, 0x85, 0xC4, 0xA3,
0x22, 0x30, 0xFC, 0x09, 0xED, 0x68, 0x22, 0x73, 0xA6, 0x88, 0x0C, 0x55,
0x21, 0x58, 0xC5, 0xE1, 0x3A, 0x9F, 0x2A, 0xDD, 0xCA, 0xE1, 0x90, 0xE0,
0xD9, 0x73, 0xAB, 0x6C, 0x80, 0xB8, 0xE8, 0x0B, 0x64, 0x93, 0xA0, 0x9C,
0x8C, 0x19, 0xFF, 0xB3, 0xD2, 0x0C, 0xEC, 0x91, 0x26, 0x87, 0x8A, 0xB3,
0xA2, 0xE1, 0x70, 0x8F, 0x2C, 0x0A, 0xE5, 0xCD, 0x6D, 0x68, 0x51, 0xEB,
0xDA, 0x3F, 0x05, 0x7F, 0x8B, 0x32, 0xE6, 0x13, 0x5C, 0x6B, 0xFE, 0x5F,
0x40, 0xE2, 0x22, 0xC8, 0xB4, 0xB4, 0x64, 0x4F, 0xD6, 0xBA, 0x7D, 0x48,
0x3E, 0xA8, 0x69, 0x0C, 0xD7, 0xBB, 0x86, 0x71, 0xC9, 0x73, 0xB8, 0x3F,
0x3B, 0x9D, 0x25, 0x4B, 0xDA, 0xFF, 0x40, 0xEB
};
static const unsigned char TA6_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA7_DN[] = {
0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04,
0x0B, 0x13, 0x15, 0x77, 0x77, 0x77, 0x2E, 0x78, 0x72, 0x61, 0x6D, 0x70,
0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2E, 0x63, 0x6F, 0x6D,
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1B, 0x58,
0x52, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x24, 0x58, 0x52, 0x61, 0x6D, 0x70, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61,
0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74,
0x79
};
static const unsigned char TA7_RSA_N[] = {
0x98, 0x24, 0x1E, 0xBD, 0x15, 0xB4, 0xBA, 0xDF, 0xC7, 0x8C, 0xA5, 0x27,
0xB6, 0x38, 0x0B, 0x69, 0xF3, 0xB6, 0x4E, 0xA8, 0x2C, 0x2E, 0x21, 0x1D,
0x5C, 0x44, 0xDF, 0x21, 0x5D, 0x7E, 0x23, 0x74, 0xFE, 0x5E, 0x7E, 0xB4,
0x4A, 0xB7, 0xA6, 0xAD, 0x1F, 0xAE, 0xE0, 0x06, 0x16, 0xE2, 0x9B, 0x5B,
0xD9, 0x67, 0x74, 0x6B, 0x5D, 0x80, 0x8F, 0x29, 0x9D, 0x86, 0x1B, 0xD9,
0x9C, 0x0D, 0x98, 0x6D, 0x76, 0x10, 0x28, 0x58, 0xE4, 0x65, 0xB0, 0x7F,
0x4A, 0x98, 0x79, 0x9F, 0xE0, 0xC3, 0x31, 0x7E, 0x80, 0x2B, 0xB5, 0x8C,
0xC0, 0x40, 0x3B, 0x11, 0x86, 0xD0, 0xCB, 0xA2, 0x86, 0x36, 0x60, 0xA4,
0xD5, 0x30, 0x82, 0x6D, 0xD9, 0x6E, 0xD0, 0x0F, 0x12, 0x04, 0x33, 0x97,
0x5F, 0x4F, 0x61, 0x5A, 0xF0, 0xE4, 0xF9, 0x91, 0xAB, 0xE7, 0x1D, 0x3B,
0xBC, 0xE8, 0xCF, 0xF4, 0x6B, 0x2D, 0x34, 0x7C, 0xE2, 0x48, 0x61, 0x1C,
0x8E, 0xF3, 0x61, 0x44, 0xCC, 0x6F, 0xA0, 0x4A, 0xA9, 0x94, 0xB0, 0x4D,
0xDA, 0xE7, 0xA9, 0x34, 0x7A, 0x72, 0x38, 0xA8, 0x41, 0xCC, 0x3C, 0x94,
0x11, 0x7D, 0xEB, 0xC8, 0xA6, 0x8C, 0xB7, 0x86, 0xCB, 0xCA, 0x33, 0x3B,
0xD9, 0x3D, 0x37, 0x8B, 0xFB, 0x7A, 0x3E, 0x86, 0x2C, 0xE7, 0x73, 0xD7,
0x0A, 0x57, 0xAC, 0x64, 0x9B, 0x19, 0xEB, 0xF4, 0x0F, 0x04, 0x08, 0x8A,
0xAC, 0x03, 0x17, 0x19, 0x64, 0xF4, 0x5A, 0x25, 0x22, 0x8D, 0x34, 0x2C,
0xB2, 0xF6, 0x68, 0x1D, 0x12, 0x6D, 0xD3, 0x8A, 0x1E, 0x14, 0xDA, 0xC4,
0x8F, 0xA6, 0xE2, 0x23, 0x85, 0xD5, 0x7A, 0x0D, 0xBD, 0x6A, 0xE0, 0xE9,
0xEC, 0xEC, 0x17, 0xBB, 0x42, 0x1B, 0x67, 0xAA, 0x25, 0xED, 0x45, 0x83,
0x21, 0xFC, 0xC1, 0xC9, 0x7C, 0xD5, 0x62, 0x3E, 0xFA, 0xF2, 0xC5, 0x2D,
0xD3, 0xFD, 0xD4, 0x65
};
static const unsigned char TA7_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA8_DN[] = {
0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x18, 0x54, 0x68, 0x65, 0x20, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64,
0x64, 0x79, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x2C, 0x20, 0x49, 0x6E,
0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x28, 0x47, 0x6F, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x43, 0x6C,
0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68,
0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA8_RSA_N[] = {
0xDE, 0x9D, 0xD7, 0xEA, 0x57, 0x18, 0x49, 0xA1, 0x5B, 0xEB, 0xD7, 0x5F,
0x48, 0x86, 0xEA, 0xBE, 0xDD, 0xFF, 0xE4, 0xEF, 0x67, 0x1C, 0xF4, 0x65,
0x68, 0xB3, 0x57, 0x71, 0xA0, 0x5E, 0x77, 0xBB, 0xED, 0x9B, 0x49, 0xE9,
0x70, 0x80, 0x3D, 0x56, 0x18, 0x63, 0x08, 0x6F, 0xDA, 0xF2, 0xCC, 0xD0,
0x3F, 0x7F, 0x02, 0x54, 0x22, 0x54, 0x10, 0xD8, 0xB2, 0x81, 0xD4, 0xC0,
0x75, 0x3D, 0x4B, 0x7F, 0xC7, 0x77, 0xC3, 0x3E, 0x78, 0xAB, 0x1A, 0x03,
0xB5, 0x20, 0x6B, 0x2F, 0x6A, 0x2B, 0xB1, 0xC5, 0x88, 0x7E, 0xC4, 0xBB,
0x1E, 0xB0, 0xC1, 0xD8, 0x45, 0x27, 0x6F, 0xAA, 0x37, 0x58, 0xF7, 0x87,
0x26, 0xD7, 0xD8, 0x2D, 0xF6, 0xA9, 0x17, 0xB7, 0x1F, 0x72, 0x36, 0x4E,
0xA6, 0x17, 0x3F, 0x65, 0x98, 0x92, 0xDB, 0x2A, 0x6E, 0x5D, 0xA2, 0xFE,
0x88, 0xE0, 0x0B, 0xDE, 0x7F, 0xE5, 0x8D, 0x15, 0xE1, 0xEB, 0xCB, 0x3A,
0xD5, 0xE2, 0x12, 0xA2, 0x13, 0x2D, 0xD8, 0x8E, 0xAF, 0x5F, 0x12, 0x3D,
0xA0, 0x08, 0x05, 0x08, 0xB6, 0x5C, 0xA5, 0x65, 0x38, 0x04, 0x45, 0x99,
0x1E, 0xA3, 0x60, 0x60, 0x74, 0xC5, 0x41, 0xA5, 0x72, 0x62, 0x1B, 0x62,
0xC5, 0x1F, 0x6F, 0x5F, 0x1A, 0x42, 0xBE, 0x02, 0x51, 0x65, 0xA8, 0xAE,
0x23, 0x18, 0x6A, 0xFC, 0x78, 0x03, 0xA9, 0x4D, 0x7F, 0x80, 0xC3, 0xFA,
0xAB, 0x5A, 0xFC, 0xA1, 0x40, 0xA4, 0xCA, 0x19, 0x16, 0xFE, 0xB2, 0xC8,
0xEF, 0x5E, 0x73, 0x0D, 0xEE, 0x77, 0xBD, 0x9A, 0xF6, 0x79, 0x98, 0xBC,
0xB1, 0x07, 0x67, 0xA2, 0x15, 0x0D, 0xDD, 0xA0, 0x58, 0xC6, 0x44, 0x7B,
0x0A, 0x3E, 0x62, 0x28, 0x5F, 0xBA, 0x41, 0x07, 0x53, 0x58, 0xCF, 0x11,
0x7E, 0x38, 0x74, 0xC5, 0xF8, 0xFF, 0xB5, 0x69, 0x90, 0x8F, 0x84, 0x74,
0xEA, 0x97, 0x1B, 0xAF
};
static const unsigned char TA8_RSA_E[] = {
0x03
};
static const unsigned char TA9_DN[] = {
0x30, 0x68, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20,
0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73,
0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03,
0x55, 0x04, 0x0B, 0x13, 0x29, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69, 0x65,
0x6C, 0x64, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32, 0x20, 0x43,
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E,
0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA9_RSA_N[] = {
0xB7, 0x32, 0xC8, 0xFE, 0xE9, 0x71, 0xA6, 0x04, 0x85, 0xAD, 0x0C, 0x11,
0x64, 0xDF, 0xCE, 0x4D, 0xEF, 0xC8, 0x03, 0x18, 0x87, 0x3F, 0xA1, 0xAB,
0xFB, 0x3C, 0xA6, 0x9F, 0xF0, 0xC3, 0xA1, 0xDA, 0xD4, 0xD8, 0x6E, 0x2B,
0x53, 0x90, 0xFB, 0x24, 0xA4, 0x3E, 0x84, 0xF0, 0x9E, 0xE8, 0x5F, 0xEC,
0xE5, 0x27, 0x44, 0xF5, 0x28, 0xA6, 0x3F, 0x7B, 0xDE, 0xE0, 0x2A, 0xF0,
0xC8, 0xAF, 0x53, 0x2F, 0x9E, 0xCA, 0x05, 0x01, 0x93, 0x1E, 0x8F, 0x66,
0x1C, 0x39, 0xA7, 0x4D, 0xFA, 0x5A, 0xB6, 0x73, 0x04, 0x25, 0x66, 0xEB,
0x77, 0x7F, 0xE7, 0x59, 0xC6, 0x4A, 0x99, 0x25, 0x14, 0x54, 0xEB, 0x26,
0xC7, 0xF3, 0x7F, 0x19, 0xD5, 0x30, 0x70, 0x8F, 0xAF, 0xB0, 0x46, 0x2A,
0xFF, 0xAD, 0xEB, 0x29, 0xED, 0xD7, 0x9F, 0xAA, 0x04, 0x87, 0xA3, 0xD4,
0xF9, 0x89, 0xA5, 0x34, 0x5F, 0xDB, 0x43, 0x91, 0x82, 0x36, 0xD9, 0x66,
0x3C, 0xB1, 0xB8, 0xB9, 0x82, 0xFD, 0x9C, 0x3A, 0x3E, 0x10, 0xC8, 0x3B,
0xEF, 0x06, 0x65, 0x66, 0x7A, 0x9B, 0x19, 0x18, 0x3D, 0xFF, 0x71, 0x51,
0x3C, 0x30, 0x2E, 0x5F, 0xBE, 0x3D, 0x77, 0x73, 0xB2, 0x5D, 0x06, 0x6C,
0xC3, 0x23, 0x56, 0x9A, 0x2B, 0x85, 0x26, 0x92, 0x1C, 0xA7, 0x02, 0xB3,
0xE4, 0x3F, 0x0D, 0xAF, 0x08, 0x79, 0x82, 0xB8, 0x36, 0x3D, 0xEA, 0x9C,
0xD3, 0x35, 0xB3, 0xBC, 0x69, 0xCA, 0xF5, 0xCC, 0x9D, 0xE8, 0xFD, 0x64,
0x8D, 0x17, 0x80, 0x33, 0x6E, 0x5E, 0x4A, 0x5D, 0x99, 0xC9, 0x1E, 0x87,
0xB4, 0x9D, 0x1A, 0xC0, 0xD5, 0x6E, 0x13, 0x35, 0x23, 0x5E, 0xDF, 0x9B,
0x5F, 0x3D, 0xEF, 0xD6, 0xF7, 0x76, 0xC2, 0xEA, 0x3E, 0xBB, 0x78, 0x0D,
0x1C, 0x42, 0x67, 0x6B, 0x04, 0xD8, 0xF8, 0xD6, 0xDA, 0x6F, 0x8B, 0xF2,
0x44, 0xA0, 0x01, 0xAB
};
static const unsigned char TA9_RSA_E[] = {
0x03
};
static const unsigned char TA10_DN[] = {
0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA10_RSA_N[] = {
0xAD, 0x0E, 0x15, 0xCE, 0xE4, 0x43, 0x80, 0x5C, 0xB1, 0x87, 0xF3, 0xB7,
0x60, 0xF9, 0x71, 0x12, 0xA5, 0xAE, 0xDC, 0x26, 0x94, 0x88, 0xAA, 0xF4,
0xCE, 0xF5, 0x20, 0x39, 0x28, 0x58, 0x60, 0x0C, 0xF8, 0x80, 0xDA, 0xA9,
0x15, 0x95, 0x32, 0x61, 0x3C, 0xB5, 0xB1, 0x28, 0x84, 0x8A, 0x8A, 0xDC,
0x9F, 0x0A, 0x0C, 0x83, 0x17, 0x7A, 0x8F, 0x90, 0xAC, 0x8A, 0xE7, 0x79,
0x53, 0x5C, 0x31, 0x84, 0x2A, 0xF6, 0x0F, 0x98, 0x32, 0x36, 0x76, 0xCC,
0xDE, 0xDD, 0x3C, 0xA8, 0xA2, 0xEF, 0x6A, 0xFB, 0x21, 0xF2, 0x52, 0x61,
0xDF, 0x9F, 0x20, 0xD7, 0x1F, 0xE2, 0xB1, 0xD9, 0xFE, 0x18, 0x64, 0xD2,
0x12, 0x5B, 0x5F, 0xF9, 0x58, 0x18, 0x35, 0xBC, 0x47, 0xCD, 0xA1, 0x36,
0xF9, 0x6B, 0x7F, 0xD4, 0xB0, 0x38, 0x3E, 0xC1, 0x1B, 0xC3, 0x8C, 0x33,
0xD9, 0xD8, 0x2F, 0x18, 0xFE, 0x28, 0x0F, 0xB3, 0xA7, 0x83, 0xD6, 0xC3,
0x6E, 0x44, 0xC0, 0x61, 0x35, 0x96, 0x16, 0xFE, 0x59, 0x9C, 0x8B, 0x76,
0x6D, 0xD7, 0xF1, 0xA2, 0x4B, 0x0D, 0x2B, 0xFF, 0x0B, 0x72, 0xDA, 0x9E,
0x60, 0xD0, 0x8E, 0x90, 0x35, 0xC6, 0x78, 0x55, 0x87, 0x20, 0xA1, 0xCF,
0xE5, 0x6D, 0x0A, 0xC8, 0x49, 0x7C, 0x31, 0x98, 0x33, 0x6C, 0x22, 0xE9,
0x87, 0xD0, 0x32, 0x5A, 0xA2, 0xBA, 0x13, 0x82, 0x11, 0xED, 0x39, 0x17,
0x9D, 0x99, 0x3A, 0x72, 0xA1, 0xE6, 0xFA, 0xA4, 0xD9, 0xD5, 0x17, 0x31,
0x75, 0xAE, 0x85, 0x7D, 0x22, 0xAE, 0x3F, 0x01, 0x46, 0x86, 0xF6, 0x28,
0x79, 0xC8, 0xB1, 0xDA, 0xE4, 0x57, 0x17, 0xC4, 0x7E, 0x1C, 0x0E, 0xB0,
0xB4, 0x92, 0xA6, 0x56, 0xB3, 0xBD, 0xB2, 0x97, 0xED, 0xAA, 0xA7, 0xF0,
0xB7, 0xC5, 0xA8, 0x3F, 0x95, 0x16, 0xD0, 0xFF, 0xA1, 0x96, 0xEB, 0x08,
0x5F, 0x18, 0x77, 0x4F
};
static const unsigned char TA10_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA11_DN[] = {
0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41
};
static const unsigned char TA11_RSA_N[] = {
0xE2, 0x3B, 0xE1, 0x11, 0x72, 0xDE, 0xA8, 0xA4, 0xD3, 0xA3, 0x57, 0xAA,
0x50, 0xA2, 0x8F, 0x0B, 0x77, 0x90, 0xC9, 0xA2, 0xA5, 0xEE, 0x12, 0xCE,
0x96, 0x5B, 0x01, 0x09, 0x20, 0xCC, 0x01, 0x93, 0xA7, 0x4E, 0x30, 0xB7,
0x53, 0xF7, 0x43, 0xC4, 0x69, 0x00, 0x57, 0x9D, 0xE2, 0x8D, 0x22, 0xDD,
0x87, 0x06, 0x40, 0x00, 0x81, 0x09, 0xCE, 0xCE, 0x1B, 0x83, 0xBF, 0xDF,
0xCD, 0x3B, 0x71, 0x46, 0xE2, 0xD6, 0x66, 0xC7, 0x05, 0xB3, 0x76, 0x27,
0x16, 0x8F, 0x7B, 0x9E, 0x1E, 0x95, 0x7D, 0xEE, 0xB7, 0x48, 0xA3, 0x08,
0xDA, 0xD6, 0xAF, 0x7A, 0x0C, 0x39, 0x06, 0x65, 0x7F, 0x4A, 0x5D, 0x1F,
0xBC, 0x17, 0xF8, 0xAB, 0xBE, 0xEE, 0x28, 0xD7, 0x74, 0x7F, 0x7A, 0x78,
0x99, 0x59, 0x85, 0x68, 0x6E, 0x5C, 0x23, 0x32, 0x4B, 0xBF, 0x4E, 0xC0,
0xE8, 0x5A, 0x6D, 0xE3, 0x70, 0xBF, 0x77, 0x10, 0xBF, 0xFC, 0x01, 0xF6,
0x85, 0xD9, 0xA8, 0x44, 0x10, 0x58, 0x32, 0xA9, 0x75, 0x18, 0xD5, 0xD1,
0xA2, 0xBE, 0x47, 0xE2, 0x27, 0x6A, 0xF4, 0x9A, 0x33, 0xF8, 0x49, 0x08,
0x60, 0x8B, 0xD4, 0x5F, 0xB4, 0x3A, 0x84, 0xBF, 0xA1, 0xAA, 0x4A, 0x4C,
0x7D, 0x3E, 0xCF, 0x4F, 0x5F, 0x6C, 0x76, 0x5E, 0xA0, 0x4B, 0x37, 0x91,
0x9E, 0xDC, 0x22, 0xE6, 0x6D, 0xCE, 0x14, 0x1A, 0x8E, 0x6A, 0xCB, 0xFE,
0xCD, 0xB3, 0x14, 0x64, 0x17, 0xC7, 0x5B, 0x29, 0x9E, 0x32, 0xBF, 0xF2,
0xEE, 0xFA, 0xD3, 0x0B, 0x42, 0xD4, 0xAB, 0xB7, 0x41, 0x32, 0xDA, 0x0C,
0xD4, 0xEF, 0xF8, 0x81, 0xD5, 0xBB, 0x8D, 0x58, 0x3F, 0xB5, 0x1B, 0xE8,
0x49, 0x28, 0xA2, 0x70, 0xDA, 0x31, 0x04, 0xDD, 0xF7, 0xB2, 0x16, 0xF2,
0x4C, 0x0A, 0x4E, 0x07, 0xA8, 0xED, 0x4A, 0x3D, 0x5E, 0xB5, 0x7F, 0xA3,
0x90, 0xC3, 0xAF, 0x27
};
static const unsigned char TA11_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA12_DN[] = {
0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x48, 0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61,
0x6E, 0x63, 0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x41
};
static const unsigned char TA12_RSA_N[] = {
0xC6, 0xCC, 0xE5, 0x73, 0xE6, 0xFB, 0xD4, 0xBB, 0xE5, 0x2D, 0x2D, 0x32,
0xA6, 0xDF, 0xE5, 0x81, 0x3F, 0xC9, 0xCD, 0x25, 0x49, 0xB6, 0x71, 0x2A,
0xC3, 0xD5, 0x94, 0x34, 0x67, 0xA2, 0x0A, 0x1C, 0xB0, 0x5F, 0x69, 0xA6,
0x40, 0xB1, 0xC4, 0xB7, 0xB2, 0x8F, 0xD0, 0x98, 0xA4, 0xA9, 0x41, 0x59,
0x3A, 0xD3, 0xDC, 0x94, 0xD6, 0x3C, 0xDB, 0x74, 0x38, 0xA4, 0x4A, 0xCC,
0x4D, 0x25, 0x82, 0xF7, 0x4A, 0xA5, 0x53, 0x12, 0x38, 0xEE, 0xF3, 0x49,
0x6D, 0x71, 0x91, 0x7E, 0x63, 0xB6, 0xAB, 0xA6, 0x5F, 0xC3, 0xA4, 0x84,
0xF8, 0x4F, 0x62, 0x51, 0xBE, 0xF8, 0xC5, 0xEC, 0xDB, 0x38, 0x92, 0xE3,
0x06, 0xE5, 0x08, 0x91, 0x0C, 0xC4, 0x28, 0x41, 0x55, 0xFB, 0xCB, 0x5A,
0x89, 0x15, 0x7E, 0x71, 0xE8, 0x35, 0xBF, 0x4D, 0x72, 0x09, 0x3D, 0xBE,
0x3A, 0x38, 0x50, 0x5B, 0x77, 0x31, 0x1B, 0x8D, 0xB3, 0xC7, 0x24, 0x45,
0x9A, 0xA7, 0xAC, 0x6D, 0x00, 0x14, 0x5A, 0x04, 0xB7, 0xBA, 0x13, 0xEB,
0x51, 0x0A, 0x98, 0x41, 0x41, 0x22, 0x4E, 0x65, 0x61, 0x87, 0x81, 0x41,
0x50, 0xA6, 0x79, 0x5C, 0x89, 0xDE, 0x19, 0x4A, 0x57, 0xD5, 0x2E, 0xE6,
0x5D, 0x1C, 0x53, 0x2C, 0x7E, 0x98, 0xCD, 0x1A, 0x06, 0x16, 0xA4, 0x68,
0x73, 0xD0, 0x34, 0x04, 0x13, 0x5C, 0xA1, 0x71, 0xD3, 0x5A, 0x7C, 0x55,
0xDB, 0x5E, 0x64, 0xE1, 0x37, 0x87, 0x30, 0x56, 0x04, 0xE5, 0x11, 0xB4,
0x29, 0x80, 0x12, 0xF1, 0x79, 0x39, 0x88, 0xA2, 0x02, 0x11, 0x7C, 0x27,
0x66, 0xB7, 0x88, 0xB7, 0x78, 0xF2, 0xCA, 0x0A, 0xA8, 0x38, 0xAB, 0x0A,
0x64, 0xC2, 0xBF, 0x66, 0x5D, 0x95, 0x84, 0xC1, 0xA1, 0x25, 0x1E, 0x87,
0x5D, 0x1A, 0x50, 0x0B, 0x20, 0x12, 0xCC, 0x41, 0xBB, 0x6E, 0x0B, 0x51,
0x38, 0xB8, 0x4B, 0xCB
};
static const unsigned char TA12_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA13_DN[] = {
0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x48, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20,
0x41, 0x47, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x16, 0x53, 0x77, 0x69, 0x73, 0x73, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x47,
0x6F, 0x6C, 0x64, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x32
};
static const unsigned char TA13_RSA_N[] = {
0xAF, 0xE4, 0xEE, 0x7E, 0x8B, 0x24, 0x0E, 0x12, 0x6E, 0xA9, 0x50, 0x2D,
0x16, 0x44, 0x3B, 0x92, 0x92, 0x5C, 0xCA, 0xB8, 0x5D, 0x84, 0x92, 0x42,
0x13, 0x2A, 0xBC, 0x65, 0x57, 0x82, 0x40, 0x3E, 0x57, 0x24, 0xCD, 0x50,
0x8B, 0x25, 0x2A, 0xB7, 0x6F, 0xFC, 0xEF, 0xA2, 0xD0, 0xC0, 0x1F, 0x02,
0x24, 0x4A, 0x13, 0x96, 0x8F, 0x23, 0x13, 0xE6, 0x28, 0x58, 0x00, 0xA3,
0x47, 0xC7, 0x06, 0xA7, 0x84, 0x23, 0x2B, 0xBB, 0xBD, 0x96, 0x2B, 0x7F,
0x55, 0xCC, 0x8B, 0xC1, 0x57, 0x1F, 0x0E, 0x62, 0x65, 0x0F, 0xDD, 0x3D,
0x56, 0x8A, 0x73, 0xDA, 0xAE, 0x7E, 0x6D, 0xBA, 0x81, 0x1C, 0x7E, 0x42,
0x8C, 0x20, 0x35, 0xD9, 0x43, 0x4D, 0x84, 0xFA, 0x84, 0xDB, 0x52, 0x2C,
0xF3, 0x0E, 0x27, 0x77, 0x0B, 0x6B, 0xBF, 0x11, 0x2F, 0x72, 0x78, 0x9F,
0x2E, 0xD8, 0x3E, 0xE6, 0x18, 0x37, 0x5A, 0x2A, 0x72, 0xF9, 0xDA, 0x62,
0x90, 0x92, 0x95, 0xCA, 0x1F, 0x9C, 0xE9, 0xB3, 0x3C, 0x2B, 0xCB, 0xF3,
0x01, 0x13, 0xBF, 0x5A, 0xCF, 0xC1, 0xB5, 0x0A, 0x60, 0xBD, 0xDD, 0xB5,
0x99, 0x64, 0x53, 0xB8, 0xA0, 0x96, 0xB3, 0x6F, 0xE2, 0x26, 0x77, 0x91,
0x8C, 0xE0, 0x62, 0x10, 0x02, 0x9F, 0x34, 0x0F, 0xA4, 0xD5, 0x92, 0x33,
0x51, 0xDE, 0xBE, 0x8D, 0xBA, 0x84, 0x7A, 0x60, 0x3C, 0x6A, 0xDB, 0x9F,
0x2B, 0xEC, 0xDE, 0xDE, 0x01, 0x3F, 0x6E, 0x4D, 0xE5, 0x50, 0x86, 0xCB,
0xB4, 0xAF, 0xED, 0x44, 0x40, 0xC5, 0xCA, 0x5A, 0x8C, 0xDA, 0xD2, 0x2B,
0x7C, 0xA8, 0xEE, 0xBE, 0xA6, 0xE5, 0x0A, 0xAA, 0x0E, 0xA5, 0xDF, 0x05,
0x52, 0xB7, 0x55, 0xC7, 0x22, 0x5D, 0x32, 0x6A, 0x97, 0x97, 0x63, 0x13,
0xDB, 0xC9, 0xDB, 0x79, 0x36, 0x7B, 0x85, 0x3A, 0x4A, 0xC5, 0x52, 0x89,
0xF9, 0x24, 0xE7, 0x9D, 0x77, 0xA9, 0x82, 0xFF, 0x55, 0x1C, 0xA5, 0x71,
0x69, 0x2B, 0xD1, 0x02, 0x24, 0xF2, 0xB3, 0x26, 0xD4, 0x6B, 0xDA, 0x04,
0x55, 0xE5, 0xC1, 0x0A, 0xC7, 0x6D, 0x30, 0x37, 0x90, 0x2A, 0xE4, 0x9E,
0x14, 0x33, 0x5E, 0x16, 0x17, 0x55, 0xC5, 0x5B, 0xB5, 0xCB, 0x34, 0x89,
0x92, 0xF1, 0x9D, 0x26, 0x8F, 0xA1, 0x07, 0xD4, 0xC6, 0xB2, 0x78, 0x50,
0xDB, 0x0C, 0x0C, 0x0B, 0x7C, 0x0B, 0x8C, 0x41, 0xD7, 0xB9, 0xE9, 0xDD,
0x8C, 0x88, 0xF7, 0xA3, 0x4D, 0xB2, 0x32, 0xCC, 0xD8, 0x17, 0xDA, 0xCD,
0xB7, 0xCE, 0x66, 0x9D, 0xD4, 0xFD, 0x5E, 0xFF, 0xBD, 0x97, 0x3E, 0x29,
0x75, 0xE7, 0x7E, 0xA7, 0x62, 0x58, 0xAF, 0x25, 0x34, 0xA5, 0x41, 0xC7,
0x3D, 0xBC, 0x0D, 0x50, 0xCA, 0x03, 0x03, 0x0F, 0x08, 0x5A, 0x1F, 0x95,
0x73, 0x78, 0x62, 0xBF, 0xAF, 0x72, 0x14, 0x69, 0x0E, 0xA5, 0xE5, 0x03,
0x0E, 0x78, 0x8E, 0x26, 0x28, 0x42, 0xF0, 0x07, 0x0B, 0x62, 0x20, 0x10,
0x67, 0x39, 0x46, 0xFA, 0xA9, 0x03, 0xCC, 0x04, 0x38, 0x7A, 0x66, 0xEF,
0x20, 0x83, 0xB5, 0x8C, 0x4A, 0x56, 0x8E, 0x91, 0x00, 0xFC, 0x8E, 0x5C,
0x82, 0xDE, 0x88, 0xA0, 0xC3, 0xE2, 0x68, 0x6E, 0x7D, 0x8D, 0xEF, 0x3C,
0xDD, 0x65, 0xF4, 0x5D, 0xAC, 0x51, 0xEF, 0x24, 0x80, 0xAE, 0xAA, 0x56,
0x97, 0x6F, 0xF9, 0xAD, 0x7D, 0xDA, 0x61, 0x3F, 0x98, 0x77, 0x3C, 0xA5,
0x91, 0xB6, 0x1C, 0x8C, 0x26, 0xDA, 0x65, 0xA2, 0x09, 0x6D, 0xC1, 0xE2,
0x54, 0xE3, 0xB9, 0xCA, 0x4C, 0x4C, 0x80, 0x8F, 0x77, 0x7B, 0x60, 0x9A,
0x1E, 0xDF, 0xB6, 0xF2, 0x48, 0x1E, 0x0E, 0xBA, 0x4E, 0x54, 0x6D, 0x98,
0xE0, 0xE1, 0xA2, 0x1A, 0xA2, 0x77, 0x50, 0xCF, 0xC4, 0x63, 0x92, 0xEC,
0x47, 0x19, 0x9D, 0xEB, 0xE6, 0x6B, 0xCE, 0xC1
};
static const unsigned char TA13_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA14_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73,
0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0E,
0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
0x43, 0x41
};
static const unsigned char TA14_RSA_N[] = {
0xAB, 0xA4, 0x81, 0xE5, 0x95, 0xCD, 0xF5, 0xF6, 0x14, 0x8E, 0xC2, 0x4F,
0xCA, 0xD4, 0xE2, 0x78, 0x95, 0x58, 0x9C, 0x41, 0xE1, 0x0D, 0x99, 0x40,
0x24, 0x17, 0x39, 0x91, 0x33, 0x66, 0xE9, 0xBE, 0xE1, 0x83, 0xAF, 0x62,
0x5C, 0x89, 0xD1, 0xFC, 0x24, 0x5B, 0x61, 0xB3, 0xE0, 0x11, 0x11, 0x41,
0x1C, 0x1D, 0x6E, 0xF0, 0xB8, 0xBB, 0xF8, 0xDE, 0xA7, 0x81, 0xBA, 0xA6,
0x48, 0xC6, 0x9F, 0x1D, 0xBD, 0xBE, 0x8E, 0xA9, 0x41, 0x3E, 0xB8, 0x94,
0xED, 0x29, 0x1A, 0xD4, 0x8E, 0xD2, 0x03, 0x1D, 0x03, 0xEF, 0x6D, 0x0D,
0x67, 0x1C, 0x57, 0xD7, 0x06, 0xAD, 0xCA, 0xC8, 0xF5, 0xFE, 0x0E, 0xAF,
0x66, 0x25, 0x48, 0x04, 0x96, 0x0B, 0x5D, 0xA3, 0xBA, 0x16, 0xC3, 0x08,
0x4F, 0xD1, 0x46, 0xF8, 0x14, 0x5C, 0xF2, 0xC8, 0x5E, 0x01, 0x99, 0x6D,
0xFD, 0x88, 0xCC, 0x86, 0xA8, 0xC1, 0x6F, 0x31, 0x42, 0x6C, 0x52, 0x3E,
0x68, 0xCB, 0xF3, 0x19, 0x34, 0xDF, 0xBB, 0x87, 0x18, 0x56, 0x80, 0x26,
0xC4, 0xD0, 0xDC, 0xC0, 0x6F, 0xDF, 0xDE, 0xA0, 0xC2, 0x91, 0x16, 0xA0,
0x64, 0x11, 0x4B, 0x44, 0xBC, 0x1E, 0xF6, 0xE7, 0xFA, 0x63, 0xDE, 0x66,
0xAC, 0x76, 0xA4, 0x71, 0xA3, 0xEC, 0x36, 0x94, 0x68, 0x7A, 0x77, 0xA4,
0xB1, 0xE7, 0x0E, 0x2F, 0x81, 0x7A, 0xE2, 0xB5, 0x72, 0x86, 0xEF, 0xA2,
0x6B, 0x8B, 0xF0, 0x0F, 0xDB, 0xD3, 0x59, 0x3F, 0xBA, 0x72, 0xBC, 0x44,
0x24, 0x9C, 0xE3, 0x73, 0xB3, 0xF7, 0xAF, 0x57, 0x2F, 0x42, 0x26, 0x9D,
0xA9, 0x74, 0xBA, 0x00, 0x52, 0xF2, 0x4B, 0xCD, 0x53, 0x7C, 0x47, 0x0B,
0x36, 0x85, 0x0E, 0x66, 0xA9, 0x08, 0x97, 0x16, 0x34, 0x57, 0xC1, 0x66,
0xF7, 0x80, 0xE3, 0xED, 0x70, 0x54, 0xC7, 0x93, 0xE0, 0x2E, 0x28, 0x15,
0x59, 0x87, 0xBA, 0xBB
};
static const unsigned char TA14_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA15_DN[] = {
0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x17, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x54, 0x72, 0x75, 0x73,
0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F,
0x6E, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10,
0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61,
0x6C, 0x20, 0x43, 0x41
};
static const unsigned char TA15_RSA_N[] = {
0xAF, 0x35, 0x2E, 0xD8, 0xAC, 0x6C, 0x55, 0x69, 0x06, 0x71, 0xE5, 0x13,
0x68, 0x24, 0xB3, 0x4F, 0xD8, 0xCC, 0x21, 0x47, 0xF8, 0xF1, 0x60, 0x38,
0x89, 0x89, 0x03, 0xE9, 0xBD, 0xEA, 0x5E, 0x46, 0x53, 0x09, 0xDC, 0x5C,
0xF5, 0x5A, 0xE8, 0xF7, 0x45, 0x2A, 0x02, 0xEB, 0x31, 0x61, 0xD7, 0x29,
0x33, 0x4C, 0xCE, 0xC7, 0x7C, 0x0A, 0x37, 0x7E, 0x0F, 0xBA, 0x32, 0x98,
0xE1, 0x1D, 0x97, 0xAF, 0x8F, 0xC7, 0xDC, 0xC9, 0x38, 0x96, 0xF3, 0xDB,
0x1A, 0xFC, 0x51, 0xED, 0x68, 0xC6, 0xD0, 0x6E, 0xA4, 0x7C, 0x24, 0xD1,
0xAE, 0x42, 0xC8, 0x96, 0x50, 0x63, 0x2E, 0xE0, 0xFE, 0x75, 0xFE, 0x98,
0xA7, 0x5F, 0x49, 0x2E, 0x95, 0xE3, 0x39, 0x33, 0x64, 0x8E, 0x1E, 0xA4,
0x5F, 0x90, 0xD2, 0x67, 0x3C, 0xB2, 0xD9, 0xFE, 0x41, 0xB9, 0x55, 0xA7,
0x09, 0x8E, 0x72, 0x05, 0x1E, 0x8B, 0xDD, 0x44, 0x85, 0x82, 0x42, 0xD0,
0x49, 0xC0, 0x1D, 0x60, 0xF0, 0xD1, 0x17, 0x2C, 0x95, 0xEB, 0xF6, 0xA5,
0xC1, 0x92, 0xA3, 0xC5, 0xC2, 0xA7, 0x08, 0x60, 0x0D, 0x60, 0x04, 0x10,
0x96, 0x79, 0x9E, 0x16, 0x34, 0xE6, 0xA9, 0xB6, 0xFA, 0x25, 0x45, 0x39,
0xC8, 0x1E, 0x65, 0xF9, 0x93, 0xF5, 0xAA, 0xF1, 0x52, 0xDC, 0x99, 0x98,
0x3D, 0xA5, 0x86, 0x1A, 0x0C, 0x35, 0x33, 0xFA, 0x4B, 0xA5, 0x04, 0x06,
0x15, 0x1C, 0x31, 0x80, 0xEF, 0xAA, 0x18, 0x6B, 0xC2, 0x7B, 0xD7, 0xDA,
0xCE, 0xF9, 0x33, 0x20, 0xD5, 0xF5, 0xBD, 0x6A, 0x33, 0x2D, 0x81, 0x04,
0xFB, 0xB0, 0x5C, 0xD4, 0x9C, 0xA3, 0xE2, 0x5C, 0x1D, 0xE3, 0xA9, 0x42,
0x75, 0x5E, 0x7B, 0xD4, 0x77, 0xEF, 0x39, 0x54, 0xBA, 0xC9, 0x0A, 0x18,
0x1B, 0x12, 0x99, 0x49, 0x2F, 0x88, 0x4B, 0xFD, 0x50, 0x62, 0xD1, 0x73,
0xE7, 0x8F, 0x7A, 0x43
};
static const unsigned char TA15_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA16_DN[] = {
0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D,
0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30,
0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66,
0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20,
0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x27, 0x30, 0x25, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F,
0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA16_RSA_N[] = {
0xD0, 0x40, 0x8B, 0x8B, 0x72, 0xE3, 0x91, 0x1B, 0xF7, 0x51, 0xC1, 0x1B,
0x54, 0x04, 0x98, 0xD3, 0xA9, 0xBF, 0xC1, 0xE6, 0x8A, 0x5D, 0x3B, 0x87,
0xFB, 0xBB, 0x88, 0xCE, 0x0D, 0xE3, 0x2F, 0x3F, 0x06, 0x96, 0xF0, 0xA2,
0x29, 0x50, 0x99, 0xAE, 0xDB, 0x3B, 0xA1, 0x57, 0xB0, 0x74, 0x51, 0x71,
0xCD, 0xED, 0x42, 0x91, 0x4D, 0x41, 0xFE, 0xA9, 0xC8, 0xD8, 0x6A, 0x86,
0x77, 0x44, 0xBB, 0x59, 0x66, 0x97, 0x50, 0x5E, 0xB4, 0xD4, 0x2C, 0x70,
0x44, 0xCF, 0xDA, 0x37, 0x95, 0x42, 0x69, 0x3C, 0x30, 0xC4, 0x71, 0xB3,
0x52, 0xF0, 0x21, 0x4D, 0xA1, 0xD8, 0xBA, 0x39, 0x7C, 0x1C, 0x9E, 0xA3,
0x24, 0x9D, 0xF2, 0x83, 0x16, 0x98, 0xAA, 0x16, 0x7C, 0x43, 0x9B, 0x15,
0x5B, 0xB7, 0xAE, 0x34, 0x91, 0xFE, 0xD4, 0x62, 0x26, 0x18, 0x46, 0x9A,
0x3F, 0xEB, 0xC1, 0xF9, 0xF1, 0x90, 0x57, 0xEB, 0xAC, 0x7A, 0x0D, 0x8B,
0xDB, 0x72, 0x30, 0x6A, 0x66, 0xD5, 0xE0, 0x46, 0xA3, 0x70, 0xDC, 0x68,
0xD9, 0xFF, 0x04, 0x48, 0x89, 0x77, 0xDE, 0xB5, 0xE9, 0xFB, 0x67, 0x6D,
0x41, 0xE9, 0xBC, 0x39, 0xBD, 0x32, 0xD9, 0x62, 0x02, 0xF1, 0xB1, 0xA8,
0x3D, 0x6E, 0x37, 0x9C, 0xE2, 0x2F, 0xE2, 0xD3, 0xA2, 0x26, 0x8B, 0xC6,
0xB8, 0x55, 0x43, 0x88, 0xE1, 0x23, 0x3E, 0xA5, 0xD2, 0x24, 0x39, 0x6A,
0x47, 0xAB, 0x00, 0xD4, 0xA1, 0xB3, 0xA9, 0x25, 0xFE, 0x0D, 0x3F, 0xA7,
0x1D, 0xBA, 0xD3, 0x51, 0xC1, 0x0B, 0xA4, 0xDA, 0xAC, 0x38, 0xEF, 0x55,
0x50, 0x24, 0x05, 0x65, 0x46, 0x93, 0x34, 0x4F, 0x2D, 0x8D, 0xAD, 0xC6,
0xD4, 0x21, 0x19, 0xD2, 0x8E, 0xCA, 0x05, 0x61, 0x71, 0x07, 0x73, 0x47,
0xE5, 0x8A, 0x19, 0x12, 0xBD, 0x04, 0x4D, 0xCE, 0x4E, 0x9C, 0xA5, 0x48,
0xAC, 0xBB, 0x26, 0xF7
};
static const unsigned char TA16_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA17_DN[] = {
0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D,
0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30,
0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66,
0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20,
0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F,
0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA17_EC_Q[] = {
0x04, 0x03, 0x47, 0x7B, 0x2F, 0x75, 0xC9, 0x82, 0x15, 0x85, 0xFB, 0x75,
0xE4, 0x91, 0x16, 0xD4, 0xAB, 0x62, 0x99, 0xF5, 0x3E, 0x52, 0x0B, 0x06,
0xCE, 0x41, 0x00, 0x7F, 0x97, 0xE1, 0x0A, 0x24, 0x3C, 0x1D, 0x01, 0x04,
0xEE, 0x3D, 0xD2, 0x8D, 0x09, 0x97, 0x0C, 0xE0, 0x75, 0xE4, 0xFA, 0xFB,
0x77, 0x8A, 0x2A, 0xF5, 0x03, 0x60, 0x4B, 0x36, 0x8B, 0x16, 0x23, 0x16,
0xAD, 0x09, 0x71, 0xF4, 0x4A, 0xF4, 0x28, 0x50, 0xB4, 0xFE, 0x88, 0x1C,
0x6E, 0x3F, 0x6C, 0x2F, 0x2F, 0x09, 0x59, 0x5B, 0xA5, 0x5B, 0x0B, 0x33,
0x99, 0xE2, 0xC3, 0x3D, 0x89, 0xF9, 0x6A, 0x2C, 0xEF, 0xB2, 0xD3, 0x06,
0xE9
};
static const unsigned char TA18_DN[] = {
0x30, 0x34, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31,
0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x08, 0x43, 0x65,
0x72, 0x74, 0x69, 0x67, 0x6E, 0x61
};
static const unsigned char TA18_RSA_N[] = {
0xC8, 0x68, 0xF1, 0xC9, 0xD6, 0xD6, 0xB3, 0x34, 0x75, 0x26, 0x82, 0x1E,
0xEC, 0xB4, 0xBE, 0xEA, 0x5C, 0xE1, 0x26, 0xED, 0x11, 0x47, 0x61, 0xE1,
0xA2, 0x7C, 0x16, 0x78, 0x40, 0x21, 0xE4, 0x60, 0x9E, 0x5A, 0xC8, 0x63,
0xE1, 0xC4, 0xB1, 0x96, 0x92, 0xFF, 0x18, 0x6D, 0x69, 0x23, 0xE1, 0x2B,
0x62, 0xF7, 0xDD, 0xE2, 0x36, 0x2F, 0x91, 0x07, 0xB9, 0x48, 0xCF, 0x0E,
0xEC, 0x79, 0xB6, 0x2C, 0xE7, 0x34, 0x4B, 0x70, 0x08, 0x25, 0xA3, 0x3C,
0x87, 0x1B, 0x19, 0xF2, 0x81, 0x07, 0x0F, 0x38, 0x90, 0x19, 0xD3, 0x11,
0xFE, 0x86, 0xB4, 0xF2, 0xD1, 0x5E, 0x1E, 0x1E, 0x96, 0xCD, 0x80, 0x6C,
0xCE, 0x3B, 0x31, 0x93, 0xB6, 0xF2, 0xA0, 0xD0, 0xA9, 0x95, 0x12, 0x7D,
0xA5, 0x9A, 0xCC, 0x6B, 0xC8, 0x84, 0x56, 0x8A, 0x33, 0xA9, 0xE7, 0x22,
0x15, 0x53, 0x16, 0xF0, 0xCC, 0x17, 0xEC, 0x57, 0x5F, 0xE9, 0xA2, 0x0A,
0x98, 0x09, 0xDE, 0xE3, 0x5F, 0x9C, 0x6F, 0xDC, 0x48, 0xE3, 0x85, 0x0B,
0x15, 0x5A, 0xA6, 0xBA, 0x9F, 0xAC, 0x48, 0xE3, 0x09, 0xB2, 0xF7, 0xF4,
0x32, 0xDE, 0x5E, 0x34, 0xBE, 0x1C, 0x78, 0x5D, 0x42, 0x5B, 0xCE, 0x0E,
0x22, 0x8F, 0x4D, 0x90, 0xD7, 0x7D, 0x32, 0x18, 0xB3, 0x0B, 0x2C, 0x6A,
0xBF, 0x8E, 0x3F, 0x14, 0x11, 0x89, 0x20, 0x0E, 0x77, 0x14, 0xB5, 0x3D,
0x94, 0x08, 0x87, 0xF7, 0x25, 0x1E, 0xD5, 0xB2, 0x60, 0x00, 0xEC, 0x6F,
0x2A, 0x28, 0x25, 0x6E, 0x2A, 0x3E, 0x18, 0x63, 0x17, 0x25, 0x3F, 0x3E,
0x44, 0x20, 0x16, 0xF6, 0x26, 0xC8, 0x25, 0xAE, 0x05, 0x4A, 0xB4, 0xE7,
0x63, 0x2C, 0xF3, 0x8C, 0x16, 0x53, 0x7E, 0x5C, 0xFB, 0x11, 0x1A, 0x08,
0xC1, 0x46, 0x62, 0x9F, 0x22, 0xB8, 0xF1, 0xC2, 0x8D, 0x69, 0xDC, 0xFA,
0x3A, 0x58, 0x06, 0xDF
};
static const unsigned char TA18_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA19_DN[] = {
0x30, 0x5E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54,
0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20,
0x4C, 0x74, 0x64, 0x2E, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04,
0x0B, 0x0C, 0x21, 0x65, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69,
0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA19_RSA_N[] = {
0xE1, 0x25, 0x0F, 0xEE, 0x8D, 0xDB, 0x88, 0x33, 0x75, 0x67, 0xCD, 0xAD,
0x1F, 0x7D, 0x3A, 0x4E, 0x6D, 0x9D, 0xD3, 0x2F, 0x14, 0xF3, 0x63, 0x74,
0xCB, 0x01, 0x21, 0x6A, 0x37, 0xEA, 0x84, 0x50, 0x07, 0x4B, 0x26, 0x5B,
0x09, 0x43, 0x6C, 0x21, 0x9E, 0x6A, 0xC8, 0xD5, 0x03, 0xF5, 0x60, 0x69,
0x8F, 0xCC, 0xF0, 0x22, 0xE4, 0x1F, 0xE7, 0xF7, 0x6A, 0x22, 0x31, 0xB7,
0x2C, 0x15, 0xF2, 0xE0, 0xFE, 0x00, 0x6A, 0x43, 0xFF, 0x87, 0x65, 0xC6,
0xB5, 0x1A, 0xC1, 0xA7, 0x4C, 0x6D, 0x22, 0x70, 0x21, 0x8A, 0x31, 0xF2,
0x97, 0x74, 0x89, 0x09, 0x12, 0x26, 0x1C, 0x9E, 0xCA, 0xD9, 0x12, 0xA2,
0x95, 0x3C, 0xDA, 0xE9, 0x67, 0xBF, 0x08, 0xA0, 0x64, 0xE3, 0xD6, 0x42,
0xB7, 0x45, 0xEF, 0x97, 0xF4, 0xF6, 0xF5, 0xD7, 0xB5, 0x4A, 0x15, 0x02,
0x58, 0x7D, 0x98, 0x58, 0x4B, 0x60, 0xBC, 0xCD, 0xD7, 0x0D, 0x9A, 0x13,
0x33, 0x53, 0xD1, 0x61, 0xF9, 0x7A, 0xD5, 0xD7, 0x78, 0xB3, 0x9A, 0x33,
0xF7, 0x00, 0x86, 0xCE, 0x1D, 0x4D, 0x94, 0x38, 0xAF, 0xA8, 0xEC, 0x78,
0x51, 0x70, 0x8A, 0x5C, 0x10, 0x83, 0x51, 0x21, 0xF7, 0x11, 0x3D, 0x34,
0x86, 0x5E, 0xE5, 0x48, 0xCD, 0x97, 0x81, 0x82, 0x35, 0x4C, 0x19, 0xEC,
0x65, 0xF6, 0x6B, 0xC5, 0x05, 0xA1, 0xEE, 0x47, 0x13, 0xD6, 0xB3, 0x21,
0x27, 0x94, 0x10, 0x0A, 0xD9, 0x24, 0x3B, 0xBA, 0xBE, 0x44, 0x13, 0x46,
0x30, 0x3F, 0x97, 0x3C, 0xD8, 0xD7, 0xD7, 0x6A, 0xEE, 0x3B, 0x38, 0xE3,
0x2B, 0xD4, 0x97, 0x0E, 0xB9, 0x1B, 0xE7, 0x07, 0x49, 0x7F, 0x37, 0x2A,
0xF9, 0x77, 0x78, 0xCF, 0x54, 0xED, 0x5B, 0x46, 0x9D, 0xA3, 0x80, 0x0E,
0x91, 0x43, 0xC1, 0xD6, 0x5B, 0x5F, 0x14, 0xBA, 0x9F, 0xA6, 0x8D, 0x24,
0x47, 0x40, 0x59, 0xBF, 0x72, 0x38, 0xB2, 0x36, 0x6C, 0x37, 0xFF, 0x99,
0xD1, 0x5D, 0x0E, 0x59, 0x0A, 0xAB, 0x69, 0xF7, 0xC0, 0xB2, 0x04, 0x45,
0x7A, 0x54, 0x00, 0xAE, 0xBE, 0x53, 0xF6, 0xB5, 0xE7, 0xE1, 0xF8, 0x3C,
0xA3, 0x31, 0xD2, 0xA9, 0xFE, 0x21, 0x52, 0x64, 0xC5, 0xA6, 0x67, 0xF0,
0x75, 0x07, 0x06, 0x94, 0x14, 0x81, 0x55, 0xC6, 0x27, 0xE4, 0x01, 0x8F,
0x17, 0xC1, 0x6A, 0x71, 0xD7, 0xBE, 0x4B, 0xFB, 0x94, 0x58, 0x7D, 0x7E,
0x11, 0x33, 0xB1, 0x42, 0xF7, 0x62, 0x6C, 0x18, 0xD6, 0xCF, 0x09, 0x68,
0x3E, 0x7F, 0x6C, 0xF6, 0x1E, 0x8F, 0x62, 0xAD, 0xA5, 0x63, 0xDB, 0x09,
0xA7, 0x1F, 0x22, 0x42, 0x41, 0x1E, 0x6F, 0x99, 0x8A, 0x3E, 0xD7, 0xF9,
0x3F, 0x40, 0x7A, 0x79, 0xB0, 0xA5, 0x01, 0x92, 0xD2, 0x9D, 0x3D, 0x08,
0x15, 0xA5, 0x10, 0x01, 0x2D, 0xB3, 0x32, 0x76, 0xA8, 0x95, 0x0D, 0xB3,
0x7A, 0x9A, 0xFB, 0x07, 0x10, 0x78, 0x11, 0x6F, 0xE1, 0x8F, 0xC7, 0xBA,
0x0F, 0x25, 0x1A, 0x74, 0x2A, 0xE5, 0x1C, 0x98, 0x41, 0x99, 0xDF, 0x21,
0x87, 0xE8, 0x95, 0x06, 0x6A, 0x0A, 0xB3, 0x6A, 0x47, 0x76, 0x65, 0xF6,
0x3A, 0xCF, 0x8F, 0x62, 0x17, 0x19, 0x7B, 0x0A, 0x28, 0xCD, 0x1A, 0xD2,
0x83, 0x1E, 0x21, 0xC7, 0x2C, 0xBF, 0xBE, 0xFF, 0x61, 0x68, 0xB7, 0x67,
0x1B, 0xBB, 0x78, 0x4D, 0x8D, 0xCE, 0x67, 0xE5, 0xE4, 0xC1, 0x8E, 0xB7,
0x23, 0x66, 0xE2, 0x9D, 0x90, 0x75, 0x34, 0x98, 0xA9, 0x36, 0x2B, 0x8A,
0x9A, 0x94, 0xB9, 0x9D, 0xEC, 0xCC, 0x8A, 0xB1, 0xF8, 0x25, 0x89, 0x5C,
0x5A, 0xB6, 0x2F, 0x8C, 0x1F, 0x6D, 0x79, 0x24, 0xA7, 0x52, 0x68, 0xC3,
0x84, 0x35, 0xE2, 0x66, 0x8D, 0x63, 0x0E, 0x25, 0x4D, 0xD5, 0x19, 0xB2,
0xE6, 0x79, 0x37, 0xA7, 0x22, 0x9D, 0x54, 0x31
};
static const unsigned char TA19_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA20_DN[] = {
0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x52, 0x4F, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x08, 0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x31, 0x19,
0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x10, 0x63, 0x65, 0x72,
0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43,
0x41
};
static const unsigned char TA20_RSA_N[] = {
0xB7, 0x33, 0xB9, 0x7E, 0xC8, 0x25, 0x4A, 0x8E, 0xB5, 0xDB, 0xB4, 0x28,
0x1B, 0xAA, 0x57, 0x90, 0xE8, 0xD1, 0x22, 0xD3, 0x64, 0xBA, 0xD3, 0x93,
0xE8, 0xD4, 0xAC, 0x86, 0x61, 0x40, 0x6A, 0x60, 0x57, 0x68, 0x54, 0x84,
0x4D, 0xBC, 0x6A, 0x54, 0x02, 0x05, 0xFF, 0xDF, 0x9B, 0x9A, 0x2A, 0xAE,
0x5D, 0x07, 0x8F, 0x4A, 0xC3, 0x28, 0x7F, 0xEF, 0xFB, 0x2B, 0xFA, 0x79,
0xF1, 0xC7, 0xAD, 0xF0, 0x10, 0x53, 0x24, 0x90, 0x8B, 0x66, 0xC9, 0xA8,
0x88, 0xAB, 0xAF, 0x5A, 0xA3, 0x00, 0xE9, 0xBE, 0xBA, 0x46, 0xEE, 0x5B,
0x73, 0x7B, 0x2C, 0x17, 0x82, 0x81, 0x5E, 0x62, 0x2C, 0xA1, 0x02, 0x65,
0xB3, 0xBD, 0xC5, 0x2B, 0x00, 0x7E, 0xC4, 0xFC, 0x03, 0x33, 0x57, 0x0D,
0xED, 0xE2, 0xFA, 0xCE, 0x5D, 0x45, 0xD6, 0x38, 0xCD, 0x35, 0xB6, 0xB2,
0xC1, 0xD0, 0x9C, 0x81, 0x4A, 0xAA, 0xE4, 0xB2, 0x01, 0x5C, 0x1D, 0x8F,
0x5F, 0x99, 0xC4, 0xB1, 0xAD, 0xDB, 0x88, 0x21, 0xEB, 0x90, 0x08, 0x82,
0x80, 0xF3, 0x30, 0xA3, 0x43, 0xE6, 0x90, 0x82, 0xAE, 0x55, 0x28, 0x49,
0xED, 0x5B, 0xD7, 0xA9, 0x10, 0x38, 0x0E, 0xFE, 0x8F, 0x4C, 0x5B, 0x9B,
0x46, 0xEA, 0x41, 0xF5, 0xB0, 0x08, 0x74, 0xC3, 0xD0, 0x88, 0x33, 0xB6,
0x7C, 0xD7, 0x74, 0xDF, 0xDC, 0x84, 0xD1, 0x43, 0x0E, 0x75, 0x39, 0xA1,
0x25, 0x40, 0x28, 0xEA, 0x78, 0xCB, 0x0E, 0x2C, 0x2E, 0x39, 0x9D, 0x8C,
0x8B, 0x6E, 0x16, 0x1C, 0x2F, 0x26, 0x82, 0x10, 0xE2, 0xE3, 0x65, 0x94,
0x0A, 0x04, 0xC0, 0x5E, 0xF7, 0x5D, 0x5B, 0xF8, 0x10, 0xE2, 0xD0, 0xBA,
0x7A, 0x4B, 0xFB, 0xDE, 0x37, 0x00, 0x00, 0x1A, 0x5B, 0x28, 0xE3, 0xD2,
0x9C, 0x73, 0x3E, 0x32, 0x87, 0x98, 0xA1, 0xC9, 0x51, 0x2F, 0xD7, 0xDE,
0xAC, 0x33, 0xB3, 0x4F
};
static const unsigned char TA20_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA21_DN[] = {
0x30, 0x81, 0xA7, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04,
0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31,
0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x4E, 0x65,
0x74, 0x4C, 0x6F, 0x63, 0x6B, 0x20, 0x4B, 0x66, 0x74, 0x2E, 0x31, 0x37,
0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x2E, 0x54, 0x61, 0x6E,
0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1, 0x6E, 0x79, 0x6B,
0x69, 0x61, 0x64, 0xC3, 0xB3, 0x6B, 0x20, 0x28, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x29, 0x31, 0x35, 0x30, 0x33, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x2C, 0x4E, 0x65, 0x74, 0x4C, 0x6F, 0x63,
0x6B, 0x20, 0x41, 0x72, 0x61, 0x6E, 0x79, 0x20, 0x28, 0x43, 0x6C, 0x61,
0x73, 0x73, 0x20, 0x47, 0x6F, 0x6C, 0x64, 0x29, 0x20, 0x46, 0xC5, 0x91,
0x74, 0x61, 0x6E, 0xC3, 0xBA, 0x73, 0xC3, 0xAD, 0x74, 0x76, 0xC3, 0xA1,
0x6E, 0x79
};
static const unsigned char TA21_RSA_N[] = {
0xC4, 0x24, 0x5E, 0x73, 0xBE, 0x4B, 0x6D, 0x14, 0xC3, 0xA1, 0xF4, 0xE3,
0x97, 0x90, 0x6E, 0xD2, 0x30, 0x45, 0x1E, 0x3C, 0xEE, 0x67, 0xD9, 0x64,
0xE0, 0x1A, 0x8A, 0x7F, 0xCA, 0x30, 0xCA, 0x83, 0xE3, 0x20, 0xC1, 0xE3,
0xF4, 0x3A, 0xD3, 0x94, 0x5F, 0x1A, 0x7C, 0x5B, 0x6D, 0xBF, 0x30, 0x4F,
0x84, 0x27, 0xF6, 0x9F, 0x1F, 0x49, 0xBC, 0xC6, 0x99, 0x0A, 0x90, 0xF2,
0x0F, 0xF5, 0x7F, 0x43, 0x84, 0x37, 0x63, 0x51, 0x8B, 0x7A, 0xA5, 0x70,
0xFC, 0x7A, 0x58, 0xCD, 0x8E, 0x9B, 0xED, 0xC3, 0x46, 0x6C, 0x84, 0x70,
0x5D, 0xDA, 0xF3, 0x01, 0x90, 0x23, 0xFC, 0x4E, 0x30, 0xA9, 0x7E, 0xE1,
0x27, 0x63, 0xE7, 0xED, 0x64, 0x3C, 0xA0, 0xB8, 0xC9, 0x33, 0x63, 0xFE,
0x16, 0x90, 0xFF, 0xB0, 0xB8, 0xFD, 0xD7, 0xA8, 0xC0, 0xC0, 0x94, 0x43,
0x0B, 0xB6, 0xD5, 0x59, 0xA6, 0x9E, 0x56, 0xD0, 0x24, 0x1F, 0x70, 0x79,
0xAF, 0xDB, 0x39, 0x54, 0x0D, 0x65, 0x75, 0xD9, 0x15, 0x41, 0x94, 0x01,
0xAF, 0x5E, 0xEC, 0xF6, 0x8D, 0xF1, 0xFF, 0xAD, 0x64, 0xFE, 0x20, 0x9A,
0xD7, 0x5C, 0xEB, 0xFE, 0xA6, 0x1F, 0x08, 0x64, 0xA3, 0x8B, 0x76, 0x55,
0xAD, 0x1E, 0x3B, 0x28, 0x60, 0x2E, 0x87, 0x25, 0xE8, 0xAA, 0xAF, 0x1F,
0xC6, 0x64, 0x46, 0x20, 0xB7, 0x70, 0x7F, 0x3C, 0xDE, 0x48, 0xDB, 0x96,
0x53, 0xB7, 0x39, 0x77, 0xE4, 0x1A, 0xE2, 0xC7, 0x16, 0x84, 0x76, 0x97,
0x5B, 0x2F, 0xBB, 0x19, 0x15, 0x85, 0xF8, 0x69, 0x85, 0xF5, 0x99, 0xA7,
0xA9, 0xF2, 0x34, 0xA7, 0xA9, 0xB6, 0xA6, 0x03, 0xFC, 0x6F, 0x86, 0x3D,
0x54, 0x7C, 0x76, 0x04, 0x9B, 0x6B, 0xF9, 0x40, 0x5D, 0x00, 0x34, 0xC7,
0x2E, 0x99, 0x75, 0x9D, 0xE5, 0x88, 0x03, 0xAA, 0x4D, 0xF8, 0x03, 0xD2,
0x42, 0x76, 0xC0, 0x1B
};
static const unsigned char TA21_RSA_E[] = {
0xA8, 0x8B
};
static const unsigned char TA22_DN[] = {
0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04,
0x07, 0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31,
0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69,
0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31,
0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x4D, 0x69,
0x63, 0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x65, 0x2D, 0x53, 0x7A, 0x69,
0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20,
0x32, 0x30, 0x30, 0x39, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86,
0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66,
0x6F, 0x40, 0x65, 0x2D, 0x73, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x2E, 0x68,
0x75
};
static const unsigned char TA22_RSA_N[] = {
0xE9, 0xF8, 0x8F, 0xF3, 0x63, 0xAD, 0xDA, 0x86, 0xD8, 0xA7, 0xE0, 0x42,
0xFB, 0xCF, 0x91, 0xDE, 0xA6, 0x26, 0xF8, 0x99, 0xA5, 0x63, 0x70, 0xAD,
0x9B, 0xAE, 0xCA, 0x33, 0x40, 0x7D, 0x6D, 0x96, 0x6E, 0xA1, 0x0E, 0x44,
0xEE, 0xE1, 0x13, 0x9D, 0x94, 0x42, 0x52, 0x9A, 0xBD, 0x75, 0x85, 0x74,
0x2C, 0xA8, 0x0E, 0x1D, 0x93, 0xB6, 0x18, 0xB7, 0x8C, 0x2C, 0xA8, 0xCF,
0xFB, 0x5C, 0x71, 0xB9, 0xDA, 0xEC, 0xFE, 0xE8, 0x7E, 0x8F, 0xE4, 0x2F,
0x1D, 0xB2, 0xA8, 0x75, 0x87, 0xD8, 0xB7, 0xA1, 0xE5, 0x3B, 0xCF, 0x99,
0x4A, 0x46, 0xD0, 0x83, 0x19, 0x7D, 0xC0, 0xA1, 0x12, 0x1C, 0x95, 0x6D,
0x4A, 0xF4, 0xD8, 0xC7, 0xA5, 0x4D, 0x33, 0x2E, 0x85, 0x39, 0x40, 0x75,
0x7E, 0x14, 0x7C, 0x80, 0x12, 0x98, 0x50, 0xC7, 0x41, 0x67, 0xB8, 0xA0,
0x80, 0x61, 0x54, 0xA6, 0x6C, 0x4E, 0x1F, 0xE0, 0x9D, 0x0E, 0x07, 0xE9,
0xC9, 0xBA, 0x33, 0xE7, 0xFE, 0xC0, 0x55, 0x28, 0x2C, 0x02, 0x80, 0xA7,
0x19, 0xF5, 0x9E, 0xDC, 0x55, 0x53, 0x03, 0x97, 0x7B, 0x07, 0x48, 0xFF,
0x99, 0xFB, 0x37, 0x8A, 0x24, 0xC4, 0x59, 0xCC, 0x50, 0x10, 0x63, 0x8E,
0xAA, 0xA9, 0x1A, 0xB0, 0x84, 0x1A, 0x86, 0xF9, 0x5F, 0xBB, 0xB1, 0x50,
0x6E, 0xA4, 0xD1, 0x0A, 0xCC, 0xD5, 0x71, 0x7E, 0x1F, 0xA7, 0x1B, 0x7C,
0xF5, 0x53, 0x6E, 0x22, 0x5F, 0xCB, 0x2B, 0xE6, 0xD4, 0x7C, 0x5D, 0xAE,
0xD6, 0xC2, 0xC6, 0x4C, 0xE5, 0x05, 0x01, 0xD9, 0xED, 0x57, 0xFC, 0xC1,
0x23, 0x79, 0xFC, 0xFA, 0xC8, 0x24, 0x83, 0x95, 0xF3, 0xB5, 0x6A, 0x51,
0x01, 0xD0, 0x77, 0xD6, 0xE9, 0x12, 0xA1, 0xF9, 0x1A, 0x83, 0xFB, 0x82,
0x1B, 0xB9, 0xB0, 0x97, 0xF4, 0x76, 0x06, 0x33, 0x43, 0x49, 0xA0, 0xFF,
0x0B, 0xB5, 0xFA, 0xB5
};
static const unsigned char TA22_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA23_DN[] = {
0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x33,
0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47,
0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30,
0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62,
0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E
};
static const unsigned char TA23_RSA_N[] = {
0xCC, 0x25, 0x76, 0x90, 0x79, 0x06, 0x78, 0x22, 0x16, 0xF5, 0xC0, 0x83,
0xB6, 0x84, 0xCA, 0x28, 0x9E, 0xFD, 0x05, 0x76, 0x11, 0xC5, 0xAD, 0x88,
0x72, 0xFC, 0x46, 0x02, 0x43, 0xC7, 0xB2, 0x8A, 0x9D, 0x04, 0x5F, 0x24,
0xCB, 0x2E, 0x4B, 0xE1, 0x60, 0x82, 0x46, 0xE1, 0x52, 0xAB, 0x0C, 0x81,
0x47, 0x70, 0x6C, 0xDD, 0x64, 0xD1, 0xEB, 0xF5, 0x2C, 0xA3, 0x0F, 0x82,
0x3D, 0x0C, 0x2B, 0xAE, 0x97, 0xD7, 0xB6, 0x14, 0x86, 0x10, 0x79, 0xBB,
0x3B, 0x13, 0x80, 0x77, 0x8C, 0x08, 0xE1, 0x49, 0xD2, 0x6A, 0x62, 0x2F,
0x1F, 0x5E, 0xFA, 0x96, 0x68, 0xDF, 0x89, 0x27, 0x95, 0x38, 0x9F, 0x06,
0xD7, 0x3E, 0xC9, 0xCB, 0x26, 0x59, 0x0D, 0x73, 0xDE, 0xB0, 0xC8, 0xE9,
0x26, 0x0E, 0x83, 0x15, 0xC6, 0xEF, 0x5B, 0x8B, 0xD2, 0x04, 0x60, 0xCA,
0x49, 0xA6, 0x28, 0xF6, 0x69, 0x3B, 0xF6, 0xCB, 0xC8, 0x28, 0x91, 0xE5,
0x9D, 0x8A, 0x61, 0x57, 0x37, 0xAC, 0x74, 0x14, 0xDC, 0x74, 0xE0, 0x3A,
0xEE, 0x72, 0x2F, 0x2E, 0x9C, 0xFB, 0xD0, 0xBB, 0xBF, 0xF5, 0x3D, 0x00,
0xE1, 0x06, 0x33, 0xE8, 0x82, 0x2B, 0xAE, 0x53, 0xA6, 0x3A, 0x16, 0x73,
0x8C, 0xDD, 0x41, 0x0E, 0x20, 0x3A, 0xC0, 0xB4, 0xA7, 0xA1, 0xE9, 0xB2,
0x4F, 0x90, 0x2E, 0x32, 0x60, 0xE9, 0x57, 0xCB, 0xB9, 0x04, 0x92, 0x68,
0x68, 0xE5, 0x38, 0x26, 0x60, 0x75, 0xB2, 0x9F, 0x77, 0xFF, 0x91, 0x14,
0xEF, 0xAE, 0x20, 0x49, 0xFC, 0xAD, 0x40, 0x15, 0x48, 0xD1, 0x02, 0x31,
0x61, 0x19, 0x5E, 0xB8, 0x97, 0xEF, 0xAD, 0x77, 0xB7, 0x64, 0x9A, 0x7A,
0xBF, 0x5F, 0xC1, 0x13, 0xEF, 0x9B, 0x62, 0xFB, 0x0D, 0x6C, 0xE0, 0x54,
0x69, 0x16, 0xA9, 0x03, 0xDA, 0x6E, 0xE9, 0x83, 0x93, 0x71, 0x76, 0xC6,
0x69, 0x85, 0x82, 0x17
};
static const unsigned char TA23_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA24_DN[] = {
0x30, 0x38, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x45, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0B, 0x49, 0x5A, 0x45, 0x4E, 0x50, 0x45, 0x20, 0x53, 0x2E, 0x41,
0x2E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0A,
0x49, 0x7A, 0x65, 0x6E, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D
};
static const unsigned char TA24_RSA_N[] = {
0xC9, 0xD3, 0x7A, 0xCA, 0x0F, 0x1E, 0xAC, 0xA7, 0x86, 0xE8, 0x16, 0x65,
0x6A, 0xB1, 0xC2, 0x1B, 0x45, 0x32, 0x71, 0x95, 0xD9, 0xFE, 0x10, 0x5B,
0xCC, 0xAF, 0xE7, 0xA5, 0x79, 0x01, 0x8F, 0x89, 0xC3, 0xCA, 0xF2, 0x55,
0x71, 0xF7, 0x77, 0xBE, 0x77, 0x94, 0xF3, 0x72, 0xA4, 0x2C, 0x44, 0xD8,
0x9E, 0x92, 0x9B, 0x14, 0x3A, 0xA1, 0xE7, 0x24, 0x90, 0x0A, 0x0A, 0x56,
0x8E, 0xC5, 0xD8, 0x26, 0x94, 0xE1, 0xD9, 0x48, 0xE1, 0x2D, 0x3E, 0xDA,
0x0A, 0x72, 0xDD, 0xA3, 0x99, 0x15, 0xDA, 0x81, 0xA2, 0x87, 0xF4, 0x7B,
0x6E, 0x26, 0x77, 0x89, 0x58, 0xAD, 0xD6, 0xEB, 0x0C, 0xB2, 0x41, 0x7A,
0x73, 0x6E, 0x6D, 0xDB, 0x7A, 0x78, 0x41, 0xE9, 0x08, 0x88, 0x12, 0x7E,
0x87, 0x2E, 0x66, 0x11, 0x63, 0x6C, 0x54, 0xFB, 0x3C, 0x9D, 0x72, 0xC0,
0xBC, 0x2E, 0xFF, 0xC2, 0xB7, 0xDD, 0x0D, 0x76, 0xE3, 0x3A, 0xD7, 0xF7,
0xB4, 0x68, 0xBE, 0xA2, 0xF5, 0xE3, 0x81, 0x6E, 0xC1, 0x46, 0x6F, 0x5D,
0x8D, 0xE0, 0x4D, 0xC6, 0x54, 0x55, 0x89, 0x1A, 0x33, 0x31, 0x0A, 0xB1,
0x57, 0xB9, 0xA3, 0x8A, 0x98, 0xC3, 0xEC, 0x3B, 0x34, 0xC5, 0x95, 0x41,
0x69, 0x7E, 0x75, 0xC2, 0x3C, 0x20, 0xC5, 0x61, 0xBA, 0x51, 0x47, 0xA0,
0x20, 0x90, 0x93, 0xA1, 0x90, 0x4B, 0xF3, 0x4E, 0x7C, 0x85, 0x45, 0x54,
0x9A, 0xD1, 0x05, 0x26, 0x41, 0xB0, 0xB5, 0x4D, 0x1D, 0x33, 0xBE, 0xC4,
0x03, 0xC8, 0x25, 0x7C, 0xC1, 0x70, 0xDB, 0x3B, 0xF4, 0x09, 0x2D, 0x54,
0x27, 0x48, 0xAC, 0x2F, 0xE1, 0xC4, 0xAC, 0x3E, 0xC8, 0xCB, 0x92, 0x4C,
0x53, 0x39, 0x37, 0x23, 0xEC, 0xD3, 0x01, 0xF9, 0xE0, 0x09, 0x44, 0x4D,
0x4D, 0x64, 0xC0, 0xE1, 0x0D, 0x5A, 0x87, 0x22, 0xBC, 0xAD, 0x1B, 0xA3,
0xFE, 0x26, 0xB5, 0x15, 0xF3, 0xA7, 0xFC, 0x84, 0x19, 0xE9, 0xEC, 0xA1,
0x88, 0xB4, 0x44, 0x69, 0x84, 0x83, 0xF3, 0x89, 0xD1, 0x74, 0x06, 0xA9,
0xCC, 0x0B, 0xD6, 0xC2, 0xDE, 0x27, 0x85, 0x50, 0x26, 0xCA, 0x17, 0xB8,
0xC9, 0x7A, 0x87, 0x56, 0x2C, 0x1A, 0x01, 0x1E, 0x6C, 0xBE, 0x13, 0xAD,
0x10, 0xAC, 0xB5, 0x24, 0xF5, 0x38, 0x91, 0xA1, 0xD6, 0x4B, 0xDA, 0xF1,
0xBB, 0xD2, 0xDE, 0x47, 0xB5, 0xF1, 0xBC, 0x81, 0xF6, 0x59, 0x6B, 0xCF,
0x19, 0x53, 0xE9, 0x8D, 0x15, 0xCB, 0x4A, 0xCB, 0xA9, 0x6F, 0x44, 0xE5,
0x1B, 0x41, 0xCF, 0xE1, 0x86, 0xA7, 0xCA, 0xD0, 0x6A, 0x9F, 0xBC, 0x4C,
0x8D, 0x06, 0x33, 0x5A, 0xA2, 0x85, 0xE5, 0x90, 0x35, 0xA0, 0x62, 0x5C,
0x16, 0x4E, 0xF0, 0xE3, 0xA2, 0xFA, 0x03, 0x1A, 0xB4, 0x2C, 0x71, 0xB3,
0x58, 0x2C, 0xDE, 0x7B, 0x0B, 0xDB, 0x1A, 0x0F, 0xEB, 0xDE, 0x21, 0x1F,
0x06, 0x77, 0x06, 0x03, 0xB0, 0xC9, 0xEF, 0x99, 0xFC, 0xC0, 0xB9, 0x4F,
0x0B, 0x86, 0x28, 0xFE, 0xD2, 0xB9, 0xEA, 0xE3, 0xDA, 0xA5, 0xC3, 0x47,
0x69, 0x12, 0xE0, 0xDB, 0xF0, 0xF6, 0x19, 0x8B, 0xED, 0x7B, 0x70, 0xD7,
0x02, 0xD6, 0xED, 0x87, 0x18, 0x28, 0x2C, 0x04, 0x24, 0x4C, 0x77, 0xE4,
0x48, 0x8A, 0x1A, 0xC6, 0x3B, 0x9A, 0xD4, 0x0F, 0xCA, 0xFA, 0x75, 0xD2,
0x01, 0x40, 0x5A, 0x8D, 0x79, 0xBF, 0x8B, 0xCF, 0x4B, 0xCF, 0xAA, 0x16,
0xC1, 0x95, 0xE4, 0xAD, 0x4C, 0x8A, 0x3E, 0x17, 0x91, 0xD4, 0xB1, 0x62,
0xE5, 0x82, 0xE5, 0x80, 0x04, 0xA4, 0x03, 0x7E, 0x8D, 0xBF, 0xDA, 0x7F,
0xA2, 0x0F, 0x97, 0x4F, 0x0C, 0xD3, 0x0D, 0xFB, 0xD7, 0xD1, 0xE5, 0x72,
0x7E, 0x1C, 0xC8, 0x77, 0xFF, 0x5B, 0x9A, 0x0F, 0xB7, 0xAE, 0x05, 0x46,
0xE5, 0xF1, 0xA8, 0x16, 0xEC, 0x47, 0xA4, 0x17
};
static const unsigned char TA24_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA25_DN[] = {
0x30, 0x81, 0x83, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F,
0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x1A, 0x30, 0x18, 0x06,
0x03, 0x55, 0x04, 0x0A, 0x13, 0x11, 0x47, 0x6F, 0x44, 0x61, 0x64, 0x64,
0x79, 0x2E, 0x63, 0x6F, 0x6D, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31,
0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x28, 0x47, 0x6F,
0x20, 0x44, 0x61, 0x64, 0x64, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20,
0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20,
0x47, 0x32
};
static const unsigned char TA25_RSA_N[] = {
0xBF, 0x71, 0x62, 0x08, 0xF1, 0xFA, 0x59, 0x34, 0xF7, 0x1B, 0xC9, 0x18,
0xA3, 0xF7, 0x80, 0x49, 0x58, 0xE9, 0x22, 0x83, 0x13, 0xA6, 0xC5, 0x20,
0x43, 0x01, 0x3B, 0x84, 0xF1, 0xE6, 0x85, 0x49, 0x9F, 0x27, 0xEA, 0xF6,
0x84, 0x1B, 0x4E, 0xA0, 0xB4, 0xDB, 0x70, 0x98, 0xC7, 0x32, 0x01, 0xB1,
0x05, 0x3E, 0x07, 0x4E, 0xEE, 0xF4, 0xFA, 0x4F, 0x2F, 0x59, 0x30, 0x22,
0xE7, 0xAB, 0x19, 0x56, 0x6B, 0xE2, 0x80, 0x07, 0xFC, 0xF3, 0x16, 0x75,
0x80, 0x39, 0x51, 0x7B, 0xE5, 0xF9, 0x35, 0xB6, 0x74, 0x4E, 0xA9, 0x8D,
0x82, 0x13, 0xE4, 0xB6, 0x3F, 0xA9, 0x03, 0x83, 0xFA, 0xA2, 0xBE, 0x8A,
0x15, 0x6A, 0x7F, 0xDE, 0x0B, 0xC3, 0xB6, 0x19, 0x14, 0x05, 0xCA, 0xEA,
0xC3, 0xA8, 0x04, 0x94, 0x3B, 0x46, 0x7C, 0x32, 0x0D, 0xF3, 0x00, 0x66,
0x22, 0xC8, 0x8D, 0x69, 0x6D, 0x36, 0x8C, 0x11, 0x18, 0xB7, 0xD3, 0xB2,
0x1C, 0x60, 0xB4, 0x38, 0xFA, 0x02, 0x8C, 0xCE, 0xD3, 0xDD, 0x46, 0x07,
0xDE, 0x0A, 0x3E, 0xEB, 0x5D, 0x7C, 0xC8, 0x7C, 0xFB, 0xB0, 0x2B, 0x53,
0xA4, 0x92, 0x62, 0x69, 0x51, 0x25, 0x05, 0x61, 0x1A, 0x44, 0x81, 0x8C,
0x2C, 0xA9, 0x43, 0x96, 0x23, 0xDF, 0xAC, 0x3A, 0x81, 0x9A, 0x0E, 0x29,
0xC5, 0x1C, 0xA9, 0xE9, 0x5D, 0x1E, 0xB6, 0x9E, 0x9E, 0x30, 0x0A, 0x39,
0xCE, 0xF1, 0x88, 0x80, 0xFB, 0x4B, 0x5D, 0xCC, 0x32, 0xEC, 0x85, 0x62,
0x43, 0x25, 0x34, 0x02, 0x56, 0x27, 0x01, 0x91, 0xB4, 0x3B, 0x70, 0x2A,
0x3F, 0x6E, 0xB1, 0xE8, 0x9C, 0x88, 0x01, 0x7D, 0x9F, 0xD4, 0xF9, 0xDB,
0x53, 0x6D, 0x60, 0x9D, 0xBF, 0x2C, 0xE7, 0x58, 0xAB, 0xB8, 0x5F, 0x46,
0xFC, 0xCE, 0xC4, 0x1B, 0x03, 0x3C, 0x09, 0xEB, 0x49, 0x31, 0x5C, 0x69,
0x46, 0xB3, 0xE0, 0x47
};
static const unsigned char TA25_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA26_DN[] = {
0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F,
0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06,
0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69,
0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F,
0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x32,
0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x53, 0x74, 0x61,
0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20,
0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20,
0x47, 0x32
};
static const unsigned char TA26_RSA_N[] = {
0xBD, 0xED, 0xC1, 0x03, 0xFC, 0xF6, 0x8F, 0xFC, 0x02, 0xB1, 0x6F, 0x5B,
0x9F, 0x48, 0xD9, 0x9D, 0x79, 0xE2, 0xA2, 0xB7, 0x03, 0x61, 0x56, 0x18,
0xC3, 0x47, 0xB6, 0xD7, 0xCA, 0x3D, 0x35, 0x2E, 0x89, 0x43, 0xF7, 0xA1,
0x69, 0x9B, 0xDE, 0x8A, 0x1A, 0xFD, 0x13, 0x20, 0x9C, 0xB4, 0x49, 0x77,
0x32, 0x29, 0x56, 0xFD, 0xB9, 0xEC, 0x8C, 0xDD, 0x22, 0xFA, 0x72, 0xDC,
0x27, 0x61, 0x97, 0xEE, 0xF6, 0x5A, 0x84, 0xEC, 0x6E, 0x19, 0xB9, 0x89,
0x2C, 0xDC, 0x84, 0x5B, 0xD5, 0x74, 0xFB, 0x6B, 0x5F, 0xC5, 0x89, 0xA5,
0x10, 0x52, 0x89, 0x46, 0x55, 0xF4, 0xB8, 0x75, 0x1C, 0xE6, 0x7F, 0xE4,
0x54, 0xAE, 0x4B, 0xF8, 0x55, 0x72, 0x57, 0x02, 0x19, 0xF8, 0x17, 0x71,
0x59, 0xEB, 0x1E, 0x28, 0x07, 0x74, 0xC5, 0x9D, 0x48, 0xBE, 0x6C, 0xB4,
0xF4, 0xA4, 0xB0, 0xF3, 0x64, 0x37, 0x79, 0x92, 0xC0, 0xEC, 0x46, 0x5E,
0x7F, 0xE1, 0x6D, 0x53, 0x4C, 0x62, 0xAF, 0xCD, 0x1F, 0x0B, 0x63, 0xBB,
0x3A, 0x9D, 0xFB, 0xFC, 0x79, 0x00, 0x98, 0x61, 0x74, 0xCF, 0x26, 0x82,
0x40, 0x63, 0xF3, 0xB2, 0x72, 0x6A, 0x19, 0x0D, 0x99, 0xCA, 0xD4, 0x0E,
0x75, 0xCC, 0x37, 0xFB, 0x8B, 0x89, 0xC1, 0x59, 0xF1, 0x62, 0x7F, 0x5F,
0xB3, 0x5F, 0x65, 0x30, 0xF8, 0xA7, 0xB7, 0x4D, 0x76, 0x5A, 0x1E, 0x76,
0x5E, 0x34, 0xC0, 0xE8, 0x96, 0x56, 0x99, 0x8A, 0xB3, 0xF0, 0x7F, 0xA4,
0xCD, 0xBD, 0xDC, 0x32, 0x31, 0x7C, 0x91, 0xCF, 0xE0, 0x5F, 0x11, 0xF8,
0x6B, 0xAA, 0x49, 0x5C, 0xD1, 0x99, 0x94, 0xD1, 0xA2, 0xE3, 0x63, 0x5B,
0x09, 0x76, 0xB5, 0x56, 0x62, 0xE1, 0x4B, 0x74, 0x1D, 0x96, 0xD4, 0x26,
0xD4, 0x08, 0x04, 0x59, 0xD0, 0x98, 0x0E, 0x0E, 0xE6, 0xDE, 0xFC, 0xC3,
0xEC, 0x1F, 0x90, 0xF1
};
static const unsigned char TA26_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA27_DN[] = {
0x30, 0x81, 0x98, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7A, 0x6F, 0x6E, 0x61, 0x31, 0x13,
0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0A, 0x53, 0x63, 0x6F,
0x74, 0x74, 0x73, 0x64, 0x61, 0x6C, 0x65, 0x31, 0x25, 0x30, 0x23, 0x06,
0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x53, 0x74, 0x61, 0x72, 0x66, 0x69,
0x65, 0x6C, 0x64, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F,
0x67, 0x69, 0x65, 0x73, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3B,
0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x32, 0x53, 0x74, 0x61,
0x72, 0x66, 0x69, 0x65, 0x6C, 0x64, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69,
0x63, 0x65, 0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74,
0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47, 0x32
};
static const unsigned char TA27_RSA_N[] = {
0xD5, 0x0C, 0x3A, 0xC4, 0x2A, 0xF9, 0x4E, 0xE2, 0xF5, 0xBE, 0x19, 0x97,
0x5F, 0x8E, 0x88, 0x53, 0xB1, 0x1F, 0x3F, 0xCB, 0xCF, 0x9F, 0x20, 0x13,
0x6D, 0x29, 0x3A, 0xC8, 0x0F, 0x7D, 0x3C, 0xF7, 0x6B, 0x76, 0x38, 0x63,
0xD9, 0x36, 0x60, 0xA8, 0x9B, 0x5E, 0x5C, 0x00, 0x80, 0xB2, 0x2F, 0x59,
0x7F, 0xF6, 0x87, 0xF9, 0x25, 0x43, 0x86, 0xE7, 0x69, 0x1B, 0x52, 0x9A,
0x90, 0xE1, 0x71, 0xE3, 0xD8, 0x2D, 0x0D, 0x4E, 0x6F, 0xF6, 0xC8, 0x49,
0xD9, 0xB6, 0xF3, 0x1A, 0x56, 0xAE, 0x2B, 0xB6, 0x74, 0x14, 0xEB, 0xCF,
0xFB, 0x26, 0xE3, 0x1A, 0xBA, 0x1D, 0x96, 0x2E, 0x6A, 0x3B, 0x58, 0x94,
0x89, 0x47, 0x56, 0xFF, 0x25, 0xA0, 0x93, 0x70, 0x53, 0x83, 0xDA, 0x84,
0x74, 0x14, 0xC3, 0x67, 0x9E, 0x04, 0x68, 0x3A, 0xDF, 0x8E, 0x40, 0x5A,
0x1D, 0x4A, 0x4E, 0xCF, 0x43, 0x91, 0x3B, 0xE7, 0x56, 0xD6, 0x00, 0x70,
0xCB, 0x52, 0xEE, 0x7B, 0x7D, 0xAE, 0x3A, 0xE7, 0xBC, 0x31, 0xF9, 0x45,
0xF6, 0xC2, 0x60, 0xCF, 0x13, 0x59, 0x02, 0x2B, 0x80, 0xCC, 0x34, 0x47,
0xDF, 0xB9, 0xDE, 0x90, 0x65, 0x6D, 0x02, 0xCF, 0x2C, 0x91, 0xA6, 0xA6,
0xE7, 0xDE, 0x85, 0x18, 0x49, 0x7C, 0x66, 0x4E, 0xA3, 0x3A, 0x6D, 0xA9,
0xB5, 0xEE, 0x34, 0x2E, 0xBA, 0x0D, 0x03, 0xB8, 0x33, 0xDF, 0x47, 0xEB,
0xB1, 0x6B, 0x8D, 0x25, 0xD9, 0x9B, 0xCE, 0x81, 0xD1, 0x45, 0x46, 0x32,
0x96, 0x70, 0x87, 0xDE, 0x02, 0x0E, 0x49, 0x43, 0x85, 0xB6, 0x6C, 0x73,
0xBB, 0x64, 0xEA, 0x61, 0x41, 0xAC, 0xC9, 0xD4, 0x54, 0xDF, 0x87, 0x2F,
0xC7, 0x22, 0xB2, 0x26, 0xCC, 0x9F, 0x59, 0x54, 0x68, 0x9F, 0xFC, 0xBE,
0x2A, 0x2F, 0xC4, 0x55, 0x1C, 0x75, 0x40, 0x60, 0x17, 0x85, 0x02, 0x55,
0x39, 0x8B, 0x7F, 0x05
};
static const unsigned char TA27_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA28_DN[] = {
0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73,
0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16,
0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C
};
static const unsigned char TA28_RSA_N[] = {
0xF6, 0x1B, 0x4F, 0x67, 0x07, 0x2B, 0xA1, 0x15, 0xF5, 0x06, 0x22, 0xCB,
0x1F, 0x01, 0xB2, 0xE3, 0x73, 0x45, 0x06, 0x44, 0x49, 0x2C, 0xBB, 0x49,
0x25, 0x14, 0xD6, 0xCE, 0xC3, 0xB7, 0xAB, 0x2C, 0x4F, 0xC6, 0x41, 0x32,
0x94, 0x57, 0xFA, 0x12, 0xA7, 0x5B, 0x0E, 0xE2, 0x8F, 0x1F, 0x1E, 0x86,
0x19, 0xA7, 0xAA, 0xB5, 0x2D, 0xB9, 0x5F, 0x0D, 0x8A, 0xC2, 0xAF, 0x85,
0x35, 0x79, 0x32, 0x2D, 0xBB, 0x1C, 0x62, 0x37, 0xF2, 0xB1, 0x5B, 0x4A,
0x3D, 0xCA, 0xCD, 0x71, 0x5F, 0xE9, 0x42, 0xBE, 0x94, 0xE8, 0xC8, 0xDE,
0xF9, 0x22, 0x48, 0x64, 0xC6, 0xE5, 0xAB, 0xC6, 0x2B, 0x6D, 0xAD, 0x05,
0xF0, 0xFA, 0xD5, 0x0B, 0xCF, 0x9A, 0xE5, 0xF0, 0x50, 0xA4, 0x8B, 0x3B,
0x47, 0xA5, 0x23, 0x5B, 0x7A, 0x7A, 0xF8, 0x33, 0x3F, 0xB8, 0xEF, 0x99,
0x97, 0xE3, 0x20, 0xC1, 0xD6, 0x28, 0x89, 0xCF, 0x94, 0xFB, 0xB9, 0x45,
0xED, 0xE3, 0x40, 0x17, 0x11, 0xD4, 0x74, 0xF0, 0x0B, 0x31, 0xE2, 0x2B,
0x26, 0x6A, 0x9B, 0x4C, 0x57, 0xAE, 0xAC, 0x20, 0x3E, 0xBA, 0x45, 0x7A,
0x05, 0xF3, 0xBD, 0x9B, 0x69, 0x15, 0xAE, 0x7D, 0x4E, 0x20, 0x63, 0xC4,
0x35, 0x76, 0x3A, 0x07, 0x02, 0xC9, 0x37, 0xFD, 0xC7, 0x47, 0xEE, 0xE8,
0xF1, 0x76, 0x1D, 0x73, 0x15, 0xF2, 0x97, 0xA4, 0xB5, 0xC8, 0x7A, 0x79,
0xD9, 0x42, 0xAA, 0x2B, 0x7F, 0x5C, 0xFE, 0xCE, 0x26, 0x4F, 0xA3, 0x66,
0x81, 0x35, 0xAF, 0x44, 0xBA, 0x54, 0x1E, 0x1C, 0x30, 0x32, 0x65, 0x9D,
0xE6, 0x3C, 0x93, 0x5E, 0x50, 0x4E, 0x7A, 0xE3, 0x3A, 0xD4, 0x6E, 0xCC,
0x1A, 0xFB, 0xF9, 0xD2, 0x37, 0xAE, 0x24, 0x2A, 0xAB, 0x57, 0x03, 0x22,
0x28, 0x0D, 0x49, 0x75, 0x7F, 0xB7, 0x28, 0xDA, 0x75, 0xBF, 0x8E, 0xE3,
0xDC, 0x0E, 0x79, 0x31
};
static const unsigned char TA28_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA29_DN[] = {
0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73,
0x74, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16,
0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x69, 0x6E, 0x67
};
static const unsigned char TA29_RSA_N[] = {
0xB4, 0x84, 0xCC, 0x33, 0x17, 0x2E, 0x6B, 0x94, 0x6C, 0x6B, 0x61, 0x52,
0xA0, 0xEB, 0xA3, 0xCF, 0x79, 0x94, 0x4C, 0xE5, 0x94, 0x80, 0x99, 0xCB,
0x55, 0x64, 0x44, 0x65, 0x8F, 0x67, 0x64, 0xE2, 0x06, 0xE3, 0x5C, 0x37,
0x49, 0xF6, 0x2F, 0x9B, 0x84, 0x84, 0x1E, 0x2D, 0xF2, 0x60, 0x9D, 0x30,
0x4E, 0xCC, 0x84, 0x85, 0xE2, 0x2C, 0xCF, 0x1E, 0x9E, 0xFE, 0x36, 0xAB,
0x33, 0x77, 0x35, 0x44, 0xD8, 0x35, 0x96, 0x1A, 0x3D, 0x36, 0xE8, 0x7A,
0x0E, 0xD8, 0xD5, 0x47, 0xA1, 0x6A, 0x69, 0x8B, 0xD9, 0xFC, 0xBB, 0x3A,
0xAE, 0x79, 0x5A, 0xD5, 0xF4, 0xD6, 0x71, 0xBB, 0x9A, 0x90, 0x23, 0x6B,
0x9A, 0xB7, 0x88, 0x74, 0x87, 0x0C, 0x1E, 0x5F, 0xB9, 0x9E, 0x2D, 0xFA,
0xAB, 0x53, 0x2B, 0xDC, 0xBB, 0x76, 0x3E, 0x93, 0x4C, 0x08, 0x08, 0x8C,
0x1E, 0xA2, 0x23, 0x1C, 0xD4, 0x6A, 0xAD, 0x22, 0xBA, 0x99, 0x01, 0x2E,
0x6D, 0x65, 0xCB, 0xBE, 0x24, 0x66, 0x55, 0x24, 0x4B, 0x40, 0x44, 0xB1,
0x1B, 0xD7, 0xE1, 0xC2, 0x85, 0xC0, 0xDE, 0x10, 0x3F, 0x3D, 0xED, 0xB8,
0xFC, 0xF1, 0xF1, 0x23, 0x53, 0xDC, 0xBF, 0x65, 0x97, 0x6F, 0xD9, 0xF9,
0x40, 0x71, 0x8D, 0x7D, 0xBD, 0x95, 0xD4, 0xCE, 0xBE, 0xA0, 0x5E, 0x27,
0x23, 0xDE, 0xFD, 0xA6, 0xD0, 0x26, 0x0E, 0x00, 0x29, 0xEB, 0x3C, 0x46,
0xF0, 0x3D, 0x60, 0xBF, 0x3F, 0x50, 0xD2, 0xDC, 0x26, 0x41, 0x51, 0x9E,
0x14, 0x37, 0x42, 0x04, 0xA3, 0x70, 0x57, 0xA8, 0x1B, 0x87, 0xED, 0x2D,
0xFA, 0x7B, 0xEE, 0x8C, 0x0A, 0xE3, 0xA9, 0x66, 0x89, 0x19, 0xCB, 0x41,
0xF9, 0xDD, 0x44, 0x36, 0x61, 0xCF, 0xE2, 0x77, 0x46, 0xC8, 0x7D, 0xF6,
0xF4, 0x92, 0x81, 0x36, 0xFD, 0xDB, 0x34, 0xF1, 0x72, 0x7E, 0xF3, 0x0C,
0x16, 0xBD, 0xB4, 0x15
};
static const unsigned char TA29_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA30_DN[] = {
0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73,
0x74, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x13,
0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D
};
static const unsigned char TA30_RSA_N[] = {
0xC4, 0x12, 0xDF, 0xA9, 0x5F, 0xFE, 0x41, 0xDD, 0xDD, 0xF5, 0x9F, 0x8A,
0xE3, 0xF6, 0xAC, 0xE1, 0x3C, 0x78, 0x9A, 0xBC, 0xD8, 0xF0, 0x7F, 0x7A,
0xA0, 0x33, 0x2A, 0xDC, 0x8D, 0x20, 0x5B, 0xAE, 0x2D, 0x6F, 0xE7, 0x93,
0xD9, 0x36, 0x70, 0x6A, 0x68, 0xCF, 0x8E, 0x51, 0xA3, 0x85, 0x5B, 0x67,
0x04, 0xA0, 0x10, 0x24, 0x6F, 0x5D, 0x28, 0x82, 0xC1, 0x97, 0x57, 0xD8,
0x48, 0x29, 0x13, 0xB6, 0xE1, 0xBE, 0x91, 0x4D, 0xDF, 0x85, 0x0C, 0x53,
0x18, 0x9A, 0x1E, 0x24, 0xA2, 0x4F, 0x8F, 0xF0, 0xA2, 0x85, 0x0B, 0xCB,
0xF4, 0x29, 0x7F, 0xD2, 0xA4, 0x58, 0xEE, 0x26, 0x4D, 0xC9, 0xAA, 0xA8,
0x7B, 0x9A, 0xD9, 0xFA, 0x38, 0xDE, 0x44, 0x57, 0x15, 0xE5, 0xF8, 0x8C,
0xC8, 0xD9, 0x48, 0xE2, 0x0D, 0x16, 0x27, 0x1D, 0x1E, 0xC8, 0x83, 0x85,
0x25, 0xB7, 0xBA, 0xAA, 0x55, 0x41, 0xCC, 0x03, 0x22, 0x4B, 0x2D, 0x91,
0x8D, 0x8B, 0xE6, 0x89, 0xAF, 0x66, 0xC7, 0xE9, 0xFF, 0x2B, 0xE9, 0x3C,
0xAC, 0xDA, 0xD2, 0xB3, 0xC3, 0xE1, 0x68, 0x9C, 0x89, 0xF8, 0x7A, 0x00,
0x56, 0xDE, 0xF4, 0x55, 0x95, 0x6C, 0xFB, 0xBA, 0x64, 0xDD, 0x62, 0x8B,
0xDF, 0x0B, 0x77, 0x32, 0xEB, 0x62, 0xCC, 0x26, 0x9A, 0x9B, 0xBB, 0xAA,
0x62, 0x83, 0x4C, 0xB4, 0x06, 0x7A, 0x30, 0xC8, 0x29, 0xBF, 0xED, 0x06,
0x4D, 0x97, 0xB9, 0x1C, 0xC4, 0x31, 0x2B, 0xD5, 0x5F, 0xBC, 0x53, 0x12,
0x17, 0x9C, 0x99, 0x57, 0x29, 0x66, 0x77, 0x61, 0x21, 0x31, 0x07, 0x2E,
0x25, 0x49, 0x9D, 0x18, 0xF2, 0xEE, 0xF3, 0x2B, 0x71, 0x8C, 0xB5, 0xBA,
0x39, 0x07, 0x49, 0x77, 0xFC, 0xEF, 0x2E, 0x92, 0x90, 0x05, 0x8D, 0x2D,
0x2F, 0x77, 0x7B, 0xEF, 0x43, 0xBF, 0x35, 0xBB, 0x9A, 0xD8, 0xF9, 0x73,
0xA7, 0x2C, 0xF2, 0xD0, 0x57, 0xEE, 0x28, 0x4E, 0x26, 0x5F, 0x8F, 0x90,
0x68, 0x09, 0x2F, 0xB8, 0xF8, 0xDC, 0x06, 0xE9, 0x2E, 0x9A, 0x3E, 0x51,
0xA7, 0xD1, 0x22, 0xC4, 0x0A, 0xA7, 0x38, 0x48, 0x6C, 0xB3, 0xF9, 0xFF,
0x7D, 0xAB, 0x86, 0x57, 0xE3, 0xBA, 0xD6, 0x85, 0x78, 0x77, 0xBA, 0x43,
0xEA, 0x48, 0x7F, 0xF6, 0xD8, 0xBE, 0x23, 0x6D, 0x1E, 0xBF, 0xD1, 0x36,
0x6C, 0x58, 0x5C, 0xF1, 0xEE, 0xA4, 0x19, 0x54, 0x1A, 0xF5, 0x03, 0xD2,
0x76, 0xE6, 0xE1, 0x8C, 0xBD, 0x3C, 0xB3, 0xD3, 0x48, 0x4B, 0xE2, 0xC8,
0xF8, 0x7F, 0x92, 0xA8, 0x76, 0x46, 0x9C, 0x42, 0x65, 0x3E, 0xA4, 0x1E,
0xC1, 0x07, 0x03, 0x5A, 0x46, 0x2D, 0xB8, 0x97, 0xF3, 0xB7, 0xD5, 0xB2,
0x55, 0x21, 0xEF, 0xBA, 0xDC, 0x4C, 0x00, 0x97, 0xFB, 0x14, 0x95, 0x27,
0x33, 0xBF, 0xE8, 0x43, 0x47, 0x46, 0xD2, 0x08, 0x99, 0x16, 0x60, 0x3B,
0x9A, 0x7E, 0xD2, 0xE6, 0xED, 0x38, 0xEA, 0xEC, 0x01, 0x1E, 0x3C, 0x48,
0x56, 0x49, 0x09, 0xC7, 0x4C, 0x37, 0x00, 0x9E, 0x88, 0x0E, 0xC0, 0x73,
0xE1, 0x6F, 0x66, 0xE9, 0x72, 0x47, 0x30, 0x3E, 0x10, 0xE5, 0x0B, 0x03,
0xC9, 0x9A, 0x42, 0x00, 0x6C, 0xC5, 0x94, 0x7E, 0x61, 0xC4, 0x8A, 0xDF,
0x7F, 0x82, 0x1A, 0x0B, 0x59, 0xC4, 0x59, 0x32, 0x77, 0xB3, 0xBC, 0x60,
0x69, 0x56, 0x39, 0xFD, 0xB4, 0x06, 0x7B, 0x2C, 0xD6, 0x64, 0x36, 0xD9,
0xBD, 0x48, 0xED, 0x84, 0x1F, 0x7E, 0xA5, 0x22, 0x8F, 0x2A, 0xB8, 0x42,
0xF4, 0x82, 0xB7, 0xD4, 0x53, 0x90, 0x78, 0x4E, 0x2D, 0x1A, 0xFD, 0x81,
0x6F, 0x44, 0xD7, 0x3B, 0x01, 0x74, 0x96, 0x42, 0xE0, 0x00, 0xE2, 0x2E,
0x6B, 0xEA, 0xC5, 0xEE, 0x72, 0xAC, 0xBB, 0xBF, 0xFE, 0xEA, 0xAA, 0xA8,
0xF8, 0xDC, 0xF6, 0xB2, 0x79, 0x8A, 0xB6, 0x67
};
static const unsigned char TA30_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA31_DN[] = {
0x30, 0x45, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0B, 0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73,
0x74, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17,
0x41, 0x66, 0x66, 0x69, 0x72, 0x6D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20,
0x50, 0x72, 0x65, 0x6D, 0x69, 0x75, 0x6D, 0x20, 0x45, 0x43, 0x43
};
static const unsigned char TA31_EC_Q[] = {
0x04, 0x0D, 0x30, 0x5E, 0x1B, 0x15, 0x9D, 0x03, 0xD0, 0xA1, 0x79, 0x35,
0xB7, 0x3A, 0x3C, 0x92, 0x7A, 0xCA, 0x15, 0x1C, 0xCD, 0x62, 0xF3, 0x9C,
0x26, 0x5C, 0x07, 0x3D, 0xE5, 0x54, 0xFA, 0xA3, 0xD6, 0xCC, 0x12, 0xEA,
0xF4, 0x14, 0x5F, 0xE8, 0x8E, 0x19, 0xAB, 0x2F, 0x2E, 0x48, 0xE6, 0xAC,
0x18, 0x43, 0x78, 0xAC, 0xD0, 0x37, 0xC3, 0xBD, 0xB2, 0xCD, 0x2C, 0xE6,
0x47, 0xE2, 0x1A, 0xE6, 0x63, 0xB8, 0x3D, 0x2E, 0x2F, 0x78, 0xC4, 0x4F,
0xDB, 0xF4, 0x0F, 0xA4, 0x68, 0x4C, 0x55, 0x72, 0x6B, 0x95, 0x1D, 0x4E,
0x18, 0x42, 0x95, 0x78, 0xCC, 0x37, 0x3C, 0x91, 0xE2, 0x9B, 0x65, 0x2B,
0x29
};
static const unsigned char TA32_DN[] = {
0x30, 0x7E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54, 0x65,
0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x53,
0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B,
0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x22, 0x30, 0x20,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x19, 0x43, 0x65, 0x72, 0x74, 0x75,
0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E, 0x65,
0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41
};
static const unsigned char TA32_RSA_N[] = {
0xE3, 0xFB, 0x7D, 0xA3, 0x72, 0xBA, 0xC2, 0xF0, 0xC9, 0x14, 0x87, 0xF5,
0x6B, 0x01, 0x4E, 0xE1, 0x6E, 0x40, 0x07, 0xBA, 0x6D, 0x27, 0x5D, 0x7F,
0xF7, 0x5B, 0x2D, 0xB3, 0x5A, 0xC7, 0x51, 0x5F, 0xAB, 0xA4, 0x32, 0xA6,
0x61, 0x87, 0xB6, 0x6E, 0x0F, 0x86, 0xD2, 0x30, 0x02, 0x97, 0xF8, 0xD7,
0x69, 0x57, 0xA1, 0x18, 0x39, 0x5D, 0x6A, 0x64, 0x79, 0xC6, 0x01, 0x59,
0xAC, 0x3C, 0x31, 0x4A, 0x38, 0x7C, 0xD2, 0x04, 0xD2, 0x4B, 0x28, 0xE8,
0x20, 0x5F, 0x3B, 0x07, 0xA2, 0xCC, 0x4D, 0x73, 0xDB, 0xF3, 0xAE, 0x4F,
0xC7, 0x56, 0xD5, 0x5A, 0xA7, 0x96, 0x89, 0xFA, 0xF3, 0xAB, 0x68, 0xD4,
0x23, 0x86, 0x59, 0x27, 0xCF, 0x09, 0x27, 0xBC, 0xAC, 0x6E, 0x72, 0x83,
0x1C, 0x30, 0x72, 0xDF, 0xE0, 0xA2, 0xE9, 0xD2, 0xE1, 0x74, 0x75, 0x19,
0xBD, 0x2A, 0x9E, 0x7B, 0x15, 0x54, 0x04, 0x1B, 0xD7, 0x43, 0x39, 0xAD,
0x55, 0x28, 0xC5, 0xE2, 0x1A, 0xBB, 0xF4, 0xC0, 0xE4, 0xAE, 0x38, 0x49,
0x33, 0xCC, 0x76, 0x85, 0x9F, 0x39, 0x45, 0xD2, 0xA4, 0x9E, 0xF2, 0x12,
0x8C, 0x51, 0xF8, 0x7C, 0xE4, 0x2D, 0x7F, 0xF5, 0xAC, 0x5F, 0xEB, 0x16,
0x9F, 0xB1, 0x2D, 0xD1, 0xBA, 0xCC, 0x91, 0x42, 0x77, 0x4C, 0x25, 0xC9,
0x90, 0x38, 0x6F, 0xDB, 0xF0, 0xCC, 0xFB, 0x8E, 0x1E, 0x97, 0x59, 0x3E,
0xD5, 0x60, 0x4E, 0xE6, 0x05, 0x28, 0xED, 0x49, 0x79, 0x13, 0x4B, 0xBA,
0x48, 0xDB, 0x2F, 0xF9, 0x72, 0xD3, 0x39, 0xCA, 0xFE, 0x1F, 0xD8, 0x34,
0x72, 0xF5, 0xB4, 0x40, 0xCF, 0x31, 0x01, 0xC3, 0xEC, 0xDE, 0x11, 0x2D,
0x17, 0x5D, 0x1F, 0xB8, 0x50, 0xD1, 0x5E, 0x19, 0xA7, 0x69, 0xDE, 0x07,
0x33, 0x28, 0xCA, 0x50, 0x95, 0xF9, 0xA7, 0x54, 0xCB, 0x54, 0x86, 0x50,
0x45, 0xA9, 0xF9, 0x49
};
static const unsigned char TA32_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA33_DN[] = {
0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31,
0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0C, 0x21, 0x54, 0x57, 0x43, 0x41, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74,
0x79
};
static const unsigned char TA33_RSA_N[] = {
0xB0, 0x7E, 0x72, 0xB8, 0xA4, 0x03, 0x94, 0xE6, 0xA7, 0xDE, 0x09, 0x38,
0x91, 0x4A, 0x11, 0x40, 0x87, 0xA7, 0x7C, 0x59, 0x64, 0x14, 0x7B, 0xB5,
0x11, 0x10, 0xDD, 0xFE, 0xBF, 0xD5, 0xC0, 0xBB, 0x56, 0xE2, 0x85, 0x25,
0xF4, 0x35, 0x72, 0x0F, 0xF8, 0x53, 0xD0, 0x41, 0xE1, 0x44, 0x01, 0xC2,
0xB4, 0x1C, 0xC3, 0x31, 0x42, 0x16, 0x47, 0x85, 0x33, 0x22, 0x76, 0xB2,
0x0A, 0x6F, 0x0F, 0xE5, 0x25, 0x50, 0x4F, 0x85, 0x86, 0xBE, 0xBF, 0x98,
0x2E, 0x10, 0x67, 0x1E, 0xBE, 0x11, 0x05, 0x86, 0x05, 0x90, 0xC4, 0x59,
0xD0, 0x7C, 0x78, 0x10, 0xB0, 0x80, 0x5C, 0xB7, 0xE1, 0xC7, 0x2B, 0x75,
0xCB, 0x7C, 0x9F, 0xAE, 0xB5, 0xD1, 0x9D, 0x23, 0x37, 0x63, 0xA7, 0xDC,
0x42, 0xA2, 0x2D, 0x92, 0x04, 0x1B, 0x50, 0xC1, 0x7B, 0xB8, 0x3E, 0x1B,
0xC9, 0x56, 0x04, 0x8B, 0x2F, 0x52, 0x9B, 0xAD, 0xA9, 0x56, 0xE9, 0xC1,
0xFF, 0xAD, 0xA9, 0x58, 0x87, 0x30, 0xB6, 0x81, 0xF7, 0x97, 0x45, 0xFC,
0x19, 0x57, 0x3B, 0x2B, 0x6F, 0xE4, 0x47, 0xF4, 0x99, 0x45, 0xFE, 0x1D,
0xF1, 0xF8, 0x97, 0xA3, 0x88, 0x1D, 0x37, 0x1C, 0x5C, 0x8F, 0xE0, 0x76,
0x25, 0x9A, 0x50, 0xF8, 0xA0, 0x54, 0xFF, 0x44, 0x90, 0x76, 0x23, 0xD2,
0x32, 0xC6, 0xC3, 0xAB, 0x06, 0xBF, 0xFC, 0xFB, 0xBF, 0xF3, 0xAD, 0x7D,
0x92, 0x62, 0x02, 0x5B, 0x29, 0xD3, 0x35, 0xA3, 0x93, 0x9A, 0x43, 0x64,
0x60, 0x5D, 0xB2, 0xFA, 0x32, 0xFF, 0x3B, 0x04, 0xAF, 0x4D, 0x40, 0x6A,
0xF9, 0xC7, 0xE3, 0xEF, 0x23, 0xFD, 0x6B, 0xCB, 0xE5, 0x0F, 0x8B, 0x38,
0x0D, 0xEE, 0x0A, 0xFC, 0xFE, 0x0F, 0x98, 0x9F, 0x30, 0x31, 0xDD, 0x6C,
0x52, 0x65, 0xF9, 0x8B, 0x81, 0xBE, 0x22, 0xE1, 0x1C, 0x58, 0x03, 0xBA,
0x91, 0x1B, 0x89, 0x07
};
static const unsigned char TA33_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA34_DN[] = {
0x30, 0x5D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73,
0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F,
0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03,
0x55, 0x04, 0x0B, 0x13, 0x1E, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x32
};
static const unsigned char TA34_RSA_N[] = {
0xD0, 0x15, 0x39, 0x52, 0xB1, 0x52, 0xB3, 0xBA, 0xC5, 0x59, 0x82, 0xC4,
0x5D, 0x52, 0xAE, 0x3A, 0x43, 0x65, 0x80, 0x4B, 0xC7, 0xF2, 0x96, 0xBC,
0xDB, 0x36, 0x97, 0xD6, 0xA6, 0x64, 0x8C, 0xA8, 0x5E, 0xF0, 0xE3, 0x0A,
0x1C, 0xF7, 0xDF, 0x97, 0x3D, 0x4B, 0xAE, 0xF6, 0x5D, 0xEC, 0x21, 0xB5,
0x41, 0xAB, 0xCD, 0xB9, 0x7E, 0x76, 0x9F, 0xBE, 0xF9, 0x3E, 0x36, 0x34,
0xA0, 0x3B, 0xC1, 0xF6, 0x31, 0x11, 0x45, 0x74, 0x93, 0x3D, 0x57, 0x80,
0xC5, 0xF9, 0x89, 0x99, 0xCA, 0xE5, 0xAB, 0x6A, 0xD4, 0xB5, 0xDA, 0x41,
0x90, 0x10, 0xC1, 0xD6, 0xD6, 0x42, 0x89, 0xC2, 0xBF, 0xF4, 0x38, 0x12,
0x95, 0x4C, 0x54, 0x05, 0xF7, 0x36, 0xE4, 0x45, 0x83, 0x7B, 0x14, 0x65,
0xD6, 0xDC, 0x0C, 0x4D, 0xD1, 0xDE, 0x7E, 0x0C, 0xAB, 0x3B, 0xC4, 0x15,
0xBE, 0x3A, 0x56, 0xA6, 0x5A, 0x6F, 0x76, 0x69, 0x52, 0xA9, 0x7A, 0xB9,
0xC8, 0xEB, 0x6A, 0x9A, 0x5D, 0x52, 0xD0, 0x2D, 0x0A, 0x6B, 0x35, 0x16,
0x09, 0x10, 0x84, 0xD0, 0x6A, 0xCA, 0x3A, 0x06, 0x00, 0x37, 0x47, 0xE4,
0x7E, 0x57, 0x4F, 0x3F, 0x8B, 0xEB, 0x67, 0xB8, 0x88, 0xAA, 0xC5, 0xBE,
0x53, 0x55, 0xB2, 0x91, 0xC4, 0x7D, 0xB9, 0xB0, 0x85, 0x19, 0x06, 0x78,
0x2E, 0xDB, 0x61, 0x1A, 0xFA, 0x85, 0xF5, 0x4A, 0x91, 0xA1, 0xE7, 0x16,
0xD5, 0x8E, 0xA2, 0x39, 0xDF, 0x94, 0xB8, 0x70, 0x1F, 0x28, 0x3F, 0x8B,
0xFC, 0x40, 0x5E, 0x63, 0x83, 0x3C, 0x83, 0x2A, 0x1A, 0x99, 0x6B, 0xCF,
0xDE, 0x59, 0x6A, 0x3B, 0xFC, 0x6F, 0x16, 0xD7, 0x1F, 0xFD, 0x4A, 0x10,
0xEB, 0x4E, 0x82, 0x16, 0x3A, 0xAC, 0x27, 0x0C, 0x53, 0xF1, 0xAD, 0xD5,
0x24, 0xB0, 0x6B, 0x03, 0x50, 0xC1, 0x2D, 0x3C, 0x16, 0xDD, 0x44, 0x34,
0x27, 0x1A, 0x75, 0xFB
};
static const unsigned char TA34_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA35_DN[] = {
0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x49, 0x54, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07,
0x0C, 0x05, 0x4D, 0x69, 0x6C, 0x61, 0x6E, 0x31, 0x23, 0x30, 0x21, 0x06,
0x03, 0x55, 0x04, 0x0A, 0x0C, 0x1A, 0x41, 0x63, 0x74, 0x61, 0x6C, 0x69,
0x73, 0x20, 0x53, 0x2E, 0x70, 0x2E, 0x41, 0x2E, 0x2F, 0x30, 0x33, 0x33,
0x35, 0x38, 0x35, 0x32, 0x30, 0x39, 0x36, 0x37, 0x31, 0x27, 0x30, 0x25,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x41, 0x63, 0x74, 0x61, 0x6C,
0x69, 0x73, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63,
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
0x41
};
static const unsigned char TA35_RSA_N[] = {
0xA7, 0xC6, 0xC4, 0xA5, 0x29, 0xA4, 0x2C, 0xEF, 0xE5, 0x18, 0xC5, 0xB0,
0x50, 0xA3, 0x6F, 0x51, 0x3B, 0x9F, 0x0A, 0x5A, 0xC9, 0xC2, 0x48, 0x38,
0x0A, 0xC2, 0x1C, 0xA0, 0x18, 0x7F, 0x91, 0xB5, 0x87, 0xB9, 0x40, 0x3F,
0xDD, 0x1D, 0x68, 0x1F, 0x08, 0x83, 0xD5, 0x2D, 0x1E, 0x88, 0xA0, 0xF8,
0x8F, 0x56, 0x8F, 0x6D, 0x99, 0x02, 0x92, 0x90, 0x16, 0xD5, 0x5F, 0x08,
0x6C, 0x89, 0xD7, 0xE1, 0xAC, 0xBC, 0x20, 0xC2, 0xB1, 0xE0, 0x83, 0x51,
0x8A, 0x69, 0x4D, 0x00, 0x96, 0x5A, 0x6F, 0x2F, 0xC0, 0x44, 0x7E, 0xA3,
0x0E, 0xE4, 0x91, 0xCD, 0x58, 0xEE, 0xDC, 0xFB, 0xC7, 0x1E, 0x45, 0x47,
0xDD, 0x27, 0xB9, 0x08, 0x01, 0x9F, 0xA6, 0x21, 0x1D, 0xF5, 0x41, 0x2D,
0x2F, 0x4C, 0xFD, 0x28, 0xAD, 0xE0, 0x8A, 0xAD, 0x22, 0xB4, 0x56, 0x65,
0x8E, 0x86, 0x54, 0x8F, 0x93, 0x43, 0x29, 0xDE, 0x39, 0x46, 0x78, 0xA3,
0x30, 0x23, 0xBA, 0xCD, 0xF0, 0x7D, 0x13, 0x57, 0xC0, 0x5D, 0xD2, 0x83,
0x6B, 0x48, 0x4C, 0xC4, 0xAB, 0x9F, 0x80, 0x5A, 0x5B, 0x3A, 0xBD, 0xC9,
0xA7, 0x22, 0x3F, 0x80, 0x27, 0x33, 0x5B, 0x0E, 0xB7, 0x8A, 0x0C, 0x5D,
0x07, 0x37, 0x08, 0xCB, 0x6C, 0xD2, 0x7A, 0x47, 0x22, 0x44, 0x35, 0xC5,
0xCC, 0xCC, 0x2E, 0x8E, 0xDD, 0x2A, 0xED, 0xB7, 0x7D, 0x66, 0x0D, 0x5F,
0x61, 0x51, 0x22, 0x55, 0x1B, 0xE3, 0x46, 0xE3, 0xE3, 0x3D, 0xD0, 0x35,
0x62, 0x9A, 0xDB, 0xAF, 0x14, 0xC8, 0x5B, 0xA1, 0xCC, 0x89, 0x1B, 0xE1,
0x30, 0x26, 0xFC, 0xA0, 0x9B, 0x1F, 0x81, 0xA7, 0x47, 0x1F, 0x04, 0xEB,
0xA3, 0x39, 0x92, 0x06, 0x9F, 0x99, 0xD3, 0xBF, 0xD3, 0xEA, 0x4F, 0x50,
0x9C, 0x19, 0xFE, 0x96, 0x87, 0x1E, 0x3C, 0x65, 0xF6, 0xA3, 0x18, 0x24,
0x83, 0x86, 0x10, 0xE7, 0x54, 0x3E, 0xA8, 0x3A, 0x76, 0x24, 0x4F, 0x81,
0x21, 0xC5, 0xE3, 0x0F, 0x02, 0xF8, 0x93, 0x94, 0x47, 0x20, 0xBB, 0xFE,
0xD4, 0x0E, 0xD3, 0x68, 0xB9, 0xDD, 0xC4, 0x7A, 0x84, 0x82, 0xE3, 0x53,
0x54, 0x79, 0xDD, 0xDB, 0x9C, 0xD2, 0xF2, 0x07, 0x9B, 0x2E, 0xB6, 0xBC,
0x3E, 0xED, 0x85, 0x6D, 0xEF, 0x25, 0x11, 0xF2, 0x97, 0x1A, 0x42, 0x61,
0xF7, 0x4A, 0x97, 0xE8, 0x8B, 0xB1, 0x10, 0x07, 0xFA, 0x65, 0x81, 0xB2,
0xA2, 0x39, 0xCF, 0xF7, 0x3C, 0xFF, 0x18, 0xFB, 0xC6, 0xF1, 0x5A, 0x8B,
0x59, 0xE2, 0x02, 0xAC, 0x7B, 0x92, 0xD0, 0x4E, 0x14, 0x4F, 0x59, 0x45,
0xF6, 0x0C, 0x5E, 0x28, 0x5F, 0xB0, 0xE8, 0x3F, 0x45, 0xCF, 0xCF, 0xAF,
0x9B, 0x6F, 0xFB, 0x84, 0xD3, 0x77, 0x5A, 0x95, 0x6F, 0xAC, 0x94, 0x84,
0x9E, 0xEE, 0xBC, 0xC0, 0x4A, 0x8F, 0x4A, 0x93, 0xF8, 0x44, 0x21, 0xE2,
0x31, 0x45, 0x61, 0x50, 0x4E, 0x10, 0xD8, 0xE3, 0x35, 0x7C, 0x4C, 0x19,
0xB4, 0xDE, 0x05, 0xBF, 0xA3, 0x06, 0x9F, 0xC8, 0xB5, 0xCD, 0xE4, 0x1F,
0xD7, 0x17, 0x06, 0x0D, 0x7A, 0x95, 0x74, 0x55, 0x0D, 0x68, 0x1A, 0xFC,
0x10, 0x1B, 0x62, 0x64, 0x9D, 0x6D, 0xE0, 0x95, 0xA0, 0xC3, 0x94, 0x07,
0x57, 0x0D, 0x14, 0xE6, 0xBD, 0x05, 0xFB, 0xB8, 0x9F, 0xE6, 0xDF, 0x8B,
0xE2, 0xC6, 0xE7, 0x7E, 0x96, 0xF6, 0x53, 0xC5, 0x80, 0x34, 0x50, 0x28,
0x58, 0xF0, 0x12, 0x50, 0x71, 0x17, 0x30, 0xBA, 0xE6, 0x78, 0x63, 0xBC,
0xF4, 0xB2, 0xAD, 0x9B, 0x2B, 0xB2, 0xFE, 0xE1, 0x39, 0x8C, 0x5E, 0xBA,
0x0B, 0x20, 0x94, 0xDE, 0x7B, 0x83, 0xB8, 0xFF, 0xE3, 0x56, 0x8D, 0xB7,
0x11, 0xE9, 0x3B, 0x8C, 0xF2, 0xB1, 0xC1, 0x5D, 0x9D, 0xA4, 0x0B, 0x4C,
0x2B, 0xD9, 0xB2, 0x18, 0xF5, 0xB5, 0x9F, 0x4B
};
static const unsigned char TA35_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA36_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53,
0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20,
0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79,
0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x32,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA36_RSA_N[] = {
0xD7, 0xC7, 0x5E, 0xF7, 0xC1, 0x07, 0xD4, 0x77, 0xFB, 0x43, 0x21, 0xF4,
0xF4, 0xF5, 0x69, 0xE4, 0xEE, 0x32, 0x01, 0xDB, 0xA3, 0x86, 0x1F, 0xE4,
0x59, 0x0D, 0xBA, 0xE7, 0x75, 0x83, 0x52, 0xEB, 0xEA, 0x1C, 0x61, 0x15,
0x48, 0xBB, 0x1D, 0x07, 0xCA, 0x8C, 0xAE, 0xB0, 0xDC, 0x96, 0x9D, 0xEA,
0xC3, 0x60, 0x92, 0x86, 0x82, 0x28, 0x73, 0x9C, 0x56, 0x06, 0xFF, 0x4B,
0x64, 0xF0, 0x0C, 0x2A, 0x37, 0x49, 0xB5, 0xE5, 0xCF, 0x0C, 0x7C, 0xEE,
0xF1, 0x4A, 0xBB, 0x73, 0x30, 0x65, 0xF3, 0xD5, 0x2F, 0x83, 0xB6, 0x7E,
0xE3, 0xE7, 0xF5, 0x9E, 0xAB, 0x60, 0xF9, 0xD3, 0xF1, 0x9D, 0x92, 0x74,
0x8A, 0xE4, 0x1C, 0x96, 0xAC, 0x5B, 0x80, 0xE9, 0xB5, 0xF4, 0x31, 0x87,
0xA3, 0x51, 0xFC, 0xC7, 0x7E, 0xA1, 0x6F, 0x8E, 0x53, 0x77, 0xD4, 0x97,
0xC1, 0x55, 0x33, 0x92, 0x3E, 0x18, 0x2F, 0x75, 0xD4, 0xAD, 0x86, 0x49,
0xCB, 0x95, 0xAF, 0x54, 0x06, 0x6C, 0xD8, 0x06, 0x13, 0x8D, 0x5B, 0xFF,
0xE1, 0x26, 0x19, 0x59, 0xC0, 0x24, 0xBA, 0x81, 0x71, 0x79, 0x90, 0x44,
0x50, 0x68, 0x24, 0x94, 0x5F, 0xB8, 0xB3, 0x11, 0xF1, 0x29, 0x41, 0x61,
0xA3, 0x41, 0xCB, 0x23, 0x36, 0xD5, 0xC1, 0xF1, 0x32, 0x50, 0x10, 0x4E,
0x7F, 0xF4, 0x86, 0x93, 0xEC, 0x84, 0xD3, 0x8E, 0xBC, 0x4B, 0xBF, 0x5C,
0x01, 0x4E, 0x07, 0x3D, 0xDC, 0x14, 0x8A, 0x94, 0x0A, 0xA4, 0xEA, 0x73,
0xFB, 0x0B, 0x51, 0xE8, 0x13, 0x07, 0x18, 0xFA, 0x0E, 0xF1, 0x2B, 0xD1,
0x54, 0x15, 0x7D, 0x3C, 0xE1, 0xF7, 0xB4, 0x19, 0x42, 0x67, 0x62, 0x5E,
0x77, 0xE0, 0xA2, 0x55, 0xEC, 0xB6, 0xD9, 0x69, 0x17, 0xD5, 0x3A, 0xAF,
0x44, 0xED, 0x4A, 0xC5, 0x9E, 0xE4, 0x7A, 0x27, 0x7C, 0xE5, 0x75, 0xD7,
0xAA, 0xCB, 0x25, 0xE7, 0xDF, 0x6B, 0x0A, 0xDB, 0x0F, 0x4D, 0x93, 0x4E,
0xA8, 0xA0, 0xCD, 0x7B, 0x2E, 0xF2, 0x59, 0x01, 0x6A, 0xB7, 0x0D, 0xB8,
0x07, 0x81, 0x7E, 0x8B, 0x38, 0x1B, 0x38, 0xE6, 0x0A, 0x57, 0x99, 0x3D,
0xEE, 0x21, 0xE8, 0xA3, 0xF5, 0x0C, 0x16, 0xDD, 0x8B, 0xEC, 0x34, 0x8E,
0x9C, 0x2A, 0x1C, 0x00, 0x15, 0x17, 0x8D, 0x68, 0x83, 0xD2, 0x70, 0x9F,
0x18, 0x08, 0xCD, 0x11, 0x68, 0xD5, 0xC9, 0x6B, 0x52, 0xCD, 0xC4, 0x46,
0x8F, 0xDC, 0xB5, 0xF3, 0xD8, 0x57, 0x73, 0x1E, 0xE9, 0x94, 0x39, 0x04,
0xBF, 0xD3, 0xDE, 0x38, 0xDE, 0xB4, 0x53, 0xEC, 0x69, 0x1C, 0xA2, 0x7E,
0xC4, 0x8F, 0xE4, 0x1B, 0x70, 0xAD, 0xF2, 0xA2, 0xF9, 0xFB, 0xF7, 0x16,
0x64, 0x66, 0x69, 0x9F, 0x49, 0x51, 0xA2, 0xE2, 0x15, 0x18, 0x67, 0x06,
0x4A, 0x7F, 0xD5, 0x6C, 0xB5, 0x4D, 0xB3, 0x33, 0xE0, 0x61, 0xEB, 0x5D,
0xBE, 0xE9, 0x98, 0x0F, 0x32, 0xD7, 0x1D, 0x4B, 0x3C, 0x2E, 0x5A, 0x01,
0x52, 0x91, 0x09, 0xF2, 0xDF, 0xEA, 0x8D, 0xD8, 0x06, 0x40, 0x63, 0xAA,
0x11, 0xE4, 0xFE, 0xC3, 0x37, 0x9E, 0x14, 0x52, 0x3F, 0xF4, 0xE2, 0xCC,
0xF2, 0x61, 0x93, 0xD1, 0xFD, 0x67, 0x6B, 0xD7, 0x52, 0xAE, 0xBF, 0x68,
0xAB, 0x40, 0x43, 0xA0, 0x57, 0x35, 0x53, 0x78, 0xF0, 0x53, 0xF8, 0x61,
0x42, 0x07, 0x64, 0xC6, 0xD7, 0x6F, 0x9B, 0x4C, 0x38, 0x0D, 0x63, 0xAC,
0x62, 0xAF, 0x36, 0x8B, 0xA2, 0x73, 0x0A, 0x0D, 0xF5, 0x21, 0xBD, 0x74,
0xAA, 0x4D, 0xEA, 0x72, 0x03, 0x49, 0xDB, 0xC7, 0x5F, 0x1D, 0x62, 0x63,
0xC7, 0xFD, 0xDD, 0x91, 0xEC, 0x33, 0xEE, 0xF5, 0x6D, 0xB4, 0x6E, 0x30,
0x68, 0xDE, 0xC8, 0xD6, 0x26, 0xB0, 0x75, 0x5E, 0x7B, 0xB4, 0x07, 0x20,
0x98, 0xA1, 0x76, 0x32, 0xB8, 0x4D, 0x6C, 0x4F
};
static const unsigned char TA36_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA37_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4E, 0x4F, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x14, 0x42, 0x75, 0x79, 0x70, 0x61, 0x73, 0x73, 0x20, 0x41, 0x53,
0x2D, 0x39, 0x38, 0x33, 0x31, 0x36, 0x33, 0x33, 0x32, 0x37, 0x31, 0x20,
0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x42, 0x75, 0x79,
0x70, 0x61, 0x73, 0x73, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA37_RSA_N[] = {
0xA5, 0xDA, 0x0A, 0x95, 0x16, 0x50, 0xE3, 0x95, 0xF2, 0x5E, 0x9D, 0x76,
0x31, 0x06, 0x32, 0x7A, 0x9B, 0xF1, 0x10, 0x76, 0xB8, 0x00, 0x9A, 0xB5,
0x52, 0x36, 0xCD, 0x24, 0x47, 0xB0, 0x9F, 0x18, 0x64, 0xBC, 0x9A, 0xF6,
0xFA, 0xD5, 0x79, 0xD8, 0x90, 0x62, 0x4C, 0x22, 0x2F, 0xDE, 0x38, 0x3D,
0xD6, 0xE0, 0xA8, 0xE9, 0x1C, 0x2C, 0xDB, 0x78, 0x11, 0xE9, 0x8E, 0x68,
0x51, 0x15, 0x72, 0xC7, 0xF3, 0x33, 0x87, 0xE4, 0xA0, 0x5D, 0x0B, 0x5C,
0xE0, 0x57, 0x07, 0x2A, 0x30, 0xF5, 0xCD, 0xC4, 0x37, 0x77, 0x28, 0x4D,
0x18, 0x91, 0xE6, 0xBF, 0xD5, 0x52, 0xFD, 0x71, 0x2D, 0x70, 0x3E, 0xE7,
0xC6, 0xC4, 0x8A, 0xE3, 0xF0, 0x28, 0x0B, 0xF4, 0x76, 0x98, 0xA1, 0x8B,
0x87, 0x55, 0xB2, 0x3A, 0x13, 0xFC, 0xB7, 0x3E, 0x27, 0x37, 0x8E, 0x22,
0xE3, 0xA8, 0x4F, 0x2A, 0xEF, 0x60, 0xBB, 0x3D, 0xB7, 0x39, 0xC3, 0x0E,
0x01, 0x47, 0x99, 0x5D, 0x12, 0x4F, 0xDB, 0x43, 0xFA, 0x57, 0xA1, 0xED,
0xF9, 0x9D, 0xBE, 0x11, 0x47, 0x26, 0x5B, 0x13, 0x98, 0xAB, 0x5D, 0x16,
0x8A, 0xB0, 0x37, 0x1C, 0x57, 0x9D, 0x45, 0xFF, 0x88, 0x96, 0x36, 0xBF,
0xBB, 0xCA, 0x07, 0x7B, 0x6F, 0x87, 0x63, 0xD7, 0xD0, 0x32, 0x6A, 0xD6,
0x5D, 0x6C, 0x0C, 0xF1, 0xB3, 0x6E, 0x39, 0xE2, 0x6B, 0x31, 0x2E, 0x39,
0x00, 0x27, 0x14, 0xDE, 0x38, 0xC0, 0xEC, 0x19, 0x66, 0x86, 0x12, 0xE8,
0x9D, 0x72, 0x16, 0x13, 0x64, 0x52, 0xC7, 0xA9, 0x37, 0x1C, 0xFD, 0x82,
0x30, 0xED, 0x84, 0x18, 0x1D, 0xF4, 0xAE, 0x5C, 0xFF, 0x70, 0x13, 0x00,
0xEB, 0xB1, 0xF5, 0x33, 0x7A, 0x4B, 0xD6, 0x55, 0xF8, 0x05, 0x8D, 0x4B,
0x69, 0xB0, 0xF5, 0xB3, 0x28, 0x36, 0x5C, 0x14, 0xC4, 0x51, 0x73, 0x4D,
0x6B, 0x0B, 0xF1, 0x34, 0x07, 0xDB, 0x17, 0x39, 0xD7, 0xDC, 0x28, 0x7B,
0x6B, 0xF5, 0x9F, 0xF3, 0x2E, 0xC1, 0x4F, 0x17, 0x2A, 0x10, 0xF3, 0xCC,
0xCA, 0xE8, 0xEB, 0xFD, 0x6B, 0xAB, 0x2E, 0x9A, 0x9F, 0x2D, 0x82, 0x6E,
0x04, 0xD4, 0x52, 0x01, 0x93, 0x2D, 0x3D, 0x86, 0xFC, 0x7E, 0xFC, 0xDF,
0xEF, 0x42, 0x1D, 0xA6, 0x6B, 0xEF, 0xB9, 0x20, 0xC6, 0xF7, 0xBD, 0xA0,
0xA7, 0x95, 0xFD, 0xA7, 0xE6, 0x89, 0x24, 0xD8, 0xCC, 0x8C, 0x34, 0x6C,
0xE2, 0x23, 0x2F, 0xD9, 0x12, 0x1A, 0x21, 0xB9, 0x55, 0x91, 0x6F, 0x0B,
0x91, 0x79, 0x19, 0x0C, 0xAD, 0x40, 0x88, 0x0B, 0x70, 0xE2, 0x7A, 0xD2,
0x0E, 0xD8, 0x68, 0x48, 0xBB, 0x82, 0x13, 0x39, 0x10, 0x58, 0xE9, 0xD8,
0x2A, 0x07, 0xC6, 0x12, 0xDB, 0x58, 0xDB, 0xD2, 0x3B, 0x55, 0x10, 0x47,
0x05, 0x15, 0x67, 0x62, 0x7E, 0x18, 0x63, 0xA6, 0x46, 0x3F, 0x09, 0x0E,
0x54, 0x32, 0x5E, 0xBF, 0x0D, 0x62, 0x7A, 0x27, 0xEF, 0x80, 0xE8, 0xDB,
0xD9, 0x4B, 0x06, 0x5A, 0x37, 0x5A, 0x25, 0xD0, 0x08, 0x12, 0x77, 0xD4,
0x6F, 0x09, 0x50, 0x97, 0x3D, 0xC8, 0x1D, 0xC3, 0xDF, 0x8C, 0x45, 0x30,
0x56, 0xC6, 0xD3, 0x64, 0xAB, 0x66, 0xF3, 0xC0, 0x5E, 0x96, 0x9C, 0xC3,
0xC4, 0xEF, 0xC3, 0x7C, 0x6B, 0x8B, 0x3A, 0x79, 0x7F, 0xB3, 0x49, 0xCF,
0x3D, 0xE2, 0x89, 0x9F, 0xA0, 0x30, 0x4B, 0x85, 0xB9, 0x9C, 0x94, 0x24,
0x79, 0x8F, 0x7D, 0x6B, 0xA9, 0x45, 0x68, 0x0F, 0x2B, 0xD0, 0xF1, 0xDA,
0x1C, 0xCB, 0x69, 0xB8, 0xCA, 0x49, 0x62, 0x6D, 0xC8, 0xD0, 0x63, 0x62,
0xDD, 0x60, 0x0F, 0x58, 0xAA, 0x8F, 0xA1, 0xBC, 0x05, 0xA5, 0x66, 0xA2,
0xCF, 0x1B, 0x76, 0xB2, 0x84, 0x64, 0xB1, 0x4C, 0x39, 0x52, 0xC0, 0x30,
0xBA, 0xF0, 0x8C, 0x4B, 0x02, 0xB0, 0xB6, 0xB7
};
static const unsigned char TA37_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA38_DN[] = {
0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62,
0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16,
0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72,
0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25,
0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54,
0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61,
0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20,
0x33
};
static const unsigned char TA38_RSA_N[] = {
0xBD, 0x75, 0x93, 0xF0, 0x62, 0x22, 0x6F, 0x24, 0xAE, 0xE0, 0x7A, 0x76,
0xAC, 0x7D, 0xBD, 0xD9, 0x24, 0xD5, 0xB8, 0xB7, 0xFC, 0xCD, 0xF0, 0x42,
0xE0, 0xEB, 0x78, 0x88, 0x56, 0x5E, 0x9B, 0x9A, 0x54, 0x1D, 0x4D, 0x0C,
0x8A, 0xF6, 0xD3, 0xCF, 0x70, 0xF4, 0x52, 0xB5, 0xD8, 0x93, 0x04, 0xE3,
0x46, 0x86, 0x71, 0x41, 0x4A, 0x2B, 0xF0, 0x2A, 0x2C, 0x55, 0x03, 0xD6,
0x48, 0xC3, 0xE0, 0x39, 0x38, 0xED, 0xF2, 0x5C, 0x3C, 0x3F, 0x44, 0xBC,
0x93, 0x3D, 0x61, 0xAB, 0x4E, 0xCD, 0x0D, 0xBE, 0xF0, 0x20, 0x27, 0x58,
0x0E, 0x44, 0x7F, 0x04, 0x1A, 0x87, 0xA5, 0xD7, 0x96, 0x14, 0x36, 0x90,
0xD0, 0x49, 0x7B, 0xA1, 0x75, 0xFB, 0x1A, 0x6B, 0x73, 0xB1, 0xF8, 0xCE,
0xA9, 0x09, 0x2C, 0xF2, 0x53, 0xD5, 0xC3, 0x14, 0x44, 0xB8, 0x86, 0xA5,
0xF6, 0x8B, 0x2B, 0x39, 0xDA, 0xA3, 0x33, 0x54, 0xD9, 0xFA, 0x72, 0x1A,
0xF7, 0x22, 0x15, 0x1C, 0x88, 0x91, 0x6B, 0x7F, 0x66, 0xE5, 0xC3, 0x6A,
0x80, 0xB0, 0x24, 0xF3, 0xDF, 0x86, 0x45, 0x88, 0xFD, 0x19, 0x7F, 0x75,
0x87, 0x1F, 0x1F, 0xB1, 0x1B, 0x0A, 0x73, 0x24, 0x5B, 0xB9, 0x65, 0xE0,
0x2C, 0x54, 0xC8, 0x60, 0xD3, 0x66, 0x17, 0x3F, 0xE1, 0xCC, 0x54, 0x33,
0x73, 0x91, 0x02, 0x3A, 0xA6, 0x7F, 0x7B, 0x76, 0x39, 0xA2, 0x1F, 0x96,
0xB6, 0x38, 0xAE, 0xB5, 0xC8, 0x93, 0x74, 0x1D, 0x9E, 0xB9, 0xB4, 0xE5,
0x60, 0x9D, 0x2F, 0x56, 0xD1, 0xE0, 0xEB, 0x5E, 0x5B, 0x4C, 0x12, 0x70,
0x0C, 0x6C, 0x44, 0x20, 0xAB, 0x11, 0xD8, 0xF4, 0x19, 0xF6, 0xD2, 0x9C,
0x52, 0x37, 0xE7, 0xFA, 0xB6, 0xC2, 0x31, 0x3B, 0x4A, 0xD4, 0x14, 0x99,
0xAD, 0xC7, 0x1A, 0xF5, 0x5D, 0x5F, 0xFA, 0x07, 0xB8, 0x7C, 0x0D, 0x1F,
0xD6, 0x83, 0x1E, 0xB3
};
static const unsigned char TA38_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA39_DN[] = {
0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D,
0x62, 0x48, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x1E, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41,
0x20, 0x32, 0x20, 0x32, 0x30, 0x30, 0x39
};
static const unsigned char TA39_RSA_N[] = {
0xD3, 0xB2, 0x4A, 0xCF, 0x7A, 0x47, 0xEF, 0x75, 0x9B, 0x23, 0xFA, 0x3A,
0x2F, 0xD6, 0x50, 0x45, 0x89, 0x35, 0x3A, 0xC6, 0x6B, 0xDB, 0xFE, 0xDB,
0x00, 0x68, 0xA8, 0xE0, 0x03, 0x11, 0x1D, 0x37, 0x50, 0x08, 0x9F, 0x4D,
0x4A, 0x68, 0x94, 0x35, 0xB3, 0x53, 0xD1, 0x94, 0x63, 0xA7, 0x20, 0x56,
0xAF, 0xDE, 0x51, 0x78, 0xEC, 0x2A, 0x3D, 0xF3, 0x48, 0x48, 0x50, 0x3E,
0x0A, 0xDF, 0x46, 0x55, 0x8B, 0x27, 0x6D, 0xC3, 0x10, 0x4D, 0x0D, 0x91,
0x52, 0x43, 0xD8, 0x87, 0xE0, 0x5D, 0x4E, 0x36, 0xB5, 0x21, 0xCA, 0x5F,
0x39, 0x40, 0x04, 0x5F, 0x5B, 0x7E, 0xCC, 0xA3, 0xC6, 0x2B, 0xA9, 0x40,
0x1E, 0xD9, 0x36, 0x84, 0xD6, 0x48, 0xF3, 0x92, 0x1E, 0x34, 0x46, 0x20,
0x24, 0xC1, 0xA4, 0x51, 0x8E, 0x4A, 0x1A, 0xEF, 0x50, 0x3F, 0x69, 0x5D,
0x19, 0x7F, 0x45, 0xC3, 0xC7, 0x01, 0x8F, 0x51, 0xC9, 0x23, 0xE8, 0x72,
0xAE, 0xB4, 0xBC, 0x56, 0x09, 0x7F, 0x12, 0xCB, 0x1C, 0xB1, 0xAF, 0x29,
0x90, 0x0A, 0xC9, 0x55, 0xCC, 0x0F, 0xD3, 0xB4, 0x1A, 0xED, 0x47, 0x35,
0x5A, 0x4A, 0xED, 0x9C, 0x73, 0x04, 0x21, 0xD0, 0xAA, 0xBD, 0x0C, 0x13,
0xB5, 0x00, 0xCA, 0x26, 0x6C, 0xC4, 0x6B, 0x0C, 0x94, 0x5A, 0x95, 0x94,
0xDA, 0x50, 0x9A, 0xF1, 0xFF, 0xA5, 0x2B, 0x66, 0x31, 0xA4, 0xC9, 0x38,
0xA0, 0xDF, 0x1D, 0x1F, 0xB8, 0x09, 0x2E, 0xF3, 0xA7, 0xE8, 0x67, 0x52,
0xAB, 0x95, 0x1F, 0xE0, 0x46, 0x3E, 0xD8, 0xA4, 0xC3, 0xCA, 0x5A, 0xC5,
0x31, 0x80, 0xE8, 0x48, 0x9A, 0x9F, 0x94, 0x69, 0xFE, 0x19, 0xDD, 0xD8,
0x73, 0x7C, 0x81, 0xCA, 0x96, 0xDE, 0x8E, 0xED, 0xB3, 0x32, 0x05, 0x65,
0x84, 0x34, 0xE6, 0xE6, 0xFD, 0x57, 0x10, 0xB5, 0x5F, 0x76, 0xBF, 0x2F,
0xB0, 0x10, 0x0D, 0xC5
};
static const unsigned char TA39_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA40_DN[] = {
0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D,
0x62, 0x48, 0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x21, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20, 0x33, 0x20, 0x43, 0x41,
0x20, 0x32, 0x20, 0x45, 0x56, 0x20, 0x32, 0x30, 0x30, 0x39
};
static const unsigned char TA40_RSA_N[] = {
0x99, 0xF1, 0x84, 0x34, 0x70, 0xBA, 0x2F, 0xB7, 0x30, 0xA0, 0x8E, 0xBD,
0x7C, 0x04, 0xCF, 0xBE, 0x62, 0xBC, 0x99, 0xFD, 0x82, 0x97, 0xD2, 0x7A,
0x0A, 0x67, 0x96, 0x38, 0x09, 0xF6, 0x10, 0x4E, 0x95, 0x22, 0x73, 0x99,
0x8D, 0xDA, 0x15, 0x2D, 0xE7, 0x05, 0xFC, 0x19, 0x73, 0x22, 0xB7, 0x8E,
0x98, 0x00, 0xBC, 0x3C, 0x3D, 0xAC, 0xA1, 0x6C, 0xFB, 0xD6, 0x79, 0x25,
0x4B, 0xAD, 0xF0, 0xCC, 0x64, 0xDA, 0x88, 0x3E, 0x29, 0xB8, 0x0F, 0x09,
0xD3, 0x34, 0xDD, 0x33, 0xF5, 0x62, 0xD1, 0xE1, 0xCD, 0x19, 0xE9, 0xEE,
0x18, 0x4F, 0x4C, 0x58, 0xAE, 0xE2, 0x1E, 0xD6, 0x0C, 0x5B, 0x15, 0x5A,
0xD8, 0x3A, 0xB8, 0xC4, 0x18, 0x64, 0x1E, 0xE3, 0x33, 0xB2, 0xB5, 0x89,
0x77, 0x4E, 0x0C, 0xBF, 0xD9, 0x94, 0x6B, 0x13, 0x97, 0x6F, 0x12, 0xA3,
0xFE, 0x99, 0xA9, 0x04, 0xCC, 0x15, 0xEC, 0x60, 0x68, 0x36, 0xED, 0x08,
0x7B, 0xB7, 0xF5, 0xBF, 0x93, 0xED, 0x66, 0x31, 0x83, 0x8C, 0xC6, 0x71,
0x34, 0x87, 0x4E, 0x17, 0xEA, 0xAF, 0x8B, 0x91, 0x8D, 0x1C, 0x56, 0x41,
0xAE, 0x22, 0x37, 0x5E, 0x37, 0xF2, 0x1D, 0xD9, 0xD1, 0x2D, 0x0D, 0x2F,
0x69, 0x51, 0xA7, 0xBE, 0x66, 0xA6, 0x8A, 0x3A, 0x2A, 0xBD, 0xC7, 0x1A,
0xB1, 0xE1, 0x14, 0xF0, 0xBE, 0x3A, 0x1D, 0xB9, 0xCF, 0x5B, 0xB1, 0x6A,
0xFE, 0xB4, 0xB1, 0x46, 0x20, 0xA2, 0xFB, 0x1E, 0x3B, 0x70, 0xEF, 0x93,
0x98, 0x7D, 0x8C, 0x73, 0x96, 0xF2, 0xC5, 0xEF, 0x85, 0x70, 0xAD, 0x29,
0x26, 0xFC, 0x1E, 0x04, 0x3E, 0x1C, 0xA0, 0xD8, 0x0F, 0xCB, 0x52, 0x83,
0x62, 0x7C, 0xEE, 0x8B, 0x53, 0x95, 0x90, 0xA9, 0x57, 0xA2, 0xEA, 0x61,
0x05, 0xD8, 0xF9, 0x4D, 0xC4, 0x27, 0xFA, 0x6E, 0xAD, 0xED, 0xF9, 0xD7,
0x51, 0xF7, 0x6B, 0xA5
};
static const unsigned char TA40_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA41_DN[] = {
0x30, 0x52, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x53, 0x4B, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07,
0x13, 0x0A, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6C, 0x61, 0x76, 0x61,
0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x44,
0x69, 0x73, 0x69, 0x67, 0x20, 0x61, 0x2E, 0x73, 0x2E, 0x31, 0x19, 0x30,
0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x41, 0x20, 0x44,
0x69, 0x73, 0x69, 0x67, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x32
};
static const unsigned char TA41_RSA_N[] = {
0xA2, 0xA3, 0xC4, 0x00, 0x09, 0xD6, 0x85, 0x5D, 0x2D, 0x6D, 0x14, 0xF6,
0xC2, 0xC3, 0x73, 0x9E, 0x35, 0xC2, 0x71, 0x55, 0x7E, 0x81, 0xFB, 0xAB,
0x46, 0x50, 0xE0, 0xC1, 0x7C, 0x49, 0x78, 0xE6, 0xAB, 0x79, 0x58, 0x3C,
0xDA, 0xFF, 0x7C, 0x1C, 0x9F, 0xD8, 0x97, 0x02, 0x78, 0x3E, 0x6B, 0x41,
0x04, 0xE9, 0x41, 0xBD, 0xBE, 0x03, 0x2C, 0x45, 0xF6, 0x2F, 0x64, 0xD4,
0xAB, 0x5D, 0xA3, 0x47, 0x3D, 0x64, 0x9B, 0xE9, 0x68, 0x9A, 0xC6, 0xCC,
0x1B, 0x3F, 0xBA, 0xBE, 0xB2, 0x8B, 0x34, 0x02, 0x2E, 0x98, 0x55, 0x19,
0xFC, 0x8C, 0x6F, 0xAA, 0x5F, 0xDA, 0x4C, 0xCE, 0x4D, 0x03, 0x21, 0xA3,
0xD8, 0xD2, 0x34, 0x93, 0x56, 0x96, 0xCB, 0x4C, 0x0C, 0x00, 0x16, 0x3C,
0x5F, 0x1A, 0xCD, 0xC8, 0xC7, 0x6C, 0xA6, 0xAD, 0xD3, 0x31, 0xA7, 0xBC,
0xE8, 0xE5, 0xE1, 0x66, 0xD6, 0xD2, 0xFB, 0x03, 0xB4, 0x41, 0x65, 0xC9,
0x10, 0xAE, 0x0E, 0x05, 0x63, 0xC6, 0x80, 0x6A, 0x69, 0x30, 0xFD, 0xD2,
0xEE, 0x90, 0xEF, 0x0D, 0x27, 0xDF, 0x9F, 0x95, 0x73, 0xF4, 0xE1, 0x25,
0xDA, 0x6C, 0x16, 0xDE, 0x41, 0x38, 0x34, 0xEA, 0x8B, 0xFC, 0xD1, 0xE8,
0x04, 0x14, 0x61, 0x2D, 0x41, 0x7E, 0xAC, 0xC7, 0x77, 0x4E, 0xCB, 0x51,
0x54, 0xFB, 0x5E, 0x92, 0x18, 0x1B, 0x04, 0x5A, 0x68, 0xC6, 0xC9, 0xC4,
0xFA, 0xB7, 0x13, 0xA0, 0x98, 0xB7, 0x11, 0x2B, 0xB7, 0xD6, 0x57, 0xCC,
0x7C, 0x9E, 0x17, 0xD1, 0xCB, 0x25, 0xFE, 0x86, 0x4E, 0x24, 0x2E, 0x56,
0x0C, 0x78, 0x4D, 0x9E, 0x01, 0x12, 0xA6, 0x2B, 0xA7, 0x01, 0x65, 0x6E,
0x7C, 0x62, 0x1D, 0x84, 0x84, 0xDF, 0xEA, 0xC0, 0x6B, 0xB5, 0xA5, 0x2A,
0x95, 0x83, 0xC3, 0x53, 0x11, 0x0C, 0x73, 0x1D, 0x0B, 0xB2, 0x46, 0x90,
0xD1, 0x42, 0x3A, 0xCE, 0x40, 0x6E, 0x95, 0xAD, 0xFF, 0xC6, 0x94, 0xAD,
0x6E, 0x97, 0x84, 0x8E, 0x7D, 0x6F, 0x9E, 0x8A, 0x80, 0x0D, 0x49, 0x6D,
0x73, 0xE2, 0x7B, 0x92, 0x1E, 0xC3, 0xF3, 0xC1, 0xF3, 0xEB, 0x2E, 0x05,
0x6F, 0xD9, 0x1B, 0xCF, 0x37, 0x76, 0x04, 0xC8, 0xB4, 0x5A, 0xE4, 0x17,
0xA7, 0xCB, 0xDD, 0x76, 0x1F, 0xD0, 0x19, 0x76, 0xE8, 0x2C, 0x05, 0xB3,
0xD6, 0x9C, 0x34, 0xD8, 0x96, 0xDC, 0x61, 0x87, 0x91, 0x05, 0xE4, 0x44,
0x08, 0x33, 0xC1, 0xDA, 0xB9, 0x08, 0x65, 0xD4, 0xAE, 0xB2, 0x36, 0x0D,
0xEB, 0xBA, 0x38, 0xBA, 0x0C, 0xE5, 0x9B, 0x9E, 0xEB, 0x8D, 0x66, 0xDD,
0x99, 0xCF, 0xD6, 0x89, 0x41, 0xF6, 0x04, 0x92, 0x8A, 0x29, 0x29, 0x6D,
0x6B, 0x3A, 0x1C, 0xE7, 0x75, 0x7D, 0x02, 0x71, 0x0E, 0xF3, 0xC0, 0xE7,
0xBD, 0xCB, 0x19, 0xDD, 0x9D, 0x60, 0xB2, 0xC2, 0x66, 0x60, 0xB6, 0xB1,
0x04, 0xEE, 0xC9, 0xE6, 0x86, 0xB9, 0x9A, 0x66, 0x40, 0xA8, 0xE7, 0x11,
0xED, 0x81, 0x45, 0x03, 0x8B, 0xF6, 0x67, 0x59, 0xE8, 0xC1, 0x06, 0x11,
0xBD, 0xDD, 0xCF, 0x80, 0x02, 0x4F, 0x65, 0x40, 0x78, 0x5C, 0x47, 0x50,
0xC8, 0x9B, 0xE6, 0x1F, 0x81, 0x7B, 0xE4, 0x44, 0xA8, 0x5B, 0x85, 0x9A,
0xE2, 0xDE, 0x5A, 0xD5, 0xC7, 0xF9, 0x3A, 0x44, 0x66, 0x4B, 0xE4, 0x32,
0x54, 0x7C, 0xE4, 0x6C, 0x9C, 0xB3, 0x0E, 0x3D, 0x17, 0xA2, 0xB2, 0x34,
0x12, 0xD6, 0x7E, 0xB2, 0xA8, 0x49, 0xBB, 0xD1, 0x7A, 0x28, 0x40, 0xBE,
0xA2, 0x16, 0x1F, 0xDF, 0xE4, 0x37, 0x1F, 0x11, 0x73, 0xFB, 0x90, 0x0A,
0x65, 0x43, 0xA2, 0x0D, 0x7C, 0xF8, 0x06, 0x01, 0x55, 0x33, 0x7D, 0xB0,
0x0D, 0xB8, 0xF4, 0xF5, 0xAE, 0xA5, 0x42, 0x57, 0x7C, 0x36, 0x11, 0x8C,
0x7B, 0x5E, 0xC4, 0x03, 0x9D, 0x8C, 0x79, 0x9D
};
static const unsigned char TA41_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA42_DN[] = {
0x30, 0x42, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x09, 0x41, 0x43, 0x43, 0x56, 0x52, 0x41, 0x49, 0x5A, 0x31, 0x31, 0x10,
0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x50, 0x4B, 0x49,
0x41, 0x43, 0x43, 0x56, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x0C, 0x04, 0x41, 0x43, 0x43, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06,
0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53
};
static const unsigned char TA42_RSA_N[] = {
0x9B, 0xA9, 0xAB, 0xBF, 0x61, 0x4A, 0x97, 0xAF, 0x2F, 0x97, 0x66, 0x9A,
0x74, 0x5F, 0xD0, 0xD9, 0x96, 0xFD, 0xCF, 0xE2, 0xE4, 0x66, 0xEF, 0x1F,
0x1F, 0x47, 0x33, 0xC2, 0x44, 0xA3, 0xDF, 0x9A, 0xDE, 0x1F, 0xB5, 0x54,
0xDD, 0x15, 0x7C, 0x69, 0x35, 0x11, 0x6F, 0xBB, 0xC8, 0x0C, 0x8E, 0x6A,
0x18, 0x1E, 0xD8, 0x8F, 0xD9, 0x16, 0xBC, 0x10, 0x48, 0x36, 0x5C, 0xF0,
0x63, 0xB3, 0x90, 0x5A, 0x5C, 0x24, 0x37, 0xD7, 0xA3, 0xD6, 0xCB, 0x09,
0x71, 0xB9, 0xF1, 0x01, 0x72, 0x84, 0xB0, 0x7D, 0xDB, 0x4D, 0x80, 0xCD,
0xFC, 0xD3, 0x6F, 0xC9, 0xF8, 0xDA, 0xB6, 0x0E, 0x82, 0xD2, 0x45, 0x85,
0xA8, 0x1B, 0x68, 0xA8, 0x3D, 0xE8, 0xF4, 0x44, 0x6C, 0xBD, 0xA1, 0xC2,
0xCB, 0x03, 0xBE, 0x8C, 0x3E, 0x13, 0x00, 0x84, 0xDF, 0x4A, 0x48, 0xC0,
0xE3, 0x22, 0x0A, 0xE8, 0xE9, 0x37, 0xA7, 0x18, 0x4C, 0xB1, 0x09, 0x0D,
0x23, 0x56, 0x7F, 0x04, 0x4D, 0xD9, 0x17, 0x84, 0x18, 0xA5, 0xC8, 0xDA,
0x40, 0x94, 0x73, 0xEB, 0xCE, 0x0E, 0x57, 0x3C, 0x03, 0x81, 0x3A, 0x9D,
0x0A, 0xA1, 0x57, 0x43, 0x69, 0xAC, 0x57, 0x6D, 0x79, 0x90, 0x78, 0xE5,
0xB5, 0xB4, 0x3B, 0xD8, 0xBC, 0x4C, 0x8D, 0x28, 0xA1, 0xA7, 0xA3, 0xA7,
0xBA, 0x02, 0x4E, 0x25, 0xD1, 0x2A, 0xAE, 0xED, 0xAE, 0x03, 0x22, 0xB8,
0x6B, 0x20, 0x0F, 0x30, 0x28, 0x54, 0x95, 0x7F, 0xE0, 0xEE, 0xCE, 0x0A,
0x66, 0x9D, 0xD1, 0x40, 0x2D, 0x6E, 0x22, 0xAF, 0x9D, 0x1A, 0xC1, 0x05,
0x19, 0xD2, 0x6F, 0xC0, 0xF2, 0x9F, 0xF8, 0x7B, 0xB3, 0x02, 0x42, 0xFB,
0x50, 0xA9, 0x1D, 0x2D, 0x93, 0x0F, 0x23, 0xAB, 0xC6, 0xC1, 0x0F, 0x92,
0xFF, 0xD0, 0xA2, 0x15, 0xF5, 0x53, 0x09, 0x71, 0x1C, 0xFF, 0x45, 0x13,
0x84, 0xE6, 0x26, 0x5E, 0xF8, 0xE0, 0x88, 0x1C, 0x0A, 0xFC, 0x16, 0xB6,
0xA8, 0x73, 0x06, 0xB8, 0xF0, 0x63, 0x84, 0x02, 0xA0, 0xC6, 0x5A, 0xEC,
0xE7, 0x74, 0xDF, 0x70, 0xAE, 0xA3, 0x83, 0x25, 0xEA, 0xD6, 0xC7, 0x97,
0x87, 0x93, 0xA7, 0xC6, 0x8A, 0x8A, 0x33, 0x97, 0x60, 0x37, 0x10, 0x3E,
0x97, 0x3E, 0x6E, 0x29, 0x15, 0xD6, 0xA1, 0x0F, 0xD1, 0x88, 0x2C, 0x12,
0x9F, 0x6F, 0xAA, 0xA4, 0xC6, 0x42, 0xEB, 0x41, 0xA2, 0xE3, 0x95, 0x43,
0xD3, 0x01, 0x85, 0x6D, 0x8E, 0xBB, 0x3B, 0xF3, 0x23, 0x36, 0xC7, 0xFE,
0x3B, 0xE0, 0xA1, 0x25, 0x07, 0x48, 0xAB, 0xC9, 0x89, 0x74, 0xFF, 0x08,
0x8F, 0x80, 0xBF, 0xC0, 0x96, 0x65, 0xF3, 0xEE, 0xEC, 0x4B, 0x68, 0xBD,
0x9D, 0x88, 0xC3, 0x31, 0xB3, 0x40, 0xF1, 0xE8, 0xCF, 0xF6, 0x38, 0xBB,
0x9C, 0xE4, 0xD1, 0x7F, 0xD4, 0xE5, 0x58, 0x9B, 0x7C, 0xFA, 0xD4, 0xF3,
0x0E, 0x9B, 0x75, 0x91, 0xE4, 0xBA, 0x52, 0x2E, 0x19, 0x7E, 0xD1, 0xF5,
0xCD, 0x5A, 0x19, 0xFC, 0xBA, 0x06, 0xF6, 0xFB, 0x52, 0xA8, 0x4B, 0x99,
0x04, 0xDD, 0xF8, 0xF9, 0xB4, 0x8B, 0x50, 0xA3, 0x4E, 0x62, 0x89, 0xF0,
0x87, 0x24, 0xFA, 0x83, 0x42, 0xC1, 0x87, 0xFA, 0xD5, 0x2D, 0x29, 0x2A,
0x5A, 0x71, 0x7A, 0x64, 0x6A, 0xD7, 0x27, 0x60, 0x63, 0x0D, 0xDB, 0xCE,
0x49, 0xF5, 0x8D, 0x1F, 0x90, 0x89, 0x32, 0x17, 0xF8, 0x73, 0x43, 0xB8,
0xD2, 0x5A, 0x93, 0x86, 0x61, 0xD6, 0xE1, 0x75, 0x0A, 0xEA, 0x79, 0x66,
0x76, 0x88, 0x4F, 0x71, 0xEB, 0x04, 0x25, 0xD6, 0x0A, 0x5A, 0x7A, 0x93,
0xE5, 0xB9, 0x4B, 0x17, 0x40, 0x0F, 0xB1, 0xB6, 0xB9, 0xF5, 0xDE, 0x4F,
0xDC, 0xE0, 0xB3, 0xAC, 0x3B, 0x11, 0x70, 0x60, 0x84, 0x4A, 0x43, 0x6E,
0x99, 0x20, 0xC0, 0x29, 0x71, 0x0A, 0xC0, 0x65
};
static const unsigned char TA42_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA43_DN[] = {
0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31,
0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x13, 0x54, 0x57, 0x43, 0x41, 0x20, 0x47, 0x6C, 0x6F,
0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA43_RSA_N[] = {
0xB0, 0x05, 0xDB, 0xC8, 0xEB, 0x8C, 0xC4, 0x6E, 0x8A, 0x21, 0xEF, 0x8E,
0x4D, 0x9C, 0x71, 0x0A, 0x1F, 0x52, 0x70, 0xED, 0x6D, 0x82, 0x9C, 0x97,
0xC5, 0xD7, 0x4C, 0x4E, 0x45, 0x49, 0xCB, 0x40, 0x42, 0xB5, 0x12, 0x34,
0x6C, 0x19, 0xC2, 0x74, 0xA4, 0x31, 0x5F, 0x85, 0x02, 0x97, 0xEC, 0x43,
0x33, 0x0A, 0x53, 0xD2, 0x9C, 0x8C, 0x8E, 0xB7, 0xB8, 0x79, 0xDB, 0x2B,
0xD5, 0x6A, 0xF2, 0x8E, 0x66, 0xC4, 0xEE, 0x2B, 0x01, 0x07, 0x92, 0xD4,
0xB3, 0xD0, 0x02, 0xDF, 0x50, 0xF6, 0x55, 0xAF, 0x66, 0x0E, 0xCB, 0xE0,
0x47, 0x60, 0x2F, 0x2B, 0x32, 0x39, 0x35, 0x52, 0x3A, 0x28, 0x83, 0xF8,
0x7B, 0x16, 0xC6, 0x18, 0xB8, 0x62, 0xD6, 0x47, 0x25, 0x91, 0xCE, 0xF0,
0x19, 0x12, 0x4D, 0xAD, 0x63, 0xF5, 0xD3, 0x3F, 0x75, 0x5F, 0x29, 0xF0,
0xA1, 0x30, 0x1C, 0x2A, 0xA0, 0x98, 0xA6, 0x15, 0xBD, 0xEE, 0xFD, 0x19,
0x36, 0xF0, 0xE2, 0x91, 0x43, 0x8F, 0xFA, 0xCA, 0xD6, 0x10, 0x27, 0x49,
0x4C, 0xEF, 0xDD, 0xC1, 0xF1, 0x85, 0x70, 0x9B, 0xCA, 0xEA, 0xA8, 0x5A,
0x43, 0xFC, 0x6D, 0x86, 0x6F, 0x73, 0xE9, 0x37, 0x45, 0xA9, 0xF0, 0x36,
0xC7, 0xCC, 0x88, 0x75, 0x1E, 0xBB, 0x6C, 0x06, 0xFF, 0x9B, 0x6B, 0x3E,
0x17, 0xEC, 0x61, 0xAA, 0x71, 0x7C, 0xC6, 0x1D, 0xA2, 0xF7, 0x49, 0xE9,
0x15, 0xB5, 0x3C, 0xD6, 0xA1, 0x61, 0xF5, 0x11, 0xF7, 0x05, 0x6F, 0x1D,
0xFD, 0x11, 0xBE, 0xD0, 0x30, 0x07, 0xC2, 0x29, 0xB0, 0x09, 0x4E, 0x26,
0xDC, 0xE3, 0xA2, 0xA8, 0x91, 0x6A, 0x1F, 0xC2, 0x91, 0x45, 0x88, 0x5C,
0xE5, 0x98, 0xB8, 0x71, 0xA5, 0x15, 0x19, 0xC9, 0x7C, 0x75, 0x11, 0xCC,
0x70, 0x74, 0x4F, 0x2D, 0x9B, 0x1D, 0x91, 0x44, 0xFD, 0x56, 0x28, 0xA0,
0xFE, 0xBB, 0x86, 0x6A, 0xC8, 0xFA, 0x5C, 0x0B, 0x58, 0xDC, 0xC6, 0x4B,
0x76, 0xC8, 0xAB, 0x22, 0xD9, 0x73, 0x0F, 0xA5, 0xF4, 0x5A, 0x02, 0x89,
0x3F, 0x4F, 0x9E, 0x22, 0x82, 0xEE, 0xA2, 0x74, 0x53, 0x2A, 0x3D, 0x53,
0x27, 0x69, 0x1D, 0x6C, 0x8E, 0x32, 0x2C, 0x64, 0x00, 0x26, 0x63, 0x61,
0x36, 0x4E, 0xA3, 0x46, 0xB7, 0x3F, 0x7D, 0xB3, 0x2D, 0xAC, 0x6D, 0x90,
0xA2, 0x95, 0xA2, 0xCE, 0xCF, 0xDA, 0x82, 0xE7, 0x07, 0x34, 0x19, 0x96,
0xE9, 0xB8, 0x21, 0xAA, 0x29, 0x7E, 0xA6, 0x38, 0xBE, 0x8E, 0x29, 0x4A,
0x21, 0x66, 0x79, 0x1F, 0xB3, 0xC3, 0xB5, 0x09, 0x67, 0xDE, 0xD6, 0xD4,
0x07, 0x46, 0xF3, 0x2A, 0xDA, 0xE6, 0x22, 0x37, 0x60, 0xCB, 0x81, 0xB6,
0x0F, 0xA0, 0x0F, 0xE9, 0xC8, 0x95, 0x7F, 0xBF, 0x55, 0x91, 0x05, 0x7A,
0xCF, 0x3D, 0x15, 0xC0, 0x6F, 0xDE, 0x09, 0x94, 0x01, 0x83, 0xD7, 0x34,
0x1B, 0xCC, 0x40, 0xA5, 0xF0, 0xB8, 0x9B, 0x67, 0xD5, 0x98, 0x91, 0x3B,
0xA7, 0x84, 0x78, 0x95, 0x26, 0xA4, 0x5A, 0x08, 0xF8, 0x2B, 0x74, 0xB4,
0x00, 0x04, 0x3C, 0xDF, 0xB8, 0x14, 0x8E, 0xE8, 0xDF, 0xA9, 0x8D, 0x6C,
0x67, 0x92, 0x33, 0x1D, 0xC0, 0xB7, 0xD2, 0xEC, 0x92, 0xC8, 0xBE, 0x09,
0xBF, 0x2C, 0x29, 0x05, 0x6F, 0x02, 0x6B, 0x9E, 0xEF, 0xBC, 0xBF, 0x2A,
0xBC, 0x5B, 0xC0, 0x50, 0x8F, 0x41, 0x70, 0x71, 0x87, 0xB2, 0x4D, 0xB7,
0x04, 0xA9, 0x84, 0xA3, 0x32, 0xAF, 0xAE, 0xEE, 0x6B, 0x17, 0x8B, 0xB2,
0xB1, 0xFE, 0x6C, 0xE1, 0x90, 0x8C, 0x88, 0xA8, 0x97, 0x48, 0xCE, 0xC8,
0x4D, 0xCB, 0xF3, 0x06, 0xCF, 0x5F, 0x6A, 0x0A, 0x42, 0xB1, 0x1E, 0x1E,
0x77, 0x2F, 0x8E, 0xA0, 0xE6, 0x92, 0x0E, 0x06, 0xFC, 0x05, 0x22, 0xD2,
0x26, 0xE1, 0x31, 0x51, 0x7D, 0x32, 0xDC, 0x0F
};
static const unsigned char TA43_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA44_DN[] = {
0x30, 0x37, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C,
0x0B, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61,
0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54,
0x65, 0x6C, 0x69, 0x61, 0x53, 0x6F, 0x6E, 0x65, 0x72, 0x61, 0x20, 0x52,
0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x31
};
static const unsigned char TA44_RSA_N[] = {
0xC2, 0xBE, 0xEB, 0x27, 0xF0, 0x21, 0xA3, 0xF3, 0x69, 0x26, 0x55, 0x7E,
0x9D, 0xC5, 0x55, 0x16, 0x91, 0x5C, 0xFD, 0xEF, 0x21, 0xBF, 0x53, 0x80,
0x7A, 0x2D, 0xD2, 0x91, 0x8C, 0x63, 0x31, 0xF0, 0xEC, 0x24, 0xF0, 0xC3,
0xA5, 0xD2, 0x72, 0x7C, 0x10, 0x6D, 0xF4, 0x37, 0xB7, 0xE5, 0xE6, 0x7C,
0x79, 0xEA, 0x8C, 0xB5, 0x82, 0x8B, 0xAE, 0x48, 0xB6, 0xAC, 0x00, 0xDC,
0x65, 0x75, 0xEC, 0x2A, 0x4D, 0x5F, 0xC1, 0x87, 0xF5, 0x20, 0x65, 0x2B,
0x81, 0xA8, 0x47, 0x3E, 0x89, 0x23, 0x95, 0x30, 0x16, 0x90, 0x7F, 0xE8,
0x57, 0x07, 0x48, 0xE7, 0x19, 0xAE, 0xBF, 0x45, 0x67, 0xB1, 0x37, 0x1B,
0x06, 0x2A, 0xFE, 0xDE, 0xF9, 0xAC, 0x7D, 0x83, 0xFB, 0x5E, 0xBA, 0xE4,
0x8F, 0x97, 0x67, 0xBE, 0x4B, 0x8E, 0x8D, 0x64, 0x07, 0x57, 0x38, 0x55,
0x69, 0x34, 0x36, 0x3D, 0x13, 0x48, 0xEF, 0x4F, 0xE2, 0xD3, 0x66, 0x1E,
0xA4, 0xCF, 0x1A, 0xB7, 0x5E, 0x36, 0x33, 0xD4, 0xB4, 0x06, 0xBD, 0x18,
0x01, 0xFD, 0x77, 0x84, 0x50, 0x00, 0x45, 0xF5, 0x8C, 0x5D, 0xE8, 0x23,
0xBC, 0x7E, 0xFE, 0x35, 0xE1, 0xED, 0x50, 0x7B, 0xA9, 0x30, 0x8D, 0x19,
0xD3, 0x09, 0x8E, 0x68, 0x67, 0x5D, 0xBF, 0x3C, 0x97, 0x18, 0x53, 0xBB,
0x29, 0x62, 0xC5, 0xCA, 0x5E, 0x72, 0xC1, 0xC7, 0x96, 0xD4, 0xDB, 0x2D,
0xA0, 0xB4, 0x1F, 0x69, 0x03, 0xEC, 0xEA, 0xE2, 0x50, 0xF1, 0x0C, 0x3C,
0xF0, 0xAC, 0xF3, 0x53, 0x2D, 0xF0, 0x1C, 0xF5, 0xED, 0x6C, 0x39, 0x39,
0x73, 0x80, 0x16, 0xC8, 0x52, 0xB0, 0x23, 0xCD, 0xE0, 0x3E, 0xDC, 0xDD,
0x3C, 0x47, 0xA0, 0xBB, 0x35, 0x8A, 0xE2, 0x98, 0x68, 0x8B, 0xBE, 0xE5,
0xBF, 0x72, 0xEE, 0xD2, 0xFA, 0xA5, 0xED, 0x12, 0xED, 0xFC, 0x98, 0x18,
0xA9, 0x26, 0x76, 0xDC, 0x28, 0x4B, 0x10, 0x20, 0x1C, 0xD3, 0x7F, 0x16,
0x77, 0x2D, 0xED, 0x6F, 0x80, 0xF7, 0x49, 0xBB, 0x53, 0x05, 0xBB, 0x5D,
0x68, 0xC7, 0xD4, 0xC8, 0x75, 0x16, 0x3F, 0x89, 0x5A, 0x8B, 0xF7, 0x17,
0x47, 0xD4, 0x4C, 0xF1, 0xD2, 0x89, 0x79, 0x3E, 0x4D, 0x3D, 0x98, 0xA8,
0x61, 0xDE, 0x3A, 0x1E, 0xD2, 0xF8, 0x5E, 0x03, 0xE0, 0xC1, 0xC9, 0x1C,
0x8C, 0xD3, 0x8D, 0x4D, 0xD3, 0x95, 0x36, 0xB3, 0x37, 0x5F, 0x63, 0x63,
0x9B, 0x33, 0x14, 0xF0, 0x2D, 0x26, 0x6B, 0x53, 0x7C, 0x89, 0x8C, 0x32,
0xC2, 0x6E, 0xEC, 0x3D, 0x21, 0x00, 0x39, 0xC9, 0xA1, 0x68, 0xE2, 0x50,
0x83, 0x2E, 0xB0, 0x3A, 0x2B, 0xF3, 0x36, 0xA0, 0xAC, 0x2F, 0xE4, 0x6F,
0x61, 0xC2, 0x51, 0x09, 0x39, 0x3E, 0x8B, 0x53, 0xB9, 0xBB, 0x67, 0xDA,
0xDC, 0x53, 0xB9, 0x76, 0x59, 0x36, 0x9D, 0x43, 0xE5, 0x20, 0xE0, 0x3D,
0x32, 0x60, 0x85, 0x22, 0x51, 0xB7, 0xC7, 0x33, 0xBB, 0xDD, 0x15, 0x2F,
0xA4, 0x78, 0xA6, 0x07, 0x7B, 0x81, 0x46, 0x36, 0x04, 0x86, 0xDD, 0x79,
0x35, 0xC7, 0x95, 0x2C, 0x3B, 0xB0, 0xA3, 0x17, 0x35, 0xE5, 0x73, 0x1F,
0xB4, 0x5C, 0x59, 0xEF, 0xDA, 0xEA, 0x10, 0x65, 0x7B, 0x7A, 0xD0, 0x7F,
0x9F, 0xB3, 0xB4, 0x2A, 0x37, 0x3B, 0x70, 0x8B, 0x9B, 0x5B, 0xB9, 0x2B,
0xB7, 0xEC, 0xB2, 0x51, 0x12, 0x97, 0x53, 0x29, 0x5A, 0xD4, 0xF0, 0x12,
0x10, 0xDC, 0x4F, 0x02, 0xBB, 0x12, 0x92, 0x2F, 0x62, 0xD4, 0x3F, 0x69,
0x43, 0x7C, 0x0D, 0xD6, 0xFC, 0x58, 0x75, 0x01, 0x88, 0x9D, 0x58, 0x16,
0x4B, 0xDE, 0xBA, 0x90, 0xFF, 0x47, 0x01, 0x89, 0x06, 0x6A, 0xF6, 0x5F,
0xB2, 0x90, 0x6A, 0xB3, 0x02, 0xA6, 0x02, 0x88, 0xBF, 0xB3, 0x47, 0x7E,
0x2A, 0xD9, 0xD5, 0xFA, 0x68, 0x78, 0x35, 0x4D
};
static const unsigned char TA44_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA45_DN[] = {
0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x44, 0x45, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x0C, 0x22, 0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
0x20, 0x45, 0x6E, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x20,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x47, 0x6D, 0x62,
0x48, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x16,
0x54, 0x2D, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x54, 0x72,
0x75, 0x73, 0x74, 0x20, 0x43, 0x65, 0x6E, 0x74, 0x65, 0x72, 0x31, 0x25,
0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x2D, 0x54,
0x65, 0x6C, 0x65, 0x53, 0x65, 0x63, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61,
0x6C, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x6C, 0x61, 0x73, 0x73, 0x20,
0x32
};
static const unsigned char TA45_RSA_N[] = {
0xAA, 0x5F, 0xDA, 0x1B, 0x5F, 0xE8, 0x73, 0x91, 0xE5, 0xDA, 0x5C, 0xF4,
0xA2, 0xE6, 0x47, 0xE5, 0xF3, 0x68, 0x55, 0x60, 0x05, 0x1D, 0x02, 0xA4,
0xB3, 0x9B, 0x59, 0xF3, 0x1E, 0x8A, 0xAF, 0x34, 0xAD, 0xFC, 0x0D, 0xC2,
0xD9, 0x48, 0x19, 0xEE, 0x69, 0x8F, 0xC9, 0x20, 0xFC, 0x21, 0xAA, 0x07,
0x19, 0xED, 0xB0, 0x5C, 0xAC, 0x65, 0xC7, 0x5F, 0xED, 0x02, 0x7C, 0x7B,
0x7C, 0x2D, 0x1B, 0xD6, 0xBA, 0xB9, 0x80, 0xC2, 0x18, 0x82, 0x16, 0x84,
0xFA, 0x66, 0xB0, 0x08, 0xC6, 0x54, 0x23, 0x81, 0xE4, 0xCD, 0xB9, 0x49,
0x3F, 0xF6, 0x4F, 0x6E, 0x37, 0x48, 0x28, 0x38, 0x0F, 0xC5, 0xBE, 0xE7,
0x68, 0x70, 0xFD, 0x39, 0x97, 0x4D, 0xD2, 0xC7, 0x98, 0x91, 0x50, 0xAA,
0xC4, 0x44, 0xB3, 0x23, 0x7D, 0x39, 0x47, 0xE9, 0x52, 0x62, 0xD6, 0x12,
0x93, 0x5E, 0xB7, 0x31, 0x96, 0x42, 0x05, 0xFB, 0x76, 0xA7, 0x1E, 0xA3,
0xF5, 0xC2, 0xFC, 0xE9, 0x7A, 0xC5, 0x6C, 0xA9, 0x71, 0x4F, 0xEA, 0xCB,
0x78, 0xBC, 0x60, 0xAF, 0xC7, 0xDE, 0xF4, 0xD9, 0xCB, 0xBE, 0x7E, 0x33,
0xA5, 0x6E, 0x94, 0x83, 0xF0, 0x34, 0xFA, 0x21, 0xAB, 0xEA, 0x8E, 0x72,
0xA0, 0x3F, 0xA4, 0xDE, 0x30, 0x5B, 0xEF, 0x86, 0x4D, 0x6A, 0x95, 0x5B,
0x43, 0x44, 0xA8, 0x10, 0x15, 0x1C, 0xE5, 0x01, 0x57, 0xC5, 0x98, 0xF1,
0xE6, 0x06, 0x28, 0x91, 0xAA, 0x20, 0xC5, 0xB7, 0x53, 0x26, 0x51, 0x43,
0xB2, 0x0B, 0x11, 0x95, 0x58, 0xE1, 0xC0, 0x0F, 0x76, 0xD9, 0xC0, 0x8D,
0x7C, 0x81, 0xF3, 0x72, 0x70, 0x9E, 0x6F, 0xFE, 0x1A, 0x8E, 0xD9, 0x5F,
0x35, 0xC6, 0xB2, 0x6F, 0x34, 0x7C, 0xBE, 0x48, 0x4F, 0xE2, 0x5A, 0x39,
0xD7, 0xD8, 0x9D, 0x78, 0x9E, 0x9F, 0x86, 0x3E, 0x03, 0x5E, 0x19, 0x8B,
0x44, 0xA2, 0xD5, 0xC7
};
static const unsigned char TA45_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA46_DN[] = {
0x30, 0x3C, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x15, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65,
0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x32, 0x30, 0x31, 0x31, 0x31, 0x0D,
0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x04, 0x41, 0x74, 0x6F,
0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
0x44, 0x45
};
static const unsigned char TA46_RSA_N[] = {
0x95, 0x85, 0x3B, 0x97, 0x6F, 0x2A, 0x3B, 0x2E, 0x3B, 0xCF, 0xA6, 0xF3,
0x29, 0x35, 0xBE, 0xCF, 0x18, 0xAC, 0x3E, 0xAA, 0xD9, 0xF8, 0x4D, 0xA0,
0x3E, 0x1A, 0x47, 0xB9, 0xBC, 0x9A, 0xDF, 0xF2, 0xFE, 0xCC, 0x3E, 0x47,
0xE8, 0x7A, 0x96, 0xC2, 0x24, 0x8E, 0x35, 0xF4, 0xA9, 0x0C, 0xFC, 0x82,
0xFD, 0x6D, 0xC1, 0x72, 0x62, 0x27, 0xBD, 0xEA, 0x6B, 0xEB, 0xE7, 0x8A,
0xCC, 0x54, 0x3E, 0x90, 0x50, 0xCF, 0x80, 0xD4, 0x95, 0xFB, 0xE8, 0xB5,
0x82, 0xD4, 0x14, 0xC5, 0xB6, 0xA9, 0x55, 0x25, 0x57, 0xDB, 0xB1, 0x50,
0xF6, 0xB0, 0x60, 0x64, 0x59, 0x7A, 0x69, 0xCF, 0x03, 0xB7, 0x6F, 0x0D,
0xBE, 0xCA, 0x3E, 0x6F, 0x74, 0x72, 0xEA, 0xAA, 0x30, 0x2A, 0x73, 0x62,
0xBE, 0x49, 0x91, 0x61, 0xC8, 0x11, 0xFE, 0x0E, 0x03, 0x2A, 0xF7, 0x6A,
0x20, 0xDC, 0x02, 0x15, 0x0D, 0x5E, 0x15, 0x6A, 0xFC, 0xE3, 0x82, 0xC1,
0xB5, 0xC5, 0x9D, 0x64, 0x09, 0x6C, 0xA3, 0x59, 0x98, 0x07, 0x27, 0xC7,
0x1B, 0x96, 0x2B, 0x61, 0x74, 0x71, 0x6C, 0x43, 0xF1, 0xF7, 0x35, 0x89,
0x10, 0xE0, 0x9E, 0xEC, 0x55, 0xA1, 0x37, 0x22, 0xA2, 0x87, 0x04, 0x05,
0x2C, 0x47, 0x7D, 0xB4, 0x1C, 0xB9, 0x62, 0x29, 0x66, 0x28, 0xCA, 0xB7,
0xE1, 0x93, 0xF5, 0xA4, 0x94, 0x03, 0x99, 0xB9, 0x70, 0x85, 0xB5, 0xE6,
0x48, 0xEA, 0x8D, 0x50, 0xFC, 0xD9, 0xDE, 0xCC, 0x6F, 0x07, 0x0E, 0xDD,
0x0B, 0x72, 0x9D, 0x80, 0x30, 0x16, 0x07, 0x95, 0x3F, 0x28, 0x0E, 0xFD,
0xC5, 0x75, 0x4F, 0x53, 0xD6, 0x74, 0x9A, 0xB4, 0x24, 0x2E, 0x8E, 0x02,
0x91, 0xCF, 0x76, 0xC5, 0x9B, 0x1E, 0x55, 0x74, 0x9C, 0x78, 0x21, 0xB1,
0xF0, 0x2D, 0xF1, 0x0B, 0x9F, 0xC2, 0xD5, 0x96, 0x18, 0x1F, 0xF0, 0x54,
0x22, 0x7A, 0x8C, 0x07
};
static const unsigned char TA46_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA47_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C,
0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20,
0x47, 0x33
};
static const unsigned char TA47_RSA_N[] = {
0xA0, 0xBE, 0x50, 0x10, 0x8E, 0xE9, 0xF2, 0x6C, 0x40, 0xB4, 0x04, 0x9C,
0x85, 0xB9, 0x31, 0xCA, 0xDC, 0x2D, 0xE4, 0x11, 0xA9, 0x04, 0x3C, 0x1B,
0x55, 0xC1, 0xE7, 0x58, 0x30, 0x1D, 0x24, 0xB4, 0xC3, 0xEF, 0x85, 0xDE,
0x8C, 0x2C, 0xE1, 0xC1, 0x3D, 0xDF, 0x82, 0xE6, 0x4F, 0xAD, 0x47, 0x87,
0x6C, 0xEC, 0x5B, 0x49, 0xC1, 0x4A, 0xD5, 0xBB, 0x8F, 0xEC, 0x87, 0xAC,
0x7F, 0x82, 0x9A, 0x86, 0xEC, 0x3D, 0x03, 0x99, 0x52, 0x01, 0xD2, 0x35,
0x9E, 0xAC, 0xDA, 0xF0, 0x53, 0xC9, 0x66, 0x3C, 0xD4, 0xAC, 0x02, 0x01,
0xDA, 0x24, 0xD3, 0x3B, 0xA8, 0x02, 0x46, 0xAF, 0xA4, 0x1C, 0xE3, 0xF8,
0x73, 0x58, 0x76, 0xB7, 0xF6, 0x0E, 0x90, 0x0D, 0xB5, 0xF0, 0xCF, 0xCC,
0xFA, 0xF9, 0xC6, 0x4C, 0xE5, 0xC3, 0x86, 0x30, 0x0A, 0x8D, 0x17, 0x7E,
0x35, 0xEB, 0xC5, 0xDF, 0xBB, 0x0E, 0x9C, 0xC0, 0x8D, 0x87, 0xE3, 0x88,
0x38, 0x85, 0x67, 0xFA, 0x3E, 0xC7, 0xAB, 0xE0, 0x13, 0x9C, 0x05, 0x18,
0x98, 0xCF, 0x93, 0xF5, 0xB1, 0x92, 0xB4, 0xFC, 0x23, 0xD3, 0xCF, 0xD5,
0xC4, 0x27, 0x49, 0xE0, 0x9E, 0x3C, 0x9B, 0x08, 0xA3, 0x8B, 0x5D, 0x2A,
0x21, 0xE0, 0xFC, 0x39, 0xAA, 0x53, 0xDA, 0x7D, 0x7E, 0xCF, 0x1A, 0x09,
0x53, 0xBC, 0x5D, 0x05, 0x04, 0xCF, 0xA1, 0x4A, 0x8F, 0x8B, 0x76, 0x82,
0x0D, 0xA1, 0xF8, 0xD2, 0xC7, 0x14, 0x77, 0x5B, 0x90, 0x36, 0x07, 0x81,
0x9B, 0x3E, 0x06, 0xFA, 0x52, 0x5E, 0x63, 0xC5, 0xA6, 0x00, 0xFE, 0xA5,
0xE9, 0x52, 0x1B, 0x52, 0xB5, 0x92, 0x39, 0x72, 0x03, 0x09, 0x62, 0xBD,
0xB0, 0x60, 0x16, 0x6E, 0xA6, 0xDD, 0x25, 0xC2, 0x03, 0x66, 0xDD, 0xF3,
0x04, 0xD1, 0x40, 0xE2, 0x4E, 0x8B, 0x86, 0xF4, 0x6F, 0xE5, 0x83, 0xA0,
0x27, 0x84, 0x5E, 0x04, 0xC1, 0xF5, 0x90, 0xBD, 0x30, 0x3D, 0xC4, 0xEF,
0xA8, 0x69, 0xBC, 0x38, 0x9B, 0xA4, 0xA4, 0x96, 0xD1, 0x62, 0xDA, 0x69,
0xC0, 0x01, 0x96, 0xAE, 0xCB, 0xC4, 0x51, 0x34, 0xEA, 0x0C, 0xAA, 0xFF,
0x21, 0x8E, 0x59, 0x8F, 0x4A, 0x5C, 0xE4, 0x61, 0x9A, 0xA7, 0xD2, 0xE9,
0x2A, 0x78, 0x8D, 0x51, 0x3D, 0x3A, 0x15, 0xEE, 0xA2, 0x59, 0x8E, 0xA9,
0x5C, 0xDE, 0xC5, 0xF9, 0x90, 0x22, 0xE5, 0x88, 0x45, 0x71, 0xDD, 0x91,
0x99, 0x6C, 0x7A, 0x9F, 0x3D, 0x3D, 0x98, 0x7C, 0x5E, 0xF6, 0xBE, 0x16,
0x68, 0xA0, 0x5E, 0xAE, 0x0B, 0x23, 0xFC, 0x5A, 0x0F, 0xAA, 0x22, 0x76,
0x2D, 0xC9, 0xA1, 0x10, 0x1D, 0xE4, 0xD3, 0x44, 0x23, 0x90, 0x88, 0x9F,
0xC6, 0x2A, 0xE6, 0xD7, 0xF5, 0x9A, 0xB3, 0x58, 0x1E, 0x2F, 0x30, 0x89,
0x08, 0x1B, 0x54, 0xA2, 0xB5, 0x98, 0x23, 0xEC, 0x08, 0x77, 0x1C, 0x95,
0x5D, 0x61, 0xD1, 0xCB, 0x89, 0x9C, 0x5F, 0xA2, 0x4A, 0x91, 0x9A, 0xEF,
0x21, 0xAA, 0x49, 0x16, 0x08, 0xA8, 0xBD, 0x61, 0x28, 0x31, 0xC9, 0x74,
0xAD, 0x85, 0xF6, 0xD9, 0xC5, 0xB1, 0x8B, 0xD1, 0xE5, 0x10, 0x32, 0x4D,
0x5F, 0x8B, 0x20, 0x3A, 0x3C, 0x49, 0x1F, 0x33, 0x85, 0x59, 0x0D, 0xDB,
0xCB, 0x09, 0x75, 0x43, 0x69, 0x73, 0xFB, 0x6B, 0x71, 0x7D, 0xF0, 0xDF,
0xC4, 0x4C, 0x7D, 0xC6, 0xA3, 0x2E, 0xC8, 0x95, 0x79, 0xCB, 0x73, 0xA2,
0x8E, 0x4E, 0x4D, 0x24, 0xFB, 0x5E, 0xE4, 0x04, 0xBE, 0x72, 0x1B, 0xA6,
0x27, 0x2D, 0x49, 0x5A, 0x99, 0x7A, 0xD7, 0x5C, 0x09, 0x20, 0xB7, 0x7F,
0x94, 0xB9, 0x4F, 0xF1, 0x0D, 0x1C, 0x5E, 0x88, 0x42, 0x1B, 0x11, 0xB7,
0xE7, 0x91, 0xDB, 0x9E, 0x6C, 0xF4, 0x6A, 0xDF, 0x8C, 0x06, 0x98, 0x03,
0xAD, 0xCC, 0x28, 0xEF, 0xA5, 0x47, 0xF3, 0x53
};
static const unsigned char TA47_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA48_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C,
0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20,
0x47, 0x33
};
static const unsigned char TA48_RSA_N[] = {
0xA1, 0xAE, 0x25, 0xB2, 0x01, 0x18, 0xDC, 0x57, 0x88, 0x3F, 0x46, 0xEB,
0xF9, 0xAF, 0xE2, 0xEB, 0x23, 0x71, 0xE2, 0x9A, 0xD1, 0x61, 0x66, 0x21,
0x5F, 0xAA, 0xAF, 0x27, 0x51, 0xE5, 0x6E, 0x1B, 0x16, 0xD4, 0x2D, 0x7D,
0x50, 0xB0, 0x53, 0x77, 0xBD, 0x78, 0x3A, 0x60, 0xE2, 0x64, 0x02, 0x9B,
0x7C, 0x86, 0x9B, 0xD6, 0x1A, 0x8E, 0xAD, 0xFF, 0x1F, 0x15, 0x7F, 0xD5,
0x95, 0x1E, 0x12, 0xCB, 0xE6, 0x14, 0x84, 0x04, 0xC1, 0xDF, 0x36, 0xB3,
0x16, 0x9F, 0x8A, 0xE3, 0xC9, 0xDB, 0x98, 0x34, 0xCE, 0xD8, 0x33, 0x17,
0x28, 0x46, 0xFC, 0xA7, 0xC9, 0xF0, 0xD2, 0xB4, 0xD5, 0x4D, 0x09, 0x72,
0x49, 0xF9, 0xF2, 0x87, 0xE3, 0xA9, 0xDA, 0x7D, 0xA1, 0x7D, 0x6B, 0xB2,
0x3A, 0x25, 0xA9, 0x6D, 0x52, 0x44, 0xAC, 0xF8, 0xBE, 0x6E, 0xFB, 0xDC,
0xA6, 0x73, 0x91, 0x90, 0x61, 0xA6, 0x03, 0x14, 0x20, 0xF2, 0xE7, 0x87,
0xA3, 0x88, 0xAD, 0xAD, 0xA0, 0x8C, 0xFF, 0xA6, 0x0B, 0x25, 0x52, 0x25,
0xE7, 0x16, 0x01, 0xD5, 0xCB, 0xB8, 0x35, 0x81, 0x0C, 0xA3, 0x3B, 0xF0,
0xE1, 0xE1, 0xFC, 0x5A, 0x5D, 0xCE, 0x80, 0x71, 0x6D, 0xF8, 0x49, 0xAB,
0x3E, 0x3B, 0xBA, 0xB8, 0xD7, 0x80, 0x01, 0xFB, 0xA5, 0xEB, 0x5B, 0xB3,
0xC5, 0x5E, 0x60, 0x2A, 0x31, 0xA0, 0xAF, 0x37, 0xE8, 0x20, 0x3A, 0x9F,
0xA8, 0x32, 0x2C, 0x0C, 0xCC, 0x09, 0x1D, 0xD3, 0x9E, 0x8E, 0x5D, 0xBC,
0x4C, 0x98, 0xEE, 0xC5, 0x1A, 0x68, 0x7B, 0xEC, 0x53, 0xA6, 0xE9, 0x14,
0x35, 0xA3, 0xDF, 0xCD, 0x80, 0x9F, 0x0C, 0x48, 0xFB, 0x1C, 0xF4, 0xF1,
0xBF, 0x4A, 0xB8, 0xFA, 0xD5, 0x8C, 0x71, 0x4A, 0xC7, 0x1F, 0xAD, 0xFE,
0x41, 0x9A, 0xB3, 0x83, 0x5D, 0xF2, 0x84, 0x56, 0xEF, 0xA5, 0x57, 0x43,
0xCE, 0x29, 0xAD, 0x8C, 0xAB, 0x55, 0xBF, 0xC4, 0xFB, 0x5B, 0x01, 0xDD,
0x23, 0x21, 0xA1, 0x58, 0x00, 0x8E, 0xC3, 0xD0, 0x6A, 0x13, 0xED, 0x13,
0xE3, 0x12, 0x2B, 0x80, 0xDC, 0x67, 0xE6, 0x95, 0xB2, 0xCD, 0x1E, 0x22,
0x6E, 0x2A, 0xF8, 0x41, 0xD4, 0xF2, 0xCA, 0x14, 0x07, 0x8D, 0x8A, 0x55,
0x12, 0xC6, 0x69, 0xF5, 0xB8, 0x86, 0x68, 0x2F, 0x53, 0x5E, 0xB0, 0xD2,
0xAA, 0x21, 0xC1, 0x98, 0xE6, 0x30, 0xE3, 0x67, 0x55, 0xC7, 0x9B, 0x6E,
0xAC, 0x19, 0xA8, 0x55, 0xA6, 0x45, 0x06, 0xD0, 0x23, 0x3A, 0xDB, 0xEB,
0x65, 0x5D, 0x2A, 0x11, 0x11, 0xF0, 0x3B, 0x4F, 0xCA, 0x6D, 0xF4, 0x34,
0xC4, 0x71, 0xE4, 0xFF, 0x00, 0x5A, 0xF6, 0x5C, 0xAE, 0x23, 0x60, 0x85,
0x73, 0xF1, 0xE4, 0x10, 0xB1, 0x25, 0xAE, 0xD5, 0x92, 0xBB, 0x13, 0xC1,
0x0C, 0xE0, 0x39, 0xDA, 0xB4, 0x39, 0x57, 0xB5, 0xAB, 0x35, 0xAA, 0x72,
0x21, 0x3B, 0x83, 0x35, 0xE7, 0x31, 0xDF, 0x7A, 0x21, 0x6E, 0xB8, 0x32,
0x08, 0x7D, 0x1D, 0x32, 0x91, 0x15, 0x4A, 0x62, 0x72, 0xCF, 0xE3, 0x77,
0xA1, 0xBC, 0xD5, 0x11, 0x1B, 0x76, 0x01, 0x67, 0x08, 0xE0, 0x41, 0x0B,
0xC3, 0xEB, 0x15, 0x6E, 0xF8, 0xA4, 0x19, 0xD9, 0xA2, 0xAB, 0xAF, 0xE2,
0x27, 0x52, 0x56, 0x2B, 0x02, 0x8A, 0x2C, 0x14, 0x24, 0xF9, 0xBF, 0x42,
0x02, 0xBF, 0x26, 0xC8, 0xC6, 0x8F, 0xE0, 0x6E, 0x38, 0x7D, 0x53, 0x2D,
0xE5, 0xED, 0x98, 0xB3, 0x95, 0x63, 0x68, 0x7F, 0xF9, 0x35, 0xF4, 0xDF,
0x88, 0xC5, 0x60, 0x35, 0x92, 0xC0, 0x7C, 0x69, 0x1C, 0x61, 0x95, 0x16,
0xD0, 0xEB, 0xDE, 0x0B, 0xAF, 0x3E, 0x04, 0x10, 0x45, 0x65, 0x58, 0x50,
0x38, 0xAF, 0x48, 0xF2, 0x59, 0xB6, 0x16, 0xF2, 0x3C, 0x0D, 0x90, 0x02,
0xC6, 0x70, 0x2E, 0x01, 0xAD, 0x3C, 0x15, 0xD7
};
static const unsigned char TA48_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA49_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x4D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69, 0x73, 0x20, 0x4C,
0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x15, 0x51, 0x75, 0x6F, 0x56, 0x61, 0x64, 0x69,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33, 0x20,
0x47, 0x33
};
static const unsigned char TA49_RSA_N[] = {
0xB3, 0xCB, 0x0E, 0x10, 0x67, 0x8E, 0xEA, 0x14, 0x97, 0xA7, 0x32, 0x2A,
0x0A, 0x56, 0x36, 0x7F, 0x68, 0x4C, 0xC7, 0xB3, 0x6F, 0x3A, 0x23, 0x14,
0x91, 0xFF, 0x19, 0x7F, 0xA5, 0xCA, 0xAC, 0xEE, 0xB3, 0x76, 0x9D, 0x7A,
0xE9, 0x8B, 0x1B, 0xAB, 0x6B, 0x31, 0xDB, 0xFA, 0x0B, 0x53, 0x4C, 0xAF,
0xC5, 0xA5, 0x1A, 0x79, 0x3C, 0x8A, 0x4C, 0xFF, 0xAC, 0xDF, 0x25, 0xDE,
0x4E, 0xD9, 0x82, 0x32, 0x0B, 0x44, 0xDE, 0xCA, 0xDB, 0x8C, 0xAC, 0xA3,
0x6E, 0x16, 0x83, 0x3B, 0xA6, 0x64, 0x4B, 0x32, 0x89, 0xFB, 0x16, 0x16,
0x38, 0x7E, 0xEB, 0x43, 0xE2, 0xD3, 0x74, 0x4A, 0xC2, 0x62, 0x0A, 0x73,
0x0A, 0xDD, 0x49, 0xB3, 0x57, 0xD2, 0xB0, 0x0A, 0x85, 0x9D, 0x71, 0x3C,
0xDE, 0xA3, 0xCB, 0xC0, 0x32, 0xF3, 0x01, 0x39, 0x20, 0x43, 0x1B, 0x35,
0xD1, 0x53, 0xB3, 0xB1, 0xEE, 0xC5, 0x93, 0x69, 0x82, 0x3E, 0x16, 0xB5,
0x28, 0x46, 0xA1, 0xDE, 0xEA, 0x89, 0x09, 0xED, 0x43, 0xB8, 0x05, 0x46,
0x8A, 0x86, 0xF5, 0x59, 0x47, 0xBE, 0x1B, 0x6F, 0x01, 0x21, 0x10, 0xB9,
0xFD, 0xA9, 0xD2, 0x28, 0xCA, 0x10, 0x39, 0x09, 0xCA, 0x13, 0x36, 0xCF,
0x9C, 0xAD, 0xAD, 0x40, 0x74, 0x79, 0x2B, 0x02, 0x3F, 0x34, 0xFF, 0xFA,
0x20, 0x69, 0x7D, 0xD3, 0xEE, 0x61, 0xF5, 0xBA, 0xB3, 0xE7, 0x30, 0xD0,
0x37, 0x23, 0x86, 0x72, 0x61, 0x45, 0x29, 0x48, 0x59, 0x68, 0x6F, 0x77,
0xA6, 0x2E, 0x81, 0xBE, 0x07, 0x4D, 0x6F, 0xAF, 0xCE, 0xC4, 0x45, 0x13,
0x91, 0x14, 0x70, 0x06, 0x8F, 0x1F, 0x9F, 0xF8, 0x87, 0x69, 0xB1, 0x0E,
0xEF, 0xC3, 0x89, 0x19, 0xEB, 0xEA, 0x1C, 0x61, 0xFC, 0x7A, 0x6C, 0x8A,
0xDC, 0xD6, 0x03, 0x0B, 0x9E, 0x26, 0xBA, 0x12, 0xDD, 0xD4, 0x54, 0x39,
0xAB, 0x26, 0xA3, 0x33, 0xEA, 0x75, 0x81, 0xDA, 0x2D, 0xCD, 0x0F, 0x4F,
0xE4, 0x03, 0xD1, 0xEF, 0x15, 0x97, 0x1B, 0x6B, 0x90, 0xC5, 0x02, 0x90,
0x93, 0x66, 0x02, 0x21, 0xB1, 0x47, 0xDE, 0x8B, 0x9A, 0x4A, 0x80, 0xB9,
0x55, 0x8F, 0xB5, 0xA2, 0x2F, 0xC0, 0xD6, 0x33, 0x67, 0xDA, 0x7E, 0xC4,
0xA7, 0xB4, 0x04, 0x44, 0xEB, 0x47, 0xFB, 0xE6, 0x58, 0xB9, 0xF7, 0x0C,
0xF0, 0x7B, 0x2B, 0xB1, 0xC0, 0x70, 0x29, 0xC3, 0x40, 0x62, 0x2D, 0x3B,
0x48, 0x69, 0xDC, 0x23, 0x3C, 0x48, 0xEB, 0x7B, 0x09, 0x79, 0xA9, 0x6D,
0xDA, 0xA8, 0x30, 0x98, 0xCF, 0x80, 0x72, 0x03, 0x88, 0xA6, 0x5B, 0x46,
0xAE, 0x72, 0x79, 0x7C, 0x08, 0x03, 0x21, 0x65, 0xAE, 0xB7, 0xE1, 0x1C,
0xA5, 0xB1, 0x2A, 0xA2, 0x31, 0xDE, 0x66, 0x04, 0xF7, 0xC0, 0x74, 0xE8,
0x71, 0xDE, 0xFF, 0x3D, 0x59, 0xCC, 0x96, 0x26, 0x12, 0x8B, 0x85, 0x95,
0x57, 0x1A, 0xAB, 0x6B, 0x75, 0x0B, 0x44, 0x3D, 0x11, 0x28, 0x3C, 0x7B,
0x61, 0xB7, 0xE2, 0x8F, 0x67, 0x4F, 0xE5, 0xEC, 0x3C, 0x4C, 0x60, 0x80,
0x69, 0x57, 0x38, 0x1E, 0x01, 0x5B, 0x8D, 0x55, 0xE8, 0xC7, 0xDF, 0xC0,
0xCC, 0x77, 0x23, 0x34, 0x49, 0x75, 0x7C, 0xF6, 0x98, 0x11, 0xEB, 0x2D,
0xDE, 0xED, 0x41, 0x2E, 0x14, 0x05, 0x02, 0x7F, 0xE0, 0xFE, 0x20, 0xEB,
0x35, 0xE7, 0x11, 0xAC, 0x22, 0xCE, 0x57, 0x3D, 0xDE, 0xC9, 0x30, 0x6D,
0x10, 0x03, 0x85, 0xCD, 0xF1, 0xFF, 0x8C, 0x16, 0xB5, 0xC1, 0xB2, 0x3E,
0x88, 0x6C, 0x60, 0x7F, 0x90, 0x4F, 0x95, 0xF7, 0xF6, 0x2D, 0xAD, 0x01,
0x39, 0x07, 0x04, 0xFA, 0x75, 0x80, 0x7D, 0xBF, 0x49, 0x50, 0xED, 0xEF,
0xC9, 0xC4, 0x7C, 0x1C, 0xEB, 0x80, 0x7E, 0xDB, 0xB6, 0xD0, 0xDD, 0x13,
0xFE, 0xC9, 0xD3, 0x9C, 0xD7, 0xB2, 0x97, 0xA9
};
static const unsigned char TA49_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA50_DN[] = {
0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x32
};
static const unsigned char TA50_RSA_N[] = {
0xD9, 0xE7, 0x28, 0x2F, 0x52, 0x3F, 0x36, 0x72, 0x49, 0x88, 0x93, 0x34,
0xF3, 0xF8, 0x6A, 0x1E, 0x31, 0x54, 0x80, 0x9F, 0xAD, 0x54, 0x41, 0xB5,
0x47, 0xDF, 0x96, 0xA8, 0xD4, 0xAF, 0x80, 0x2D, 0xB9, 0x0A, 0xCF, 0x75,
0xFD, 0x89, 0xA5, 0x7D, 0x24, 0xFA, 0xE3, 0x22, 0x0C, 0x2B, 0xBC, 0x95,
0x17, 0x0B, 0x33, 0xBF, 0x19, 0x4D, 0x41, 0x06, 0x90, 0x00, 0xBD, 0x0C,
0x4D, 0x10, 0xFE, 0x07, 0xB5, 0xE7, 0x1C, 0x6E, 0x22, 0x55, 0x31, 0x65,
0x97, 0xBD, 0xD3, 0x17, 0xD2, 0x1E, 0x62, 0xF3, 0xDB, 0xEA, 0x6C, 0x50,
0x8C, 0x3F, 0x84, 0x0C, 0x96, 0xCF, 0xB7, 0xCB, 0x03, 0xE0, 0xCA, 0x6D,
0xA1, 0x14, 0x4C, 0x1B, 0x89, 0xDD, 0xED, 0x00, 0xB0, 0x52, 0x7C, 0xAF,
0x91, 0x6C, 0xB1, 0x38, 0x13, 0xD1, 0xE9, 0x12, 0x08, 0xC0, 0x00, 0xB0,
0x1C, 0x2B, 0x11, 0xDA, 0x77, 0x70, 0x36, 0x9B, 0xAE, 0xCE, 0x79, 0x87,
0xDC, 0x82, 0x70, 0xE6, 0x09, 0x74, 0x70, 0x55, 0x69, 0xAF, 0xA3, 0x68,
0x9F, 0xBF, 0xDD, 0xB6, 0x79, 0xB3, 0xF2, 0x9D, 0x70, 0x29, 0x55, 0xF4,
0xAB, 0xFF, 0x95, 0x61, 0xF3, 0xC9, 0x40, 0x6F, 0x1D, 0xD1, 0xBE, 0x93,
0xBB, 0xD3, 0x88, 0x2A, 0xBB, 0x9D, 0xBF, 0x72, 0x5A, 0x56, 0x71, 0x3B,
0x3F, 0xD4, 0xF3, 0xD1, 0x0A, 0xFE, 0x28, 0xEF, 0xA3, 0xEE, 0xD9, 0x99,
0xAF, 0x03, 0xD3, 0x8F, 0x60, 0xB7, 0xF2, 0x92, 0xA1, 0xB1, 0xBD, 0x89,
0x89, 0x1F, 0x30, 0xCD, 0xC3, 0xA6, 0x2E, 0x62, 0x33, 0xAE, 0x16, 0x02,
0x77, 0x44, 0x5A, 0xE7, 0x81, 0x0A, 0x3C, 0xA7, 0x44, 0x2E, 0x79, 0xB8,
0x3F, 0x04, 0xBC, 0x5C, 0xA0, 0x87, 0xE1, 0x1B, 0xAF, 0x51, 0x8E, 0xCD,
0xEC, 0x2C, 0xFA, 0xF8, 0xFE, 0x6D, 0xF0, 0x3A, 0x7C, 0xAA, 0x8B, 0xE4,
0x67, 0x95, 0x31, 0x8D
};
static const unsigned char TA50_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA51_DN[] = {
0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x1B, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x65, 0x64, 0x20, 0x49, 0x44, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x33
};
static const unsigned char TA51_EC_Q[] = {
0x04, 0x19, 0xE7, 0xBC, 0xAC, 0x44, 0x65, 0xED, 0xCD, 0xB8, 0x3F, 0x58,
0xFB, 0x8D, 0xB1, 0x57, 0xA9, 0x44, 0x2D, 0x05, 0x15, 0xF2, 0xEF, 0x0B,
0xFF, 0x10, 0x74, 0x9F, 0xB5, 0x62, 0x52, 0x5F, 0x66, 0x7E, 0x1F, 0xE5,
0xDC, 0x1B, 0x45, 0x79, 0x0B, 0xCC, 0xC6, 0x53, 0x0A, 0x9D, 0x8D, 0x5D,
0x02, 0xD9, 0xA9, 0x59, 0xDE, 0x02, 0x5A, 0xF6, 0x95, 0x2A, 0x0E, 0x8D,
0x38, 0x4A, 0x8A, 0x49, 0xC6, 0xBC, 0xC6, 0x03, 0x38, 0x07, 0x5F, 0x55,
0xDA, 0x7E, 0x09, 0x6E, 0xE2, 0x7F, 0x5E, 0xD0, 0x45, 0x20, 0x0F, 0x59,
0x76, 0x10, 0xD6, 0xA0, 0x24, 0xF0, 0x2D, 0xDE, 0x36, 0xF2, 0x6C, 0x29,
0x39
};
static const unsigned char TA52_DN[] = {
0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x47, 0x32
};
static const unsigned char TA52_RSA_N[] = {
0xBB, 0x37, 0xCD, 0x34, 0xDC, 0x7B, 0x6B, 0xC9, 0xB2, 0x68, 0x90, 0xAD,
0x4A, 0x75, 0xFF, 0x46, 0xBA, 0x21, 0x0A, 0x08, 0x8D, 0xF5, 0x19, 0x54,
0xC9, 0xFB, 0x88, 0xDB, 0xF3, 0xAE, 0xF2, 0x3A, 0x89, 0x91, 0x3C, 0x7A,
0xE6, 0xAB, 0x06, 0x1A, 0x6B, 0xCF, 0xAC, 0x2D, 0xE8, 0x5E, 0x09, 0x24,
0x44, 0xBA, 0x62, 0x9A, 0x7E, 0xD6, 0xA3, 0xA8, 0x7E, 0xE0, 0x54, 0x75,
0x20, 0x05, 0xAC, 0x50, 0xB7, 0x9C, 0x63, 0x1A, 0x6C, 0x30, 0xDC, 0xDA,
0x1F, 0x19, 0xB1, 0xD7, 0x1E, 0xDE, 0xFD, 0xD7, 0xE0, 0xCB, 0x94, 0x83,
0x37, 0xAE, 0xEC, 0x1F, 0x43, 0x4E, 0xDD, 0x7B, 0x2C, 0xD2, 0xBD, 0x2E,
0xA5, 0x2F, 0xE4, 0xA9, 0xB8, 0xAD, 0x3A, 0xD4, 0x99, 0xA4, 0xB6, 0x25,
0xE9, 0x9B, 0x6B, 0x00, 0x60, 0x92, 0x60, 0xFF, 0x4F, 0x21, 0x49, 0x18,
0xF7, 0x67, 0x90, 0xAB, 0x61, 0x06, 0x9C, 0x8F, 0xF2, 0xBA, 0xE9, 0xB4,
0xE9, 0x92, 0x32, 0x6B, 0xB5, 0xF3, 0x57, 0xE8, 0x5D, 0x1B, 0xCD, 0x8C,
0x1D, 0xAB, 0x95, 0x04, 0x95, 0x49, 0xF3, 0x35, 0x2D, 0x96, 0xE3, 0x49,
0x6D, 0xDD, 0x77, 0xE3, 0xFB, 0x49, 0x4B, 0xB4, 0xAC, 0x55, 0x07, 0xA9,
0x8F, 0x95, 0xB3, 0xB4, 0x23, 0xBB, 0x4C, 0x6D, 0x45, 0xF0, 0xF6, 0xA9,
0xB2, 0x95, 0x30, 0xB4, 0xFD, 0x4C, 0x55, 0x8C, 0x27, 0x4A, 0x57, 0x14,
0x7C, 0x82, 0x9D, 0xCD, 0x73, 0x92, 0xD3, 0x16, 0x4A, 0x06, 0x0C, 0x8C,
0x50, 0xD1, 0x8F, 0x1E, 0x09, 0xBE, 0x17, 0xA1, 0xE6, 0x21, 0xCA, 0xFD,
0x83, 0xE5, 0x10, 0xBC, 0x83, 0xA5, 0x0A, 0xC4, 0x67, 0x28, 0xF6, 0x73,
0x14, 0x14, 0x3D, 0x46, 0x76, 0xC3, 0x87, 0x14, 0x89, 0x21, 0x34, 0x4D,
0xAF, 0x0F, 0x45, 0x0C, 0xA6, 0x49, 0xA1, 0xBA, 0xBB, 0x9C, 0xC5, 0xB1,
0x33, 0x83, 0x29, 0x85
};
static const unsigned char TA52_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA53_DN[] = {
0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x47, 0x33
};
static const unsigned char TA53_EC_Q[] = {
0x04, 0xDD, 0xA7, 0xD9, 0xBB, 0x8A, 0xB8, 0x0B, 0xFB, 0x0B, 0x7F, 0x21,
0xD2, 0xF0, 0xBE, 0xBE, 0x73, 0xF3, 0x33, 0x5D, 0x1A, 0xBC, 0x34, 0xEA,
0xDE, 0xC6, 0x9B, 0xBC, 0xD0, 0x95, 0xF6, 0xF0, 0xCC, 0xD0, 0x0B, 0xBA,
0x61, 0x5B, 0x51, 0x46, 0x7E, 0x9E, 0x2D, 0x9F, 0xEE, 0x8E, 0x63, 0x0C,
0x17, 0xEC, 0x07, 0x70, 0xF5, 0xCF, 0x84, 0x2E, 0x40, 0x83, 0x9C, 0xE8,
0x3F, 0x41, 0x6D, 0x3B, 0xAD, 0xD3, 0xA4, 0x14, 0x59, 0x36, 0x78, 0x9D,
0x03, 0x43, 0xEE, 0x10, 0x13, 0x6C, 0x72, 0xDE, 0xAE, 0x88, 0xA7, 0xA1,
0x6B, 0xB5, 0x43, 0xCE, 0x67, 0xDC, 0x23, 0xFF, 0x03, 0x1C, 0xA3, 0xE2,
0x3E
};
static const unsigned char TA54_DN[] = {
0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49,
0x6E, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x10, 0x77, 0x77, 0x77, 0x2E, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72,
0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x18, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74,
0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x47, 0x34
};
static const unsigned char TA54_RSA_N[] = {
0xBF, 0xE6, 0x90, 0x73, 0x68, 0xDE, 0xBB, 0xE4, 0x5D, 0x4A, 0x3C, 0x30,
0x22, 0x30, 0x69, 0x33, 0xEC, 0xC2, 0xA7, 0x25, 0x2E, 0xC9, 0x21, 0x3D,
0xF2, 0x8A, 0xD8, 0x59, 0xC2, 0xE1, 0x29, 0xA7, 0x3D, 0x58, 0xAB, 0x76,
0x9A, 0xCD, 0xAE, 0x7B, 0x1B, 0x84, 0x0D, 0xC4, 0x30, 0x1F, 0xF3, 0x1B,
0xA4, 0x38, 0x16, 0xEB, 0x56, 0xC6, 0x97, 0x6D, 0x1D, 0xAB, 0xB2, 0x79,
0xF2, 0xCA, 0x11, 0xD2, 0xE4, 0x5F, 0xD6, 0x05, 0x3C, 0x52, 0x0F, 0x52,
0x1F, 0xC6, 0x9E, 0x15, 0xA5, 0x7E, 0xBE, 0x9F, 0xA9, 0x57, 0x16, 0x59,
0x55, 0x72, 0xAF, 0x68, 0x93, 0x70, 0xC2, 0xB2, 0xBA, 0x75, 0x99, 0x6A,
0x73, 0x32, 0x94, 0xD1, 0x10, 0x44, 0x10, 0x2E, 0xDF, 0x82, 0xF3, 0x07,
0x84, 0xE6, 0x74, 0x3B, 0x6D, 0x71, 0xE2, 0x2D, 0x0C, 0x1B, 0xEE, 0x20,
0xD5, 0xC9, 0x20, 0x1D, 0x63, 0x29, 0x2D, 0xCE, 0xEC, 0x5E, 0x4E, 0xC8,
0x93, 0xF8, 0x21, 0x61, 0x9B, 0x34, 0xEB, 0x05, 0xC6, 0x5E, 0xEC, 0x5B,
0x1A, 0xBC, 0xEB, 0xC9, 0xCF, 0xCD, 0xAC, 0x34, 0x40, 0x5F, 0xB1, 0x7A,
0x66, 0xEE, 0x77, 0xC8, 0x48, 0xA8, 0x66, 0x57, 0x57, 0x9F, 0x54, 0x58,
0x8E, 0x0C, 0x2B, 0xB7, 0x4F, 0xA7, 0x30, 0xD9, 0x56, 0xEE, 0xCA, 0x7B,
0x5D, 0xE3, 0xAD, 0xC9, 0x4F, 0x5E, 0xE5, 0x35, 0xE7, 0x31, 0xCB, 0xDA,
0x93, 0x5E, 0xDC, 0x8E, 0x8F, 0x80, 0xDA, 0xB6, 0x91, 0x98, 0x40, 0x90,
0x79, 0xC3, 0x78, 0xC7, 0xB6, 0xB1, 0xC4, 0xB5, 0x6A, 0x18, 0x38, 0x03,
0x10, 0x8D, 0xD8, 0xD4, 0x37, 0xA4, 0x2E, 0x05, 0x7D, 0x88, 0xF5, 0x82,
0x3E, 0x10, 0x91, 0x70, 0xAB, 0x55, 0x82, 0x41, 0x32, 0xD7, 0xDB, 0x04,
0x73, 0x2A, 0x6E, 0x91, 0x01, 0x7C, 0x21, 0x4C, 0xD4, 0xBC, 0xAE, 0x1B,
0x03, 0x75, 0x5D, 0x78, 0x66, 0xD9, 0x3A, 0x31, 0x44, 0x9A, 0x33, 0x40,
0xBF, 0x08, 0xD7, 0x5A, 0x49, 0xA4, 0xC2, 0xE6, 0xA9, 0xA0, 0x67, 0xDD,
0xA4, 0x27, 0xBC, 0xA1, 0x4F, 0x39, 0xB5, 0x11, 0x58, 0x17, 0xF7, 0x24,
0x5C, 0x46, 0x8F, 0x64, 0xF7, 0xC1, 0x69, 0x88, 0x76, 0x98, 0x76, 0x3D,
0x59, 0x5D, 0x42, 0x76, 0x87, 0x89, 0x97, 0x69, 0x7A, 0x48, 0xF0, 0xE0,
0xA2, 0x12, 0x1B, 0x66, 0x9A, 0x74, 0xCA, 0xDE, 0x4B, 0x1E, 0xE7, 0x0E,
0x63, 0xAE, 0xE6, 0xD4, 0xEF, 0x92, 0x92, 0x3A, 0x9E, 0x3D, 0xDC, 0x00,
0xE4, 0x45, 0x25, 0x89, 0xB6, 0x9A, 0x44, 0x19, 0x2B, 0x7E, 0xC0, 0x94,
0xB4, 0xD2, 0x61, 0x6D, 0xEB, 0x33, 0xD9, 0xC5, 0xDF, 0x4B, 0x04, 0x00,
0xCC, 0x7D, 0x1C, 0x95, 0xC3, 0x8F, 0xF7, 0x21, 0xB2, 0xB2, 0x11, 0xB7,
0xBB, 0x7F, 0xF2, 0xD5, 0x8C, 0x70, 0x2C, 0x41, 0x60, 0xAA, 0xB1, 0x63,
0x18, 0x44, 0x95, 0x1A, 0x76, 0x62, 0x7E, 0xF6, 0x80, 0xB0, 0xFB, 0xE8,
0x64, 0xA6, 0x33, 0xD1, 0x89, 0x07, 0xE1, 0xBD, 0xB7, 0xE6, 0x43, 0xA4,
0x18, 0xB8, 0xA6, 0x77, 0x01, 0xE1, 0x0F, 0x94, 0x0C, 0x21, 0x1D, 0xB2,
0x54, 0x29, 0x25, 0x89, 0x6C, 0xE5, 0x0E, 0x52, 0x51, 0x47, 0x74, 0xBE,
0x26, 0xAC, 0xB6, 0x41, 0x75, 0xDE, 0x7A, 0xAC, 0x5F, 0x8D, 0x3F, 0xC9,
0xBC, 0xD3, 0x41, 0x11, 0x12, 0x5B, 0xE5, 0x10, 0x50, 0xEB, 0x31, 0xC5,
0xCA, 0x72, 0x16, 0x22, 0x09, 0xDF, 0x7C, 0x4C, 0x75, 0x3F, 0x63, 0xEC,
0x21, 0x5F, 0xC4, 0x20, 0x51, 0x6B, 0x6F, 0xB1, 0xAB, 0x86, 0x8B, 0x4F,
0xC2, 0xD6, 0x45, 0x5F, 0x9D, 0x20, 0xFC, 0xA1, 0x1E, 0xC5, 0xC0, 0x8F,
0xA2, 0xB1, 0x7E, 0x0A, 0x26, 0x99, 0xF5, 0xE4, 0x69, 0x2F, 0x98, 0x1D,
0x2D, 0xF5, 0xD9, 0xA9, 0xB2, 0x1D, 0xE5, 0x1B
};
static const unsigned char TA54_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA55_DN[] = {
0x30, 0x81, 0x85, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x47, 0x42, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4D,
0x61, 0x6E, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30,
0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6C, 0x66,
0x6F, 0x72, 0x64, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x11, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F, 0x20, 0x43, 0x41, 0x20,
0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x2B, 0x30, 0x29, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x43, 0x4F, 0x4D, 0x4F, 0x44, 0x4F,
0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA55_RSA_N[] = {
0x91, 0xE8, 0x54, 0x92, 0xD2, 0x0A, 0x56, 0xB1, 0xAC, 0x0D, 0x24, 0xDD,
0xC5, 0xCF, 0x44, 0x67, 0x74, 0x99, 0x2B, 0x37, 0xA3, 0x7D, 0x23, 0x70,
0x00, 0x71, 0xBC, 0x53, 0xDF, 0xC4, 0xFA, 0x2A, 0x12, 0x8F, 0x4B, 0x7F,
0x10, 0x56, 0xBD, 0x9F, 0x70, 0x72, 0xB7, 0x61, 0x7F, 0xC9, 0x4B, 0x0F,
0x17, 0xA7, 0x3D, 0xE3, 0xB0, 0x04, 0x61, 0xEE, 0xFF, 0x11, 0x97, 0xC7,
0xF4, 0x86, 0x3E, 0x0A, 0xFA, 0x3E, 0x5C, 0xF9, 0x93, 0xE6, 0x34, 0x7A,
0xD9, 0x14, 0x6B, 0xE7, 0x9C, 0xB3, 0x85, 0xA0, 0x82, 0x7A, 0x76, 0xAF,
0x71, 0x90, 0xD7, 0xEC, 0xFD, 0x0D, 0xFA, 0x9C, 0x6C, 0xFA, 0xDF, 0xB0,
0x82, 0xF4, 0x14, 0x7E, 0xF9, 0xBE, 0xC4, 0xA6, 0x2F, 0x4F, 0x7F, 0x99,
0x7F, 0xB5, 0xFC, 0x67, 0x43, 0x72, 0xBD, 0x0C, 0x00, 0xD6, 0x89, 0xEB,
0x6B, 0x2C, 0xD3, 0xED, 0x8F, 0x98, 0x1C, 0x14, 0xAB, 0x7E, 0xE5, 0xE3,
0x6E, 0xFC, 0xD8, 0xA8, 0xE4, 0x92, 0x24, 0xDA, 0x43, 0x6B, 0x62, 0xB8,
0x55, 0xFD, 0xEA, 0xC1, 0xBC, 0x6C, 0xB6, 0x8B, 0xF3, 0x0E, 0x8D, 0x9A,
0xE4, 0x9B, 0x6C, 0x69, 0x99, 0xF8, 0x78, 0x48, 0x30, 0x45, 0xD5, 0xAD,
0xE1, 0x0D, 0x3C, 0x45, 0x60, 0xFC, 0x32, 0x96, 0x51, 0x27, 0xBC, 0x67,
0xC3, 0xCA, 0x2E, 0xB6, 0x6B, 0xEA, 0x46, 0xC7, 0xC7, 0x20, 0xA0, 0xB1,
0x1F, 0x65, 0xDE, 0x48, 0x08, 0xBA, 0xA4, 0x4E, 0xA9, 0xF2, 0x83, 0x46,
0x37, 0x84, 0xEB, 0xE8, 0xCC, 0x81, 0x48, 0x43, 0x67, 0x4E, 0x72, 0x2A,
0x9B, 0x5C, 0xBD, 0x4C, 0x1B, 0x28, 0x8A, 0x5C, 0x22, 0x7B, 0xB4, 0xAB,
0x98, 0xD9, 0xEE, 0xE0, 0x51, 0x83, 0xC3, 0x09, 0x46, 0x4E, 0x6D, 0x3E,
0x99, 0xFA, 0x95, 0x17, 0xDA, 0x7C, 0x33, 0x57, 0x41, 0x3C, 0x8D, 0x51,
0xED, 0x0B, 0xB6, 0x5C, 0xAF, 0x2C, 0x63, 0x1A, 0xDF, 0x57, 0xC8, 0x3F,
0xBC, 0xE9, 0x5D, 0xC4, 0x9B, 0xAF, 0x45, 0x99, 0xE2, 0xA3, 0x5A, 0x24,
0xB4, 0xBA, 0xA9, 0x56, 0x3D, 0xCF, 0x6F, 0xAA, 0xFF, 0x49, 0x58, 0xBE,
0xF0, 0xA8, 0xFF, 0xF4, 0xB8, 0xAD, 0xE9, 0x37, 0xFB, 0xBA, 0xB8, 0xF4,
0x0B, 0x3A, 0xF9, 0xE8, 0x43, 0x42, 0x1E, 0x89, 0xD8, 0x84, 0xCB, 0x13,
0xF1, 0xD9, 0xBB, 0xE1, 0x89, 0x60, 0xB8, 0x8C, 0x28, 0x56, 0xAC, 0x14,
0x1D, 0x9C, 0x0A, 0xE7, 0x71, 0xEB, 0xCF, 0x0E, 0xDD, 0x3D, 0xA9, 0x96,
0xA1, 0x48, 0xBD, 0x3C, 0xF7, 0xAF, 0xB5, 0x0D, 0x22, 0x4C, 0xC0, 0x11,
0x81, 0xEC, 0x56, 0x3B, 0xF6, 0xD3, 0xA2, 0xE2, 0x5B, 0xB7, 0xB2, 0x04,
0x22, 0x52, 0x95, 0x80, 0x93, 0x69, 0xE8, 0x8E, 0x4C, 0x65, 0xF1, 0x91,
0x03, 0x2D, 0x70, 0x74, 0x02, 0xEA, 0x8B, 0x67, 0x15, 0x29, 0x69, 0x52,
0x02, 0xBB, 0xD7, 0xDF, 0x50, 0x6A, 0x55, 0x46, 0xBF, 0xA0, 0xA3, 0x28,
0x61, 0x7F, 0x70, 0xD0, 0xC3, 0xA2, 0xAA, 0x2C, 0x21, 0xAA, 0x47, 0xCE,
0x28, 0x9C, 0x06, 0x45, 0x76, 0xBF, 0x82, 0x18, 0x27, 0xB4, 0xD5, 0xAE,
0xB4, 0xCB, 0x50, 0xE6, 0x6B, 0xF4, 0x4C, 0x86, 0x71, 0x30, 0xE9, 0xA6,
0xDF, 0x16, 0x86, 0xE0, 0xD8, 0xFF, 0x40, 0xDD, 0xFB, 0xD0, 0x42, 0x88,
0x7F, 0xA3, 0x33, 0x3A, 0x2E, 0x5C, 0x1E, 0x41, 0x11, 0x81, 0x63, 0xCE,
0x18, 0x71, 0x6B, 0x2B, 0xEC, 0xA6, 0x8A, 0xB7, 0x31, 0x5C, 0x3A, 0x6A,
0x47, 0xE0, 0xC3, 0x79, 0x59, 0xD6, 0x20, 0x1A, 0xAF, 0xF2, 0x6A, 0x98,
0xAA, 0x72, 0xBC, 0x57, 0x4A, 0xD2, 0x4B, 0x9D, 0xBB, 0x10, 0xFC, 0xB0,
0x4C, 0x41, 0xE5, 0xED, 0x1D, 0x3D, 0x5E, 0x28, 0x9D, 0x9C, 0xCC, 0xBF,
0xB3, 0x51, 0xDA, 0xA7, 0x47, 0xE5, 0x84, 0x53
};
static const unsigned char TA55_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA56_DN[] = {
0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65,
0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B,
0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31,
0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68,
0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20,
0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72,
0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA56_RSA_N[] = {
0x80, 0x12, 0x65, 0x17, 0x36, 0x0E, 0xC3, 0xDB, 0x08, 0xB3, 0xD0, 0xAC,
0x57, 0x0D, 0x76, 0xED, 0xCD, 0x27, 0xD3, 0x4C, 0xAD, 0x50, 0x83, 0x61,
0xE2, 0xAA, 0x20, 0x4D, 0x09, 0x2D, 0x64, 0x09, 0xDC, 0xCE, 0x89, 0x9F,
0xCC, 0x3D, 0xA9, 0xEC, 0xF6, 0xCF, 0xC1, 0xDC, 0xF1, 0xD3, 0xB1, 0xD6,
0x7B, 0x37, 0x28, 0x11, 0x2B, 0x47, 0xDA, 0x39, 0xC6, 0xBC, 0x3A, 0x19,
0xB4, 0x5F, 0xA6, 0xBD, 0x7D, 0x9D, 0xA3, 0x63, 0x42, 0xB6, 0x76, 0xF2,
0xA9, 0x3B, 0x2B, 0x91, 0xF8, 0xE2, 0x6F, 0xD0, 0xEC, 0x16, 0x20, 0x90,
0x09, 0x3E, 0xE2, 0xE8, 0x74, 0xC9, 0x18, 0xB4, 0x91, 0xD4, 0x62, 0x64,
0xDB, 0x7F, 0xA3, 0x06, 0xF1, 0x88, 0x18, 0x6A, 0x90, 0x22, 0x3C, 0xBC,
0xFE, 0x13, 0xF0, 0x87, 0x14, 0x7B, 0xF6, 0xE4, 0x1F, 0x8E, 0xD4, 0xE4,
0x51, 0xC6, 0x11, 0x67, 0x46, 0x08, 0x51, 0xCB, 0x86, 0x14, 0x54, 0x3F,
0xBC, 0x33, 0xFE, 0x7E, 0x6C, 0x9C, 0xFF, 0x16, 0x9D, 0x18, 0xBD, 0x51,
0x8E, 0x35, 0xA6, 0xA7, 0x66, 0xC8, 0x72, 0x67, 0xDB, 0x21, 0x66, 0xB1,
0xD4, 0x9B, 0x78, 0x03, 0xC0, 0x50, 0x3A, 0xE8, 0xCC, 0xF0, 0xDC, 0xBC,
0x9E, 0x4C, 0xFE, 0xAF, 0x05, 0x96, 0x35, 0x1F, 0x57, 0x5A, 0xB7, 0xFF,
0xCE, 0xF9, 0x3D, 0xB7, 0x2C, 0xB6, 0xF6, 0x54, 0xDD, 0xC8, 0xE7, 0x12,
0x3A, 0x4D, 0xAE, 0x4C, 0x8A, 0xB7, 0x5C, 0x9A, 0xB4, 0xB7, 0x20, 0x3D,
0xCA, 0x7F, 0x22, 0x34, 0xAE, 0x7E, 0x3B, 0x68, 0x66, 0x01, 0x44, 0xE7,
0x01, 0x4E, 0x46, 0x53, 0x9B, 0x33, 0x60, 0xF7, 0x94, 0xBE, 0x53, 0x37,
0x90, 0x73, 0x43, 0xF3, 0x32, 0xC3, 0x53, 0xEF, 0xDB, 0xAA, 0xFE, 0x74,
0x4E, 0x69, 0xC7, 0x6B, 0x8C, 0x60, 0x93, 0xDE, 0xC4, 0xC7, 0x0C, 0xDF,
0xE1, 0x32, 0xAE, 0xCC, 0x93, 0x3B, 0x51, 0x78, 0x95, 0x67, 0x8B, 0xEE,
0x3D, 0x56, 0xFE, 0x0C, 0xD0, 0x69, 0x0F, 0x1B, 0x0F, 0xF3, 0x25, 0x26,
0x6B, 0x33, 0x6D, 0xF7, 0x6E, 0x47, 0xFA, 0x73, 0x43, 0xE5, 0x7E, 0x0E,
0xA5, 0x66, 0xB1, 0x29, 0x7C, 0x32, 0x84, 0x63, 0x55, 0x89, 0xC4, 0x0D,
0xC1, 0x93, 0x54, 0x30, 0x19, 0x13, 0xAC, 0xD3, 0x7D, 0x37, 0xA7, 0xEB,
0x5D, 0x3A, 0x6C, 0x35, 0x5C, 0xDB, 0x41, 0xD7, 0x12, 0xDA, 0xA9, 0x49,
0x0B, 0xDF, 0xD8, 0x80, 0x8A, 0x09, 0x93, 0x62, 0x8E, 0xB5, 0x66, 0xCF,
0x25, 0x88, 0xCD, 0x84, 0xB8, 0xB1, 0x3F, 0xA4, 0x39, 0x0F, 0xD9, 0x02,
0x9E, 0xEB, 0x12, 0x4C, 0x95, 0x7C, 0xF3, 0x6B, 0x05, 0xA9, 0x5E, 0x16,
0x83, 0xCC, 0xB8, 0x67, 0xE2, 0xE8, 0x13, 0x9D, 0xCC, 0x5B, 0x82, 0xD3,
0x4C, 0xB3, 0xED, 0x5B, 0xFF, 0xDE, 0xE5, 0x73, 0xAC, 0x23, 0x3B, 0x2D,
0x00, 0xBF, 0x35, 0x55, 0x74, 0x09, 0x49, 0xD8, 0x49, 0x58, 0x1A, 0x7F,
0x92, 0x36, 0xE6, 0x51, 0x92, 0x0E, 0xF3, 0x26, 0x7D, 0x1C, 0x4D, 0x17,
0xBC, 0xC9, 0xEC, 0x43, 0x26, 0xD0, 0xBF, 0x41, 0x5F, 0x40, 0xA9, 0x44,
0x44, 0xF4, 0x99, 0xE7, 0x57, 0x87, 0x9E, 0x50, 0x1F, 0x57, 0x54, 0xA8,
0x3E, 0xFD, 0x74, 0x63, 0x2F, 0xB1, 0x50, 0x65, 0x09, 0xE6, 0x58, 0x42,
0x2E, 0x43, 0x1A, 0x4C, 0xB4, 0xF0, 0x25, 0x47, 0x59, 0xFA, 0x04, 0x1E,
0x93, 0xD4, 0x26, 0x46, 0x4A, 0x50, 0x81, 0xB2, 0xDE, 0xBE, 0x78, 0xB7,
0xFC, 0x67, 0x15, 0xE1, 0xC9, 0x57, 0x84, 0x1E, 0x0F, 0x63, 0xD6, 0xE9,
0x62, 0xBA, 0xD6, 0x5F, 0x55, 0x2E, 0xEA, 0x5C, 0xC6, 0x28, 0x08, 0x04,
0x25, 0x39, 0xB8, 0x0E, 0x2B, 0xA9, 0xF2, 0x4C, 0x97, 0x1C, 0x07, 0x3F,
0x0D, 0x52, 0xF5, 0xED, 0xEF, 0x2F, 0x82, 0x0F
};
static const unsigned char TA56_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA57_DN[] = {
0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x0A, 0x4E, 0x65, 0x77, 0x20, 0x4A, 0x65, 0x72, 0x73, 0x65,
0x79, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0B,
0x4A, 0x65, 0x72, 0x73, 0x65, 0x79, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31,
0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x54, 0x68,
0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20,
0x4E, 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x2E, 0x30, 0x2C, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x25, 0x55, 0x53, 0x45, 0x52, 0x54, 0x72,
0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA57_EC_Q[] = {
0x04, 0x1A, 0xAC, 0x54, 0x5A, 0xA9, 0xF9, 0x68, 0x23, 0xE7, 0x7A, 0xD5,
0x24, 0x6F, 0x53, 0xC6, 0x5A, 0xD8, 0x4B, 0xAB, 0xC6, 0xD5, 0xB6, 0xD1,
0xE6, 0x73, 0x71, 0xAE, 0xDD, 0x9C, 0xD6, 0x0C, 0x61, 0xFD, 0xDB, 0xA0,
0x89, 0x03, 0xB8, 0x05, 0x14, 0xEC, 0x57, 0xCE, 0xEE, 0x5D, 0x3F, 0xE2,
0x21, 0xB3, 0xCE, 0xF7, 0xD4, 0x8A, 0x79, 0xE0, 0xA3, 0x83, 0x7E, 0x2D,
0x97, 0xD0, 0x61, 0xC4, 0xF1, 0x99, 0xDC, 0x25, 0x91, 0x63, 0xAB, 0x7F,
0x30, 0xA3, 0xB4, 0x70, 0xE2, 0xC7, 0xA1, 0x33, 0x9C, 0xF3, 0xBF, 0x2E,
0x5C, 0x53, 0xB1, 0x5F, 0xB3, 0x7D, 0x32, 0x7F, 0x8A, 0x34, 0xE3, 0x79,
0x79
};
static const unsigned char TA58_DN[] = {
0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20,
0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20,
0x2D, 0x20, 0x52, 0x35, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67,
0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A,
0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E
};
static const unsigned char TA58_EC_Q[] = {
0x04, 0x47, 0x45, 0x0E, 0x96, 0xFB, 0x7D, 0x5D, 0xBF, 0xE9, 0x39, 0xD1,
0x21, 0xF8, 0x9F, 0x0B, 0xB6, 0xD5, 0x7B, 0x1E, 0x92, 0x3A, 0x48, 0x59,
0x1C, 0xF0, 0x62, 0x31, 0x2D, 0xC0, 0x7A, 0x28, 0xFE, 0x1A, 0xA7, 0x5C,
0xB3, 0xB6, 0xCC, 0x97, 0xE7, 0x45, 0xD4, 0x58, 0xFA, 0xD1, 0x77, 0x6D,
0x43, 0xA2, 0xC0, 0x87, 0x65, 0x34, 0x0A, 0x1F, 0x7A, 0xDD, 0xEB, 0x3C,
0x33, 0xA1, 0xC5, 0x9D, 0x4D, 0xA4, 0x6F, 0x41, 0x95, 0x38, 0x7F, 0xC9,
0x1E, 0x84, 0xEB, 0xD1, 0x9E, 0x49, 0x92, 0x87, 0x94, 0x87, 0x0C, 0x3A,
0x85, 0x4A, 0x66, 0x9F, 0x9D, 0x59, 0x93, 0x4D, 0x97, 0x61, 0x06, 0x86,
0x4A
};
static const unsigned char TA59_DN[] = {
0x30, 0x4A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31,
0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1E, 0x49, 0x64,
0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x43, 0x6F, 0x6D, 0x6D,
0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x41, 0x20, 0x31
};
static const unsigned char TA59_RSA_N[] = {
0xA7, 0x50, 0x19, 0xDE, 0x3F, 0x99, 0x3D, 0xD4, 0x33, 0x46, 0xF1, 0x6F,
0x51, 0x61, 0x82, 0xB2, 0xA9, 0x4F, 0x8F, 0x67, 0x89, 0x5D, 0x84, 0xD9,
0x53, 0xDD, 0x0C, 0x28, 0xD9, 0xD7, 0xF0, 0xFF, 0xAE, 0x95, 0x43, 0x72,
0x99, 0xF9, 0xB5, 0x5D, 0x7C, 0x8A, 0xC1, 0x42, 0xE1, 0x31, 0x50, 0x74,
0xD1, 0x81, 0x0D, 0x7C, 0xCD, 0x9B, 0x21, 0xAB, 0x43, 0xE2, 0xAC, 0xAD,
0x5E, 0x86, 0x6E, 0xF3, 0x09, 0x8A, 0x1F, 0x5A, 0x32, 0xBD, 0xA2, 0xEB,
0x94, 0xF9, 0xE8, 0x5C, 0x0A, 0xEC, 0xFF, 0x98, 0xD2, 0xAF, 0x71, 0xB3,
0xB4, 0x53, 0x9F, 0x4E, 0x87, 0xEF, 0x92, 0xBC, 0xBD, 0xEC, 0x4F, 0x32,
0x30, 0x88, 0x4B, 0x17, 0x5E, 0x57, 0xC4, 0x53, 0xC2, 0xF6, 0x02, 0x97,
0x8D, 0xD9, 0x62, 0x2B, 0xBF, 0x24, 0x1F, 0x62, 0x8D, 0xDF, 0xC3, 0xB8,
0x29, 0x4B, 0x49, 0x78, 0x3C, 0x93, 0x60, 0x88, 0x22, 0xFC, 0x99, 0xDA,
0x36, 0xC8, 0xC2, 0xA2, 0xD4, 0x2C, 0x54, 0x00, 0x67, 0x35, 0x6E, 0x73,
0xBF, 0x02, 0x58, 0xF0, 0xA4, 0xDD, 0xE5, 0xB0, 0xA2, 0x26, 0x7A, 0xCA,
0xE0, 0x36, 0xA5, 0x19, 0x16, 0xF5, 0xFD, 0xB7, 0xEF, 0xAE, 0x3F, 0x40,
0xF5, 0x6D, 0x5A, 0x04, 0xFD, 0xCE, 0x34, 0xCA, 0x24, 0xDC, 0x74, 0x23,
0x1B, 0x5D, 0x33, 0x13, 0x12, 0x5D, 0xC4, 0x01, 0x25, 0xF6, 0x30, 0xDD,
0x02, 0x5D, 0x9F, 0xE0, 0xD5, 0x47, 0xBD, 0xB4, 0xEB, 0x1B, 0xA1, 0xBB,
0x49, 0x49, 0xD8, 0x9F, 0x5B, 0x02, 0xF3, 0x8A, 0xE4, 0x24, 0x90, 0xE4,
0x62, 0x4F, 0x4F, 0xC1, 0xAF, 0x8B, 0x0E, 0x74, 0x17, 0xA8, 0xD1, 0x72,
0x88, 0x6A, 0x7A, 0x01, 0x49, 0xCC, 0xB4, 0x46, 0x79, 0xC6, 0x17, 0xB1,
0xDA, 0x98, 0x1E, 0x07, 0x59, 0xFA, 0x75, 0x21, 0x85, 0x65, 0xDD, 0x90,
0x56, 0xCE, 0xFB, 0xAB, 0xA5, 0x60, 0x9D, 0xC4, 0x9D, 0xF9, 0x52, 0xB0,
0x8B, 0xBD, 0x87, 0xF9, 0x8F, 0x2B, 0x23, 0x0A, 0x23, 0x76, 0x3B, 0xF7,
0x33, 0xE1, 0xC9, 0x00, 0xF3, 0x69, 0xF9, 0x4B, 0xA2, 0xE0, 0x4E, 0xBC,
0x7E, 0x93, 0x39, 0x84, 0x07, 0xF7, 0x44, 0x70, 0x7E, 0xFE, 0x07, 0x5A,
0xE5, 0xB1, 0xAC, 0xD1, 0x18, 0xCC, 0xF2, 0x35, 0xE5, 0x49, 0x49, 0x08,
0xCA, 0x56, 0xC9, 0x3D, 0xFB, 0x0F, 0x18, 0x7D, 0x8B, 0x3B, 0xC1, 0x13,
0xC2, 0x4D, 0x8F, 0xC9, 0x4F, 0x0E, 0x37, 0xE9, 0x1F, 0xA1, 0x0E, 0x6A,
0xDF, 0x62, 0x2E, 0xCB, 0x35, 0x06, 0x51, 0x79, 0x2C, 0xC8, 0x25, 0x38,
0xF4, 0xFA, 0x4B, 0xA7, 0x89, 0x5C, 0x9C, 0xD2, 0xE3, 0x0D, 0x39, 0x86,
0x4A, 0x74, 0x7C, 0xD5, 0x59, 0x87, 0xC2, 0x3F, 0x4E, 0x0C, 0x5C, 0x52,
0xF4, 0x3D, 0xF7, 0x52, 0x82, 0xF1, 0xEA, 0xA3, 0xAC, 0xFD, 0x49, 0x34,
0x1A, 0x28, 0xF3, 0x41, 0x88, 0x3A, 0x13, 0xEE, 0xE8, 0xDE, 0xFF, 0x99,
0x1D, 0x5F, 0xBA, 0xCB, 0xE8, 0x1E, 0xF2, 0xB9, 0x50, 0x60, 0xC0, 0x31,
0xD3, 0x73, 0xE5, 0xEF, 0xBE, 0xA0, 0xED, 0x33, 0x0B, 0x74, 0xBE, 0x20,
0x20, 0xC4, 0x67, 0x6C, 0xF0, 0x08, 0x03, 0x7A, 0x55, 0x80, 0x7F, 0x46,
0x4E, 0x96, 0xA7, 0xF4, 0x1E, 0x3E, 0xE1, 0xF6, 0xD8, 0x09, 0xE1, 0x33,
0x64, 0x2B, 0x63, 0xD7, 0x32, 0x5E, 0x9F, 0xF9, 0xC0, 0x7B, 0x0F, 0x78,
0x6F, 0x97, 0xBC, 0x93, 0x9A, 0xF9, 0x9C, 0x12, 0x90, 0x78, 0x7A, 0x80,
0x87, 0x15, 0xD7, 0x72, 0x74, 0x9C, 0x55, 0x74, 0x78, 0xB1, 0xBA, 0xE1,
0x6E, 0x70, 0x04, 0xBA, 0x4F, 0xA0, 0xBA, 0x68, 0xC3, 0x7B, 0xFF, 0x31,
0xF0, 0x73, 0x3D, 0x3D, 0x94, 0x2A, 0xB1, 0x0B, 0x41, 0x0E, 0xA0, 0xFE,
0x4D, 0x88, 0x65, 0x6B, 0x79, 0x33, 0xB4, 0xD7
};
static const unsigned char TA59_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA60_DN[] = {
0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x49, 0x64, 0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31,
0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x21, 0x49, 0x64,
0x65, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x50, 0x75, 0x62, 0x6C,
0x69, 0x63, 0x20, 0x53, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31
};
static const unsigned char TA60_RSA_N[] = {
0xB6, 0x22, 0x94, 0xFC, 0xA4, 0x48, 0xAF, 0xE8, 0x47, 0x6B, 0x0A, 0xFB,
0x27, 0x76, 0xE4, 0xF2, 0x3F, 0x8A, 0x3B, 0x7A, 0x4A, 0x2C, 0x31, 0x2A,
0x8C, 0x8D, 0xB0, 0xA9, 0xC3, 0x31, 0x6B, 0xA8, 0x77, 0x76, 0x84, 0x26,
0xB6, 0xAC, 0x81, 0x42, 0x0D, 0x08, 0xEB, 0x55, 0x58, 0xBB, 0x7A, 0xF8,
0xBC, 0x65, 0x7D, 0xF2, 0xA0, 0x6D, 0x8B, 0xA8, 0x47, 0xE9, 0x62, 0x76,
0x1E, 0x11, 0xEE, 0x08, 0x14, 0xD1, 0xB2, 0x44, 0x16, 0xF4, 0xEA, 0xD0,
0xFA, 0x1E, 0x2F, 0x5E, 0xDB, 0xCB, 0x73, 0x41, 0xAE, 0xBC, 0x00, 0xB0,
0x4A, 0x2B, 0x40, 0xB2, 0xAC, 0xE1, 0x3B, 0x4B, 0xC2, 0x2D, 0x9D, 0xE4,
0xA1, 0x9B, 0xEC, 0x1A, 0x3A, 0x1E, 0xF0, 0x08, 0xB3, 0xD0, 0xE4, 0x24,
0x35, 0x07, 0x9F, 0x9C, 0xB4, 0xC9, 0x52, 0x6D, 0xDB, 0x07, 0xCA, 0x8F,
0xB5, 0x5B, 0xF0, 0x83, 0xF3, 0x4F, 0xC7, 0x2D, 0xA5, 0xC8, 0xAD, 0xCB,
0x95, 0x20, 0xA4, 0x31, 0x28, 0x57, 0x58, 0x5A, 0xE4, 0x8D, 0x1B, 0x9A,
0xAB, 0x9E, 0x0D, 0x0C, 0xF2, 0x0A, 0x33, 0x39, 0x22, 0x39, 0x0A, 0x97,
0x2E, 0xF3, 0x53, 0x77, 0xB9, 0x44, 0x45, 0xFD, 0x84, 0xCB, 0x36, 0x20,
0x81, 0x59, 0x2D, 0x9A, 0x6F, 0x6D, 0x48, 0x48, 0x61, 0xCA, 0x4C, 0xDF,
0x53, 0xD1, 0xAF, 0x52, 0xBC, 0x44, 0x9F, 0xAB, 0x2F, 0x6B, 0x83, 0x72,
0xEF, 0x75, 0x80, 0xDA, 0x06, 0x33, 0x1B, 0x5D, 0xC8, 0xDA, 0x63, 0xC6,
0x4D, 0xCD, 0xAC, 0x66, 0x31, 0xCD, 0xD1, 0xDE, 0x3E, 0x87, 0x10, 0x36,
0xE1, 0xB9, 0xA4, 0x7A, 0xEF, 0x60, 0x50, 0xB2, 0xCB, 0xCA, 0xA6, 0x56,
0xE0, 0x37, 0xAF, 0xAB, 0x34, 0x13, 0x39, 0x25, 0xE8, 0x39, 0x66, 0xE4,
0x98, 0x7A, 0xAA, 0x12, 0x98, 0x9C, 0x59, 0x66, 0x86, 0x3E, 0xAD, 0xF1,
0xB0, 0xCA, 0x3E, 0x06, 0x0F, 0x7B, 0xF0, 0x11, 0x4B, 0x37, 0xA0, 0x44,
0x6D, 0x7B, 0xCB, 0xA8, 0x8C, 0x71, 0xF4, 0xD5, 0xB5, 0x91, 0x36, 0xCC,
0xF0, 0x15, 0xC6, 0x2B, 0xDE, 0x51, 0x17, 0xB1, 0x97, 0x4C, 0x50, 0x3D,
0xB1, 0x95, 0x59, 0x7C, 0x05, 0x7D, 0x2D, 0x21, 0xD5, 0x00, 0xBF, 0x01,
0x67, 0xA2, 0x5E, 0x7B, 0xA6, 0x5C, 0xF2, 0xF7, 0x22, 0xF1, 0x90, 0x0D,
0x93, 0xDB, 0xAA, 0x44, 0x51, 0x66, 0xCC, 0x7D, 0x76, 0x03, 0xEB, 0x6A,
0xA8, 0x2A, 0x38, 0x19, 0x97, 0x76, 0x0D, 0x6B, 0x8A, 0x61, 0xF9, 0xBC,
0xF6, 0xEE, 0x76, 0xFD, 0x70, 0x2B, 0xDD, 0x29, 0x3C, 0xF8, 0x0A, 0x1E,
0x5B, 0x42, 0x1C, 0x8B, 0x56, 0x2F, 0x55, 0x1B, 0x1C, 0xA1, 0x2E, 0xB5,
0xC7, 0x16, 0xE6, 0xF8, 0xAA, 0x3C, 0x92, 0x8E, 0x69, 0xB6, 0x01, 0xC1,
0xB5, 0x86, 0x9D, 0x89, 0x0F, 0x0B, 0x38, 0x94, 0x54, 0xE8, 0xEA, 0xDC,
0x9E, 0x3D, 0x25, 0xBC, 0x53, 0x26, 0xED, 0xD5, 0xAB, 0x39, 0xAA, 0xC5,
0x40, 0x4C, 0x54, 0xAB, 0xB2, 0xB4, 0xD9, 0xD9, 0xF8, 0xD7, 0x72, 0xDB,
0x1C, 0xBC, 0x6D, 0xBD, 0x65, 0x5F, 0xEF, 0x88, 0x35, 0x2A, 0x66, 0x2F,
0xEE, 0xF6, 0xB3, 0x65, 0xF0, 0x33, 0x8D, 0x7C, 0x98, 0x41, 0x69, 0x46,
0x0F, 0x43, 0x1C, 0x69, 0xFA, 0x9B, 0xB5, 0xD0, 0x61, 0x6A, 0xCD, 0xCA,
0x4B, 0xD9, 0x4C, 0x90, 0x46, 0xAB, 0x15, 0x59, 0xA1, 0x47, 0x54, 0x29,
0x2E, 0x83, 0x28, 0x5F, 0x1C, 0xC2, 0xA2, 0xAB, 0x72, 0x17, 0x00, 0x06,
0x8E, 0x45, 0xEC, 0x8B, 0xE2, 0x33, 0x3D, 0x7F, 0xDA, 0x19, 0x44, 0xE4,
0x62, 0x72, 0xC3, 0xDF, 0x22, 0xC6, 0xF2, 0x56, 0xD4, 0xDD, 0x5F, 0x95,
0x72, 0xED, 0x6D, 0x5F, 0xF7, 0x48, 0x03, 0x5B, 0xFD, 0xC5, 0x2A, 0xA0,
0xF6, 0x73, 0x23, 0x84, 0x10, 0x1B, 0x01, 0xE7
};
static const unsigned char TA60_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA61_DN[] = {
0x30, 0x81, 0xBE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04,
0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65,
0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C,
0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39,
0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29,
0x20, 0x32, 0x30, 0x30, 0x39, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73,
0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F,
0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64,
0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x32, 0x30,
0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, 0x45, 0x6E, 0x74, 0x72,
0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x47,
0x32
};
static const unsigned char TA61_RSA_N[] = {
0xBA, 0x84, 0xB6, 0x72, 0xDB, 0x9E, 0x0C, 0x6B, 0xE2, 0x99, 0xE9, 0x30,
0x01, 0xA7, 0x76, 0xEA, 0x32, 0xB8, 0x95, 0x41, 0x1A, 0xC9, 0xDA, 0x61,
0x4E, 0x58, 0x72, 0xCF, 0xFE, 0xF6, 0x82, 0x79, 0xBF, 0x73, 0x61, 0x06,
0x0A, 0xA5, 0x27, 0xD8, 0xB3, 0x5F, 0xD3, 0x45, 0x4E, 0x1C, 0x72, 0xD6,
0x4E, 0x32, 0xF2, 0x72, 0x8A, 0x0F, 0xF7, 0x83, 0x19, 0xD0, 0x6A, 0x80,
0x80, 0x00, 0x45, 0x1E, 0xB0, 0xC7, 0xE7, 0x9A, 0xBF, 0x12, 0x57, 0x27,
0x1C, 0xA3, 0x68, 0x2F, 0x0A, 0x87, 0xBD, 0x6A, 0x6B, 0x0E, 0x5E, 0x65,
0xF3, 0x1C, 0x77, 0xD5, 0xD4, 0x85, 0x8D, 0x70, 0x21, 0xB4, 0xB3, 0x32,
0xE7, 0x8B, 0xA2, 0xD5, 0x86, 0x39, 0x02, 0xB1, 0xB8, 0xD2, 0x47, 0xCE,
0xE4, 0xC9, 0x49, 0xC4, 0x3B, 0xA7, 0xDE, 0xFB, 0x54, 0x7D, 0x57, 0xBE,
0xF0, 0xE8, 0x6E, 0xC2, 0x79, 0xB2, 0x3A, 0x0B, 0x55, 0xE2, 0x50, 0x98,
0x16, 0x32, 0x13, 0x5C, 0x2F, 0x78, 0x56, 0xC1, 0xC2, 0x94, 0xB3, 0xF2,
0x5A, 0xE4, 0x27, 0x9A, 0x9F, 0x24, 0xD7, 0xC6, 0xEC, 0xD0, 0x9B, 0x25,
0x82, 0xE3, 0xCC, 0xC2, 0xC4, 0x45, 0xC5, 0x8C, 0x97, 0x7A, 0x06, 0x6B,
0x2A, 0x11, 0x9F, 0xA9, 0x0A, 0x6E, 0x48, 0x3B, 0x6F, 0xDB, 0xD4, 0x11,
0x19, 0x42, 0xF7, 0x8F, 0x07, 0xBF, 0xF5, 0x53, 0x5F, 0x9C, 0x3E, 0xF4,
0x17, 0x2C, 0xE6, 0x69, 0xAC, 0x4E, 0x32, 0x4C, 0x62, 0x77, 0xEA, 0xB7,
0xE8, 0xE5, 0xBB, 0x34, 0xBC, 0x19, 0x8B, 0xAE, 0x9C, 0x51, 0xE7, 0xB7,
0x7E, 0xB5, 0x53, 0xB1, 0x33, 0x22, 0xE5, 0x6D, 0xCF, 0x70, 0x3C, 0x1A,
0xFA, 0xE2, 0x9B, 0x67, 0xB6, 0x83, 0xF4, 0x8D, 0xA5, 0xAF, 0x62, 0x4C,
0x4D, 0xE0, 0x58, 0xAC, 0x64, 0x34, 0x12, 0x03, 0xF8, 0xB6, 0x8D, 0x94,
0x63, 0x24, 0xA4, 0x71
};
static const unsigned char TA61_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA62_DN[] = {
0x30, 0x81, 0xBF, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x13, 0x0D, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04,
0x0B, 0x13, 0x1F, 0x53, 0x65, 0x65, 0x20, 0x77, 0x77, 0x77, 0x2E, 0x65,
0x6E, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x6C,
0x65, 0x67, 0x61, 0x6C, 0x2D, 0x74, 0x65, 0x72, 0x6D, 0x73, 0x31, 0x39,
0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x30, 0x28, 0x63, 0x29,
0x20, 0x32, 0x30, 0x31, 0x32, 0x20, 0x45, 0x6E, 0x74, 0x72, 0x75, 0x73,
0x74, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x20, 0x2D, 0x20, 0x66, 0x6F,
0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x7A, 0x65, 0x64,
0x20, 0x75, 0x73, 0x65, 0x20, 0x6F, 0x6E, 0x6C, 0x79, 0x31, 0x33, 0x30,
0x31, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2A, 0x45, 0x6E, 0x74, 0x72,
0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72,
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x2D, 0x20, 0x45,
0x43, 0x31
};
static const unsigned char TA62_EC_Q[] = {
0x04, 0x84, 0x13, 0xC9, 0xD0, 0xBA, 0x6D, 0x41, 0x7B, 0xE2, 0x6C, 0xD0,
0xEB, 0x55, 0x5F, 0x66, 0x02, 0x1A, 0x24, 0xF4, 0x5B, 0x89, 0x69, 0x47,
0xE3, 0xB8, 0xC2, 0x7D, 0xF1, 0xF2, 0x02, 0xC5, 0x9F, 0xA0, 0xF6, 0x5B,
0xD5, 0x8B, 0x06, 0x19, 0x86, 0x4F, 0x53, 0x10, 0x6D, 0x07, 0x24, 0x27,
0xA1, 0xA0, 0xF8, 0xD5, 0x47, 0x19, 0x61, 0x4C, 0x7D, 0xCA, 0x93, 0x27,
0xEA, 0x74, 0x0C, 0xEF, 0x6F, 0x96, 0x09, 0xFE, 0x63, 0xEC, 0x70, 0x5D,
0x36, 0xAD, 0x67, 0x77, 0xAE, 0xC9, 0x9D, 0x7C, 0x55, 0x44, 0x3A, 0xA2,
0x63, 0x51, 0x1F, 0xF5, 0xE3, 0x62, 0xD4, 0xA9, 0x47, 0x07, 0x3E, 0xCC,
0x20
};
static const unsigned char TA63_DN[] = {
0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x30, 0x30, 0x2E, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x27, 0x43, 0x68, 0x69, 0x6E, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x61,
0x6E, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68,
0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0C, 0x0C, 0x43, 0x46, 0x43, 0x41, 0x20, 0x45, 0x56, 0x20,
0x52, 0x4F, 0x4F, 0x54
};
static const unsigned char TA63_RSA_N[] = {
0xD7, 0x5D, 0x6B, 0xCD, 0x10, 0x3F, 0x1F, 0x05, 0x59, 0xD5, 0x05, 0x4D,
0x37, 0xB1, 0x0E, 0xEC, 0x98, 0x2B, 0x8E, 0x15, 0x1D, 0xFA, 0x93, 0x4B,
0x17, 0x82, 0x21, 0x71, 0x10, 0x52, 0xD7, 0x51, 0x64, 0x70, 0x16, 0xC2,
0x55, 0x69, 0x4D, 0x8E, 0x15, 0x6D, 0x9F, 0xBF, 0x0C, 0x1B, 0xC2, 0xE0,
0xA3, 0x67, 0xD6, 0x0C, 0xAC, 0xCF, 0x22, 0xAE, 0xAF, 0x77, 0x54, 0x2A,
0x4B, 0x4C, 0x8A, 0x53, 0x52, 0x7A, 0xC3, 0xEE, 0x2E, 0xDE, 0xB3, 0x71,
0x25, 0xC1, 0xE9, 0x5D, 0x3D, 0xEE, 0xA1, 0x2F, 0xA3, 0xF7, 0x2A, 0x3C,
0xC9, 0x23, 0x1D, 0x6A, 0xAB, 0x1D, 0xA1, 0xA7, 0xF1, 0xF3, 0xEC, 0xA0,
0xD5, 0x44, 0xCF, 0x15, 0xCF, 0x72, 0x2F, 0x1D, 0x63, 0x97, 0xE8, 0x99,
0xF9, 0xFD, 0x93, 0xA4, 0x54, 0x80, 0x4C, 0x52, 0xD4, 0x52, 0xAB, 0x2E,
0x49, 0xDF, 0x90, 0xCD, 0xB8, 0x5F, 0xBE, 0x3F, 0xDE, 0xA1, 0xCA, 0x4D,
0x20, 0xD4, 0x25, 0xE8, 0x84, 0x29, 0x53, 0xB7, 0xB1, 0x88, 0x1F, 0xFF,
0xFA, 0xDA, 0x90, 0x9F, 0x0A, 0xA9, 0x2D, 0x41, 0x3F, 0xB1, 0xF1, 0x18,
0x29, 0xEE, 0x16, 0x59, 0x2C, 0x34, 0x49, 0x1A, 0xA8, 0x06, 0xD7, 0xA8,
0x88, 0xD2, 0x03, 0x72, 0x7A, 0x32, 0xE2, 0xEA, 0x68, 0x4D, 0x6E, 0x2C,
0x96, 0x65, 0x7B, 0xCA, 0x59, 0xFA, 0xF2, 0xE2, 0xDD, 0xEE, 0x30, 0x2C,
0xFB, 0xCC, 0x46, 0xAC, 0xC4, 0x63, 0xEB, 0x6F, 0x7F, 0x36, 0x2B, 0x34,
0x73, 0x12, 0x94, 0x7F, 0xDF, 0xCC, 0x26, 0x9E, 0xF1, 0x72, 0x5D, 0x50,
0x65, 0x59, 0x8F, 0x69, 0xB3, 0x87, 0x5E, 0x32, 0x6F, 0xC3, 0x18, 0x8A,
0xB5, 0x95, 0x8F, 0xB0, 0x7A, 0x37, 0xDE, 0x5A, 0x45, 0x3B, 0xC7, 0x36,
0xE1, 0xEF, 0x67, 0xD1, 0x39, 0xD3, 0x97, 0x5B, 0x73, 0x62, 0x19, 0x48,
0x2D, 0x87, 0x1C, 0x06, 0xFB, 0x74, 0x98, 0x20, 0x49, 0x73, 0xF0, 0x05,
0xD2, 0x1B, 0xB1, 0xA0, 0xA3, 0xB7, 0x1B, 0x70, 0xD3, 0x88, 0x69, 0xB9,
0x5A, 0xD6, 0x38, 0xF4, 0x62, 0xDC, 0x25, 0x8B, 0x78, 0xBF, 0xF8, 0xE8,
0x7E, 0xB8, 0x5C, 0xC9, 0x95, 0x4F, 0x5F, 0xA7, 0x2D, 0xB9, 0x20, 0x6B,
0xCF, 0x6B, 0xDD, 0xF5, 0x0D, 0xF4, 0x82, 0xB7, 0xF4, 0xB2, 0x66, 0x2E,
0x10, 0x28, 0xF6, 0x97, 0x5A, 0x7B, 0x96, 0x16, 0x8F, 0x01, 0x19, 0x2D,
0x6C, 0x6E, 0x7F, 0x39, 0x58, 0x06, 0x64, 0x83, 0x01, 0x83, 0x83, 0xC3,
0x4D, 0x92, 0xDD, 0x32, 0xC6, 0x87, 0xA4, 0x37, 0xE9, 0x16, 0xCE, 0xAA,
0x2D, 0x68, 0xAF, 0x0A, 0x81, 0x65, 0x3A, 0x70, 0xC1, 0x9B, 0xAD, 0x4D,
0x6D, 0x54, 0xCA, 0x2A, 0x2D, 0x4B, 0x85, 0x1B, 0xB3, 0x80, 0xE6, 0x70,
0x45, 0x0D, 0x6B, 0x5E, 0x35, 0xF0, 0x7F, 0x3B, 0xB8, 0x9C, 0xE4, 0x04,
0x70, 0x89, 0x12, 0x25, 0x93, 0xDA, 0x0A, 0x99, 0x22, 0x60, 0x6A, 0x63,
0x60, 0x4E, 0x76, 0x06, 0x98, 0x4E, 0xBD, 0x83, 0xAD, 0x1D, 0x58, 0x8A,
0x25, 0x85, 0xD2, 0xC7, 0x65, 0x1E, 0x2D, 0x8E, 0xC6, 0xDF, 0xB6, 0xC6,
0xE1, 0x7F, 0x8A, 0x04, 0x21, 0x15, 0x29, 0x74, 0xF0, 0x3E, 0x9C, 0x90,
0x9D, 0x0C, 0x2E, 0xF1, 0x8A, 0x3E, 0x5A, 0xAA, 0x0C, 0x09, 0x1E, 0xC7,
0xD5, 0x3C, 0xA3, 0xED, 0x97, 0xC3, 0x1E, 0x34, 0xFA, 0x38, 0xF9, 0x08,
0x0E, 0xE3, 0xC0, 0x5D, 0x2B, 0x83, 0xD1, 0x56, 0x6A, 0xC9, 0xB6, 0xA8,
0x54, 0x53, 0x2E, 0x78, 0x32, 0x67, 0x3D, 0x82, 0x7F, 0x74, 0xD0, 0xFB,
0xE1, 0xB6, 0x05, 0x60, 0xB9, 0x70, 0xDB, 0x8E, 0x0B, 0xF9, 0x13, 0x58,
0x6F, 0x71, 0x60, 0x10, 0x52, 0x10, 0xB9, 0xC1, 0x41, 0x09, 0xEF, 0x72,
0x1F, 0x67, 0x31, 0x78, 0xFF, 0x96, 0x05, 0x8D
};
static const unsigned char TA63_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA64_DN[] = {
0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30,
0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54,
0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E,
0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30,
0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54,
0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C,
0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x42,
0x20, 0x43, 0x41
};
static const unsigned char TA64_RSA_N[] = {
0xD8, 0x17, 0xB7, 0x1C, 0x4A, 0x24, 0x2A, 0xD6, 0x97, 0xB1, 0xCA, 0xE2,
0x1E, 0xFB, 0x7D, 0x38, 0xEF, 0x98, 0xF5, 0xB2, 0x39, 0x98, 0x4E, 0x27,
0xB8, 0x11, 0x5D, 0x7B, 0xD2, 0x25, 0x94, 0x88, 0x82, 0x15, 0x26, 0x6A,
0x1B, 0x31, 0xBB, 0xA8, 0x5B, 0x21, 0x21, 0x2B, 0xD8, 0x0F, 0x4E, 0x9F,
0x5A, 0xF1, 0xB1, 0x5A, 0xE4, 0x79, 0xD6, 0x32, 0x23, 0x2B, 0xE1, 0x53,
0xCC, 0x99, 0x45, 0x5C, 0x7B, 0x4F, 0xAD, 0xBC, 0xBF, 0x87, 0x4A, 0x0B,
0x4B, 0x97, 0x5A, 0xA8, 0xF6, 0x48, 0xEC, 0x7D, 0x7B, 0x0D, 0xCD, 0x21,
0x06, 0xDF, 0x9E, 0x15, 0xFD, 0x41, 0x8A, 0x48, 0xB7, 0x20, 0xF4, 0xA1,
0x7A, 0x1B, 0x57, 0xD4, 0x5D, 0x50, 0xFF, 0xBA, 0x67, 0xD8, 0x23, 0x99,
0x1F, 0xC8, 0x3F, 0xE3, 0xDE, 0xFF, 0x6F, 0x5B, 0x77, 0xB1, 0x6B, 0x6E,
0xB8, 0xC9, 0x64, 0xF7, 0xE1, 0xCA, 0x41, 0x46, 0x0E, 0x29, 0x71, 0xD0,
0xB9, 0x23, 0xFC, 0xC9, 0x81, 0x5F, 0x4E, 0xF7, 0x6F, 0xDF, 0xBF, 0x84,
0xAD, 0x73, 0x64, 0xBB, 0xB7, 0x42, 0x8E, 0x69, 0xF6, 0xD4, 0x76, 0x1D,
0x7E, 0x9D, 0xA7, 0xB8, 0x57, 0x8A, 0x51, 0x67, 0x72, 0xD7, 0xD4, 0xA8,
0xB8, 0x95, 0x54, 0x40, 0x73, 0x03, 0xF6, 0xEA, 0xF4, 0xEB, 0xFE, 0x28,
0x42, 0x77, 0x3F, 0x9D, 0x23, 0x1B, 0xB2, 0xB6, 0x3D, 0x80, 0x14, 0x07,
0x4C, 0x2E, 0x4F, 0xF7, 0xD5, 0x0A, 0x16, 0x0D, 0xBD, 0x66, 0x43, 0x37,
0x7E, 0x23, 0x43, 0x79, 0xC3, 0x40, 0x86, 0xF5, 0x4C, 0x29, 0xDA, 0x8E,
0x9A, 0xAD, 0x0D, 0xA5, 0x04, 0x87, 0x88, 0x1E, 0x85, 0xE3, 0xE9, 0x53,
0xD5, 0x9B, 0xC8, 0x8B, 0x03, 0x63, 0x78, 0xEB, 0xE0, 0x19, 0x4A, 0x6E,
0xBB, 0x2F, 0x6B, 0x33, 0x64, 0x58, 0x93, 0xAD, 0x69, 0xBF, 0x8F, 0x1B,
0xEF, 0x82, 0x48, 0xC7
};
static const unsigned char TA64_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA65_DN[] = {
0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x50, 0x4C, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1F, 0x4B, 0x72, 0x61, 0x6A, 0x6F, 0x77, 0x61, 0x20, 0x49, 0x7A,
0x62, 0x61, 0x20, 0x52, 0x6F, 0x7A, 0x6C, 0x69, 0x63, 0x7A, 0x65, 0x6E,
0x69, 0x6F, 0x77, 0x61, 0x20, 0x53, 0x2E, 0x41, 0x2E, 0x31, 0x18, 0x30,
0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x53, 0x5A, 0x41, 0x46,
0x49, 0x52, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x20, 0x43, 0x41, 0x32
};
static const unsigned char TA65_RSA_N[] = {
0xB7, 0xBC, 0x3E, 0x50, 0xA8, 0x4B, 0xCD, 0x40, 0xB5, 0xCE, 0x61, 0xE7,
0x96, 0xCA, 0xB4, 0xA1, 0xDA, 0x0C, 0x22, 0xB0, 0xFA, 0xB5, 0x7B, 0x76,
0x00, 0x77, 0x8C, 0x0B, 0xCF, 0x7D, 0xA8, 0x86, 0xCC, 0x26, 0x51, 0xE4,
0x20, 0x3D, 0x85, 0x0C, 0xD6, 0x58, 0xE3, 0xE7, 0xF4, 0x2A, 0x18, 0x9D,
0xDA, 0xD1, 0xAE, 0x26, 0xEE, 0xEB, 0x53, 0xDC, 0xF4, 0x90, 0xD6, 0x13,
0x4A, 0x0C, 0x90, 0x3C, 0xC3, 0xF4, 0xDA, 0xD2, 0x8E, 0x0D, 0x92, 0x3A,
0xDC, 0xB1, 0xB1, 0xFF, 0x38, 0xDE, 0xC3, 0xBA, 0x2D, 0x5F, 0x80, 0xB9,
0x02, 0xBD, 0x4A, 0x9D, 0x1B, 0x0F, 0xB4, 0xC3, 0xC2, 0xC1, 0x67, 0x03,
0xDD, 0xDC, 0x1B, 0x9C, 0x3D, 0xB3, 0xB0, 0xDE, 0x00, 0x1E, 0xA8, 0x34,
0x47, 0xBB, 0x9A, 0xEB, 0xFE, 0x0B, 0x14, 0xBD, 0x36, 0x84, 0xDA, 0x0D,
0x20, 0xBF, 0xFA, 0x5B, 0xCB, 0xA9, 0x16, 0x20, 0xAD, 0x39, 0x60, 0xEE,
0x2F, 0x75, 0xB6, 0xE7, 0x97, 0x9C, 0xF9, 0x3E, 0xFD, 0x7E, 0x4D, 0x6F,
0x4D, 0x2F, 0xEF, 0x88, 0x0D, 0x6A, 0xFA, 0xDD, 0xF1, 0x3D, 0x6E, 0x20,
0xA5, 0xA0, 0x12, 0xB4, 0x4D, 0x70, 0xB9, 0xCE, 0xD7, 0x72, 0x3B, 0x89,
0x93, 0xA7, 0x80, 0x84, 0x1C, 0x27, 0x49, 0x72, 0x49, 0xB5, 0xFF, 0x3B,
0x95, 0x9E, 0xC1, 0xCC, 0xC8, 0x01, 0xEC, 0xE8, 0x0E, 0x8A, 0x0A, 0x96,
0xE7, 0xB3, 0xA6, 0x87, 0xE5, 0xD6, 0xF9, 0x05, 0x2B, 0x0D, 0x97, 0x40,
0x70, 0x3C, 0xBA, 0xAC, 0x75, 0x5A, 0x9C, 0xD5, 0x4D, 0x9D, 0x02, 0x0A,
0xD2, 0x4B, 0x9B, 0x66, 0x4B, 0x46, 0x07, 0x17, 0x65, 0xAD, 0x9F, 0x6C,
0x88, 0x00, 0xDC, 0x22, 0x89, 0xE0, 0xE1, 0x64, 0xD4, 0x67, 0xBC, 0x31,
0x79, 0x61, 0x3C, 0xBB, 0xCA, 0x41, 0xCD, 0x5C, 0x6A, 0x00, 0xC8, 0x3C,
0x38, 0x8E, 0x58, 0xAF
};
static const unsigned char TA65_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA66_DN[] = {
0x30, 0x81, 0x80, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x50, 0x4C, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x13, 0x19, 0x55, 0x6E, 0x69, 0x7A, 0x65, 0x74, 0x6F, 0x20, 0x54,
0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20,
0x53, 0x2E, 0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04,
0x0B, 0x13, 0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65,
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20,
0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x24, 0x30,
0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1B, 0x43, 0x65, 0x72, 0x74,
0x75, 0x6D, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x4E,
0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x20, 0x43, 0x41, 0x20, 0x32
};
static const unsigned char TA66_RSA_N[] = {
0xBD, 0xF9, 0x78, 0xF8, 0xE6, 0xD5, 0x80, 0x0C, 0x64, 0x9D, 0x86, 0x1B,
0x96, 0x64, 0x67, 0x3F, 0x22, 0x3A, 0x1E, 0x75, 0x01, 0x7D, 0xEF, 0xFB,
0x5C, 0x67, 0x8C, 0xC9, 0xCC, 0x5C, 0x6B, 0xA9, 0x91, 0xE6, 0xB9, 0x42,
0xE5, 0x20, 0x4B, 0x9B, 0xDA, 0x9B, 0x7B, 0xB9, 0x99, 0x5D, 0xD9, 0x9B,
0x80, 0x4B, 0xD7, 0x84, 0x40, 0x2B, 0x27, 0xD3, 0xE8, 0xBA, 0x30, 0xBB,
0x3E, 0x09, 0x1A, 0xA7, 0x49, 0x95, 0xEF, 0x2B, 0x40, 0x24, 0xC2, 0x97,
0xC7, 0xA7, 0xEE, 0x9B, 0x25, 0xEF, 0xA8, 0x0A, 0x00, 0x97, 0x85, 0x5A,
0xAA, 0x9D, 0xDC, 0x29, 0xC9, 0xE2, 0x35, 0x07, 0xEB, 0x70, 0x4D, 0x4A,
0xD6, 0xC1, 0xB3, 0x56, 0xB8, 0xA1, 0x41, 0x38, 0x9B, 0xD1, 0xFB, 0x31,
0x7F, 0x8F, 0xE0, 0x5F, 0xE1, 0xB1, 0x3F, 0x0F, 0x8E, 0x16, 0x49, 0x60,
0xD7, 0x06, 0x8D, 0x18, 0xF9, 0xAA, 0x26, 0x10, 0xAB, 0x2A, 0xD3, 0xD0,
0xD1, 0x67, 0x8D, 0x1B, 0x46, 0xBE, 0x47, 0x30, 0xD5, 0x2E, 0x72, 0xD1,
0xC5, 0x63, 0xDA, 0xE7, 0x63, 0x79, 0x44, 0x7E, 0x4B, 0x63, 0x24, 0x89,
0x86, 0x2E, 0x34, 0x3F, 0x29, 0x4C, 0x52, 0x8B, 0x2A, 0xA7, 0xC0, 0xE2,
0x91, 0x28, 0x89, 0xB9, 0xC0, 0x5B, 0xF9, 0x1D, 0xD9, 0xE7, 0x27, 0xAD,
0xFF, 0x9A, 0x02, 0x97, 0xC1, 0xC6, 0x50, 0x92, 0x9B, 0x02, 0x2C, 0xBD,
0xA9, 0xB9, 0x34, 0x59, 0x0A, 0xBF, 0x84, 0x4A, 0xFF, 0xDF, 0xFE, 0xB3,
0x9F, 0xEB, 0xD9, 0x9E, 0xE0, 0x98, 0x23, 0xEC, 0xA6, 0x6B, 0x77, 0x16,
0x2A, 0xDB, 0xCC, 0xAD, 0x3B, 0x1C, 0xA4, 0x87, 0xDC, 0x46, 0x73, 0x5E,
0x19, 0x62, 0x68, 0x45, 0x57, 0xE4, 0x90, 0x82, 0x42, 0xBB, 0x42, 0xD6,
0xF0, 0x61, 0xE0, 0xC1, 0xA3, 0x3D, 0x66, 0xA3, 0x5D, 0xF4, 0x18, 0xEE,
0x88, 0xC9, 0x8D, 0x17, 0x45, 0x29, 0x99, 0x32, 0x75, 0x02, 0x31, 0xEE,
0x29, 0x26, 0xC8, 0x6B, 0x02, 0xE6, 0xB5, 0x62, 0x45, 0x7F, 0x37, 0x15,
0x5A, 0x23, 0x68, 0x89, 0xD4, 0x3E, 0xDE, 0x4E, 0x27, 0xB0, 0xF0, 0x40,
0x0C, 0xBC, 0x4D, 0x17, 0xCB, 0x4D, 0xA2, 0xB3, 0x1E, 0xD0, 0x06, 0x5A,
0xDD, 0xF6, 0x93, 0xCF, 0x57, 0x75, 0x99, 0xF5, 0xFA, 0x86, 0x1A, 0x67,
0x78, 0xB3, 0xBF, 0x96, 0xFE, 0x34, 0xDC, 0xBD, 0xE7, 0x52, 0x56, 0xE5,
0xB3, 0xE5, 0x75, 0x7B, 0xD7, 0x41, 0x91, 0x05, 0xDC, 0x5D, 0x69, 0xE3,
0x95, 0x0D, 0x43, 0xB9, 0xFC, 0x83, 0x96, 0x39, 0x95, 0x7B, 0x6C, 0x80,
0x5A, 0x4F, 0x13, 0x72, 0xC6, 0xD7, 0x7D, 0x29, 0x7A, 0x44, 0xBA, 0x52,
0xA4, 0x2A, 0xD5, 0x41, 0x46, 0x09, 0x20, 0xFE, 0x22, 0xA0, 0xB6, 0x5B,
0x30, 0x8D, 0xBC, 0x89, 0x0C, 0xD5, 0xD7, 0x70, 0xF8, 0x87, 0x52, 0xFD,
0xDA, 0xEF, 0xAC, 0x51, 0x2E, 0x07, 0xB3, 0x4E, 0xFE, 0xD0, 0x09, 0xDA,
0x70, 0xEF, 0x98, 0xFA, 0x56, 0xE6, 0x6D, 0xDB, 0xB5, 0x57, 0x4B, 0xDC,
0xE5, 0x2C, 0x25, 0x15, 0xC8, 0x9E, 0x2E, 0x78, 0x4E, 0xF8, 0xDA, 0x9C,
0x9E, 0x86, 0x2C, 0xCA, 0x57, 0xF3, 0x1A, 0xE5, 0xC8, 0x92, 0x8B, 0x1A,
0x82, 0x96, 0x7A, 0xC3, 0xBC, 0x50, 0x12, 0x69, 0xD8, 0x0E, 0x5A, 0x46,
0x8B, 0x3A, 0xEB, 0x26, 0xFA, 0x23, 0xC9, 0xB6, 0xB0, 0x81, 0xBE, 0x42,
0x00, 0xA4, 0xF8, 0xD6, 0xFE, 0x30, 0x2E, 0xC7, 0xD2, 0x46, 0xF6, 0xE5,
0x8E, 0x75, 0xFD, 0xF2, 0xCC, 0xB9, 0xD0, 0x87, 0x5B, 0xCC, 0x06, 0x10,
0x60, 0xBB, 0x83, 0x35, 0xB7, 0x5E, 0x67, 0xDE, 0x47, 0xEC, 0x99, 0x48,
0xF1, 0xA4, 0xA1, 0x15, 0xFE, 0xAD, 0x8C, 0x62, 0x8E, 0x39, 0x55, 0x4F,
0x39, 0x16, 0xB9, 0xB1, 0x63, 0x9D, 0xFF, 0xB7
};
static const unsigned char TA66_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA67_DN[] = {
0x30, 0x81, 0xA6, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04,
0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30,
0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C,
0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69,
0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72,
0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69,
0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x40, 0x30, 0x3E, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x37, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E,
0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20,
0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31,
0x35
};
static const unsigned char TA67_RSA_N[] = {
0xC2, 0xF8, 0xA9, 0x3F, 0x1B, 0x89, 0xFC, 0x3C, 0x3C, 0x04, 0x5D, 0x3D,
0x90, 0x36, 0xB0, 0x91, 0x3A, 0x79, 0x3C, 0x66, 0x5A, 0xEF, 0x6D, 0x39,
0x01, 0x49, 0x1A, 0xB4, 0xB7, 0xCF, 0x7F, 0x4D, 0x23, 0x53, 0xB7, 0x90,
0x00, 0xE3, 0x13, 0x2A, 0x28, 0xA6, 0x31, 0xF1, 0x91, 0x00, 0xE3, 0x28,
0xEC, 0xAE, 0x21, 0x41, 0xCE, 0x1F, 0xDA, 0xFD, 0x7D, 0x12, 0x5B, 0x01,
0x83, 0x0F, 0xB9, 0xB0, 0x5F, 0x99, 0xE1, 0xF2, 0x12, 0x83, 0x80, 0x4D,
0x06, 0x3E, 0xDF, 0xAC, 0xAF, 0xE7, 0xA1, 0x88, 0x6B, 0x31, 0xAF, 0xF0,
0x8B, 0xD0, 0x18, 0x33, 0xB8, 0xDB, 0x45, 0x6A, 0x34, 0xF4, 0x02, 0x80,
0x24, 0x28, 0x0A, 0x02, 0x15, 0x95, 0x5E, 0x76, 0x2A, 0x0D, 0x99, 0x3A,
0x14, 0x5B, 0xF6, 0xCB, 0xCB, 0x53, 0xBC, 0x13, 0x4D, 0x01, 0x88, 0x37,
0x94, 0x25, 0x1B, 0x42, 0xBC, 0x22, 0xD8, 0x8E, 0xA3, 0x96, 0x5E, 0x3A,
0xD9, 0x32, 0xDB, 0x3E, 0xE8, 0xF0, 0x10, 0x65, 0xED, 0x74, 0xE1, 0x2F,
0xA7, 0x7C, 0xAF, 0x27, 0x34, 0xBB, 0x29, 0x7D, 0x9B, 0xB6, 0xCF, 0x09,
0xC8, 0xE5, 0xD3, 0x0A, 0xFC, 0x88, 0x65, 0x65, 0x74, 0x0A, 0xDC, 0x73,
0x1C, 0x5C, 0xCD, 0x40, 0xB1, 0x1C, 0xD4, 0xB6, 0x84, 0x8C, 0x4C, 0x50,
0xCF, 0x68, 0x8E, 0xA8, 0x59, 0xAE, 0xC2, 0x27, 0x4E, 0x82, 0xA2, 0x35,
0xDD, 0x14, 0xF4, 0x1F, 0xFF, 0xB2, 0x77, 0xD5, 0x87, 0x2F, 0xAA, 0x6E,
0x7D, 0x24, 0x27, 0xE7, 0xC6, 0xCB, 0x26, 0xE6, 0xE5, 0xFE, 0x67, 0x07,
0x63, 0xD8, 0x45, 0x0D, 0xDD, 0x3A, 0x59, 0x65, 0x39, 0x58, 0x7A, 0x92,
0x99, 0x72, 0x3D, 0x9C, 0x84, 0x5E, 0x88, 0x21, 0xB8, 0xD5, 0xF4, 0x2C,
0xFC, 0xD9, 0x70, 0x52, 0x4F, 0x78, 0xB8, 0xBD, 0x3C, 0x2B, 0x8B, 0x95,
0x98, 0xF5, 0xB3, 0xD1, 0x68, 0xCF, 0x20, 0x14, 0x7E, 0x4C, 0x5C, 0x5F,
0xE7, 0x8B, 0xE5, 0xF5, 0x35, 0x81, 0x19, 0x37, 0xD7, 0x11, 0x08, 0xB7,
0x66, 0xBE, 0xD3, 0x4A, 0xCE, 0x83, 0x57, 0x00, 0x3A, 0xC3, 0x81, 0xF8,
0x17, 0xCB, 0x92, 0x36, 0x5D, 0xD1, 0xA3, 0xD8, 0x75, 0x1B, 0xE1, 0x8B,
0x27, 0xEA, 0x7A, 0x48, 0x41, 0xFD, 0x45, 0x19, 0x06, 0xAD, 0x27, 0x99,
0x4E, 0xC1, 0x70, 0x47, 0xDD, 0xB5, 0x9F, 0x81, 0x53, 0x12, 0xE5, 0xB1,
0x8C, 0x48, 0x5D, 0x31, 0x43, 0x17, 0xE3, 0x8C, 0xC6, 0x7A, 0x63, 0x96,
0x4B, 0x29, 0x30, 0x4E, 0x84, 0x4E, 0x62, 0x19, 0x5E, 0x3C, 0xCE, 0x97,
0x90, 0xA5, 0x7F, 0x01, 0xEB, 0x9D, 0xE0, 0xF8, 0x8B, 0x89, 0xDD, 0x25,
0x98, 0x3D, 0x92, 0xB6, 0x7E, 0xEF, 0xD9, 0xF1, 0x51, 0x51, 0x7D, 0x2D,
0x26, 0xC8, 0x69, 0x59, 0x61, 0xE0, 0xAC, 0x6A, 0xB8, 0x2A, 0x36, 0x11,
0x04, 0x7A, 0x50, 0xBD, 0x32, 0x84, 0xBE, 0x2F, 0xDC, 0x72, 0xD5, 0xD7,
0x1D, 0x16, 0x47, 0xE4, 0x47, 0x66, 0x20, 0x3F, 0xF4, 0x96, 0xC5, 0xAF,
0x8E, 0x01, 0x7A, 0xA5, 0x0F, 0x7A, 0x64, 0xF5, 0x0D, 0x18, 0x87, 0xD9,
0xAE, 0x88, 0xD5, 0xFA, 0x84, 0xC1, 0x3A, 0xC0, 0x69, 0x28, 0x2D, 0xF2,
0x0D, 0x68, 0x51, 0xAA, 0xE3, 0xA5, 0x77, 0xC6, 0xA4, 0x90, 0x0E, 0xA1,
0x37, 0x8B, 0x31, 0x23, 0x47, 0xC1, 0x09, 0x08, 0xEB, 0x6E, 0xF7, 0x78,
0x9B, 0xD7, 0x82, 0xFC, 0x84, 0x20, 0x99, 0x49, 0x19, 0xB6, 0x12, 0x46,
0xB1, 0xFB, 0x45, 0x55, 0x16, 0xA9, 0xA3, 0x65, 0xAC, 0x9C, 0x07, 0x0F,
0xEA, 0x6B, 0xDC, 0x1F, 0x2E, 0x06, 0x72, 0xEC, 0x86, 0x88, 0x12, 0xE4,
0x2D, 0xDB, 0x5F, 0x05, 0x2F, 0xE4, 0xF0, 0x03, 0xD3, 0x26, 0x33, 0xE7,
0x80, 0xC2, 0xCD, 0x42, 0xA1, 0x17, 0x34, 0x0B
};
static const unsigned char TA67_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA68_DN[] = {
0x30, 0x81, 0xAA, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x47, 0x52, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04,
0x07, 0x13, 0x06, 0x41, 0x74, 0x68, 0x65, 0x6E, 0x73, 0x31, 0x44, 0x30,
0x42, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C,
0x65, 0x6E, 0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69,
0x63, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72,
0x63, 0x68, 0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69,
0x6F, 0x6E, 0x73, 0x20, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x44, 0x30, 0x42, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x3B, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E,
0x69, 0x63, 0x20, 0x41, 0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20,
0x61, 0x6E, 0x64, 0x20, 0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
0x20, 0x49, 0x6E, 0x73, 0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E,
0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x41,
0x20, 0x32, 0x30, 0x31, 0x35
};
static const unsigned char TA68_EC_Q[] = {
0x04, 0x92, 0xA0, 0x41, 0xE8, 0x4B, 0x82, 0x84, 0x5C, 0xE2, 0xF8, 0x31,
0x11, 0x99, 0x86, 0x64, 0x4E, 0x09, 0x25, 0x2F, 0x9D, 0x41, 0x2F, 0x0A,
0xAE, 0x35, 0x4F, 0x74, 0x95, 0xB2, 0x51, 0x64, 0x6B, 0x8D, 0x6B, 0xE6,
0x3F, 0x70, 0x95, 0xF0, 0x05, 0x44, 0x47, 0xA6, 0x72, 0x38, 0x50, 0x76,
0x95, 0x02, 0x5A, 0x8E, 0xAE, 0x28, 0x9E, 0xF9, 0x2D, 0x4E, 0x99, 0xEF,
0x2C, 0x48, 0x6F, 0x4C, 0x25, 0x29, 0xE8, 0xD1, 0x71, 0x5B, 0xDF, 0x1D,
0xC1, 0x75, 0x37, 0xB4, 0xD7, 0xFA, 0x7B, 0x7A, 0x42, 0x9C, 0x6A, 0x0A,
0x56, 0x5A, 0x7C, 0x69, 0x0B, 0xAA, 0x80, 0x09, 0x24, 0x6C, 0x7E, 0xC1,
0x46
};
static const unsigned char TA69_DN[] = {
0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53,
0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65,
0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15,
0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52,
0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x31
};
static const unsigned char TA69_RSA_N[] = {
0xAD, 0xE8, 0x24, 0x73, 0xF4, 0x14, 0x37, 0xF3, 0x9B, 0x9E, 0x2B, 0x57,
0x28, 0x1C, 0x87, 0xBE, 0xDC, 0xB7, 0xDF, 0x38, 0x90, 0x8C, 0x6E, 0x3C,
0xE6, 0x57, 0xA0, 0x78, 0xF7, 0x75, 0xC2, 0xA2, 0xFE, 0xF5, 0x6A, 0x6E,
0xF6, 0x00, 0x4F, 0x28, 0xDB, 0xDE, 0x68, 0x86, 0x6C, 0x44, 0x93, 0xB6,
0xB1, 0x63, 0xFD, 0x14, 0x12, 0x6B, 0xBF, 0x1F, 0xD2, 0xEA, 0x31, 0x9B,
0x21, 0x7E, 0xD1, 0x33, 0x3C, 0xBA, 0x48, 0xF5, 0xDD, 0x79, 0xDF, 0xB3,
0xB8, 0xFF, 0x12, 0xF1, 0x21, 0x9A, 0x4B, 0xC1, 0x8A, 0x86, 0x71, 0x69,
0x4A, 0x66, 0x66, 0x6C, 0x8F, 0x7E, 0x3C, 0x70, 0xBF, 0xAD, 0x29, 0x22,
0x06, 0xF3, 0xE4, 0xC0, 0xE6, 0x80, 0xAE, 0xE2, 0x4B, 0x8F, 0xB7, 0x99,
0x7E, 0x94, 0x03, 0x9F, 0xD3, 0x47, 0x97, 0x7C, 0x99, 0x48, 0x23, 0x53,
0xE8, 0x38, 0xAE, 0x4F, 0x0A, 0x6F, 0x83, 0x2E, 0xD1, 0x49, 0x57, 0x8C,
0x80, 0x74, 0xB6, 0xDA, 0x2F, 0xD0, 0x38, 0x8D, 0x7B, 0x03, 0x70, 0x21,
0x1B, 0x75, 0xF2, 0x30, 0x3C, 0xFA, 0x8F, 0xAE, 0xDD, 0xDA, 0x63, 0xAB,
0xEB, 0x16, 0x4F, 0xC2, 0x8E, 0x11, 0x4B, 0x7E, 0xCF, 0x0B, 0xE8, 0xFF,
0xB5, 0x77, 0x2E, 0xF4, 0xB2, 0x7B, 0x4A, 0xE0, 0x4C, 0x12, 0x25, 0x0C,
0x70, 0x8D, 0x03, 0x29, 0xA0, 0xE1, 0x53, 0x24, 0xEC, 0x13, 0xD9, 0xEE,
0x19, 0xBF, 0x10, 0xB3, 0x4A, 0x8C, 0x3F, 0x89, 0xA3, 0x61, 0x51, 0xDE,
0xAC, 0x87, 0x07, 0x94, 0xF4, 0x63, 0x71, 0xEC, 0x2E, 0xE2, 0x6F, 0x5B,
0x98, 0x81, 0xE1, 0x89, 0x5C, 0x34, 0x79, 0x6C, 0x76, 0xEF, 0x3B, 0x90,
0x62, 0x79, 0xE6, 0xDB, 0xA4, 0x9A, 0x2F, 0x26, 0xC5, 0xD0, 0x10, 0xE1,
0x0E, 0xDE, 0xD9, 0x10, 0x8E, 0x16, 0xFB, 0xB7, 0xF7, 0xA8, 0xF7, 0xC7,
0xE5, 0x02, 0x07, 0x98, 0x8F, 0x36, 0x08, 0x95, 0xE7, 0xE2, 0x37, 0x96,
0x0D, 0x36, 0x75, 0x9E, 0xFB, 0x0E, 0x72, 0xB1, 0x1D, 0x9B, 0xBC, 0x03,
0xF9, 0x49, 0x05, 0xD8, 0x81, 0xDD, 0x05, 0xB4, 0x2A, 0xD6, 0x41, 0xE9,
0xAC, 0x01, 0x76, 0x95, 0x0A, 0x0F, 0xD8, 0xDF, 0xD5, 0xBD, 0x12, 0x1F,
0x35, 0x2F, 0x28, 0x17, 0x6C, 0xD2, 0x98, 0xC1, 0xA8, 0x09, 0x64, 0x77,
0x6E, 0x47, 0x37, 0xBA, 0xCE, 0xAC, 0x59, 0x5E, 0x68, 0x9D, 0x7F, 0x72,
0xD6, 0x89, 0xC5, 0x06, 0x41, 0x29, 0x3E, 0x59, 0x3E, 0xDD, 0x26, 0xF5,
0x24, 0xC9, 0x11, 0xA7, 0x5A, 0xA3, 0x4C, 0x40, 0x1F, 0x46, 0xA1, 0x99,
0xB5, 0xA7, 0x3A, 0x51, 0x6E, 0x86, 0x3B, 0x9E, 0x7D, 0x72, 0xA7, 0x12,
0x05, 0x78, 0x59, 0xED, 0x3E, 0x51, 0x78, 0x15, 0x0B, 0x03, 0x8F, 0x8D,
0xD0, 0x2F, 0x05, 0xB2, 0x3E, 0x7B, 0x4A, 0x1C, 0x4B, 0x73, 0x05, 0x12,
0xFC, 0xC6, 0xEA, 0xE0, 0x50, 0x13, 0x7C, 0x43, 0x93, 0x74, 0xB3, 0xCA,
0x74, 0xE7, 0x8E, 0x1F, 0x01, 0x08, 0xD0, 0x30, 0xD4, 0x5B, 0x71, 0x36,
0xB4, 0x07, 0xBA, 0xC1, 0x30, 0x30, 0x5C, 0x48, 0xB7, 0x82, 0x3B, 0x98,
0xA6, 0x7D, 0x60, 0x8A, 0xA2, 0xA3, 0x29, 0x82, 0xCC, 0xBA, 0xBD, 0x83,
0x04, 0x1B, 0xA2, 0x83, 0x03, 0x41, 0xA1, 0xD6, 0x05, 0xF1, 0x1B, 0xC2,
0xB6, 0xF0, 0xA8, 0x7C, 0x86, 0x3B, 0x46, 0xA8, 0x48, 0x2A, 0x88, 0xDC,
0x76, 0x9A, 0x76, 0xBF, 0x1F, 0x6A, 0xA5, 0x3D, 0x19, 0x8F, 0xEB, 0x38,
0xF3, 0x64, 0xDE, 0xC8, 0x2B, 0x0D, 0x0A, 0x28, 0xFF, 0xF7, 0xDB, 0xE2,
0x15, 0x42, 0xD4, 0x22, 0xD0, 0x27, 0x5D, 0xE1, 0x79, 0xFE, 0x18, 0xE7,
0x70, 0x88, 0xAD, 0x4E, 0xE6, 0xD9, 0x8B, 0x3A, 0xC6, 0xDD, 0x27, 0x51,
0x6E, 0xFF, 0xBC, 0x64, 0xF5, 0x33, 0x43, 0x4F
};
static const unsigned char TA69_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA70_DN[] = {
0x30, 0x3B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x19,
0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x41, 0x43, 0x20,
0x52, 0x41, 0x49, 0x5A, 0x20, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43,
0x4D
};
static const unsigned char TA70_RSA_N[] = {
0xBA, 0x71, 0x80, 0x7A, 0x4C, 0x86, 0x6E, 0x7F, 0xC8, 0x13, 0x6D, 0xC0,
0xC6, 0x7D, 0x1C, 0x00, 0x97, 0x8F, 0x2C, 0x0C, 0x23, 0xBB, 0x10, 0x9A,
0x40, 0xA9, 0x1A, 0xB7, 0x87, 0x88, 0xF8, 0x9B, 0x56, 0x6A, 0xFB, 0xE6,
0x7B, 0x8E, 0x8B, 0x92, 0x8E, 0xA7, 0x25, 0x5D, 0x59, 0x11, 0xDB, 0x36,
0x2E, 0xB7, 0x51, 0x17, 0x1F, 0xA9, 0x08, 0x1F, 0x04, 0x17, 0x24, 0x58,
0xAA, 0x37, 0x4A, 0x18, 0xDF, 0xE5, 0x39, 0xD4, 0x57, 0xFD, 0xD7, 0xC1,
0x2C, 0x91, 0x01, 0x91, 0xE2, 0x22, 0xD4, 0x03, 0xC0, 0x58, 0xFC, 0x77,
0x47, 0xEC, 0x8F, 0x3E, 0x74, 0x43, 0xBA, 0xAC, 0x34, 0x8D, 0x4D, 0x38,
0x76, 0x67, 0x8E, 0xB0, 0xC8, 0x6F, 0x30, 0x33, 0x58, 0x71, 0x5C, 0xB4,
0xF5, 0x6B, 0x6E, 0xD4, 0x01, 0x50, 0xB8, 0x13, 0x7E, 0x6C, 0x4A, 0xA3,
0x49, 0xD1, 0x20, 0x19, 0xEE, 0xBC, 0xC0, 0x29, 0x18, 0x65, 0xA7, 0xDE,
0xFE, 0xEF, 0xDD, 0x0A, 0x90, 0x21, 0xE7, 0x1A, 0x67, 0x92, 0x42, 0x10,
0x98, 0x5F, 0x4F, 0x30, 0xBC, 0x3E, 0x1C, 0x45, 0xB4, 0x10, 0xD7, 0x68,
0x40, 0x14, 0xC0, 0x40, 0xFA, 0xE7, 0x77, 0x17, 0x7A, 0xE6, 0x0B, 0x8F,
0x65, 0x5B, 0x3C, 0xD9, 0x9A, 0x52, 0xDB, 0xB5, 0xBD, 0x9E, 0x46, 0xCF,
0x3D, 0xEB, 0x91, 0x05, 0x02, 0xC0, 0x96, 0xB2, 0x76, 0x4C, 0x4D, 0x10,
0x96, 0x3B, 0x92, 0xFA, 0x9C, 0x7F, 0x0F, 0x99, 0xDF, 0xBE, 0x23, 0x35,
0x45, 0x1E, 0x02, 0x5C, 0xFE, 0xB5, 0xA8, 0x9B, 0x99, 0x25, 0xDA, 0x5E,
0xF3, 0x22, 0xC3, 0x39, 0xF5, 0xE4, 0x2A, 0x2E, 0xD3, 0xC6, 0x1F, 0xC4,
0x6C, 0xAA, 0xC5, 0x1C, 0x6A, 0x01, 0x05, 0x4A, 0x2F, 0xD2, 0xC5, 0xC1,
0xA8, 0x34, 0x26, 0x5D, 0x66, 0xA5, 0xD2, 0x02, 0x21, 0xF9, 0x18, 0xB7,
0x06, 0xF5, 0x4E, 0x99, 0x6F, 0xA8, 0xAB, 0x4C, 0x51, 0xE8, 0xCF, 0x50,
0x18, 0xC5, 0x77, 0xC8, 0x39, 0x09, 0x2C, 0x49, 0x92, 0x32, 0x99, 0xA8,
0xBB, 0x17, 0x17, 0x79, 0xB0, 0x5A, 0xC5, 0xE6, 0xA3, 0xC4, 0x59, 0x65,
0x47, 0x35, 0x83, 0x5E, 0xA9, 0xE8, 0x35, 0x0B, 0x99, 0xBB, 0xE4, 0xCD,
0x20, 0xC6, 0x9B, 0x4A, 0x06, 0x39, 0xB5, 0x68, 0xFC, 0x22, 0xBA, 0xEE,
0x55, 0x8C, 0x2B, 0x4E, 0xEA, 0xF3, 0xB1, 0xE3, 0xFC, 0xB6, 0x99, 0x9A,
0xD5, 0x42, 0xFA, 0x71, 0x4D, 0x08, 0xCF, 0x87, 0x1E, 0x6A, 0x71, 0x7D,
0xF9, 0xD3, 0xB4, 0xE9, 0xA5, 0x71, 0x81, 0x7B, 0xC2, 0x4E, 0x47, 0x96,
0xA5, 0xF6, 0x76, 0x85, 0xA3, 0x28, 0x8F, 0xE9, 0x80, 0x6E, 0x81, 0x53,
0xA5, 0x6D, 0x5F, 0xB8, 0x48, 0xF9, 0xC2, 0xF9, 0x36, 0xA6, 0x2E, 0x49,
0xFF, 0xB8, 0x96, 0xC2, 0x8C, 0x07, 0xB3, 0x9B, 0x88, 0x58, 0xFC, 0xEB,
0x1B, 0x1C, 0xDE, 0x2D, 0x70, 0xE2, 0x97, 0x92, 0x30, 0xA1, 0x89, 0xE3,
0xBC, 0x55, 0xA8, 0x27, 0xD6, 0x4B, 0xED, 0x90, 0xAD, 0x8B, 0xFA, 0x63,
0x25, 0x59, 0x2D, 0xA8, 0x35, 0xDD, 0xCA, 0x97, 0x33, 0xBC, 0xE5, 0xCD,
0xC7, 0x9D, 0xD1, 0xEC, 0xEF, 0x5E, 0x0E, 0x4A, 0x90, 0x06, 0x26, 0x63,
0xAD, 0xB9, 0xD9, 0x35, 0x2D, 0x07, 0xBA, 0x76, 0x65, 0x2C, 0xAC, 0x57,
0x8F, 0x7D, 0xF4, 0x07, 0x94, 0xD7, 0x81, 0x02, 0x96, 0x5D, 0xA3, 0x07,
0x49, 0xD5, 0x7A, 0xD0, 0x57, 0xF9, 0x1B, 0xE7, 0x53, 0x46, 0x75, 0xAA,
0xB0, 0x79, 0x42, 0xCB, 0x68, 0x71, 0x08, 0xE9, 0x60, 0xBD, 0x39, 0x69,
0xCE, 0xF4, 0xAF, 0xC3, 0x56, 0x40, 0xC7, 0xAD, 0x52, 0xA2, 0x09, 0xE4,
0x6F, 0x86, 0x47, 0x8A, 0x1F, 0xEB, 0x28, 0x27, 0x5D, 0x83, 0x20, 0xAF,
0x04, 0xC9, 0x6C, 0x56, 0x9A, 0x8B, 0x46, 0xF5
};
static const unsigned char TA70_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA71_DN[] = {
0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31
};
static const unsigned char TA71_RSA_N[] = {
0xB2, 0x78, 0x80, 0x71, 0xCA, 0x78, 0xD5, 0xE3, 0x71, 0xAF, 0x47, 0x80,
0x50, 0x74, 0x7D, 0x6E, 0xD8, 0xD7, 0x88, 0x76, 0xF4, 0x99, 0x68, 0xF7,
0x58, 0x21, 0x60, 0xF9, 0x74, 0x84, 0x01, 0x2F, 0xAC, 0x02, 0x2D, 0x86,
0xD3, 0xA0, 0x43, 0x7A, 0x4E, 0xB2, 0xA4, 0xD0, 0x36, 0xBA, 0x01, 0xBE,
0x8D, 0xDB, 0x48, 0xC8, 0x07, 0x17, 0x36, 0x4C, 0xF4, 0xEE, 0x88, 0x23,
0xC7, 0x3E, 0xEB, 0x37, 0xF5, 0xB5, 0x19, 0xF8, 0x49, 0x68, 0xB0, 0xDE,
0xD7, 0xB9, 0x76, 0x38, 0x1D, 0x61, 0x9E, 0xA4, 0xFE, 0x82, 0x36, 0xA5,
0xE5, 0x4A, 0x56, 0xE4, 0x45, 0xE1, 0xF9, 0xFD, 0xB4, 0x16, 0xFA, 0x74,
0xDA, 0x9C, 0x9B, 0x35, 0x39, 0x2F, 0xFA, 0xB0, 0x20, 0x50, 0x06, 0x6C,
0x7A, 0xD0, 0x80, 0xB2, 0xA6, 0xF9, 0xAF, 0xEC, 0x47, 0x19, 0x8F, 0x50,
0x38, 0x07, 0xDC, 0xA2, 0x87, 0x39, 0x58, 0xF8, 0xBA, 0xD5, 0xA9, 0xF9,
0x48, 0x67, 0x30, 0x96, 0xEE, 0x94, 0x78, 0x5E, 0x6F, 0x89, 0xA3, 0x51,
0xC0, 0x30, 0x86, 0x66, 0xA1, 0x45, 0x66, 0xBA, 0x54, 0xEB, 0xA3, 0xC3,
0x91, 0xF9, 0x48, 0xDC, 0xFF, 0xD1, 0xE8, 0x30, 0x2D, 0x7D, 0x2D, 0x74,
0x70, 0x35, 0xD7, 0x88, 0x24, 0xF7, 0x9E, 0xC4, 0x59, 0x6E, 0xBB, 0x73,
0x87, 0x17, 0xF2, 0x32, 0x46, 0x28, 0xB8, 0x43, 0xFA, 0xB7, 0x1D, 0xAA,
0xCA, 0xB4, 0xF2, 0x9F, 0x24, 0x0E, 0x2D, 0x4B, 0xF7, 0x71, 0x5C, 0x5E,
0x69, 0xFF, 0xEA, 0x95, 0x02, 0xCB, 0x38, 0x8A, 0xAE, 0x50, 0x38, 0x6F,
0xDB, 0xFB, 0x2D, 0x62, 0x1B, 0xC5, 0xC7, 0x1E, 0x54, 0xE1, 0x77, 0xE0,
0x67, 0xC8, 0x0F, 0x9C, 0x87, 0x23, 0xD6, 0x3F, 0x40, 0x20, 0x7F, 0x20,
0x80, 0xC4, 0x80, 0x4C, 0x3E, 0x3B, 0x24, 0x26, 0x8E, 0x04, 0xAE, 0x6C,
0x9A, 0xC8, 0xAA, 0x0D
};
static const unsigned char TA71_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA72_DN[] = {
0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32
};
static const unsigned char TA72_RSA_N[] = {
0xAD, 0x96, 0x9F, 0x2D, 0x9C, 0x4A, 0x4C, 0x4A, 0x81, 0x79, 0x51, 0x99,
0xEC, 0x8A, 0xCB, 0x6B, 0x60, 0x51, 0x13, 0xBC, 0x4D, 0x6D, 0x06, 0xFC,
0xB0, 0x08, 0x8D, 0xDD, 0x19, 0x10, 0x6A, 0xC7, 0x26, 0x0C, 0x35, 0xD8,
0xC0, 0x6F, 0x20, 0x84, 0xE9, 0x94, 0xB1, 0x9B, 0x85, 0x03, 0xC3, 0x5B,
0xDB, 0x4A, 0xE8, 0xC8, 0xF8, 0x90, 0x76, 0xD9, 0x5B, 0x4F, 0xE3, 0x4C,
0xE8, 0x06, 0x36, 0x4D, 0xCC, 0x9A, 0xAC, 0x3D, 0x0C, 0x90, 0x2B, 0x92,
0xD4, 0x06, 0x19, 0x60, 0xAC, 0x37, 0x44, 0x79, 0x85, 0x81, 0x82, 0xAD,
0x5A, 0x37, 0xE0, 0x0D, 0xCC, 0x9D, 0xA6, 0x4C, 0x52, 0x76, 0xEA, 0x43,
0x9D, 0xB7, 0x04, 0xD1, 0x50, 0xF6, 0x55, 0xE0, 0xD5, 0xD2, 0xA6, 0x49,
0x85, 0xE9, 0x37, 0xE9, 0xCA, 0x7E, 0xAE, 0x5C, 0x95, 0x4D, 0x48, 0x9A,
0x3F, 0xAE, 0x20, 0x5A, 0x6D, 0x88, 0x95, 0xD9, 0x34, 0xB8, 0x52, 0x1A,
0x43, 0x90, 0xB0, 0xBF, 0x6C, 0x05, 0xB9, 0xB6, 0x78, 0xB7, 0xEA, 0xD0,
0xE4, 0x3A, 0x3C, 0x12, 0x53, 0x62, 0xFF, 0x4A, 0xF2, 0x7B, 0xBE, 0x35,
0x05, 0xA9, 0x12, 0x34, 0xE3, 0xF3, 0x64, 0x74, 0x62, 0x2C, 0x3D, 0x00,
0x49, 0x5A, 0x28, 0xFE, 0x32, 0x44, 0xBB, 0x87, 0xDD, 0x65, 0x27, 0x02,
0x71, 0x3B, 0xDA, 0x4A, 0xF7, 0x1F, 0xDA, 0xCD, 0xF7, 0x21, 0x55, 0x90,
0x4F, 0x0F, 0xEC, 0xAE, 0x82, 0xE1, 0x9F, 0x6B, 0xD9, 0x45, 0xD3, 0xBB,
0xF0, 0x5F, 0x87, 0xED, 0x3C, 0x2C, 0x39, 0x86, 0xDA, 0x3F, 0xDE, 0xEC,
0x72, 0x55, 0xEB, 0x79, 0xA3, 0xAD, 0xDB, 0xDD, 0x7C, 0xB0, 0xBA, 0x1C,
0xCE, 0xFC, 0xDE, 0x4F, 0x35, 0x76, 0xCF, 0x0F, 0xF8, 0x78, 0x1F, 0x6A,
0x36, 0x51, 0x46, 0x27, 0x61, 0x5B, 0xE9, 0x9E, 0xCF, 0xF0, 0xA2, 0x55,
0x7D, 0x7C, 0x25, 0x8A, 0x6F, 0x2F, 0xB4, 0xC5, 0xCF, 0x84, 0x2E, 0x2B,
0xFD, 0x0D, 0x51, 0x10, 0x6C, 0xFB, 0x5F, 0x1B, 0xBC, 0x1B, 0x7E, 0xC5,
0xAE, 0x3B, 0x98, 0x01, 0x31, 0x92, 0xFF, 0x0B, 0x57, 0xF4, 0x9A, 0xB2,
0xB9, 0x57, 0xE9, 0xAB, 0xEF, 0x0D, 0x76, 0xD1, 0xF0, 0xEE, 0xF4, 0xCE,
0x86, 0xA7, 0xE0, 0x6E, 0xE9, 0xB4, 0x69, 0xA1, 0xDF, 0x69, 0xF6, 0x33,
0xC6, 0x69, 0x2E, 0x97, 0x13, 0x9E, 0xA5, 0x87, 0xB0, 0x57, 0x10, 0x81,
0x37, 0xC9, 0x53, 0xB3, 0xBB, 0x7F, 0xF6, 0x92, 0xD1, 0x9C, 0xD0, 0x18,
0xF4, 0x92, 0x6E, 0xDA, 0x83, 0x4F, 0xA6, 0x63, 0x99, 0x4C, 0xA5, 0xFB,
0x5E, 0xEF, 0x21, 0x64, 0x7A, 0x20, 0x5F, 0x6C, 0x64, 0x85, 0x15, 0xCB,
0x37, 0xE9, 0x62, 0x0C, 0x0B, 0x2A, 0x16, 0xDC, 0x01, 0x2E, 0x32, 0xDA,
0x3E, 0x4B, 0xF5, 0x9E, 0x3A, 0xF6, 0x17, 0x40, 0x94, 0xEF, 0x9E, 0x91,
0x08, 0x86, 0xFA, 0xBE, 0x63, 0xA8, 0x5A, 0x33, 0xEC, 0xCB, 0x74, 0x43,
0x95, 0xF9, 0x6C, 0x69, 0x52, 0x36, 0xC7, 0x29, 0x6F, 0xFC, 0x55, 0x03,
0x5C, 0x1F, 0xFB, 0x9F, 0xBD, 0x47, 0xEB, 0xE7, 0x49, 0x47, 0x95, 0x0B,
0x4E, 0x89, 0x22, 0x09, 0x49, 0xE0, 0xF5, 0x61, 0x1E, 0xF1, 0xBF, 0x2E,
0x8A, 0x72, 0x6E, 0x80, 0x59, 0xFF, 0x57, 0x3A, 0xF9, 0x75, 0x32, 0xA3,
0x4E, 0x5F, 0xEC, 0xED, 0x28, 0x62, 0xD9, 0x4D, 0x73, 0xF2, 0xCC, 0x81,
0x17, 0x60, 0xED, 0xCD, 0xEB, 0xDC, 0xDB, 0xA7, 0xCA, 0xC5, 0x7E, 0x02,
0xBD, 0xF2, 0x54, 0x08, 0x54, 0xFD, 0xB4, 0x2D, 0x09, 0x2C, 0x17, 0x54,
0x4A, 0x98, 0xD1, 0x54, 0xE1, 0x51, 0x67, 0x08, 0xD2, 0xED, 0x6E, 0x7E,
0x6F, 0x3F, 0xD2, 0x2D, 0x81, 0x59, 0x29, 0x66, 0xCB, 0x90, 0x39, 0x95,
0x11, 0x1E, 0x74, 0x27, 0xFE, 0xDD, 0xEB, 0xAF
};
static const unsigned char TA72_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA73_DN[] = {
0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x33
};
static const unsigned char TA73_EC_Q[] = {
0x04, 0x29, 0x97, 0xA7, 0xC6, 0x41, 0x7F, 0xC0, 0x0D, 0x9B, 0xE8, 0x01,
0x1B, 0x56, 0xC6, 0xF2, 0x52, 0xA5, 0xBA, 0x2D, 0xB2, 0x12, 0xE8, 0xD2,
0x2E, 0xD7, 0xFA, 0xC9, 0xC5, 0xD8, 0xAA, 0x6D, 0x1F, 0x73, 0x81, 0x3B,
0x3B, 0x98, 0x6B, 0x39, 0x7C, 0x33, 0xA5, 0xC5, 0x4E, 0x86, 0x8E, 0x80,
0x17, 0x68, 0x62, 0x45, 0x57, 0x7D, 0x44, 0x58, 0x1D, 0xB3, 0x37, 0xE5,
0x67, 0x08, 0xEB, 0x66, 0xDE
};
static const unsigned char TA74_DN[] = {
0x30, 0x39, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x06, 0x41, 0x6D, 0x61, 0x7A, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17,
0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x41, 0x6D, 0x61, 0x7A, 0x6F,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x34
};
static const unsigned char TA74_EC_Q[] = {
0x04, 0xD2, 0xAB, 0x8A, 0x37, 0x4F, 0xA3, 0x53, 0x0D, 0xFE, 0xC1, 0x8A,
0x7B, 0x4B, 0xA8, 0x7B, 0x46, 0x4B, 0x63, 0xB0, 0x62, 0xF6, 0x2D, 0x1B,
0xDB, 0x08, 0x71, 0x21, 0xD2, 0x00, 0xE8, 0x63, 0xBD, 0x9A, 0x27, 0xFB,
0xF0, 0x39, 0x6E, 0x5D, 0xEA, 0x3D, 0xA5, 0xC9, 0x81, 0xAA, 0xA3, 0x5B,
0x20, 0x98, 0x45, 0x5D, 0x16, 0xDB, 0xFD, 0xE8, 0x10, 0x6D, 0xE3, 0x9C,
0xE0, 0xE3, 0xBD, 0x5F, 0x84, 0x62, 0xF3, 0x70, 0x64, 0x33, 0xA0, 0xCB,
0x24, 0x2F, 0x70, 0xBA, 0x88, 0xA1, 0x2A, 0xA0, 0x75, 0xF8, 0x81, 0xAE,
0x62, 0x06, 0xC4, 0x81, 0xDB, 0x39, 0x6E, 0x29, 0xB0, 0x1E, 0xFA, 0x2E,
0x5C
};
static const unsigned char TA75_DN[] = {
0x30, 0x81, 0xD2, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x54, 0x52, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
0x07, 0x13, 0x0F, 0x47, 0x65, 0x62, 0x7A, 0x65, 0x20, 0x2D, 0x20, 0x4B,
0x6F, 0x63, 0x61, 0x65, 0x6C, 0x69, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03,
0x55, 0x04, 0x0A, 0x13, 0x39, 0x54, 0x75, 0x72, 0x6B, 0x69, 0x79, 0x65,
0x20, 0x42, 0x69, 0x6C, 0x69, 0x6D, 0x73, 0x65, 0x6C, 0x20, 0x76, 0x65,
0x20, 0x54, 0x65, 0x6B, 0x6E, 0x6F, 0x6C, 0x6F, 0x6A, 0x69, 0x6B, 0x20,
0x41, 0x72, 0x61, 0x73, 0x74, 0x69, 0x72, 0x6D, 0x61, 0x20, 0x4B, 0x75,
0x72, 0x75, 0x6D, 0x75, 0x20, 0x2D, 0x20, 0x54, 0x55, 0x42, 0x49, 0x54,
0x41, 0x4B, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x24, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x6B, 0x61, 0x73, 0x79, 0x6F, 0x6E, 0x20, 0x4D, 0x65, 0x72, 0x6B,
0x65, 0x7A, 0x69, 0x20, 0x2D, 0x20, 0x4B, 0x61, 0x6D, 0x75, 0x20, 0x53,
0x4D, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D,
0x54, 0x55, 0x42, 0x49, 0x54, 0x41, 0x4B, 0x20, 0x4B, 0x61, 0x6D, 0x75,
0x20, 0x53, 0x4D, 0x20, 0x53, 0x53, 0x4C, 0x20, 0x4B, 0x6F, 0x6B, 0x20,
0x53, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x6B, 0x61, 0x73, 0x69, 0x20,
0x2D, 0x20, 0x53, 0x75, 0x72, 0x75, 0x6D, 0x20, 0x31
};
static const unsigned char TA75_RSA_N[] = {
0xAF, 0x75, 0x30, 0x33, 0xAA, 0xBB, 0x6B, 0xD3, 0x99, 0x2C, 0x12, 0x37,
0x84, 0xD9, 0x8D, 0x7B, 0x97, 0x80, 0xD3, 0x6E, 0xE7, 0xFF, 0x9B, 0x50,
0x95, 0x3E, 0x90, 0x95, 0x56, 0x42, 0xD7, 0x19, 0x7C, 0x26, 0x84, 0x8D,
0x92, 0xFA, 0x01, 0x1D, 0x3A, 0x0F, 0xE2, 0x64, 0x38, 0xB7, 0x8C, 0xBC,
0xE8, 0x88, 0xF9, 0x8B, 0x24, 0xAB, 0x2E, 0xA3, 0xF5, 0x37, 0xE4, 0x40,
0x8E, 0x18, 0x25, 0x79, 0x83, 0x75, 0x1F, 0x3B, 0xFF, 0x6C, 0xA8, 0xC5,
0xC6, 0x56, 0xF8, 0xB4, 0xED, 0x8A, 0x44, 0xA3, 0xAB, 0x6C, 0x4C, 0xFC,
0x1D, 0xD0, 0xDC, 0xEF, 0x68, 0xBD, 0xCF, 0xE4, 0xAA, 0xCE, 0xF0, 0x55,
0xF7, 0xA2, 0x34, 0xD4, 0x83, 0x6B, 0x37, 0x7C, 0x1C, 0xC2, 0xFE, 0xB5,
0x03, 0xEC, 0x57, 0xCE, 0xBC, 0xB4, 0xB5, 0xC5, 0xED, 0x00, 0x0F, 0x53,
0x37, 0x2A, 0x4D, 0xF4, 0x4F, 0x0C, 0x83, 0xFB, 0x86, 0xCF, 0xCB, 0xFE,
0x8C, 0x4E, 0xBD, 0x87, 0xF9, 0xA7, 0x8B, 0x21, 0x57, 0x9C, 0x7A, 0xDF,
0x03, 0x67, 0x89, 0x2C, 0x9D, 0x97, 0x61, 0xA7, 0x10, 0xB8, 0x55, 0x90,
0x7F, 0x0E, 0x2D, 0x27, 0x38, 0x74, 0xDF, 0xE7, 0xFD, 0xDA, 0x4E, 0x12,
0xE3, 0x4D, 0x15, 0x22, 0x02, 0xC8, 0xE0, 0xE0, 0xFC, 0x0F, 0xAD, 0x8A,
0xD7, 0xC9, 0x54, 0x50, 0xCC, 0x3B, 0x0F, 0xCA, 0x16, 0x80, 0x84, 0xD0,
0x51, 0x56, 0xC3, 0x8E, 0x56, 0x7F, 0x89, 0x22, 0x33, 0x2F, 0xE6, 0x85,
0x0A, 0xBD, 0xA5, 0xA8, 0x1B, 0x36, 0xDE, 0xD3, 0xDC, 0x2C, 0x6D, 0x3B,
0xC7, 0x13, 0xBD, 0x59, 0x23, 0x2C, 0xE6, 0xE5, 0xA4, 0xF7, 0xD8, 0x0B,
0xED, 0xEA, 0x90, 0x40, 0x44, 0xA8, 0x95, 0xBB, 0x93, 0xD5, 0xD0, 0x80,
0x34, 0xB6, 0x46, 0x78, 0x0E, 0x1F, 0x00, 0x93, 0x46, 0xE1, 0xEE, 0xE9,
0xF9, 0xEC, 0x4F, 0x17
};
static const unsigned char TA75_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA76_DN[] = {
0x30, 0x62, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x29, 0x47, 0x55, 0x41, 0x4E, 0x47, 0x20, 0x44, 0x4F, 0x4E, 0x47,
0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45,
0x20, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x20, 0x43,
0x4F, 0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x1F, 0x30, 0x1D, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x47, 0x44, 0x43, 0x41, 0x20, 0x54,
0x72, 0x75, 0x73, 0x74, 0x41, 0x55, 0x54, 0x48, 0x20, 0x52, 0x35, 0x20,
0x52, 0x4F, 0x4F, 0x54
};
static const unsigned char TA76_RSA_N[] = {
0xD9, 0xA3, 0x16, 0xF0, 0xC8, 0x74, 0x74, 0x77, 0x9B, 0xEF, 0x33, 0x0D,
0x3B, 0x06, 0x7E, 0x55, 0xFC, 0xB5, 0x60, 0x8F, 0x76, 0x86, 0x12, 0x42,
0x7D, 0x56, 0x66, 0x3E, 0x88, 0x82, 0xED, 0x72, 0x63, 0x0E, 0x9E, 0x8B,
0xDD, 0x34, 0x2C, 0x02, 0x51, 0x51, 0xC3, 0x19, 0xFD, 0x59, 0x54, 0x84,
0xC9, 0xF1, 0x6B, 0xB3, 0x4C, 0xB0, 0xE9, 0xE8, 0x46, 0x5D, 0x38, 0xC6,
0xA2, 0xA7, 0x2E, 0x11, 0x57, 0xBA, 0x82, 0x15, 0xA2, 0x9C, 0x8F, 0x6D,
0xB0, 0x99, 0x4A, 0x0A, 0xF2, 0xEB, 0x89, 0x70, 0x63, 0x4E, 0x79, 0xC4,
0xB7, 0x5B, 0xBD, 0xA2, 0x5D, 0xB1, 0xF2, 0x41, 0x02, 0x2B, 0xAD, 0xA9,
0x3A, 0xA3, 0xEC, 0x79, 0x0A, 0xEC, 0x5F, 0x3A, 0xE3, 0xFD, 0xEF, 0x80,
0x3C, 0xAD, 0x34, 0x9B, 0x1A, 0xAB, 0x88, 0x26, 0x7B, 0x56, 0xA2, 0x82,
0x86, 0x1F, 0xEB, 0x35, 0x89, 0x83, 0x7F, 0x5F, 0xAE, 0x29, 0x4E, 0x3D,
0xB6, 0x6E, 0xEC, 0xAE, 0xC1, 0xF0, 0x27, 0x9B, 0xAE, 0xE3, 0xF4, 0xEC,
0xEF, 0xAE, 0x7F, 0xF7, 0x86, 0x3D, 0x72, 0x7A, 0xEB, 0xA5, 0xFB, 0x59,
0x4E, 0xA7, 0xEB, 0x95, 0x8C, 0x22, 0x39, 0x79, 0xE1, 0x2D, 0x08, 0x8F,
0xCC, 0xBC, 0x91, 0xB8, 0x41, 0xF7, 0x14, 0xC1, 0x23, 0xA9, 0xC3, 0xAD,
0x9A, 0x45, 0x44, 0xB3, 0xB2, 0xD7, 0x2C, 0xCD, 0xC6, 0x29, 0xE2, 0x50,
0x10, 0xAE, 0x5C, 0xCB, 0x82, 0x8E, 0x17, 0x18, 0x36, 0x7D, 0x97, 0xE6,
0x88, 0x9A, 0xB0, 0x4D, 0x34, 0x09, 0xF4, 0x2C, 0xB9, 0x5A, 0x66, 0x2A,
0xB0, 0x17, 0x9B, 0x9E, 0x1E, 0x76, 0x9D, 0x4A, 0x66, 0x31, 0x41, 0xDF,
0x3F, 0xFB, 0xC5, 0x06, 0xEF, 0x1B, 0xB6, 0x7E, 0x1A, 0x46, 0x36, 0xF7,
0x64, 0x63, 0x3B, 0xE3, 0x39, 0x18, 0x23, 0xE7, 0x67, 0x75, 0x14, 0xD5,
0x75, 0x57, 0x92, 0x37, 0xBD, 0xBE, 0x6A, 0x1B, 0x26, 0x50, 0xF2, 0x36,
0x26, 0x06, 0x90, 0xC5, 0x70, 0x01, 0x64, 0x6D, 0x76, 0x66, 0xE1, 0x91,
0xDB, 0x6E, 0x07, 0xC0, 0x61, 0x80, 0x2E, 0xB2, 0x2E, 0x2F, 0x8C, 0x70,
0xA7, 0xD1, 0x3B, 0x3C, 0xB3, 0x91, 0xE4, 0x6E, 0xB6, 0xC4, 0x3B, 0x70,
0xF2, 0x6C, 0x92, 0x97, 0x09, 0xCD, 0x47, 0x7D, 0x18, 0xC0, 0xF3, 0xBB,
0x9E, 0x0F, 0xD6, 0x8B, 0xAE, 0x07, 0xB6, 0x5A, 0x0F, 0xCE, 0x0B, 0x0C,
0x47, 0xA7, 0xE5, 0x3E, 0xB8, 0xBD, 0x7D, 0xC7, 0x9B, 0x35, 0xA0, 0x61,
0x97, 0x3A, 0x41, 0x75, 0x17, 0xCC, 0x2B, 0x96, 0x77, 0x2A, 0x92, 0x21,
0x1E, 0xD9, 0x95, 0x76, 0x20, 0x67, 0x68, 0xCF, 0x0D, 0xBD, 0xDF, 0xD6,
0x1F, 0x09, 0x6A, 0x9A, 0xE2, 0xCC, 0x73, 0x71, 0xA4, 0x2F, 0x7D, 0x12,
0x80, 0xB7, 0x53, 0x30, 0x46, 0x5E, 0x4B, 0x54, 0x99, 0x0F, 0x67, 0xC9,
0xA5, 0xC8, 0xF2, 0x20, 0xC1, 0x82, 0xEC, 0x9D, 0x11, 0xDF, 0xC2, 0x02,
0xFB, 0x1A, 0x3B, 0xD1, 0xED, 0x20, 0x9A, 0xEF, 0x65, 0x64, 0x92, 0x10,
0x0D, 0x2A, 0xE2, 0xDE, 0x70, 0xF1, 0x18, 0x67, 0x82, 0x8C, 0x61, 0xDE,
0xB8, 0xBC, 0xD1, 0x2F, 0x9C, 0xFB, 0x0F, 0xD0, 0x2B, 0xED, 0x1B, 0x76,
0xB9, 0xE4, 0x39, 0x55, 0xF8, 0xF8, 0xA1, 0x1D, 0xB8, 0xAA, 0x80, 0x00,
0x4C, 0x82, 0xE7, 0xB2, 0x7F, 0x09, 0xB8, 0xBC, 0x30, 0xA0, 0x2F, 0x0D,
0xF5, 0x52, 0x9E, 0x8E, 0xF7, 0x92, 0xB3, 0x0A, 0x00, 0x1D, 0x00, 0x54,
0x97, 0x06, 0xE0, 0xB1, 0x07, 0xD9, 0xC7, 0x0F, 0x5C, 0x65, 0x7D, 0x3C,
0x6D, 0x59, 0x57, 0xE4, 0xED, 0xA5, 0x8D, 0xE9, 0x40, 0x53, 0x9F, 0x15,
0x4B, 0xA0, 0x71, 0xF6, 0x1A, 0x21, 0xE3, 0xDA, 0x70, 0x06, 0x21, 0x58,
0x14, 0x87, 0x85, 0x77, 0x79, 0xAA, 0x82, 0x79
};
static const unsigned char TA76_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA77_DN[] = {
0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06,
0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F,
0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F,
0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03,
0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69,
0x74, 0x79, 0x20, 0x52, 0x53, 0x41
};
static const unsigned char TA77_RSA_N[] = {
0xF9, 0x0F, 0xDD, 0xA3, 0x2B, 0x7D, 0xCB, 0xD0, 0x2A, 0xFE, 0xEC, 0x67,
0x85, 0xA6, 0xE7, 0x2E, 0x1B, 0xBA, 0x77, 0xE1, 0xE3, 0xF5, 0xAF, 0xA4,
0xEC, 0xFA, 0x4A, 0x5D, 0x91, 0xC4, 0x57, 0x47, 0x6B, 0x18, 0x77, 0x6B,
0x76, 0xF2, 0xFD, 0x93, 0xE4, 0x3D, 0x0F, 0xC2, 0x16, 0x9E, 0x0B, 0x66,
0xC3, 0x56, 0x94, 0x9E, 0x17, 0x83, 0x85, 0xCE, 0x56, 0xEF, 0xF2, 0x16,
0xFD, 0x00, 0x62, 0xF5, 0x22, 0x09, 0x54, 0xE8, 0x65, 0x17, 0x4E, 0x41,
0xB9, 0xE0, 0x4F, 0x46, 0x97, 0xAA, 0x1B, 0xC8, 0xB8, 0x6E, 0x62, 0x5E,
0x69, 0xB1, 0x5F, 0xDB, 0x2A, 0x02, 0x7E, 0xFC, 0x6C, 0xCA, 0xF3, 0x41,
0xD8, 0xED, 0xD0, 0xE8, 0xFC, 0x3F, 0x61, 0x48, 0xED, 0xB0, 0x03, 0x14,
0x1D, 0x10, 0x0E, 0x4B, 0x19, 0xE0, 0xBB, 0x4E, 0xEC, 0x86, 0x65, 0xFF,
0x36, 0xF3, 0x5E, 0x67, 0x02, 0x0B, 0x9D, 0x86, 0x55, 0x61, 0xFD, 0x7A,
0x38, 0xED, 0xFE, 0xE2, 0x19, 0x00, 0xB7, 0x6F, 0xA1, 0x50, 0x62, 0x75,
0x74, 0x3C, 0xA0, 0xFA, 0xC8, 0x25, 0x92, 0xB4, 0x6E, 0x7A, 0x22, 0xC7,
0xF8, 0x1E, 0xA1, 0xE3, 0xB2, 0xDD, 0x91, 0x31, 0xAB, 0x2B, 0x1D, 0x04,
0xFF, 0xA5, 0x4A, 0x04, 0x37, 0xE9, 0x85, 0xA4, 0x33, 0x2B, 0xFD, 0xE2,
0xD6, 0x55, 0x34, 0x7C, 0x19, 0xA4, 0x4A, 0x68, 0xC7, 0xB2, 0xA8, 0xD3,
0xB7, 0xCA, 0xA1, 0x93, 0x88, 0xEB, 0xC1, 0x97, 0xBC, 0x8C, 0xF9, 0x1D,
0xD9, 0x22, 0x84, 0x24, 0x74, 0xC7, 0x04, 0x3D, 0x6A, 0xA9, 0x29, 0x93,
0xCC, 0xEB, 0xB8, 0x5B, 0xE1, 0xFE, 0x5F, 0x25, 0xAA, 0x34, 0x58, 0xC8,
0xC1, 0x23, 0x54, 0x9D, 0x1B, 0x98, 0x11, 0xC3, 0x38, 0x9C, 0x7E, 0x3D,
0x86, 0x6C, 0xA5, 0x0F, 0x40, 0x86, 0x7C, 0x02, 0xF4, 0x5C, 0x02, 0x4F,
0x28, 0xCB, 0xAE, 0x71, 0x9F, 0x0F, 0x3A, 0xC8, 0x33, 0xFE, 0x11, 0x25,
0x35, 0xEA, 0xFC, 0xBA, 0xC5, 0x60, 0x3D, 0xD9, 0x7C, 0x18, 0xD5, 0xB2,
0xA9, 0xD3, 0x75, 0x78, 0x03, 0x72, 0x22, 0xCA, 0x3A, 0xC3, 0x1F, 0xEF,
0x2C, 0xE5, 0x2E, 0xA9, 0xFA, 0x9E, 0x2C, 0xB6, 0x51, 0x46, 0xFD, 0xAF,
0x03, 0xD6, 0xEA, 0x60, 0x68, 0xEA, 0x85, 0x16, 0x36, 0x6B, 0x85, 0xE9,
0x1E, 0xC0, 0xB3, 0xDD, 0xC4, 0x24, 0xDC, 0x80, 0x2A, 0x81, 0x41, 0x6D,
0x94, 0x3E, 0xC8, 0xE0, 0xC9, 0x81, 0x41, 0x00, 0x9E, 0x5E, 0xBF, 0x7F,
0xC5, 0x08, 0x98, 0xA2, 0x18, 0x2C, 0x42, 0x40, 0xB3, 0xF9, 0x6F, 0x38,
0x27, 0x4B, 0x4E, 0x80, 0xF4, 0x3D, 0x81, 0x47, 0xE0, 0x88, 0x7C, 0xEA,
0x1C, 0xCE, 0xB5, 0x75, 0x5C, 0x51, 0x2E, 0x1C, 0x2B, 0x7F, 0x1A, 0x72,
0x28, 0xE7, 0x00, 0xB5, 0xD1, 0x74, 0xC6, 0xD7, 0xE4, 0x9F, 0xAD, 0x07,
0x93, 0xB6, 0x53, 0x35, 0x35, 0xFC, 0x37, 0xE4, 0xC3, 0xF6, 0x5D, 0x16,
0xBE, 0x21, 0x73, 0xDE, 0x92, 0x0A, 0xF8, 0xA0, 0x63, 0x6A, 0xBC, 0x96,
0x92, 0x6A, 0x3E, 0xF8, 0xBC, 0x65, 0x55, 0x9B, 0xDE, 0xF5, 0x0D, 0x89,
0x26, 0x04, 0xFC, 0x25, 0x1A, 0xA6, 0x25, 0x69, 0xCB, 0xC2, 0x6D, 0xCA,
0x7C, 0xE2, 0x59, 0x5F, 0x97, 0xAC, 0xEB, 0xEF, 0x2E, 0xC8, 0xBC, 0xD7,
0x1B, 0x59, 0x3C, 0x2B, 0xCC, 0xF2, 0x19, 0xC8, 0x93, 0x6B, 0x27, 0x63,
0x19, 0xCF, 0xFC, 0xE9, 0x26, 0xF8, 0xCA, 0x71, 0x9B, 0x7F, 0x93, 0xFE,
0x34, 0x67, 0x84, 0x4E, 0x99, 0xEB, 0xFC, 0xB3, 0x78, 0x09, 0x33, 0x70,
0xBA, 0x66, 0xA6, 0x76, 0xED, 0x1B, 0x73, 0xEB, 0x1A, 0xA5, 0x0D, 0xC4,
0x22, 0x13, 0x20, 0x94, 0x56, 0x0A, 0x4E, 0x2C, 0x6C, 0x4E, 0xB1, 0xFD,
0xCF, 0x9C, 0x09, 0xBA, 0xA2, 0x33, 0xED, 0x87
};
static const unsigned char TA77_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA78_DN[] = {
0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06,
0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F,
0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F,
0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04, 0x03,
0x0C, 0x28, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69,
0x74, 0x79, 0x20, 0x45, 0x43, 0x43
};
static const unsigned char TA78_EC_Q[] = {
0x04, 0x45, 0x6E, 0xA9, 0x50, 0xC4, 0xA6, 0x23, 0x36, 0x9E, 0x5F, 0x28,
0x8D, 0x17, 0xCB, 0x96, 0x22, 0x64, 0x3F, 0xDC, 0x7A, 0x8E, 0x1D, 0xCC,
0x08, 0xB3, 0xA2, 0x71, 0x24, 0xBA, 0x8E, 0x49, 0xB9, 0x04, 0x1B, 0x47,
0x96, 0x58, 0xAB, 0x2D, 0x95, 0xC8, 0xED, 0x9E, 0x08, 0x35, 0xC8, 0x27,
0xEB, 0x89, 0x8C, 0x53, 0x58, 0xEB, 0x62, 0x8A, 0xFE, 0xF0, 0x5B, 0x0F,
0x6B, 0x31, 0x52, 0x63, 0x41, 0x3B, 0x89, 0xCD, 0xEC, 0xEC, 0xB6, 0x8D,
0x19, 0xD3, 0x34, 0x07, 0xDC, 0xBB, 0xC6, 0x06, 0x7F, 0xC2, 0x45, 0x95,
0xEC, 0xCB, 0x7F, 0xA8, 0x23, 0xE0, 0x09, 0xE9, 0x81, 0xFA, 0xF3, 0x47,
0xD3
};
static const unsigned char TA79_DN[] = {
0x30, 0x81, 0x82, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04,
0x08, 0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E,
0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74,
0x6F, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C,
0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61,
0x74, 0x69, 0x6F, 0x6E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04,
0x03, 0x0C, 0x2E, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45,
0x56, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74,
0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52,
0x32
};
static const unsigned char TA79_RSA_N[] = {
0x8F, 0x36, 0x65, 0x40, 0xE1, 0xD6, 0x4D, 0xC0, 0xD7, 0xB4, 0xE9, 0x46,
0xDA, 0x6B, 0xEA, 0x33, 0x47, 0xCD, 0x4C, 0xF9, 0x7D, 0x7D, 0xBE, 0xBD,
0x2D, 0x3D, 0xF0, 0xDB, 0x78, 0xE1, 0x86, 0xA5, 0xD9, 0xBA, 0x09, 0x57,
0x68, 0xED, 0x57, 0x3E, 0xA0, 0xD0, 0x08, 0x41, 0x83, 0xE7, 0x28, 0x41,
0x24, 0x1F, 0xE3, 0x72, 0x15, 0xD0, 0x01, 0x1A, 0xFB, 0x5E, 0x70, 0x23,
0xB2, 0xCB, 0x9F, 0x39, 0xE3, 0xCF, 0xC5, 0x4E, 0xC6, 0x92, 0x6D, 0x26,
0xC6, 0x7B, 0xBB, 0xB3, 0xDA, 0x27, 0x9D, 0x0A, 0x86, 0xE9, 0x81, 0x37,
0x05, 0xFE, 0xF0, 0x71, 0x71, 0xEC, 0xC3, 0x1C, 0xE9, 0x63, 0xA2, 0x17,
0x14, 0x9D, 0xEF, 0x1B, 0x67, 0xD3, 0x85, 0x55, 0x02, 0x02, 0xD6, 0x49,
0xC9, 0xCC, 0x5A, 0xE1, 0xB1, 0xF7, 0x6F, 0x32, 0x9F, 0xC9, 0xD4, 0x3B,
0x88, 0x41, 0xA8, 0x9C, 0xBD, 0xCB, 0xAB, 0xDB, 0x6D, 0x7B, 0x09, 0x1F,
0xA2, 0x4C, 0x72, 0x90, 0xDA, 0x2B, 0x08, 0xFC, 0xCF, 0x3C, 0x54, 0xCE,
0x67, 0x0F, 0xA8, 0xCF, 0x5D, 0x96, 0x19, 0x0B, 0xC4, 0xE3, 0x72, 0xEB,
0xAD, 0xD1, 0x7D, 0x1D, 0x27, 0xEF, 0x92, 0xEB, 0x10, 0xBF, 0x5B, 0xEB,
0x3B, 0xAF, 0xCF, 0x80, 0xDD, 0xC1, 0xD2, 0x96, 0x04, 0x5B, 0x7A, 0x7E,
0xA4, 0xA9, 0x3C, 0x38, 0x76, 0xA4, 0x62, 0x8E, 0xA0, 0x39, 0x5E, 0xEA,
0x77, 0xCF, 0x5D, 0x00, 0x59, 0x8F, 0x66, 0x2C, 0x3E, 0x07, 0xA2, 0xA3,
0x05, 0x26, 0x11, 0x69, 0x97, 0xEA, 0x85, 0xB7, 0x0F, 0x96, 0x0B, 0x4B,
0xC8, 0x40, 0xE1, 0x50, 0xBA, 0x2E, 0x8A, 0xCB, 0xF7, 0x0F, 0x9A, 0x22,
0xE7, 0x7F, 0x9A, 0x37, 0x13, 0xCD, 0xF2, 0x4D, 0x13, 0x6B, 0x21, 0xD1,
0xC0, 0xCC, 0x22, 0xF2, 0xA1, 0x46, 0xF6, 0x44, 0x69, 0x9C, 0xCA, 0x61,
0x35, 0x07, 0x00, 0x6F, 0xD6, 0x61, 0x08, 0x11, 0xEA, 0xBA, 0xB8, 0xF6,
0xE9, 0xB3, 0x60, 0xE5, 0x4D, 0xB9, 0xEC, 0x9F, 0x14, 0x66, 0xC9, 0x57,
0x58, 0xDB, 0xCD, 0x87, 0x69, 0xF8, 0x8A, 0x86, 0x12, 0x03, 0x47, 0xBF,
0x66, 0x13, 0x76, 0xAC, 0x77, 0x7D, 0x34, 0x24, 0x85, 0x83, 0xCD, 0xD7,
0xAA, 0x9C, 0x90, 0x1A, 0x9F, 0x21, 0x2C, 0x7F, 0x78, 0xB7, 0x64, 0xB8,
0xD8, 0xE8, 0xA6, 0xF4, 0x78, 0xB3, 0x55, 0xCB, 0x84, 0xD2, 0x32, 0xC4,
0x78, 0xAE, 0xA3, 0x8F, 0x61, 0xDD, 0xCE, 0x08, 0x53, 0xAD, 0xEC, 0x88,
0xFC, 0x15, 0xE4, 0x9A, 0x0D, 0xE6, 0x9F, 0x1A, 0x77, 0xCE, 0x4C, 0x8F,
0xB8, 0x14, 0x15, 0x3D, 0x62, 0x9C, 0x86, 0x38, 0x06, 0x00, 0x66, 0x12,
0xE4, 0x59, 0x76, 0x5A, 0x53, 0xC0, 0x02, 0x98, 0xA2, 0x10, 0x2B, 0x68,
0x44, 0x7B, 0x8E, 0x79, 0xCE, 0x33, 0x4A, 0x76, 0xAA, 0x5B, 0x81, 0x16,
0x1B, 0xB5, 0x8A, 0xD8, 0xD0, 0x00, 0x7B, 0x5E, 0x62, 0xB4, 0x09, 0xD6,
0x86, 0x63, 0x0E, 0xA6, 0x05, 0x95, 0x49, 0xBA, 0x28, 0x8B, 0x88, 0x93,
0xB2, 0x34, 0x1C, 0xD8, 0xA4, 0x55, 0x6E, 0xB7, 0x1C, 0xD0, 0xDE, 0x99,
0x55, 0x3B, 0x23, 0xF4, 0x22, 0xE0, 0xF9, 0x29, 0x66, 0x26, 0xEC, 0x20,
0x50, 0x77, 0xDB, 0x4A, 0x0B, 0x8F, 0xBE, 0xE5, 0x02, 0x60, 0x70, 0x41,
0x5E, 0xD4, 0xAE, 0x50, 0x39, 0x22, 0x14, 0x26, 0xCB, 0xB2, 0x3B, 0x73,
0x74, 0x55, 0x47, 0x07, 0x79, 0x81, 0x39, 0xA8, 0x30, 0x13, 0x44, 0xE5,
0x04, 0x8A, 0xAE, 0x96, 0x13, 0x25, 0x42, 0x0F, 0xB9, 0x53, 0xC4, 0x9B,
0xFC, 0xCD, 0xE4, 0x1C, 0xDE, 0x3C, 0xFA, 0xAB, 0xD6, 0x06, 0x4A, 0x1F,
0x67, 0xA6, 0x98, 0x30, 0x1C, 0xDD, 0x2C, 0xDB, 0xDC, 0x18, 0x95, 0x57,
0x66, 0xC6, 0xFF, 0x5C, 0x8B, 0x56, 0xF5, 0x77
};
static const unsigned char TA79_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA80_DN[] = {
0x30, 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0C, 0x05, 0x54, 0x65, 0x78, 0x61, 0x73, 0x31, 0x10, 0x30, 0x0E, 0x06,
0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x48, 0x6F, 0x75, 0x73, 0x74, 0x6F,
0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F,
0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04, 0x03,
0x0C, 0x2B, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20, 0x45, 0x56,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68,
0x6F, 0x72, 0x69, 0x74, 0x79, 0x20, 0x45, 0x43, 0x43
};
static const unsigned char TA80_EC_Q[] = {
0x04, 0xAA, 0x12, 0x47, 0x90, 0x98, 0x1B, 0xFB, 0xEF, 0xC3, 0x40, 0x07,
0x83, 0x20, 0x4E, 0xF1, 0x30, 0x82, 0xA2, 0x06, 0xD1, 0xF2, 0x92, 0x86,
0x61, 0xF2, 0xF6, 0x21, 0x68, 0xCA, 0x00, 0xC4, 0xC7, 0xEA, 0x43, 0x00,
0x54, 0x86, 0xDC, 0xFD, 0x1F, 0xDF, 0x00, 0xB8, 0x41, 0x62, 0x5C, 0xDC,
0x70, 0x16, 0x32, 0xDE, 0x1F, 0x99, 0xD4, 0xCC, 0xC5, 0x07, 0xC8, 0x08,
0x1F, 0x61, 0x16, 0x07, 0x51, 0x3D, 0x7D, 0x5C, 0x07, 0x53, 0xE3, 0x35,
0x38, 0x8C, 0xDF, 0xCD, 0x9F, 0xD9, 0x2E, 0x0D, 0x4A, 0xB6, 0x19, 0x2E,
0x5A, 0x70, 0x5A, 0x06, 0xED, 0xBE, 0xF0, 0xA1, 0xB0, 0xCA, 0xD0, 0x09,
0x29
};
static const unsigned char TA81_DN[] = {
0x30, 0x4C, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x17, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x52, 0x36,
0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0A, 0x47,
0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x31, 0x13, 0x30,
0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62,
0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E
};
static const unsigned char TA81_RSA_N[] = {
0x95, 0x07, 0xE8, 0x73, 0xCA, 0x66, 0xF9, 0xEC, 0x14, 0xCA, 0x7B, 0x3C,
0xF7, 0x0D, 0x08, 0xF1, 0xB4, 0x45, 0x0B, 0x2C, 0x82, 0xB4, 0x48, 0xC6,
0xEB, 0x5B, 0x3C, 0xAE, 0x83, 0xB8, 0x41, 0x92, 0x33, 0x14, 0xA4, 0x6F,
0x7F, 0xE9, 0x2A, 0xCC, 0xC6, 0xB0, 0x88, 0x6B, 0xC5, 0xB6, 0x89, 0xD1,
0xC6, 0xB2, 0xFF, 0x14, 0xCE, 0x51, 0x14, 0x21, 0xEC, 0x4A, 0xDD, 0x1B,
0x5A, 0xC6, 0xD6, 0x87, 0xEE, 0x4D, 0x3A, 0x15, 0x06, 0xED, 0x64, 0x66,
0x0B, 0x92, 0x80, 0xCA, 0x44, 0xDE, 0x73, 0x94, 0x4E, 0xF3, 0xA7, 0x89,
0x7F, 0x4F, 0x78, 0x63, 0x08, 0xC8, 0x12, 0x50, 0x6D, 0x42, 0x66, 0x2F,
0x4D, 0xB9, 0x79, 0x28, 0x4D, 0x52, 0x1A, 0x8A, 0x1A, 0x80, 0xB7, 0x19,
0x81, 0x0E, 0x7E, 0xC4, 0x8A, 0xBC, 0x64, 0x4C, 0x21, 0x1C, 0x43, 0x68,
0xD7, 0x3D, 0x3C, 0x8A, 0xC5, 0xB2, 0x66, 0xD5, 0x90, 0x9A, 0xB7, 0x31,
0x06, 0xC5, 0xBE, 0xE2, 0x6D, 0x32, 0x06, 0xA6, 0x1E, 0xF9, 0xB9, 0xEB,
0xAA, 0xA3, 0xB8, 0xBF, 0xBE, 0x82, 0x63, 0x50, 0xD0, 0xF0, 0x18, 0x89,
0xDF, 0xE4, 0x0F, 0x79, 0xF5, 0xEA, 0xA2, 0x1F, 0x2A, 0xD2, 0x70, 0x2E,
0x7B, 0xE7, 0xBC, 0x93, 0xBB, 0x6D, 0x53, 0xE2, 0x48, 0x7C, 0x8C, 0x10,
0x07, 0x38, 0xFF, 0x66, 0xB2, 0x77, 0x61, 0x7E, 0xE0, 0xEA, 0x8C, 0x3C,
0xAA, 0xB4, 0xA4, 0xF6, 0xF3, 0x95, 0x4A, 0x12, 0x07, 0x6D, 0xFD, 0x8C,
0xB2, 0x89, 0xCF, 0xD0, 0xA0, 0x61, 0x77, 0xC8, 0x58, 0x74, 0xB0, 0xD4,
0x23, 0x3A, 0xF7, 0x5D, 0x3A, 0xCA, 0xA2, 0xDB, 0x9D, 0x09, 0xDE, 0x5D,
0x44, 0x2D, 0x90, 0xF1, 0x81, 0xCD, 0x57, 0x92, 0xFA, 0x7E, 0xBC, 0x50,
0x04, 0x63, 0x34, 0xDF, 0x6B, 0x93, 0x18, 0xBE, 0x6B, 0x36, 0xB2, 0x39,
0xE4, 0xAC, 0x24, 0x36, 0xB7, 0xF0, 0xEF, 0xB6, 0x1C, 0x13, 0x57, 0x93,
0xB6, 0xDE, 0xB2, 0xF8, 0xE2, 0x85, 0xB7, 0x73, 0xA2, 0xB8, 0x35, 0xAA,
0x45, 0xF2, 0xE0, 0x9D, 0x36, 0xA1, 0x6F, 0x54, 0x8A, 0xF1, 0x72, 0x56,
0x6E, 0x2E, 0x88, 0xC5, 0x51, 0x42, 0x44, 0x15, 0x94, 0xEE, 0xA3, 0xC5,
0x38, 0x96, 0x9B, 0x4E, 0x4E, 0x5A, 0x0B, 0x47, 0xF3, 0x06, 0x36, 0x49,
0x77, 0x30, 0xBC, 0x71, 0x37, 0xE5, 0xA6, 0xEC, 0x21, 0x08, 0x75, 0xFC,
0xE6, 0x61, 0x16, 0x3F, 0x77, 0xD5, 0xD9, 0x91, 0x97, 0x84, 0x0A, 0x6C,
0xD4, 0x02, 0x4D, 0x74, 0xC0, 0x14, 0xED, 0xFD, 0x39, 0xFB, 0x83, 0xF2,
0x5E, 0x14, 0xA1, 0x04, 0xB0, 0x0B, 0xE9, 0xFE, 0xEE, 0x8F, 0xE1, 0x6E,
0x0B, 0xB2, 0x08, 0xB3, 0x61, 0x66, 0x09, 0x6A, 0xB1, 0x06, 0x3A, 0x65,
0x96, 0x59, 0xC0, 0xF0, 0x35, 0xFD, 0xC9, 0xDA, 0x28, 0x8D, 0x1A, 0x11,
0x87, 0x70, 0x81, 0x0A, 0xA8, 0x9A, 0x75, 0x1D, 0x9E, 0x3A, 0x86, 0x05,
0x00, 0x9E, 0xDB, 0x80, 0xD6, 0x25, 0xF9, 0xDC, 0x05, 0x9E, 0x27, 0x59,
0x4C, 0x76, 0x39, 0x5B, 0xEA, 0xF9, 0xA5, 0xA1, 0xD8, 0x83, 0x0F, 0xD1,
0xFF, 0xDF, 0x30, 0x11, 0xF9, 0x85, 0xCF, 0x33, 0x48, 0xF5, 0xCA, 0x6D,
0x64, 0x14, 0x2C, 0x7A, 0x58, 0x4F, 0xD3, 0x4B, 0x08, 0x49, 0xC5, 0x95,
0x64, 0x1A, 0x63, 0x0E, 0x79, 0x3D, 0xF5, 0xB3, 0x8C, 0xCA, 0x58, 0xAD,
0x9C, 0x42, 0x45, 0x79, 0x6E, 0x0E, 0x87, 0x19, 0x5C, 0x54, 0xB1, 0x65,
0xB6, 0xBF, 0x8C, 0x9B, 0xDC, 0x13, 0xE9, 0x0D, 0x6F, 0xB8, 0x2E, 0xDC,
0x67, 0x6E, 0xC9, 0x8B, 0x11, 0xB5, 0x84, 0x14, 0x8A, 0x00, 0x19, 0x70,
0x83, 0x79, 0x91, 0x97, 0x91, 0xD4, 0x1A, 0x27, 0xBF, 0x37, 0x1E, 0x32,
0x07, 0xD8, 0x14, 0x63, 0x3C, 0x28, 0x4C, 0xAF
};
static const unsigned char TA81_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA82_DN[] = {
0x30, 0x6D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x48, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x07, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x31, 0x22, 0x30,
0x20, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x19, 0x4F, 0x49, 0x53, 0x54,
0x45, 0x20, 0x46, 0x6F, 0x75, 0x6E, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E,
0x20, 0x45, 0x6E, 0x64, 0x6F, 0x72, 0x73, 0x65, 0x64, 0x31, 0x28, 0x30,
0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1F, 0x4F, 0x49, 0x53, 0x54,
0x45, 0x20, 0x57, 0x49, 0x53, 0x65, 0x4B, 0x65, 0x79, 0x20, 0x47, 0x6C,
0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x43,
0x20, 0x43, 0x41
};
static const unsigned char TA82_EC_Q[] = {
0x04, 0x4C, 0xE9, 0x50, 0xC0, 0xC6, 0x0F, 0x72, 0x18, 0xBC, 0xD8, 0xF1,
0xBA, 0xB3, 0x89, 0xE2, 0x79, 0x4A, 0xA3, 0x16, 0xA7, 0x6B, 0x54, 0x24,
0xDB, 0x51, 0xFF, 0xEA, 0xF4, 0x09, 0x24, 0xC3, 0x0B, 0x22, 0x9F, 0xCB,
0x6A, 0x27, 0x82, 0x81, 0x0D, 0xD2, 0xC0, 0xAF, 0x31, 0xE4, 0x74, 0x82,
0x6E, 0xCA, 0x25, 0xD9, 0x8C, 0x75, 0x9D, 0xF1, 0xDB, 0xD0, 0x9A, 0xA2,
0x4B, 0x21, 0x7E, 0x16, 0xA7, 0x63, 0x90, 0xD2, 0x39, 0xD4, 0xB1, 0x87,
0x78, 0x5F, 0x18, 0x96, 0x0F, 0x50, 0x1B, 0x35, 0x37, 0x0F, 0x6A, 0xC6,
0xDC, 0xD9, 0x13, 0x4D, 0xA4, 0x8E, 0x90, 0x37, 0xE6, 0xBD, 0x5B, 0x31,
0x91
};
static const unsigned char TA83_DN[] = {
0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x1B,
0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x55, 0x43, 0x41,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x47, 0x32, 0x20, 0x52,
0x6F, 0x6F, 0x74
};
static const unsigned char TA83_RSA_N[] = {
0xC5, 0xE6, 0x2B, 0x6F, 0x7C, 0xEF, 0x26, 0x05, 0x27, 0xA3, 0x81, 0x24,
0xDA, 0x6F, 0xCB, 0x01, 0xF9, 0x99, 0x9A, 0xA9, 0x32, 0xC2, 0x22, 0x87,
0x61, 0x41, 0x91, 0x3B, 0xCB, 0xC3, 0x68, 0x1B, 0x06, 0xC5, 0x4C, 0xA9,
0x2B, 0xC1, 0x67, 0x17, 0x22, 0x1D, 0x2B, 0xED, 0xF9, 0x29, 0x89, 0x93,
0xA2, 0x78, 0xBD, 0x92, 0x6B, 0xA0, 0xA3, 0x0D, 0xA2, 0x7E, 0xCA, 0x93,
0xB3, 0xA6, 0xD1, 0x8C, 0x35, 0xD5, 0x75, 0xF9, 0x17, 0xF6, 0xCF, 0x45,
0xC5, 0xE5, 0x7A, 0xEC, 0x77, 0x93, 0xA0, 0x8F, 0x23, 0xAE, 0x0E, 0x1A,
0x03, 0x7F, 0xBE, 0xD4, 0xD0, 0xED, 0x2E, 0x7B, 0xAB, 0x46, 0x23, 0x5B,
0xFF, 0x2C, 0xE6, 0x54, 0x7A, 0x94, 0xC0, 0x2A, 0x15, 0xF0, 0xC9, 0x8D,
0xB0, 0x7A, 0x3B, 0x24, 0xE1, 0xD7, 0x68, 0xE2, 0x31, 0x3C, 0x06, 0x33,
0x46, 0xB6, 0x54, 0x11, 0xA6, 0xA5, 0x2F, 0x22, 0x54, 0x2A, 0x58, 0x0D,
0x01, 0x02, 0xF1, 0xFA, 0x15, 0x51, 0x67, 0x6C, 0xC0, 0xFA, 0xD7, 0xB6,
0x1B, 0x7F, 0xD1, 0x56, 0x88, 0x2F, 0x1A, 0x3A, 0x8D, 0x3B, 0xBB, 0x82,
0x11, 0xE0, 0x47, 0x00, 0xD0, 0x52, 0x87, 0xAB, 0xFB, 0x86, 0x7E, 0x0F,
0x24, 0x6B, 0x40, 0x9D, 0x34, 0x67, 0xBC, 0x8D, 0xC7, 0x2D, 0x86, 0x6F,
0x79, 0x3E, 0x8E, 0xA9, 0x3C, 0x17, 0x4B, 0x7F, 0xB0, 0x99, 0xE3, 0xB0,
0x71, 0x60, 0xDC, 0x0B, 0xF5, 0x64, 0xC3, 0xCE, 0x43, 0xBC, 0x6D, 0x71,
0xB9, 0xD2, 0xDE, 0x27, 0x5B, 0x8A, 0xE8, 0xD8, 0xC6, 0xAE, 0xE1, 0x59,
0x7D, 0xCF, 0x28, 0x2D, 0x35, 0xB8, 0x95, 0x56, 0x1A, 0xF1, 0xB2, 0x58,
0x4B, 0xB7, 0x12, 0x37, 0xC8, 0x7C, 0xB3, 0xED, 0x4B, 0x80, 0xE1, 0x8D,
0xFA, 0x32, 0x23, 0xB6, 0x6F, 0xB7, 0x48, 0x95, 0x08, 0xB1, 0x44, 0x4E,
0x85, 0x8C, 0x3A, 0x02, 0x54, 0x20, 0x2F, 0xDF, 0xBF, 0x57, 0x4F, 0x3B,
0x3A, 0x90, 0x21, 0xD7, 0xC1, 0x26, 0x35, 0x54, 0x20, 0xEC, 0xC7, 0x3F,
0x47, 0xEC, 0xEF, 0x5A, 0xBF, 0x4B, 0x7A, 0xC1, 0xAD, 0x3B, 0x17, 0x50,
0x5C, 0x62, 0xD8, 0x0F, 0x4B, 0x4A, 0xDC, 0x2B, 0xFA, 0x6E, 0xBC, 0x73,
0x92, 0xCD, 0xEC, 0xC7, 0x50, 0xE8, 0x41, 0x96, 0xD7, 0xA9, 0x7E, 0x6D,
0xD8, 0xE9, 0x1D, 0x8F, 0x8A, 0xB5, 0xB9, 0x58, 0x92, 0xBA, 0x4A, 0x92,
0x2B, 0x0C, 0x56, 0xFD, 0x80, 0xEB, 0x08, 0xF0, 0x5E, 0x29, 0x6E, 0x1B,
0x1C, 0x0C, 0xAF, 0x8F, 0x93, 0x89, 0xAD, 0xDB, 0xBD, 0xA3, 0x9E, 0x21,
0xCA, 0x89, 0x19, 0xEC, 0xDF, 0xB5, 0xC3, 0x1A, 0xEB, 0x16, 0xFE, 0x78,
0x36, 0x4C, 0xD6, 0x6E, 0xD0, 0x3E, 0x17, 0x1C, 0x90, 0x17, 0x6B, 0x26,
0xBA, 0xFB, 0x7A, 0x2F, 0xBF, 0x11, 0x1C, 0x18, 0x0E, 0x2D, 0x73, 0x03,
0x8F, 0xA0, 0xE5, 0x35, 0xA0, 0x5A, 0xE2, 0x4C, 0x75, 0x1D, 0x71, 0xE1,
0x39, 0x38, 0x53, 0x78, 0x40, 0xCC, 0x83, 0x93, 0xD7, 0x0A, 0x9E, 0x9D,
0x5B, 0x8F, 0x8A, 0xE4, 0xE5, 0xE0, 0x48, 0xE4, 0x48, 0xB2, 0x47, 0xCD,
0x4E, 0x2A, 0x75, 0x2A, 0x7B, 0xF2, 0x22, 0xF6, 0xC9, 0xBE, 0x09, 0x91,
0x96, 0x57, 0x7A, 0x88, 0x88, 0xAC, 0xEE, 0x70, 0xAC, 0xF9, 0xDC, 0x29,
0xE3, 0x0C, 0x1C, 0x3B, 0x12, 0x4E, 0x44, 0xD6, 0xA7, 0x4E, 0xB0, 0x26,
0xC8, 0xF3, 0xD9, 0x1A, 0x97, 0x91, 0x68, 0xEA, 0xEF, 0x8D, 0x46, 0x06,
0xD2, 0x56, 0x45, 0x58, 0x9A, 0x3C, 0x0C, 0x0F, 0x83, 0xB8, 0x05, 0x25,
0xC3, 0x39, 0xCF, 0x3B, 0xA4, 0x34, 0x89, 0xB7, 0x79, 0x12, 0x2F, 0x47,
0xC5, 0xE7, 0xA9, 0x97, 0x69, 0xFC, 0xA6, 0x77, 0x67, 0xB5, 0xDF, 0x7B,
0xF1, 0x7A, 0x65, 0x15, 0xE4, 0x61, 0x56, 0x65
};
static const unsigned char TA83_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA84_DN[] = {
0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x08, 0x55, 0x6E, 0x69, 0x54, 0x72, 0x75, 0x73, 0x74, 0x31, 0x25,
0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x55, 0x43, 0x41,
0x20, 0x45, 0x78, 0x74, 0x65, 0x6E, 0x64, 0x65, 0x64, 0x20, 0x56, 0x61,
0x6C, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F,
0x74
};
static const unsigned char TA84_RSA_N[] = {
0xA9, 0x09, 0x07, 0x28, 0x13, 0x02, 0xB0, 0x99, 0xE0, 0x64, 0xAA, 0x1E,
0x43, 0x16, 0x7A, 0x73, 0xB1, 0x91, 0xA0, 0x75, 0x3E, 0xA8, 0xFA, 0xE3,
0x38, 0x00, 0x7A, 0xEC, 0x89, 0x6A, 0x20, 0x0F, 0x8B, 0xC5, 0xB0, 0x9B,
0x33, 0x03, 0x5A, 0x86, 0xC6, 0x58, 0x86, 0xD5, 0xC1, 0x85, 0xBB, 0x4F,
0xC6, 0x9C, 0x40, 0x4D, 0xCA, 0xBE, 0xEE, 0x69, 0x96, 0xB8, 0xAD, 0x81,
0x30, 0x9A, 0x7C, 0x92, 0x05, 0xEB, 0x05, 0x2B, 0x9A, 0x48, 0xD0, 0xB8,
0x76, 0x3E, 0x96, 0xC8, 0x20, 0xBB, 0xD2, 0xB0, 0xF1, 0x8F, 0xD8, 0xAC,
0x45, 0x46, 0xFF, 0xAA, 0x67, 0x60, 0xB4, 0x77, 0x7E, 0x6A, 0x1F, 0x3C,
0x1A, 0x52, 0x7A, 0x04, 0x3D, 0x07, 0x3C, 0x85, 0x0D, 0x84, 0xD0, 0x1F,
0x76, 0x0A, 0xF7, 0x6A, 0x14, 0xDF, 0x72, 0xE3, 0x34, 0x7C, 0x57, 0x4E,
0x56, 0x01, 0x3E, 0x79, 0xF1, 0xAA, 0x29, 0x3B, 0x6C, 0xFA, 0xF8, 0x8F,
0x6D, 0x4D, 0xC8, 0x35, 0xDF, 0xAE, 0xEB, 0xDC, 0x24, 0xEE, 0x79, 0x45,
0xA7, 0x85, 0xB6, 0x05, 0x88, 0xDE, 0x88, 0x5D, 0x25, 0x7C, 0x97, 0x64,
0x67, 0x09, 0xD9, 0xBF, 0x5A, 0x15, 0x05, 0x86, 0xF3, 0x09, 0x1E, 0xEC,
0x58, 0x32, 0x33, 0x11, 0xF3, 0x77, 0x64, 0xB0, 0x76, 0x1F, 0xE4, 0x10,
0x35, 0x17, 0x1B, 0xF2, 0x0E, 0xB1, 0x6C, 0xA4, 0x2A, 0xA3, 0x73, 0xFC,
0x09, 0x1F, 0x1E, 0x32, 0x19, 0x53, 0x11, 0xE7, 0xD9, 0xB3, 0x2C, 0x2E,
0x76, 0x2E, 0xA1, 0xA3, 0xDE, 0x7E, 0x6A, 0x88, 0x09, 0xE8, 0xF2, 0x07,
0x8A, 0xF8, 0xB2, 0xCD, 0x10, 0xE7, 0xE2, 0x73, 0x40, 0x93, 0xBB, 0x08,
0xD1, 0x3F, 0xE1, 0xFC, 0x0B, 0x94, 0xB3, 0x25, 0xEF, 0x7C, 0xA6, 0xD7,
0xD1, 0xAF, 0x9F, 0xFF, 0x96, 0x9A, 0xF5, 0x91, 0x7B, 0x98, 0x0B, 0x77,
0xD4, 0x7E, 0xE8, 0x07, 0xD2, 0x62, 0xB5, 0x95, 0x39, 0xE3, 0xF3, 0xF1,
0x6D, 0x0F, 0x0E, 0x65, 0x84, 0x8A, 0x63, 0x54, 0xC5, 0x80, 0xB6, 0xE0,
0x9E, 0x4B, 0x7D, 0x47, 0x26, 0xA7, 0x01, 0x08, 0x5D, 0xD1, 0x88, 0x9E,
0xD7, 0xC3, 0x32, 0x44, 0xFA, 0x82, 0x4A, 0x0A, 0x68, 0x54, 0x7F, 0x38,
0x53, 0x03, 0xCC, 0xA4, 0x00, 0x33, 0x64, 0x51, 0x59, 0x0B, 0xA3, 0x82,
0x91, 0x7A, 0x5E, 0xEC, 0x16, 0xC2, 0xF3, 0x2A, 0xE6, 0x62, 0xDA, 0x2A,
0xDB, 0x59, 0x62, 0x10, 0x25, 0x4A, 0x2A, 0x81, 0x0B, 0x47, 0x07, 0x43,
0x06, 0x70, 0x87, 0xD2, 0xFA, 0x93, 0x11, 0x29, 0x7A, 0x48, 0x4D, 0xEB,
0x94, 0xC7, 0x70, 0x4D, 0xAF, 0x67, 0xD5, 0x51, 0xB1, 0x80, 0x20, 0x01,
0x01, 0xB4, 0x7A, 0x08, 0xA6, 0x90, 0x7F, 0x4E, 0xE0, 0xEF, 0x07, 0x41,
0x87, 0xAF, 0x6A, 0xA5, 0x5E, 0x8B, 0xFB, 0xCF, 0x50, 0xB2, 0x9A, 0x54,
0xAF, 0xC3, 0x89, 0xBA, 0x58, 0x2D, 0xF5, 0x30, 0x98, 0xB1, 0x36, 0x72,
0x39, 0x7E, 0x49, 0x04, 0xFD, 0x29, 0xA7, 0x4C, 0x79, 0xE4, 0x05, 0x57,
0xDB, 0x94, 0xB9, 0x16, 0x53, 0x8D, 0x46, 0xB3, 0x1D, 0x95, 0x61, 0x57,
0x56, 0x7F, 0xAF, 0xF0, 0x16, 0x5B, 0x61, 0x58, 0x6F, 0x36, 0x50, 0x11,
0x0B, 0xD8, 0xAC, 0x2B, 0x95, 0x16, 0x1A, 0x0E, 0x1F, 0x08, 0xCD, 0x36,
0x34, 0x65, 0x10, 0x62, 0x66, 0xD5, 0x80, 0x5F, 0x14, 0x20, 0x5F, 0x2D,
0x0C, 0xA0, 0x78, 0x0A, 0x68, 0xD6, 0x2C, 0xD7, 0xE9, 0x6F, 0x2B, 0xD2,
0x4A, 0x05, 0x93, 0xFC, 0x9E, 0x6F, 0x6B, 0x67, 0xFF, 0x88, 0xF1, 0x4E,
0xA5, 0x69, 0x4A, 0x52, 0x37, 0x05, 0xEA, 0xC6, 0x16, 0x8D, 0xD2, 0xC4,
0x99, 0xD1, 0x82, 0x2B, 0x3B, 0xBA, 0x35, 0x75, 0xF7, 0x51, 0x51, 0x58,
0xF3, 0xC8, 0x07, 0xDD, 0xE4, 0xB4, 0x03, 0x7F
};
static const unsigned char TA84_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA85_DN[] = {
0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x46, 0x52, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x44, 0x68, 0x69, 0x6D, 0x79, 0x6F, 0x74, 0x69, 0x73, 0x31,
0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x13, 0x30, 0x30,
0x30, 0x32, 0x20, 0x34, 0x38, 0x31, 0x34, 0x36, 0x33, 0x30, 0x38, 0x31,
0x30, 0x30, 0x30, 0x33, 0x36, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0C, 0x10, 0x43, 0x65, 0x72, 0x74, 0x69, 0x67, 0x6E, 0x61,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA85_RSA_N[] = {
0xCD, 0x18, 0x39, 0x65, 0x1A, 0x59, 0xB1, 0xEA, 0x64, 0x16, 0x0E, 0x8C,
0x94, 0x24, 0x95, 0x7C, 0x83, 0xD3, 0xC5, 0x39, 0x26, 0xDC, 0x0C, 0xEF,
0x16, 0x57, 0x8D, 0xD7, 0xD8, 0xAC, 0xA3, 0x42, 0x7F, 0x82, 0xCA, 0xED,
0xCD, 0x5B, 0xDB, 0x0E, 0xB7, 0x2D, 0xED, 0x45, 0x08, 0x17, 0xB2, 0xD9,
0xB3, 0xCB, 0xD6, 0x17, 0x52, 0x72, 0x28, 0xDB, 0x8E, 0x4E, 0x9E, 0x8A,
0xB6, 0x0B, 0xF9, 0x9E, 0x84, 0x9A, 0x4D, 0x76, 0xDE, 0x22, 0x29, 0x5C,
0xD2, 0xB3, 0xD2, 0x06, 0x3E, 0x30, 0x39, 0xA9, 0x74, 0xA3, 0x92, 0x56,
0x1C, 0xA1, 0x6F, 0x4C, 0x0A, 0x20, 0x6D, 0x9F, 0x23, 0x7A, 0xB4, 0xC6,
0xDA, 0x2C, 0xE4, 0x1D, 0x2C, 0xDC, 0xB3, 0x28, 0xD0, 0x13, 0xF2, 0x4C,
0x4E, 0x02, 0x49, 0xA1, 0x54, 0x40, 0x9E, 0xE6, 0xE5, 0x05, 0xA0, 0x2D,
0x84, 0xC8, 0xFF, 0x98, 0x6C, 0xD0, 0xEB, 0x8A, 0x1A, 0x84, 0x08, 0x1E,
0xB7, 0x68, 0x23, 0xEE, 0x23, 0xD5, 0x70, 0xCE, 0x6D, 0x51, 0x69, 0x10,
0xEE, 0xA1, 0x7A, 0xC2, 0xD1, 0x22, 0x31, 0xC2, 0x82, 0x85, 0xD2, 0xF2,
0x55, 0x76, 0x50, 0x7C, 0x25, 0x7A, 0xC9, 0x84, 0x5C, 0x0B, 0xAC, 0xDD,
0x42, 0x4E, 0x2B, 0xE7, 0x82, 0xA2, 0x24, 0x89, 0xCB, 0x90, 0xB2, 0xD0,
0xEE, 0x23, 0xBA, 0x66, 0x4C, 0xBB, 0x62, 0xA4, 0xF9, 0x53, 0x5A, 0x64,
0x7B, 0x7C, 0x98, 0xFA, 0xA3, 0x48, 0x9E, 0x0F, 0x95, 0xAE, 0xA7, 0x18,
0xF4, 0x6A, 0xEC, 0x2E, 0x03, 0x45, 0xAF, 0xF0, 0x74, 0xF8, 0x2A, 0xCD,
0x7A, 0x5D, 0xD1, 0xBE, 0x44, 0x26, 0x32, 0x29, 0xF1, 0xF1, 0xF5, 0x6C,
0xCC, 0x7E, 0x02, 0x21, 0x0B, 0x9F, 0x6F, 0xA4, 0x3F, 0xBE, 0x9D, 0x53,
0xE2, 0xCF, 0x7D, 0xA9, 0x2C, 0x7C, 0x58, 0x1A, 0x97, 0xE1, 0x3D, 0x37,
0x37, 0x18, 0x66, 0x28, 0xD2, 0x40, 0xC5, 0x51, 0x8A, 0x8C, 0xC3, 0x2D,
0xCE, 0x53, 0x88, 0x24, 0x58, 0x64, 0x30, 0x16, 0xC5, 0xAA, 0xE0, 0xD6,
0x0A, 0xA6, 0x40, 0xDF, 0x78, 0xF6, 0xF5, 0x04, 0x7C, 0x69, 0x13, 0x84,
0xBC, 0xD1, 0xD1, 0xA7, 0x06, 0xCF, 0x01, 0xF7, 0x68, 0xC0, 0xA8, 0x57,
0xBB, 0x3A, 0x61, 0xAD, 0x04, 0x8C, 0x93, 0xE3, 0xAD, 0xFC, 0xF0, 0xDB,
0x44, 0x6D, 0x59, 0xDC, 0x49, 0x59, 0xAE, 0xAC, 0x9A, 0x99, 0x36, 0x30,
0x41, 0x7B, 0x76, 0x33, 0x22, 0x87, 0xA3, 0xC2, 0x92, 0x86, 0x6E, 0xF9,
0x70, 0xEE, 0xAE, 0x87, 0x87, 0x95, 0x1B, 0xC4, 0x7A, 0xBD, 0x31, 0xF3,
0xD4, 0xD2, 0xE5, 0x99, 0xFF, 0xBE, 0x48, 0xEC, 0x75, 0xF5, 0x78, 0x16,
0x1D, 0xA6, 0x70, 0xC1, 0x7F, 0x3C, 0x1B, 0xA1, 0x92, 0xFB, 0xCF, 0xC8,
0x3C, 0xD6, 0xC5, 0x93, 0x0A, 0x8F, 0xF5, 0x55, 0x3A, 0x76, 0x95, 0xCE,
0x59, 0x98, 0x8A, 0x09, 0x95, 0x77, 0x32, 0x9A, 0x83, 0xBA, 0x2C, 0x04,
0x3A, 0x97, 0xBD, 0xD4, 0x2F, 0xBE, 0xD7, 0x6C, 0x9B, 0xA2, 0xCA, 0x7D,
0x6D, 0x26, 0xC9, 0x55, 0xD5, 0xCF, 0xC3, 0x79, 0x52, 0x08, 0x09, 0x99,
0x07, 0x24, 0x2D, 0x64, 0x25, 0x6B, 0xA6, 0x21, 0x69, 0x9B, 0x6A, 0xDD,
0x74, 0x4D, 0x6B, 0x97, 0x7A, 0x41, 0xBD, 0xAB, 0x17, 0xF9, 0x90, 0x17,
0x48, 0x8F, 0x36, 0xF9, 0x2D, 0xD5, 0xC5, 0xDB, 0xEE, 0xAA, 0x85, 0x45,
0x41, 0xFA, 0xCD, 0x3A, 0x45, 0xB1, 0x68, 0xE6, 0x36, 0x4C, 0x9B, 0x90,
0x57, 0xEC, 0x23, 0xB9, 0x87, 0x08, 0xC2, 0xC4, 0x09, 0xF1, 0x97, 0x86,
0x2A, 0x28, 0x4D, 0xE2, 0x74, 0xC0, 0xDA, 0xC4, 0x8C, 0xDB, 0xDF, 0xE2,
0xA1, 0x17, 0x59, 0xCE, 0x24, 0x59, 0x74, 0x31, 0xDA, 0x7F, 0xFD, 0x30,
0x6D, 0xD9, 0xDC, 0xE1, 0x6A, 0xE1, 0xFC, 0x5F
};
static const unsigned char TA85_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA86_DN[] = {
0x30, 0x67, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B,
0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49,
0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65,
0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E,
0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69,
0x74, 0x65, 0x64, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x13, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31
};
static const unsigned char TA86_RSA_N[] = {
0x93, 0x4B, 0xBB, 0xE9, 0x66, 0x8A, 0xEE, 0x9D, 0x5B, 0xD5, 0x34, 0x93,
0xD0, 0x1B, 0x1E, 0xC3, 0xE7, 0x9E, 0xB8, 0x64, 0x33, 0x7F, 0x63, 0x78,
0x68, 0xB4, 0xCD, 0x2E, 0x71, 0x75, 0xD7, 0x9B, 0x20, 0xC6, 0x4D, 0x29,
0xBC, 0xB6, 0x68, 0x60, 0x8A, 0xF7, 0x21, 0x9A, 0x56, 0x35, 0x5A, 0xF3,
0x76, 0xBD, 0xD8, 0xCD, 0x9A, 0xFF, 0x93, 0x56, 0x4B, 0xA5, 0x59, 0x06,
0xA1, 0x93, 0x34, 0x29, 0xDD, 0x16, 0x34, 0x75, 0x4E, 0xF2, 0x81, 0xB4,
0xC7, 0x96, 0x4E, 0xAD, 0x19, 0x15, 0x52, 0x4A, 0xFE, 0x3C, 0x70, 0x75,
0x70, 0xCD, 0xAF, 0x2B, 0xAB, 0x15, 0x9A, 0x33, 0x3C, 0xAA, 0xB3, 0x8B,
0xAA, 0xCD, 0x43, 0xFD, 0xF5, 0xEA, 0x70, 0xFF, 0xED, 0xCF, 0x11, 0x3B,
0x94, 0xCE, 0x4E, 0x32, 0x16, 0xD3, 0x23, 0x40, 0x2A, 0x77, 0xB3, 0xAF,
0x3C, 0x01, 0x2C, 0x6C, 0xED, 0x99, 0x2C, 0x8B, 0xD9, 0x4E, 0x69, 0x98,
0xB2, 0xF7, 0x8F, 0x41, 0xB0, 0x32, 0x78, 0x61, 0xD6, 0x0D, 0x5F, 0xC3,
0xFA, 0xA2, 0x40, 0x92, 0x1D, 0x5C, 0x17, 0xE6, 0x70, 0x3E, 0x35, 0xE7,
0xA2, 0xB7, 0xC2, 0x62, 0xE2, 0xAB, 0xA4, 0x38, 0x4C, 0xB5, 0x39, 0x35,
0x6F, 0xEA, 0x03, 0x69, 0xFA, 0x3A, 0x54, 0x68, 0x85, 0x6D, 0xD6, 0xF2,
0x2F, 0x43, 0x55, 0x1E, 0x91, 0x0D, 0x0E, 0xD8, 0xD5, 0x6A, 0xA4, 0x96,
0xD1, 0x13, 0x3C, 0x2C, 0x78, 0x50, 0xE8, 0x3A, 0x92, 0xD2, 0x17, 0x56,
0xE5, 0x35, 0x1A, 0x40, 0x1C, 0x3E, 0x8D, 0x2C, 0xED, 0x39, 0xDF, 0x42,
0xE0, 0x83, 0x41, 0x74, 0xDF, 0xA3, 0xCD, 0xC2, 0x86, 0x60, 0x48, 0x68,
0xE3, 0x69, 0x0B, 0x54, 0x00, 0x8B, 0xE4, 0x76, 0x69, 0x21, 0x0D, 0x79,
0x4E, 0x34, 0x08, 0x5E, 0x14, 0xC2, 0xCC, 0xB1, 0xB7, 0xAD, 0xD7, 0x7C,
0x70, 0x8A, 0xC7, 0x85
};
static const unsigned char TA86_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA87_DN[] = {
0x30, 0x6B, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x49, 0x4E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B,
0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49,
0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1C, 0x65,
0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E,
0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73, 0x20, 0x4C, 0x69, 0x6D, 0x69,
0x74, 0x65, 0x64, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x17, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47,
0x33
};
static const unsigned char TA87_EC_Q[] = {
0x04, 0x23, 0xA5, 0x0C, 0xB8, 0x2D, 0x12, 0xF5, 0x28, 0xF3, 0xB1, 0xB2,
0xDD, 0xE2, 0x02, 0x12, 0x80, 0x9E, 0x39, 0x5F, 0x49, 0x4D, 0x9F, 0xC9,
0x25, 0x34, 0x59, 0x74, 0xEC, 0xBB, 0x06, 0x1C, 0xE7, 0xC0, 0x72, 0xAF,
0xE8, 0xAE, 0x2F, 0xE1, 0x41, 0x54, 0x87, 0x14, 0xA8, 0x4A, 0xB2, 0xE8,
0x7C, 0x82, 0xE6, 0x5B, 0x6A, 0xB5, 0xDC, 0xB3, 0x75, 0xCE, 0x8B, 0x06,
0xD0, 0x86, 0x23, 0xBF, 0x46, 0xD5, 0x8E, 0x0F, 0x3F, 0x04, 0xF4, 0xD7,
0x1C, 0x92, 0x7E, 0xF6, 0xA5, 0x63, 0xC2, 0xF5, 0x5F, 0x8E, 0x2E, 0x4F,
0xA1, 0x18, 0x19, 0x02, 0x2B, 0x32, 0x0A, 0x82, 0x64, 0x7D, 0x16, 0x93,
0xD1
};
static const unsigned char TA88_DN[] = {
0x30, 0x56, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B,
0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49,
0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65,
0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x1C,
0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x65, 0x6D, 0x53,
0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20,
0x2D, 0x20, 0x43, 0x31
};
static const unsigned char TA88_RSA_N[] = {
0xCF, 0xEB, 0xA9, 0xB9, 0xF1, 0x99, 0x05, 0xCC, 0xD8, 0x28, 0x21, 0x4A,
0xF3, 0x73, 0x34, 0x51, 0x84, 0x56, 0x10, 0xF5, 0xA0, 0x4F, 0x2C, 0x12,
0xE3, 0xFA, 0x13, 0x9A, 0x27, 0xD0, 0xCF, 0xF9, 0x79, 0x1A, 0x74, 0x5F,
0x1D, 0x79, 0x39, 0xFC, 0x5B, 0xF8, 0x70, 0x8E, 0xE0, 0x92, 0x52, 0xF7,
0xE4, 0x25, 0xF9, 0x54, 0x83, 0xD9, 0x1D, 0xD3, 0xC8, 0x5A, 0x85, 0x3F,
0x5E, 0xC7, 0xB6, 0x07, 0xEE, 0x3E, 0xC0, 0xCE, 0x9A, 0xAF, 0xAC, 0x56,
0x42, 0x2A, 0x39, 0x25, 0x70, 0xD6, 0xBF, 0xB5, 0x7B, 0x36, 0xAD, 0xAC,
0xF6, 0x73, 0xDC, 0xCD, 0xD7, 0x1D, 0x8A, 0x83, 0xA5, 0xFB, 0x2B, 0x90,
0x15, 0x37, 0x6B, 0x1C, 0x26, 0x47, 0xDC, 0x3B, 0x29, 0x56, 0x93, 0x6A,
0xB3, 0xC1, 0x6A, 0x3A, 0x9D, 0x3D, 0xF5, 0xC1, 0x97, 0x38, 0x58, 0x05,
0x8B, 0x1C, 0x11, 0xE3, 0xE4, 0xB4, 0xB8, 0x5D, 0x85, 0x1D, 0x83, 0xFE,
0x78, 0x5F, 0x0B, 0x45, 0x68, 0x18, 0x48, 0xA5, 0x46, 0x73, 0x34, 0x3B,
0xFE, 0x0F, 0xC8, 0x76, 0xBB, 0xC7, 0x18, 0xF3, 0x05, 0xD1, 0x86, 0xF3,
0x85, 0xED, 0xE7, 0xB9, 0xD9, 0x32, 0xAD, 0x55, 0x88, 0xCE, 0xA6, 0xB6,
0x91, 0xB0, 0x4F, 0xAC, 0x7E, 0x15, 0x23, 0x96, 0xF6, 0x3F, 0xF0, 0x20,
0x34, 0x16, 0xDE, 0x0A, 0xC6, 0xC4, 0x04, 0x45, 0x79, 0x7F, 0xA7, 0xFD,
0xBE, 0xD2, 0xA9, 0xA5, 0xAF, 0x9C, 0xC5, 0x23, 0x2A, 0xF7, 0x3C, 0x21,
0x6C, 0xBD, 0xAF, 0x8F, 0x4E, 0xC5, 0x3A, 0xB2, 0xF3, 0x34, 0x12, 0xFC,
0xDF, 0x80, 0x1A, 0x49, 0xA4, 0xD4, 0xA9, 0x95, 0xF7, 0x9E, 0x89, 0x5E,
0xA2, 0x89, 0xAC, 0x94, 0xCB, 0xA8, 0x68, 0x9B, 0xAF, 0x8A, 0x65, 0x27,
0xCD, 0x89, 0xEE, 0xDD, 0x8C, 0xB5, 0x6B, 0x29, 0x70, 0x43, 0xA0, 0x69,
0x0B, 0xE4, 0xB9, 0x0F
};
static const unsigned char TA88_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA89_DN[] = {
0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B,
0x13, 0x0A, 0x65, 0x6D, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x50, 0x4B, 0x49,
0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0B, 0x65,
0x4D, 0x75, 0x64, 0x68, 0x72, 0x61, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x20,
0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x65, 0x6D, 0x53,
0x69, 0x67, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x43, 0x33
};
static const unsigned char TA89_EC_Q[] = {
0x04, 0xFD, 0xA5, 0x61, 0xAE, 0x7B, 0x26, 0x10, 0x1D, 0xE9, 0xB7, 0x22,
0x30, 0xAE, 0x06, 0xF4, 0x81, 0xB3, 0xB1, 0x42, 0x71, 0x95, 0x39, 0xBC,
0xD3, 0x52, 0xE3, 0xAF, 0xAF, 0xF9, 0xF2, 0x97, 0x35, 0x92, 0x36, 0x46,
0x0E, 0x87, 0x95, 0x8D, 0xB9, 0x39, 0x5A, 0xE9, 0xBB, 0xDF, 0xD0, 0xFE,
0xC8, 0x07, 0x41, 0x3C, 0xBB, 0x55, 0x6F, 0x83, 0xA3, 0x6A, 0xFB, 0x62,
0xB0, 0x81, 0x89, 0x02, 0x70, 0x7D, 0x48, 0xC5, 0x4A, 0xE3, 0xE9, 0x22,
0x54, 0x22, 0x4D, 0x93, 0xBB, 0x42, 0x0C, 0xAF, 0x77, 0x9C, 0x23, 0xA6,
0x7D, 0xD7, 0x61, 0x11, 0xCE, 0x65, 0xC7, 0xF8, 0x7F, 0xFE, 0xF5, 0xF2,
0xA9
};
static const unsigned char TA90_DN[] = {
0x30, 0x6F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x48, 0x4B, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x08,
0x13, 0x09, 0x48, 0x6F, 0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31,
0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x48, 0x6F,
0x6E, 0x67, 0x20, 0x4B, 0x6F, 0x6E, 0x67, 0x31, 0x16, 0x30, 0x14, 0x06,
0x03, 0x55, 0x04, 0x0A, 0x13, 0x0D, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F,
0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x31, 0x20, 0x30, 0x1E, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x48, 0x6F, 0x6E, 0x67, 0x6B, 0x6F,
0x6E, 0x67, 0x20, 0x50, 0x6F, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41, 0x20, 0x33
};
static const unsigned char TA90_RSA_N[] = {
0xB3, 0x88, 0xD7, 0xEA, 0xCE, 0x0F, 0x20, 0x4E, 0xBE, 0xE6, 0xD6, 0x03,
0x6D, 0xEE, 0x59, 0xFC, 0xC2, 0x57, 0xDF, 0x29, 0x68, 0xA1, 0x83, 0x0E,
0x3E, 0x68, 0xC7, 0x68, 0x58, 0x9C, 0x1C, 0x60, 0x4B, 0x89, 0x43, 0x0C,
0xB9, 0xD4, 0x15, 0xB2, 0xEE, 0xC1, 0x4E, 0x75, 0xE9, 0xB5, 0xA7, 0xEF,
0xE5, 0xE9, 0x35, 0x99, 0xE4, 0xCC, 0x1C, 0xE7, 0x4B, 0x5F, 0x8D, 0x33,
0x30, 0x20, 0x33, 0x53, 0xD9, 0xA6, 0xBB, 0xD5, 0x3E, 0x13, 0x8E, 0xE9,
0x1F, 0x87, 0x49, 0xAD, 0x50, 0x2D, 0x50, 0xCA, 0x18, 0xBE, 0x01, 0x58,
0xA2, 0x13, 0x70, 0x96, 0xBB, 0x89, 0x88, 0x56, 0x80, 0x5C, 0xF8, 0xBD,
0x2C, 0x3C, 0xE1, 0x4C, 0x57, 0x88, 0xBB, 0xD3, 0xB9, 0x95, 0xEF, 0xCB,
0xC7, 0xF6, 0xDA, 0x31, 0x74, 0x28, 0xA6, 0xE6, 0x54, 0x89, 0xF5, 0x41,
0x31, 0xCA, 0xE5, 0x26, 0x1A, 0xCD, 0x82, 0xE0, 0x70, 0xDA, 0x3B, 0x29,
0xBB, 0xD5, 0x03, 0xF5, 0x99, 0xBA, 0x55, 0xF5, 0x64, 0xD1, 0x60, 0x0E,
0xB3, 0x89, 0x49, 0xB8, 0x8A, 0x2F, 0x05, 0xD2, 0x84, 0x45, 0x28, 0x7C,
0x8F, 0x68, 0x50, 0x12, 0x78, 0xFC, 0x0B, 0xB5, 0x53, 0xCB, 0xC2, 0x98,
0x1C, 0x84, 0xA3, 0x9E, 0xB0, 0xBE, 0x23, 0xA4, 0xDA, 0xDC, 0xC8, 0x2B,
0x1E, 0xDA, 0x6E, 0x45, 0x1E, 0x89, 0x98, 0xDA, 0xF9, 0x00, 0x2E, 0x06,
0xE9, 0x0C, 0x3B, 0x70, 0xD5, 0x50, 0x25, 0x88, 0x99, 0xCB, 0xCD, 0x73,
0x60, 0xF7, 0xD5, 0xFF, 0x35, 0x67, 0xC5, 0xA1, 0xBC, 0x5E, 0xAB, 0xCD,
0x4A, 0xB8, 0x45, 0xEB, 0xC8, 0x68, 0x1E, 0x0D, 0x0D, 0x14, 0x46, 0x12,
0xE3, 0xD2, 0x64, 0x62, 0x8A, 0x42, 0x98, 0xBC, 0xB4, 0xC6, 0x08, 0x08,
0xF8, 0xFD, 0xA8, 0x4C, 0x64, 0x9C, 0x76, 0x01, 0xBD, 0x2F, 0xA9, 0x6C,
0x33, 0x0F, 0xD8, 0x3F, 0x28, 0xB8, 0x3C, 0x69, 0x01, 0x42, 0x86, 0x7E,
0x69, 0xC1, 0xC9, 0x06, 0xCA, 0xE5, 0x7A, 0x46, 0x65, 0xE9, 0xC2, 0xD6,
0x50, 0x41, 0x2E, 0x3F, 0xB7, 0xE4, 0xED, 0x6C, 0xD7, 0xBF, 0x26, 0x01,
0x11, 0xA2, 0x16, 0x29, 0x4A, 0x6B, 0x34, 0x06, 0x90, 0xEC, 0x13, 0xD2,
0xB6, 0xFB, 0x6A, 0x76, 0xD2, 0x3C, 0xED, 0xF0, 0xD6, 0x2D, 0xDD, 0xE1,
0x15, 0xEC, 0xA3, 0x9B, 0x2F, 0x2C, 0xC9, 0x3E, 0x2B, 0xE4, 0x69, 0x3B,
0xFF, 0x72, 0x25, 0xB1, 0x36, 0x86, 0x5B, 0xC7, 0x7F, 0x6B, 0x8B, 0x55,
0x1B, 0x4A, 0xC5, 0x20, 0x61, 0x3D, 0xAE, 0xCB, 0x50, 0xE1, 0x08, 0x3A,
0xBE, 0xB0, 0x8F, 0x63, 0x41, 0x53, 0x30, 0x08, 0x59, 0x3C, 0x98, 0x1D,
0x77, 0xBA, 0x63, 0x91, 0x7A, 0xCA, 0x10, 0x50, 0x60, 0xBF, 0xF0, 0xD7,
0xBC, 0x95, 0x87, 0x8F, 0x97, 0xC5, 0xFE, 0x97, 0x6A, 0x01, 0x94, 0xA3,
0x7C, 0x5B, 0x85, 0x1D, 0x2A, 0x39, 0x3A, 0xD0, 0x54, 0xA1, 0xD1, 0x39,
0x71, 0x9D, 0xFD, 0x21, 0xF9, 0xB5, 0x7B, 0xF0, 0xE2, 0xE0, 0x02, 0x8F,
0x6E, 0x96, 0x24, 0x25, 0x2C, 0xA0, 0x1E, 0x2C, 0xA8, 0xC4, 0x89, 0xA7,
0xEF, 0xED, 0x99, 0x06, 0x2F, 0xB6, 0x0A, 0x4C, 0x4F, 0xDB, 0xA2, 0xCC,
0x37, 0x1A, 0xAF, 0x47, 0x85, 0x2D, 0x8A, 0x5F, 0xC4, 0x34, 0x34, 0x4C,
0x00, 0xFD, 0x18, 0x93, 0x67, 0x13, 0xD1, 0x37, 0xE6, 0x48, 0xB4, 0x8B,
0x06, 0xC5, 0x57, 0x7B, 0x19, 0x86, 0x0A, 0x79, 0xCB, 0x00, 0xC9, 0x52,
0xAF, 0x42, 0xFF, 0x37, 0x8F, 0xE1, 0xA3, 0x1E, 0x7A, 0x3D, 0x50, 0xAB,
0x63, 0x06, 0xE7, 0x15, 0xB5, 0x3F, 0xB6, 0x45, 0x37, 0x94, 0x37, 0xB1,
0x7E, 0xF2, 0x48, 0xC3, 0x7F, 0xC5, 0x75, 0xFE, 0x97, 0x8D, 0x45, 0x8F,
0x1A, 0xA7, 0x1A, 0x72, 0x28, 0x1A, 0x40, 0x0F
};
static const unsigned char TA90_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA91_DN[] = {
0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20,
0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31,
0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69,
0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69,
0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37
};
static const unsigned char TA91_EC_Q[] = {
0x04, 0xD4, 0xBC, 0x3D, 0x02, 0x42, 0x75, 0x41, 0x13, 0x23, 0xCD, 0x80,
0x04, 0x86, 0x02, 0x51, 0x2F, 0x6A, 0xA8, 0x81, 0x62, 0x0B, 0x65, 0xCC,
0xF6, 0xCA, 0x9D, 0x1E, 0x6F, 0x4A, 0x66, 0x51, 0xA2, 0x03, 0xD9, 0x9D,
0x91, 0xFA, 0xB6, 0x16, 0xB1, 0x8C, 0x6E, 0xDE, 0x7C, 0xCD, 0xDB, 0x79,
0xA6, 0x2F, 0xCE, 0xBB, 0xCE, 0x71, 0x2F, 0xE5, 0xA5, 0xAB, 0x28, 0xEC,
0x63, 0x04, 0x66, 0x99, 0xF8, 0xFA, 0xF2, 0x93, 0x10, 0x05, 0xE1, 0x81,
0x28, 0x42, 0xE3, 0xC6, 0x68, 0xF4, 0xE6, 0x1B, 0x84, 0x60, 0x4A, 0x89,
0xAF, 0xED, 0x79, 0x0F, 0x3B, 0xCE, 0xF1, 0xF6, 0x44, 0xF5, 0x01, 0x78,
0xC0
};
static const unsigned char TA92_DN[] = {
0x30, 0x65, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20,
0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31,
0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2D, 0x4D, 0x69,
0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69,
0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37
};
static const unsigned char TA92_RSA_N[] = {
0xCA, 0x5B, 0xBE, 0x94, 0x33, 0x8C, 0x29, 0x95, 0x91, 0x16, 0x0A, 0x95,
0xBD, 0x47, 0x62, 0xC1, 0x89, 0xF3, 0x99, 0x36, 0xDF, 0x46, 0x90, 0xC9,
0xA5, 0xED, 0x78, 0x6A, 0x6F, 0x47, 0x91, 0x68, 0xF8, 0x27, 0x67, 0x50,
0x33, 0x1D, 0xA1, 0xA6, 0xFB, 0xE0, 0xE5, 0x43, 0xA3, 0x84, 0x02, 0x57,
0x01, 0x5D, 0x9C, 0x48, 0x40, 0x82, 0x53, 0x10, 0xBC, 0xBF, 0xC7, 0x3B,
0x68, 0x90, 0xB6, 0x82, 0x2D, 0xE5, 0xF4, 0x65, 0xD0, 0xCC, 0x6D, 0x19,
0xCC, 0x95, 0xF9, 0x7B, 0xAC, 0x4A, 0x94, 0xAD, 0x0E, 0xDE, 0x4B, 0x43,
0x1D, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04,
0xFC, 0xE5, 0xE9, 0x6C, 0xB3, 0xB6, 0x1F, 0x50, 0x94, 0x38, 0x65, 0x50,
0x5C, 0x17, 0x46, 0xB9, 0xB6, 0x85, 0xB5, 0x1C, 0xB5, 0x17, 0xE8, 0xD6,
0x45, 0x9D, 0xD8, 0xB2, 0x26, 0xB0, 0xCA, 0xC4, 0x70, 0x4A, 0xAE, 0x60,
0xA4, 0xDD, 0xB3, 0xD9, 0xEC, 0xFC, 0x3B, 0xD5, 0x57, 0x72, 0xBC, 0x3F,
0xC8, 0xC9, 0xB2, 0xDE, 0x4B, 0x6B, 0xF8, 0x23, 0x6C, 0x03, 0xC0, 0x05,
0xBD, 0x95, 0xC7, 0xCD, 0x73, 0x3B, 0x66, 0x80, 0x64, 0xE3, 0x1A, 0xAC,
0x2E, 0xF9, 0x47, 0x05, 0xF2, 0x06, 0xB6, 0x9B, 0x73, 0xF5, 0x78, 0x33,
0x5B, 0xC7, 0xA1, 0xFB, 0x27, 0x2A, 0xA1, 0xB4, 0x9A, 0x91, 0x8C, 0x91,
0xD3, 0x3A, 0x82, 0x3E, 0x76, 0x40, 0xB4, 0xCD, 0x52, 0x61, 0x51, 0x70,
0x28, 0x3F, 0xC5, 0xC5, 0x5A, 0xF2, 0xC9, 0x8C, 0x49, 0xBB, 0x14, 0x5B,
0x4D, 0xC8, 0xFF, 0x67, 0x4D, 0x4C, 0x12, 0x96, 0xAD, 0xF5, 0xFE, 0x78,
0xA8, 0x97, 0x87, 0xD7, 0xFD, 0x5E, 0x20, 0x80, 0xDC, 0xA1, 0x4B, 0x22,
0xFB, 0xD4, 0x89, 0xAD, 0xBA, 0xCE, 0x47, 0x97, 0x47, 0x55, 0x7B, 0x8F,
0x45, 0xC8, 0x67, 0x28, 0x84, 0x95, 0x1C, 0x68, 0x30, 0xEF, 0xEF, 0x49,
0xE0, 0x35, 0x7B, 0x64, 0xE7, 0x98, 0xB0, 0x94, 0xDA, 0x4D, 0x85, 0x3B,
0x3E, 0x55, 0xC4, 0x28, 0xAF, 0x57, 0xF3, 0x9E, 0x13, 0xDB, 0x46, 0x27,
0x9F, 0x1E, 0xA2, 0x5E, 0x44, 0x83, 0xA4, 0xA5, 0xCA, 0xD5, 0x13, 0xB3,
0x4B, 0x3F, 0xC4, 0xE3, 0xC2, 0xE6, 0x86, 0x61, 0xA4, 0x52, 0x30, 0xB9,
0x7A, 0x20, 0x4F, 0x6F, 0x0F, 0x38, 0x53, 0xCB, 0x33, 0x0C, 0x13, 0x2B,
0x8F, 0xD6, 0x9A, 0xBD, 0x2A, 0xC8, 0x2D, 0xB1, 0x1C, 0x7D, 0x4B, 0x51,
0xCA, 0x47, 0xD1, 0x48, 0x27, 0x72, 0x5D, 0x87, 0xEB, 0xD5, 0x45, 0xE6,
0x48, 0x65, 0x9D, 0xAF, 0x52, 0x90, 0xBA, 0x5B, 0xA2, 0x18, 0x65, 0x57,
0x12, 0x9F, 0x68, 0xB9, 0xD4, 0x15, 0x6B, 0x94, 0xC4, 0x69, 0x22, 0x98,
0xF4, 0x33, 0xE0, 0xED, 0xF9, 0x51, 0x8E, 0x41, 0x50, 0xC9, 0x34, 0x4F,
0x76, 0x90, 0xAC, 0xFC, 0x38, 0xC1, 0xD8, 0xE1, 0x7B, 0xB9, 0xE3, 0xE3,
0x94, 0xE1, 0x46, 0x69, 0xCB, 0x0E, 0x0A, 0x50, 0x6B, 0x13, 0xBA, 0xAC,
0x0F, 0x37, 0x5A, 0xB7, 0x12, 0xB5, 0x90, 0x81, 0x1E, 0x56, 0xAE, 0x57,
0x22, 0x86, 0xD9, 0xC9, 0xD2, 0xD1, 0xD7, 0x51, 0xE3, 0xAB, 0x3B, 0xC6,
0x55, 0xFD, 0x1E, 0x0E, 0xD3, 0x74, 0x0A, 0xD1, 0xDA, 0xAA, 0xEA, 0x69,
0xB8, 0x97, 0x28, 0x8F, 0x48, 0xC4, 0x07, 0xF8, 0x52, 0x43, 0x3A, 0xF4,
0xCA, 0x55, 0x35, 0x2C, 0xB0, 0xA6, 0x6A, 0xC0, 0x9C, 0xF9, 0xF2, 0x81,
0xE1, 0x12, 0x6A, 0xC0, 0x45, 0xD9, 0x67, 0xB3, 0xCE, 0xFF, 0x23, 0xA2,
0x89, 0x0A, 0x54, 0xD4, 0x14, 0xB9, 0x2A, 0xA8, 0xD7, 0xEC, 0xF9, 0xAB,
0xCD, 0x25, 0x58, 0x32, 0x79, 0x8F, 0x90, 0x5B, 0x98, 0x39, 0xC4, 0x08,
0x06, 0xC1, 0xAC, 0x7F, 0x0E, 0x3D, 0x00, 0xA5
};
static const unsigned char TA92_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA93_DN[] = {
0x30, 0x71, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x48, 0x55, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07,
0x0C, 0x08, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65, 0x73, 0x74, 0x31, 0x16,
0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0D, 0x4D, 0x69, 0x63,
0x72, 0x6F, 0x73, 0x65, 0x63, 0x20, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x17,
0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0E, 0x56, 0x41, 0x54,
0x48, 0x55, 0x2D, 0x32, 0x33, 0x35, 0x38, 0x34, 0x34, 0x39, 0x37, 0x31,
0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x15, 0x65, 0x2D,
0x53, 0x7A, 0x69, 0x67, 0x6E, 0x6F, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x37
};
static const unsigned char TA93_EC_Q[] = {
0x04, 0x96, 0xDC, 0x3D, 0x8A, 0xD8, 0xB0, 0x7B, 0x6F, 0xC6, 0x27, 0xBE,
0x44, 0x90, 0xB1, 0xB3, 0x56, 0x15, 0x7B, 0x8E, 0x43, 0x24, 0x7D, 0x1A,
0x84, 0x59, 0xEE, 0x63, 0x68, 0xB2, 0xC6, 0x5E, 0x87, 0xD0, 0x15, 0x48,
0x1E, 0xA8, 0x90, 0xAD, 0xBD, 0x53, 0xA2, 0xDA, 0xDE, 0x3A, 0x90, 0xA6,
0x60, 0x5F, 0x68, 0x32, 0xB5, 0x86, 0x41, 0xDF, 0x87, 0x5B, 0x2C, 0x7B,
0xC5, 0xFE, 0x7C, 0x7A, 0xDA
};
static const unsigned char TA94_DN[] = {
0x30, 0x41, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x52, 0x4F, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0B, 0x43, 0x45, 0x52, 0x54, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x53,
0x41, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x13,
0x63, 0x65, 0x72, 0x74, 0x53, 0x49, 0x47, 0x4E, 0x20, 0x52, 0x4F, 0x4F,
0x54, 0x20, 0x43, 0x41, 0x20, 0x47, 0x32
};
static const unsigned char TA94_RSA_N[] = {
0xC0, 0xC5, 0x75, 0x19, 0x91, 0x7D, 0x44, 0x74, 0x74, 0x87, 0xFE, 0x0E,
0x3B, 0x96, 0xDC, 0xD8, 0x01, 0x16, 0xCC, 0xEE, 0x63, 0x91, 0xE7, 0x0B,
0x6F, 0xCE, 0x3B, 0x0A, 0x69, 0x1A, 0x7C, 0xC2, 0xE3, 0xAF, 0x82, 0x8E,
0x86, 0xD7, 0x5E, 0x8F, 0x57, 0xEB, 0xD3, 0x21, 0x59, 0xFD, 0x39, 0x37,
0x42, 0x30, 0xBE, 0x50, 0xEA, 0xB6, 0x0F, 0xA9, 0x88, 0xD8, 0x2E, 0x2D,
0x69, 0x21, 0xE7, 0xD1, 0x37, 0x18, 0x4E, 0x7D, 0x91, 0xD5, 0x16, 0x5F,
0x6B, 0x5B, 0x00, 0xC2, 0x39, 0x43, 0x0D, 0x36, 0x85, 0x52, 0xB9, 0x53,
0x65, 0x0F, 0x1D, 0x42, 0xE5, 0x8F, 0xCF, 0x05, 0xD3, 0xEE, 0xDC, 0x0C,
0x1A, 0xD9, 0xB8, 0x8B, 0x78, 0x22, 0x67, 0xE4, 0x69, 0xB0, 0x68, 0xC5,
0x3C, 0xE4, 0x6C, 0x5A, 0x46, 0xE7, 0xCD, 0xC7, 0xFA, 0xEF, 0xC4, 0xEC,
0x4B, 0xBD, 0x6A, 0xA4, 0xAC, 0xFD, 0xCC, 0x28, 0x51, 0xEF, 0x92, 0xB4,
0x29, 0xAB, 0xAB, 0x35, 0x9A, 0x4C, 0xE4, 0xC4, 0x08, 0xC6, 0x26, 0xCC,
0xF8, 0x69, 0x9F, 0xE4, 0x9C, 0xF0, 0x29, 0xD3, 0x5C, 0xF9, 0xC6, 0x16,
0x25, 0x9E, 0x23, 0xC3, 0x20, 0xC1, 0x3D, 0x0F, 0x3F, 0x38, 0x40, 0xB0,
0xFE, 0x82, 0x44, 0x38, 0xAA, 0x5A, 0x1A, 0x8A, 0x6B, 0x63, 0x58, 0x38,
0xB4, 0x15, 0xD3, 0xB6, 0x11, 0x69, 0x7B, 0x1E, 0x54, 0xEE, 0x8C, 0x1A,
0x22, 0xAC, 0x72, 0x97, 0x3F, 0x23, 0x59, 0x9B, 0xC9, 0x22, 0x84, 0xC1,
0x07, 0x4F, 0xCC, 0x7F, 0xE2, 0x57, 0xCA, 0x12, 0x70, 0xBB, 0xA6, 0x65,
0xF3, 0x69, 0x75, 0x63, 0xBD, 0x95, 0xFB, 0x1B, 0x97, 0xCD, 0xE4, 0xA8,
0xAF, 0xF6, 0xD1, 0x4E, 0xA8, 0xD9, 0x8A, 0x71, 0x24, 0xCD, 0x36, 0x3D,
0xBC, 0x96, 0xC4, 0xF1, 0x6C, 0xA9, 0xAE, 0xE5, 0xCF, 0x0D, 0x6E, 0x28,
0x0D, 0xB0, 0x0E, 0xB5, 0xCA, 0x51, 0x7B, 0x78, 0x14, 0xC3, 0x20, 0x2F,
0x7F, 0xFB, 0x14, 0x55, 0xE1, 0x11, 0x99, 0xFD, 0xD5, 0x0A, 0xA1, 0x9E,
0x02, 0xE3, 0x62, 0x5F, 0xEB, 0x35, 0x4B, 0x2C, 0xB8, 0x72, 0xE8, 0x3E,
0x3D, 0x4F, 0xAC, 0x2C, 0xBB, 0x2E, 0x86, 0xE2, 0xA3, 0x76, 0x8F, 0xE5,
0x93, 0x2A, 0xCF, 0xA5, 0xAB, 0xC8, 0x5C, 0x8D, 0x4B, 0x06, 0xFF, 0x12,
0x46, 0xAC, 0x78, 0xCB, 0x14, 0x07, 0x35, 0xE0, 0xA9, 0xDF, 0x8B, 0xE9,
0xAF, 0x15, 0x4F, 0x16, 0x89, 0x5B, 0xBD, 0xF6, 0x8D, 0xC6, 0x59, 0xAE,
0x88, 0x85, 0x0E, 0xC1, 0x89, 0xEB, 0x1F, 0x67, 0xC5, 0x45, 0x8E, 0xFF,
0x6D, 0x37, 0x36, 0x2B, 0x78, 0x66, 0x83, 0x91, 0x51, 0x2B, 0x3D, 0xFF,
0x51, 0x77, 0x76, 0x62, 0xA1, 0xEC, 0x67, 0x3E, 0x3E, 0x81, 0x83, 0xE0,
0x56, 0xA9, 0x50, 0x1F, 0x1F, 0x7A, 0x99, 0xAB, 0x63, 0xBF, 0x84, 0x17,
0x77, 0xF1, 0x0D, 0x3B, 0xDF, 0xF7, 0x9C, 0x61, 0xB3, 0x35, 0x98, 0x8A,
0x3A, 0xB2, 0xEC, 0x3C, 0x1A, 0x37, 0x3F, 0x7E, 0x8F, 0x92, 0xCF, 0xD9,
0x12, 0x14, 0x64, 0xDA, 0x10, 0x02, 0x15, 0x41, 0xFF, 0x4F, 0xC4, 0xEB,
0x1C, 0xA3, 0xC9, 0xFA, 0x99, 0xF7, 0x46, 0xE9, 0xE1, 0x18, 0xD9, 0xB1,
0xB8, 0x32, 0x2D, 0xCB, 0x14, 0x0C, 0x50, 0xD8, 0x83, 0x65, 0x83, 0xEE,
0xB9, 0x5C, 0xCF, 0xCB, 0x05, 0x5A, 0x4C, 0xFA, 0x19, 0x97, 0x6B, 0xD6,
0x5D, 0x13, 0xD3, 0xC2, 0x5C, 0x54, 0xBC, 0x32, 0x73, 0xA0, 0x78, 0xF5,
0xF1, 0x6D, 0x1E, 0xCB, 0x9F, 0xA5, 0xA6, 0x9F, 0x22, 0xDC, 0xD1, 0x51,
0x9E, 0x82, 0x79, 0x64, 0x60, 0x29, 0x13, 0x3E, 0xA3, 0xFD, 0x4F, 0x72,
0x6A, 0xAB, 0xE2, 0xD4, 0xE5, 0xB8, 0x24, 0x55, 0x2C, 0x44, 0x4B, 0x8A,
0x88, 0x44, 0x9C, 0xCA, 0x84, 0xD3, 0x2A, 0x3B
};
static const unsigned char TA94_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA95_DN[] = {
0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04,
0x08, 0x0C, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31,
0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x43, 0x68,
0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55,
0x04, 0x0A, 0x0C, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76,
0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x31, 0x30, 0x2F, 0x06, 0x03, 0x55, 0x04,
0x03, 0x0C, 0x28, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA95_RSA_N[] = {
0xB9, 0x5D, 0x51, 0x28, 0x4B, 0x3C, 0x37, 0x92, 0xD1, 0x82, 0xCE, 0xBD,
0x1D, 0xBD, 0xCD, 0xDD, 0xB8, 0xAB, 0xCF, 0x0A, 0x3E, 0xE1, 0x5D, 0xE5,
0xDC, 0xAA, 0x09, 0xB9, 0x57, 0x02, 0x3E, 0xE6, 0x63, 0x61, 0xDF, 0xF2,
0x0F, 0x82, 0x63, 0xAE, 0xA3, 0xF7, 0xAC, 0x73, 0xD1, 0x7C, 0xE7, 0xB3,
0x0B, 0xAF, 0x08, 0x00, 0x09, 0x59, 0x7F, 0xCD, 0x29, 0x2A, 0x88, 0x93,
0x87, 0x17, 0x18, 0x80, 0xED, 0x88, 0xB2, 0xB4, 0xB6, 0x10, 0x1F, 0x2D,
0xD6, 0x5F, 0x55, 0xA2, 0x13, 0x5D, 0xD1, 0xC6, 0xEB, 0x06, 0x56, 0x89,
0x88, 0xFE, 0xAC, 0x32, 0x9D, 0xFD, 0x5C, 0xC3, 0x05, 0xC7, 0x6E, 0xEE,
0x86, 0x89, 0xBA, 0x88, 0x03, 0x9D, 0x72, 0x21, 0x86, 0x90, 0xAE, 0x8F,
0x03, 0xA5, 0xDC, 0x9F, 0x88, 0x28, 0xCB, 0xA3, 0x92, 0x49, 0x0F, 0xEC,
0xD0, 0x0F, 0xE2, 0x6D, 0x44, 0x4F, 0x80, 0x6A, 0xB2, 0xD4, 0xE7, 0xA0,
0x0A, 0x53, 0x01, 0xBA, 0x8E, 0x97, 0x91, 0x76, 0x6E, 0xBC, 0xFC, 0xD5,
0x6B, 0x36, 0xE6, 0x40, 0x88, 0xD6, 0x7B, 0x2F, 0x5F, 0x05, 0xE8, 0x2C,
0x6D, 0x11, 0xF3, 0xE7, 0xB2, 0xBE, 0x92, 0x44, 0x4C, 0xD2, 0x97, 0xA4,
0xFE, 0xD2, 0x72, 0x81, 0x43, 0x07, 0x9C, 0xE9, 0x11, 0x3E, 0xF5, 0x8B,
0x1A, 0x59, 0x7D, 0x1F, 0x68, 0x58, 0xDD, 0x04, 0x00, 0x2C, 0x96, 0xF3,
0x43, 0xB3, 0x7E, 0x98, 0x19, 0x74, 0xD9, 0x9C, 0x73, 0xD9, 0x18, 0xBE,
0x41, 0xC7, 0x34, 0x79, 0xD9, 0xF4, 0x62, 0xC2, 0x43, 0xB9, 0xB3, 0x27,
0xB0, 0x22, 0xCB, 0xF9, 0x3D, 0x52, 0xC7, 0x30, 0x47, 0xB3, 0xC9, 0x3E,
0xB8, 0x6A, 0xE2, 0xE7, 0xE8, 0x81, 0x70, 0x5E, 0x42, 0x8B, 0x4F, 0x26,
0xA5, 0xFE, 0x3A, 0xC2, 0x20, 0x6E, 0xBB, 0xF8, 0x16, 0x8E, 0xCD, 0x0C,
0xA9, 0xB4, 0x1B, 0x6C, 0x76, 0x10, 0xE1, 0x58, 0x79, 0x46, 0x3E, 0x54,
0xCE, 0x80, 0xA8, 0x57, 0x09, 0x37, 0x29, 0x1B, 0x99, 0x13, 0x8F, 0x0C,
0xC8, 0xD6, 0x2C, 0x1C, 0xFB, 0x05, 0xE8, 0x08, 0x95, 0x3D, 0x65, 0x46,
0xDC, 0xEE, 0xCD, 0x69, 0xE2, 0x4D, 0x8F, 0x87, 0x28, 0x4E, 0x34, 0x0B,
0x3E, 0xCF, 0x14, 0xD9, 0xBB, 0xDD, 0xB6, 0x50, 0x9A, 0xAD, 0x77, 0xD4,
0x19, 0xD6, 0xDA, 0x1A, 0x88, 0xC8, 0x4E, 0x1B, 0x27, 0x75, 0xD8, 0xB2,
0x08, 0xF1, 0xAE, 0x83, 0x30, 0xB9, 0x11, 0x0E, 0xCD, 0x87, 0xF0, 0x84,
0x8D, 0x15, 0x72, 0x7C, 0xA1, 0xEF, 0xCC, 0xF2, 0x88, 0x61, 0xBA, 0xF4,
0x69, 0xBB, 0x0C, 0x8C, 0x0B, 0x75, 0x57, 0x04, 0xB8, 0x4E, 0x2A, 0x14,
0x2E, 0x3D, 0x0F, 0x1C, 0x1E, 0x32, 0xA6, 0x62, 0x36, 0xEE, 0x66, 0xE2,
0x22, 0xB8, 0x05, 0x40, 0x63, 0x10, 0x22, 0xF3, 0x33, 0x1D, 0x74, 0x72,
0x8A, 0x2C, 0xF5, 0x39, 0x29, 0xA0, 0xD3, 0xE7, 0x1B, 0x80, 0x84, 0x2D,
0xC5, 0x3D, 0xE3, 0x4D, 0xB1, 0xFD, 0x1A, 0x6F, 0xBA, 0x65, 0x07, 0x3B,
0x58, 0xEC, 0x42, 0x45, 0x26, 0xFB, 0xD8, 0xDA, 0x25, 0x72, 0xC4, 0xF6,
0x00, 0xB1, 0x22, 0x79, 0xBD, 0xE3, 0x7C, 0x59, 0x62, 0x4A, 0x9C, 0x05,
0x6F, 0x3D, 0xCE, 0xE6, 0xD6, 0x47, 0x63, 0x99, 0xC6, 0x24, 0x6F, 0x72,
0x12, 0xC8, 0xAC, 0x7F, 0x90, 0xB4, 0x0B, 0x91, 0x70, 0xE8, 0xB7, 0xE6,
0x16, 0x10, 0x71, 0x17, 0xCE, 0xDE, 0x06, 0x4F, 0x48, 0x41, 0x7D, 0x35,
0x4A, 0xA3, 0x89, 0xF2, 0xC9, 0x4B, 0x7B, 0x41, 0x11, 0x6D, 0x67, 0xB7,
0x08, 0x98, 0x4C, 0xE5, 0x11, 0x19, 0xAE, 0x42, 0x80, 0xDC, 0xFB, 0x90,
0x05, 0xD4, 0xF8, 0x50, 0xCA, 0xBE, 0xE4, 0xAD, 0xC7, 0xC2, 0x94, 0xD7,
0x16, 0x9D, 0xE6, 0x17, 0x8F, 0xAF, 0x36, 0xFB
};
static const unsigned char TA95_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA96_DN[] = {
0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31,
0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68,
0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55,
0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76,
0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20,
0x50, 0x32, 0x35, 0x36, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA96_EC_Q[] = {
0x04, 0x7E, 0xFB, 0x6C, 0xE6, 0x23, 0xE3, 0x73, 0x32, 0x08, 0xCA, 0x60,
0xE6, 0x53, 0x9C, 0xBA, 0x74, 0x8D, 0x18, 0xB0, 0x78, 0x90, 0x52, 0x80,
0xDD, 0x38, 0xC0, 0x4A, 0x1D, 0xD1, 0xA8, 0xCC, 0x93, 0xA4, 0x97, 0x06,
0x38, 0xCA, 0x0D, 0x15, 0x62, 0xC6, 0x8E, 0x01, 0x2A, 0x65, 0x9D, 0xAA,
0xDF, 0x34, 0x91, 0x2E, 0x81, 0xC1, 0xE4, 0x33, 0x92, 0x31, 0xC4, 0xFD,
0x09, 0x3A, 0xA6, 0x3F, 0xAD
};
static const unsigned char TA97_DN[] = {
0x30, 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
0x13, 0x02, 0x55, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04,
0x08, 0x13, 0x08, 0x49, 0x6C, 0x6C, 0x69, 0x6E, 0x6F, 0x69, 0x73, 0x31,
0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x43, 0x68,
0x69, 0x63, 0x61, 0x67, 0x6F, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55,
0x04, 0x0A, 0x13, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76,
0x65, 0x20, 0x48, 0x6F, 0x6C, 0x64, 0x69, 0x6E, 0x67, 0x73, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x3A, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x31, 0x54, 0x72, 0x75, 0x73, 0x74, 0x77, 0x61, 0x76, 0x65,
0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x45, 0x43, 0x43, 0x20,
0x50, 0x33, 0x38, 0x34, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F,
0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA97_EC_Q[] = {
0x04, 0x6B, 0xDA, 0x0D, 0x75, 0x35, 0x08, 0x31, 0x47, 0x05, 0xAE, 0x45,
0x99, 0x55, 0xF1, 0x11, 0x13, 0x2E, 0x4A, 0xF8, 0x10, 0x31, 0x23, 0xA3,
0x7E, 0x83, 0xD3, 0x7F, 0x28, 0x08, 0x3A, 0x26, 0x1A, 0x3A, 0xCF, 0x97,
0x82, 0x1F, 0x80, 0xB7, 0x27, 0x09, 0x8F, 0xD1, 0x8E, 0x30, 0xC4, 0x0A,
0x9B, 0x0E, 0xAC, 0x58, 0x04, 0xAB, 0xF7, 0x36, 0x7D, 0x94, 0x23, 0xA4,
0x9B, 0x0A, 0x8A, 0x8B, 0xAB, 0xEB, 0xFD, 0x39, 0x25, 0x66, 0xF1, 0x5E,
0xFE, 0x8C, 0xAE, 0x8D, 0x41, 0x79, 0x9D, 0x09, 0x60, 0xCE, 0x28, 0xA9,
0xD3, 0x8A, 0x6D, 0xF3, 0xD6, 0x45, 0xD4, 0xF2, 0x98, 0x84, 0x38, 0x65,
0xA0
};
static const unsigned char TA98_DN[] = {
0x30, 0x69, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4B, 0x52, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1D, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20, 0x42, 0x55, 0x53, 0x49,
0x4E, 0x45, 0x53, 0x53, 0x20, 0x50, 0x4C, 0x41, 0x54, 0x46, 0x4F, 0x52,
0x4D, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x32, 0x30, 0x30, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x29, 0x4E, 0x41, 0x56, 0x45, 0x52, 0x20,
0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F,
0x6E, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79
};
static const unsigned char TA98_RSA_N[] = {
0xB6, 0xD4, 0xF1, 0x93, 0x5C, 0xB5, 0x40, 0x89, 0x0A, 0xAB, 0x0D, 0x90,
0x5B, 0x50, 0x63, 0xAE, 0x90, 0x94, 0x74, 0x17, 0x45, 0x72, 0xD6, 0x7B,
0x65, 0x5A, 0x29, 0x4B, 0xA7, 0x56, 0xA0, 0x4B, 0xB8, 0x2F, 0x42, 0x75,
0xE9, 0xD9, 0x7B, 0x24, 0x5A, 0x31, 0x65, 0xAB, 0x17, 0x17, 0xD1, 0x33,
0x3A, 0xD9, 0x11, 0xDC, 0x40, 0x36, 0x87, 0xDF, 0xC7, 0x6A, 0xE9, 0x26,
0x5E, 0x59, 0x8A, 0x77, 0xE3, 0xE8, 0x48, 0x9C, 0x31, 0x16, 0xFA, 0x3E,
0x91, 0xB1, 0xCA, 0xC9, 0xA3, 0xE2, 0x9F, 0xCE, 0x21, 0x53, 0xA3, 0x02,
0x36, 0x30, 0xCB, 0x52, 0x02, 0xE5, 0xDA, 0x32, 0x5D, 0xC3, 0xC5, 0xE6,
0xF9, 0xEE, 0x11, 0xC7, 0x8B, 0xC9, 0x44, 0x1E, 0x84, 0x93, 0x18, 0x4A,
0xB4, 0x9F, 0xE5, 0x12, 0x64, 0x69, 0xD0, 0x26, 0x85, 0x62, 0x01, 0xB6,
0xC9, 0x02, 0x1D, 0xBE, 0x83, 0x51, 0xBB, 0x5C, 0xDA, 0xF8, 0xAD, 0x15,
0x6A, 0x99, 0xF7, 0x92, 0x54, 0xF7, 0x34, 0x5B, 0xE9, 0xBF, 0xEA, 0x29,
0x81, 0x12, 0xD4, 0x53, 0x91, 0x96, 0xB3, 0x91, 0x5A, 0xDD, 0xFE, 0x90,
0x73, 0x28, 0xFB, 0x30, 0x46, 0xB5, 0xCA, 0x08, 0x07, 0xC7, 0x71, 0x72,
0xC9, 0x66, 0xD3, 0x34, 0x97, 0xF6, 0x8C, 0xF4, 0x18, 0x4A, 0xE1, 0xD0,
0x3D, 0x5A, 0x45, 0xB6, 0x69, 0xA7, 0x29, 0xFB, 0x23, 0xCE, 0x88, 0xD8,
0x12, 0x9C, 0x00, 0x48, 0xA8, 0xA6, 0x0F, 0xB3, 0x3B, 0x92, 0x8D, 0x71,
0x0E, 0x74, 0xC5, 0x8B, 0xC8, 0x4C, 0xF9, 0xF4, 0x9B, 0x8E, 0xB8, 0x3C,
0x69, 0xED, 0x6F, 0x3B, 0x50, 0x2F, 0x58, 0xED, 0xC4, 0xB0, 0xD0, 0x1C,
0x1B, 0x6A, 0x0C, 0xE2, 0xBC, 0x44, 0xAA, 0xD8, 0xCD, 0x14, 0x5D, 0x94,
0x78, 0x61, 0xBF, 0x0E, 0x6E, 0xDA, 0x2A, 0xBC, 0x2F, 0x0C, 0x0B, 0x71,
0xA6, 0xB3, 0x16, 0x3F, 0x9C, 0xE6, 0xF9, 0xCC, 0x9F, 0x53, 0x35, 0xE2,
0x03, 0xA0, 0xA0, 0x18, 0xBF, 0xBB, 0xF1, 0xBE, 0xF4, 0xD6, 0x8C, 0x87,
0x0D, 0x42, 0xF7, 0x06, 0xB9, 0xF1, 0x6D, 0xED, 0x04, 0x94, 0xA8, 0xFE,
0xB6, 0xD3, 0x06, 0xC6, 0x40, 0x61, 0xDF, 0x9D, 0x9D, 0xF3, 0x54, 0x76,
0xCE, 0x53, 0x3A, 0x01, 0xA6, 0x92, 0x41, 0xEC, 0x04, 0xA3, 0x8F, 0x0D,
0xA2, 0xD5, 0x09, 0xCA, 0xD6, 0xCB, 0x9A, 0xF1, 0xEF, 0x43, 0x5D, 0xC0,
0xAB, 0xA5, 0x41, 0xCF, 0x5C, 0x53, 0x70, 0x70, 0xC9, 0x88, 0xA6, 0x2D,
0xD4, 0x6B, 0x61, 0x73, 0x50, 0x26, 0x86, 0x61, 0x0E, 0x5F, 0x1B, 0xC2,
0x2B, 0xE2, 0x8C, 0xD5, 0xBB, 0x9D, 0xC1, 0x03, 0x42, 0xBA, 0x94, 0xDA,
0x5F, 0xA9, 0xB0, 0xCA, 0xCC, 0x4D, 0x0A, 0xEF, 0x47, 0x69, 0x03, 0x2F,
0x22, 0xFB, 0xF1, 0x28, 0xCE, 0xBF, 0x5D, 0x50, 0x65, 0xA8, 0x90, 0x6D,
0xB3, 0x74, 0xB0, 0x08, 0xC7, 0xAC, 0xA8, 0xD1, 0xEB, 0x3E, 0x9C, 0xFC,
0x5D, 0x1A, 0x83, 0x2E, 0x2B, 0xCB, 0xB5, 0xF3, 0x44, 0x9D, 0x3A, 0xA7,
0x17, 0x61, 0x96, 0xA2, 0x71, 0xD3, 0x70, 0x96, 0x15, 0x4D, 0xB7, 0x4C,
0x73, 0xEE, 0x19, 0x5C, 0xC5, 0x5B, 0x3E, 0x41, 0xFE, 0xAC, 0x75, 0x60,
0x3B, 0x1B, 0x63, 0xCE, 0x00, 0xDD, 0xDA, 0x08, 0x90, 0x62, 0xB4, 0xE5,
0x2D, 0xEE, 0x48, 0xA7, 0x6B, 0x17, 0x99, 0x54, 0xBE, 0x87, 0x4A, 0xE3,
0xA9, 0x5E, 0x04, 0x4C, 0xEB, 0x10, 0x6D, 0x54, 0xD6, 0xEF, 0xF1, 0xE8,
0xF2, 0x62, 0x16, 0xCB, 0x80, 0x6B, 0xED, 0x3D, 0xED, 0xF5, 0x1F, 0x30,
0xA5, 0xAE, 0x4B, 0xC9, 0x13, 0xED, 0x8A, 0x01, 0x01, 0xC9, 0xB8, 0x51,
0x58, 0xC0, 0x66, 0x3A, 0xB1, 0x66, 0x4B, 0xC4, 0xD5, 0x31, 0x02, 0x62,
0xE9, 0x74, 0x84, 0x0C, 0xDB, 0x4D, 0x46, 0x2D
};
static const unsigned char TA98_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA99_DN[] = {
0x30, 0x78, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x45, 0x53, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x08, 0x46, 0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x31, 0x0E,
0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x05, 0x43, 0x65, 0x72,
0x65, 0x73, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C,
0x0F, 0x56, 0x41, 0x54, 0x45, 0x53, 0x2D, 0x51, 0x32, 0x38, 0x32, 0x36,
0x30, 0x30, 0x34, 0x4A, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04,
0x03, 0x0C, 0x23, 0x41, 0x43, 0x20, 0x52, 0x41, 0x49, 0x5A, 0x20, 0x46,
0x4E, 0x4D, 0x54, 0x2D, 0x52, 0x43, 0x4D, 0x20, 0x53, 0x45, 0x52, 0x56,
0x49, 0x44, 0x4F, 0x52, 0x45, 0x53, 0x20, 0x53, 0x45, 0x47, 0x55, 0x52,
0x4F, 0x53
};
static const unsigned char TA99_EC_Q[] = {
0x04, 0xF6, 0xBA, 0x57, 0x53, 0xC8, 0xCA, 0xAB, 0xDF, 0x36, 0x4A, 0x52,
0x21, 0xE4, 0x97, 0xD2, 0x83, 0x67, 0x9E, 0xF0, 0x65, 0x51, 0xD0, 0x5E,
0x87, 0xC7, 0x47, 0xB1, 0x59, 0xF2, 0x57, 0x47, 0x9B, 0x00, 0x02, 0x93,
0x44, 0x17, 0x69, 0xDB, 0x42, 0xC7, 0xB1, 0xB2, 0x3A, 0x18, 0x0E, 0xB4,
0x5D, 0x8C, 0xB3, 0x66, 0x5D, 0xA1, 0x34, 0xF9, 0x36, 0x2C, 0x49, 0xDB,
0xF3, 0x46, 0xFC, 0xB3, 0x44, 0x69, 0x44, 0x13, 0x66, 0xFD, 0xD7, 0xC5,
0xFD, 0xAF, 0x36, 0x4D, 0xCE, 0x03, 0x4D, 0x07, 0x71, 0xCF, 0xAF, 0x6A,
0x05, 0xD2, 0xA2, 0x43, 0x5A, 0x0A, 0x52, 0x6F, 0x01, 0x03, 0x4E, 0x8E,
0x8B
};
static const unsigned char TA100_DN[] = {
0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E,
0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53,
0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34, 0x36
};
static const unsigned char TA100_RSA_N[] = {
0xAC, 0xAC, 0x74, 0x32, 0xE8, 0xB3, 0x65, 0xE5, 0xBA, 0xED, 0x43, 0x26,
0x1D, 0xA6, 0x89, 0x0D, 0x45, 0xBA, 0x29, 0x88, 0xB2, 0xA4, 0x1D, 0x63,
0xDD, 0xD3, 0xC1, 0x2C, 0x09, 0x57, 0x89, 0x39, 0xA1, 0x55, 0xE9, 0x67,
0x34, 0x77, 0x0C, 0x6E, 0xE4, 0x55, 0x1D, 0x52, 0x25, 0xD2, 0x13, 0x6B,
0x5E, 0xE1, 0x1D, 0xA9, 0xB7, 0x7D, 0x89, 0x32, 0x5F, 0x0D, 0x9E, 0x9F,
0x2C, 0x7A, 0x63, 0x60, 0x40, 0x1F, 0xA6, 0xB0, 0xB6, 0x78, 0x8F, 0x99,
0x54, 0x96, 0x08, 0x58, 0xAE, 0xE4, 0x06, 0xBC, 0x62, 0x05, 0x02, 0x16,
0xBF, 0xAF, 0xA8, 0x23, 0x03, 0xB6, 0x94, 0x0F, 0xBC, 0x6E, 0x6C, 0xC2,
0xCB, 0xD5, 0xA6, 0xBB, 0x0C, 0xE9, 0xF6, 0xC1, 0x02, 0xFB, 0x21, 0xDE,
0x66, 0xDD, 0x17, 0xAB, 0x74, 0x42, 0xEF, 0xF0, 0x74, 0x2F, 0x25, 0xF4,
0xEA, 0x6B, 0x55, 0x5B, 0x90, 0xDB, 0x9D, 0xDF, 0x5E, 0x87, 0x0A, 0x40,
0xFB, 0xAD, 0x19, 0x6B, 0xFB, 0xF7, 0xCA, 0x60, 0x88, 0xDE, 0xDA, 0xC1,
0x8F, 0xD6, 0xAE, 0xD5, 0x7F, 0xD4, 0x3C, 0x83, 0xEE, 0xD7, 0x16, 0x4C,
0x83, 0x45, 0x33, 0x6B, 0x27, 0xD0, 0x86, 0xD0, 0x1C, 0x2D, 0x6B, 0xF3,
0xAB, 0x7D, 0xF1, 0x85, 0xA9, 0xF5, 0x28, 0xD2, 0xAD, 0xEF, 0xF3, 0x84,
0x4B, 0x1C, 0x87, 0xFC, 0x13, 0xA3, 0x3A, 0x72, 0xA2, 0x5A, 0x11, 0x2B,
0xD6, 0x27, 0x71, 0x27, 0xED, 0x81, 0x2D, 0x6D, 0x66, 0x81, 0x92, 0x87,
0xB4, 0x1B, 0x58, 0x7A, 0xCC, 0x3F, 0x0A, 0xFA, 0x46, 0x4F, 0x4D, 0x78,
0x5C, 0xF8, 0x2B, 0x48, 0xE3, 0x04, 0x84, 0xCB, 0x5D, 0xF6, 0xB4, 0x6A,
0xB3, 0x65, 0xFC, 0x42, 0x9E, 0x51, 0x26, 0x23, 0x20, 0xCB, 0x3D, 0x14,
0xF9, 0x81, 0xED, 0x65, 0x16, 0x00, 0x4F, 0x1A, 0x64, 0x97, 0x66, 0x08,
0xCF, 0x8C, 0x7B, 0xE3, 0x2B, 0xC0, 0x9D, 0xF9, 0x14, 0xF2, 0x1B, 0xF1,
0x56, 0x6A, 0x16, 0xBF, 0x2C, 0x85, 0x85, 0xCD, 0x78, 0x38, 0x9A, 0xEB,
0x42, 0x6A, 0x02, 0x34, 0x18, 0x83, 0x17, 0x4E, 0x94, 0x56, 0xF8, 0xB6,
0x82, 0xB5, 0xF3, 0x96, 0xDD, 0x3D, 0xF3, 0xBE, 0x7F, 0x20, 0x77, 0x3E,
0x7B, 0x19, 0x23, 0x6B, 0x2C, 0xD4, 0x72, 0x73, 0x43, 0x57, 0x7D, 0xE0,
0xF8, 0xD7, 0x69, 0x4F, 0x17, 0x36, 0x04, 0xF9, 0xC0, 0x90, 0x60, 0x37,
0x45, 0xDE, 0xE6, 0x0C, 0xD8, 0x74, 0x8D, 0xAE, 0x9C, 0xA2, 0x6D, 0x74,
0x5D, 0x42, 0xBE, 0x06, 0xF5, 0xD9, 0x64, 0x6E, 0x02, 0x10, 0xAC, 0x89,
0xB0, 0x4C, 0x3B, 0x07, 0x4D, 0x40, 0x7E, 0x24, 0xC5, 0x8A, 0x98, 0x82,
0x79, 0x8E, 0xA4, 0xA7, 0x82, 0x20, 0x8D, 0x23, 0xFA, 0x27, 0x71, 0xC9,
0xDF, 0xC6, 0x41, 0x74, 0xA0, 0x4D, 0xF6, 0x91, 0x16, 0xDC, 0x46, 0x8C,
0x5F, 0x29, 0x63, 0x31, 0x59, 0x71, 0x0C, 0xD8, 0x6F, 0xC2, 0xB6, 0x32,
0x7D, 0xFB, 0xE6, 0x5D, 0x53, 0xA6, 0x7E, 0x15, 0xFC, 0xBB, 0x75, 0x7C,
0x5D, 0xEC, 0xF8, 0xF6, 0x17, 0x1C, 0xEC, 0xC7, 0x6B, 0x19, 0xCB, 0xF3,
0x7B, 0xF0, 0x2B, 0x07, 0xA5, 0xD9, 0x6C, 0x79, 0x54, 0x76, 0x6C, 0x9D,
0x1C, 0xA6, 0x6E, 0x0E, 0xE9, 0x79, 0x0C, 0xA8, 0x23, 0x6A, 0xA3, 0xDF,
0x1B, 0x30, 0x31, 0x9F, 0xB1, 0x54, 0x7B, 0xFE, 0x6A, 0xCB, 0x66, 0xAA,
0xDC, 0x65, 0xD0, 0xA2, 0x9E, 0x4A, 0x9A, 0x07, 0x21, 0x6B, 0x81, 0x8F,
0xDB, 0xC4, 0x59, 0xFA, 0xDE, 0x22, 0xC0, 0x04, 0x9C, 0xE3, 0xAA, 0x5B,
0x36, 0x93, 0xE8, 0x3D, 0xBD, 0x7A, 0xA1, 0x9D, 0x0B, 0x76, 0xB1, 0x0B,
0xC7, 0x9D, 0xFD, 0xCF, 0x98, 0xA8, 0x06, 0xC2, 0xF8, 0x2A, 0xA3, 0xA1,
0x83, 0xA0, 0xB7, 0x25, 0x72, 0xA5, 0x02, 0xE3
};
static const unsigned char TA100_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA101_DN[] = {
0x30, 0x46, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x42, 0x45, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x10, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E,
0x20, 0x6E, 0x76, 0x2D, 0x73, 0x61, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x13, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53,
0x69, 0x67, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34, 0x36
};
static const unsigned char TA101_EC_Q[] = {
0x04, 0x9C, 0x0E, 0xB1, 0xCF, 0xB7, 0xE8, 0x9E, 0x52, 0x77, 0x75, 0x34,
0xFA, 0xA5, 0x46, 0xA7, 0xAD, 0x32, 0x19, 0x32, 0xB4, 0x07, 0xA9, 0x27,
0xCA, 0x94, 0xBB, 0x0C, 0xD2, 0x0A, 0x10, 0xC7, 0xDA, 0x89, 0xB0, 0x97,
0x0C, 0x70, 0x13, 0x09, 0x01, 0x8E, 0xD8, 0xEA, 0x47, 0xEA, 0xBE, 0xB2,
0x80, 0x2B, 0xCD, 0xFC, 0x28, 0x0D, 0xDB, 0xAC, 0xBC, 0xA4, 0x86, 0x37,
0xED, 0x70, 0x08, 0x00, 0x75, 0xEA, 0x93, 0x0B, 0x7B, 0x2E, 0x52, 0x9C,
0x23, 0x68, 0x23, 0x06, 0x43, 0xEC, 0x92, 0x2F, 0x53, 0x84, 0xDB, 0xFB,
0x47, 0x14, 0x07, 0xE8, 0x5F, 0x94, 0x67, 0x5D, 0xC9, 0x7A, 0x81, 0x3C,
0x20
};
static const unsigned char TA102_DN[] = {
0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x41, 0x54, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1A, 0x65, 0x2D, 0x63, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x65,
0x20, 0x6D, 0x6F, 0x6E, 0x69, 0x74, 0x6F, 0x72, 0x69, 0x6E, 0x67, 0x20,
0x47, 0x6D, 0x62, 0x48, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x10, 0x47, 0x4C, 0x4F, 0x42, 0x41, 0x4C, 0x54, 0x52, 0x55,
0x53, 0x54, 0x20, 0x32, 0x30, 0x32, 0x30
};
static const unsigned char TA102_RSA_N[] = {
0xAE, 0x2E, 0x56, 0xAD, 0x1B, 0x1C, 0xEF, 0xF6, 0x95, 0x8F, 0xA0, 0x77,
0x1B, 0x2B, 0xD3, 0x63, 0x8F, 0x84, 0x4D, 0x45, 0xA2, 0x0F, 0x9F, 0x5B,
0x45, 0xAB, 0x59, 0x7B, 0x51, 0x34, 0xF9, 0xEC, 0x8B, 0x8A, 0x78, 0xC5,
0xDD, 0x6B, 0xAF, 0xBD, 0xC4, 0xDF, 0x93, 0x45, 0x1E, 0xBF, 0x91, 0x38,
0x0B, 0xAE, 0x0E, 0x16, 0xE7, 0x41, 0x73, 0xF8, 0xDB, 0xBB, 0xD1, 0xB8,
0x51, 0xE0, 0xCB, 0x83, 0x3B, 0x73, 0x38, 0x6E, 0x77, 0x8A, 0x0F, 0x59,
0x63, 0x26, 0xCD, 0xA7, 0x2A, 0xCE, 0x54, 0xFB, 0xB8, 0xE2, 0xC0, 0x7C,
0x47, 0xCE, 0x60, 0x7C, 0x3F, 0xB2, 0x73, 0xF2, 0xC0, 0x19, 0xB6, 0x8A,
0x92, 0x87, 0x35, 0x0D, 0x90, 0x28, 0xA2, 0xE4, 0x15, 0x04, 0x63, 0x3E,
0xBA, 0xAF, 0xEE, 0x7C, 0x5E, 0xCC, 0xA6, 0x8B, 0x50, 0xB2, 0x38, 0xF7,
0x41, 0x63, 0xCA, 0xCE, 0xFF, 0x69, 0x8F, 0x68, 0x0E, 0x95, 0x36, 0xE5,
0xCC, 0xB9, 0x8C, 0x09, 0xCA, 0x4B, 0xDD, 0x31, 0x90, 0x96, 0xC8, 0xCC,
0x1F, 0xFD, 0x56, 0x96, 0x34, 0xDB, 0x8E, 0x1C, 0xEA, 0x2C, 0xBE, 0x85,
0x2E, 0x63, 0xDD, 0xAA, 0xA9, 0x95, 0xD3, 0xFD, 0x29, 0x95, 0x13, 0xF0,
0xC8, 0x98, 0x93, 0xD9, 0x2D, 0x16, 0x47, 0x90, 0x11, 0x83, 0xA2, 0x3A,
0x22, 0xA2, 0x28, 0x57, 0xA2, 0xEB, 0xFE, 0xC0, 0x8C, 0x28, 0xA0, 0xA6,
0x7D, 0xE7, 0x2A, 0x42, 0x3B, 0x82, 0x80, 0x63, 0xA5, 0x63, 0x1F, 0x19,
0xCC, 0x7C, 0xB2, 0x66, 0xA8, 0xC2, 0xD3, 0x6D, 0x37, 0x6F, 0xE2, 0x7E,
0x06, 0x51, 0xD9, 0x45, 0x84, 0x1F, 0x12, 0xCE, 0x24, 0x52, 0x64, 0x85,
0x0B, 0x48, 0x80, 0x4E, 0x87, 0xB1, 0x22, 0x22, 0x30, 0xAA, 0xEB, 0xAE,
0xBE, 0xE0, 0x02, 0xE0, 0x40, 0xE8, 0xB0, 0x42, 0x80, 0x03, 0x51, 0xAA,
0xB4, 0x7E, 0xAA, 0x44, 0xD7, 0x43, 0x61, 0xF3, 0xA2, 0x6B, 0x16, 0x89,
0x49, 0xA4, 0xA3, 0xA4, 0x2B, 0x8A, 0x02, 0xC4, 0x78, 0xF4, 0x68, 0x8A,
0xC1, 0xE4, 0x7A, 0x36, 0xB1, 0x6F, 0x1B, 0x96, 0x1B, 0x77, 0x49, 0x8D,
0xD4, 0xC9, 0x06, 0x72, 0x8F, 0xCF, 0x53, 0xE3, 0xDC, 0x17, 0x85, 0x20,
0x4A, 0xDC, 0x98, 0x27, 0xD3, 0x91, 0x26, 0x2B, 0x47, 0x1E, 0x69, 0x07,
0xAF, 0xDE, 0xA2, 0xE4, 0xE4, 0xD4, 0x6B, 0x0B, 0xB3, 0x5E, 0x7C, 0xD4,
0x24, 0x80, 0x47, 0x29, 0x69, 0x3B, 0x6E, 0xE8, 0xAC, 0xFD, 0x40, 0xEB,
0xD8, 0xED, 0x71, 0x71, 0x2B, 0xF2, 0xE8, 0x58, 0x1D, 0xEB, 0x41, 0x97,
0x22, 0xC5, 0x1F, 0xD4, 0x39, 0xD0, 0x27, 0x8F, 0x87, 0xE3, 0x18, 0xF4,
0xE0, 0xA9, 0x46, 0x0D, 0xF5, 0x74, 0x3A, 0x82, 0x2E, 0xD0, 0x6E, 0x2C,
0x91, 0xA3, 0x31, 0x5C, 0x3B, 0x46, 0xEA, 0x7B, 0x04, 0x10, 0x56, 0x5E,
0x80, 0x1D, 0xF5, 0xA5, 0x65, 0xE8, 0x82, 0xFC, 0xE2, 0x07, 0x8C, 0x62,
0x45, 0xF5, 0x20, 0xDE, 0x46, 0x70, 0x86, 0xA1, 0xBC, 0x93, 0xD3, 0x1E,
0x74, 0xA6, 0x6C, 0xB0, 0x2C, 0xF7, 0x03, 0x0C, 0x88, 0x0C, 0xCB, 0xD4,
0x72, 0x53, 0x86, 0xBC, 0x60, 0x46, 0xF3, 0x98, 0x6A, 0xC2, 0xF1, 0xBF,
0x43, 0xF9, 0x70, 0x20, 0x77, 0xCA, 0x37, 0x41, 0x79, 0x55, 0x52, 0x63,
0x8D, 0x5B, 0x12, 0x9F, 0xC5, 0x68, 0xC4, 0x88, 0x9D, 0xAC, 0xF2, 0x30,
0xAB, 0xB7, 0xA3, 0x31, 0x97, 0x67, 0xAD, 0x8F, 0x17, 0x0F, 0x6C, 0xC7,
0x73, 0xED, 0x24, 0x94, 0x6B, 0xC8, 0x83, 0x9A, 0xD0, 0x9A, 0x37, 0x49,
0x04, 0xAB, 0xB1, 0x16, 0xC8, 0x6C, 0x49, 0x49, 0x2D, 0xAB, 0xA1, 0xD0,
0x8C, 0x92, 0xF2, 0x41, 0x4A, 0x79, 0x21, 0x25, 0xDB, 0x63, 0xD7, 0xB6,
0x9C, 0xA7, 0x7E, 0x42, 0x69, 0xFB, 0x3A, 0x63
};
static const unsigned char TA102_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA103_DN[] = {
0x30, 0x81, 0x84, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x05,
0x13, 0x09, 0x47, 0x36, 0x33, 0x32, 0x38, 0x37, 0x35, 0x31, 0x30, 0x31,
0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x45, 0x53,
0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x1E, 0x41,
0x4E, 0x46, 0x20, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64,
0x20, 0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
0x61, 0x63, 0x69, 0x6F, 0x6E, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
0x04, 0x0B, 0x13, 0x0B, 0x41, 0x4E, 0x46, 0x20, 0x43, 0x41, 0x20, 0x52,
0x61, 0x69, 0x7A, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x19, 0x41, 0x4E, 0x46, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65,
0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41
};
static const unsigned char TA103_RSA_N[] = {
0xDB, 0xEB, 0x6B, 0x2B, 0xE6, 0x64, 0x54, 0x95, 0x82, 0x90, 0xA3, 0x72,
0xA4, 0x19, 0x01, 0x9D, 0x9C, 0x0B, 0x81, 0x5F, 0x73, 0x49, 0xBA, 0xA7,
0xAC, 0xF3, 0x04, 0x4E, 0x7B, 0x96, 0x0B, 0xEC, 0x11, 0xE0, 0x5B, 0xA6,
0x1C, 0xCE, 0x1B, 0xD2, 0x0D, 0x83, 0x1C, 0x2B, 0xB8, 0x9E, 0x1D, 0x7E,
0x45, 0x32, 0x60, 0x0F, 0x07, 0xE9, 0x77, 0x58, 0x7E, 0x9F, 0x6A, 0xC8,
0x61, 0x4E, 0xB6, 0x26, 0xC1, 0x4C, 0x8D, 0xFF, 0x4C, 0xEF, 0x34, 0xB2,
0x1F, 0x65, 0xD8, 0xB9, 0x78, 0xF5, 0xAD, 0xA9, 0x71, 0xB9, 0xEF, 0x4F,
0x58, 0x1D, 0xA5, 0xDE, 0x74, 0x20, 0x97, 0xA1, 0xED, 0x68, 0x4C, 0xDE,
0x92, 0x17, 0x4B, 0xBC, 0xAB, 0xFF, 0x65, 0x9A, 0x9E, 0xFB, 0x47, 0xD9,
0x57, 0x72, 0xF3, 0x09, 0xA1, 0xAE, 0x76, 0x44, 0x13, 0x6E, 0x9C, 0x2D,
0x44, 0x39, 0xBC, 0xF9, 0xC7, 0x3B, 0xA4, 0x58, 0x3D, 0x41, 0xBD, 0xB4,
0xC2, 0x49, 0xA3, 0xC8, 0x0D, 0xD2, 0x97, 0x2F, 0x07, 0x65, 0x52, 0x00,
0xA7, 0x6E, 0xC8, 0xAF, 0x68, 0xEC, 0xF4, 0x14, 0x96, 0xB6, 0x57, 0x1F,
0x56, 0xC3, 0x39, 0x9F, 0x2B, 0x6D, 0xE4, 0xF3, 0x3E, 0xF6, 0x35, 0x64,
0xDA, 0x0C, 0x1C, 0xA1, 0x84, 0x4B, 0x2F, 0x4B, 0x4B, 0xE2, 0x2C, 0x24,
0x9D, 0x6D, 0x93, 0x40, 0xEB, 0xB5, 0x23, 0x8E, 0x32, 0xCA, 0x6F, 0x45,
0xD3, 0xA8, 0x89, 0x7B, 0x1E, 0xCF, 0x1E, 0xFA, 0x5B, 0x43, 0x8B, 0xCD,
0xCD, 0xA8, 0x0F, 0x6A, 0xCA, 0x0C, 0x5E, 0xB9, 0x9E, 0x47, 0x8F, 0xF0,
0xD9, 0xB6, 0x0A, 0x0B, 0x58, 0x65, 0x17, 0x33, 0xB9, 0x23, 0xE4, 0x77,
0x19, 0x7D, 0xCB, 0x4A, 0x2E, 0x92, 0x7B, 0x4F, 0x2F, 0x10, 0x77, 0xB1,
0x8D, 0x2F, 0x68, 0x9C, 0x62, 0xCC, 0xE0, 0x50, 0xF8, 0xEC, 0x91, 0xA7,
0x54, 0x4C, 0x57, 0x09, 0xD5, 0x76, 0x63, 0xC5, 0xE8, 0x65, 0x1E, 0xEE,
0x6D, 0x6A, 0xCF, 0x09, 0x9D, 0xFA, 0x7C, 0x4F, 0xAD, 0x60, 0x08, 0xFD,
0x56, 0x99, 0x0F, 0x15, 0x2C, 0x7B, 0xA9, 0x80, 0xAB, 0x8C, 0x61, 0x8F,
0x4A, 0x07, 0x76, 0x42, 0xDE, 0x3D, 0xF4, 0xDD, 0xB2, 0x24, 0x33, 0x5B,
0xB8, 0xB5, 0xA3, 0x44, 0xC9, 0xAC, 0x7F, 0x77, 0x3C, 0x1D, 0x23, 0xEC,
0x82, 0xA9, 0xA6, 0xE2, 0xC8, 0x06, 0x4C, 0x02, 0xFE, 0xAC, 0x5C, 0x99,
0x99, 0x0B, 0x2F, 0x10, 0x8A, 0xA6, 0xF4, 0x7F, 0xD5, 0x87, 0x74, 0x0D,
0x59, 0x49, 0x45, 0xF6, 0xF0, 0x71, 0x5C, 0x39, 0x29, 0xD6, 0xBF, 0x4A,
0x23, 0x8B, 0xF5, 0x5F, 0x01, 0x63, 0xD2, 0x87, 0x73, 0x28, 0xB5, 0x4B,
0x0A, 0xF5, 0xF8, 0xAB, 0x82, 0x2C, 0x7E, 0x73, 0x25, 0x32, 0x1D, 0x0B,
0x63, 0x0A, 0x17, 0x81, 0x00, 0xFF, 0xB6, 0x76, 0x5E, 0xE7, 0xB4, 0xB1,
0x40, 0xCA, 0x21, 0xBB, 0xD5, 0x80, 0x51, 0xE5, 0x48, 0x52, 0x67, 0x2C,
0xD2, 0x61, 0x89, 0x07, 0x0D, 0x0F, 0xCE, 0x42, 0x77, 0xC0, 0x44, 0x73,
0x9C, 0x44, 0x50, 0xA0, 0xDB, 0x10, 0x0A, 0x2D, 0x95, 0x1C, 0x81, 0xAF,
0xE4, 0x1C, 0xE5, 0x14, 0x1E, 0xF1, 0x36, 0x41, 0x01, 0x02, 0x2F, 0x7D,
0x73, 0xA7, 0xDE, 0x42, 0xCC, 0x4C, 0xE9, 0x89, 0x0D, 0x56, 0xF7, 0x9F,
0x91, 0xD4, 0x03, 0xC6, 0x6C, 0xC9, 0x8F, 0xDB, 0xD8, 0x1C, 0xE0, 0x40,
0x98, 0x5D, 0x66, 0x99, 0x98, 0x80, 0x6E, 0x2D, 0xFF, 0x01, 0xC5, 0xCE,
0xCB, 0x46, 0x1F, 0xAC, 0x02, 0xC6, 0x43, 0xE6, 0xAE, 0xA2, 0x84, 0x3C,
0xC5, 0x4E, 0x1E, 0x3D, 0x6D, 0xC9, 0x14, 0x4C, 0xE3, 0x2E, 0x41, 0xBB,
0xCA, 0x39, 0xBF, 0x36, 0x3C, 0x2A, 0x19, 0xAA, 0x41, 0x87, 0x4E, 0xA5,
0xCE, 0x4B, 0x32, 0x79, 0xDD, 0x90, 0x49, 0x7F
};
static const unsigned char TA103_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA104_DN[] = {
0x30, 0x74, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74,
0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E,
0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x19, 0x30, 0x17, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D,
0x20, 0x45, 0x43, 0x2D, 0x33, 0x38, 0x34, 0x20, 0x43, 0x41
};
static const unsigned char TA104_EC_Q[] = {
0x04, 0xC4, 0x28, 0x8E, 0xAB, 0x18, 0x5B, 0x6A, 0xBE, 0x6E, 0x64, 0x37,
0x63, 0xE4, 0xCD, 0xEC, 0xAB, 0x3A, 0xF7, 0xCC, 0xA1, 0xB8, 0x0E, 0x82,
0x49, 0xD7, 0x86, 0x29, 0x9F, 0xA1, 0x94, 0xF2, 0xE3, 0x60, 0x78, 0x98,
0x81, 0x78, 0x06, 0x4D, 0xF2, 0xEC, 0x9A, 0x0E, 0x57, 0x60, 0x83, 0x9F,
0xB4, 0xE6, 0x17, 0x2F, 0x1A, 0xB3, 0x5D, 0x02, 0x5B, 0x89, 0x23, 0x3C,
0xC2, 0x11, 0x05, 0x2A, 0xA7, 0x88, 0x13, 0x18, 0xF3, 0x50, 0x84, 0xD7,
0xBD, 0x34, 0x2C, 0x27, 0x89, 0x55, 0xFF, 0xCE, 0x4C, 0xE7, 0xDF, 0xA6,
0x1F, 0x28, 0xC4, 0xF0, 0x54, 0xC3, 0xB9, 0x7C, 0xB7, 0x53, 0xAD, 0xEB,
0xC2
};
static const unsigned char TA105_DN[] = {
0x30, 0x7A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x50, 0x4C, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x18, 0x41, 0x73, 0x73, 0x65, 0x63, 0x6F, 0x20, 0x44, 0x61, 0x74,
0x61, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x53, 0x2E,
0x41, 0x2E, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x1E, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D, 0x20, 0x43, 0x65, 0x72, 0x74,
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x75,
0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x31, 0x1F, 0x30, 0x1D, 0x06,
0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x43, 0x65, 0x72, 0x74, 0x75, 0x6D,
0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA105_RSA_N[] = {
0xD1, 0x2D, 0x8E, 0xBB, 0xB7, 0x36, 0xEA, 0x6D, 0x37, 0x91, 0x9F, 0x4E,
0x93, 0xA7, 0x05, 0xE4, 0x29, 0x03, 0x25, 0xCE, 0x1C, 0x82, 0xF7, 0x7C,
0x99, 0x9F, 0x41, 0x06, 0xCD, 0xED, 0xA3, 0xBA, 0xC0, 0xDB, 0x09, 0x2C,
0xC1, 0x7C, 0xDF, 0x29, 0x7E, 0x4B, 0x65, 0x2F, 0x93, 0xA7, 0xD4, 0x01,
0x6B, 0x03, 0x28, 0x18, 0xA3, 0xD8, 0x9D, 0x05, 0xC1, 0x2A, 0xD8, 0x45,
0xF1, 0x91, 0xDE, 0xDF, 0x3B, 0xD0, 0x80, 0x02, 0x8C, 0xCF, 0x38, 0x0F,
0xEA, 0xA7, 0x5C, 0x78, 0x11, 0xA4, 0xC1, 0xC8, 0x85, 0x5C, 0x25, 0xD3,
0xD3, 0xB2, 0xE7, 0x25, 0xCF, 0x11, 0x54, 0x97, 0xAB, 0x35, 0xC0, 0x1E,
0x76, 0x1C, 0xEF, 0x00, 0x53, 0x9F, 0x39, 0xDC, 0x14, 0xA5, 0x2C, 0x22,
0x25, 0xB3, 0x72, 0x72, 0xFC, 0x8D, 0xB3, 0xE5, 0x3E, 0x08, 0x1E, 0x14,
0x2A, 0x37, 0x0B, 0x88, 0x3C, 0xCA, 0xB0, 0xF4, 0xC8, 0xC2, 0xA1, 0xAE,
0xBC, 0xC1, 0xBE, 0x29, 0x67, 0x55, 0xE2, 0xFC, 0xAD, 0x59, 0x5C, 0xFE,
0xBD, 0x57, 0x2C, 0xB0, 0x90, 0x8D, 0xC2, 0xED, 0x37, 0xB6, 0x7C, 0x99,
0x88, 0xB5, 0xD5, 0x03, 0x9A, 0x3D, 0x15, 0x0D, 0x3D, 0x3A, 0xA8, 0xA8,
0x45, 0xF0, 0x95, 0x4E, 0x25, 0x59, 0x1D, 0xCD, 0x98, 0x69, 0xBB, 0xD3,
0xCC, 0x32, 0xC9, 0x8D, 0xEF, 0x81, 0xFE, 0xAD, 0x7D, 0x89, 0xBB, 0xBA,
0x60, 0x13, 0xCA, 0x65, 0x95, 0x67, 0xA0, 0xF3, 0x19, 0xF6, 0x03, 0x56,
0xD4, 0x6A, 0xD3, 0x27, 0xE2, 0xA1, 0xAD, 0x83, 0xF0, 0x4A, 0x12, 0x22,
0x77, 0x1C, 0x05, 0x73, 0xE2, 0x19, 0x71, 0x42, 0xC0, 0xEC, 0x75, 0x46,
0x9A, 0x90, 0x58, 0xE0, 0x6A, 0x8E, 0x2B, 0xA5, 0x46, 0x30, 0x04, 0x8E,
0x19, 0xB2, 0x17, 0xE3, 0xBE, 0xA9, 0xBA, 0x7F, 0x56, 0xF1, 0x24, 0x03,
0xD7, 0xB2, 0x21, 0x28, 0x76, 0x0E, 0x36, 0x30, 0x4C, 0x79, 0xD5, 0x41,
0x9A, 0x9A, 0xA8, 0xB8, 0x35, 0xBA, 0x0C, 0x3A, 0xF2, 0x44, 0x1B, 0x20,
0x88, 0xF7, 0xC5, 0x25, 0xD7, 0x3D, 0xC6, 0xE3, 0x3E, 0x43, 0xDD, 0x87,
0xFE, 0xC4, 0xEA, 0xF5, 0x53, 0x3E, 0x4C, 0x65, 0xFF, 0x3B, 0x4A, 0xCB,
0x78, 0x5A, 0x6B, 0x17, 0x5F, 0x0D, 0xC7, 0xC3, 0x4F, 0x4E, 0x9A, 0x2A,
0xA2, 0xED, 0x57, 0x4D, 0x22, 0xE2, 0x46, 0x9A, 0x3F, 0x0F, 0x91, 0x34,
0x24, 0x7D, 0x55, 0xE3, 0x8C, 0x95, 0x37, 0xD3, 0x1A, 0xF0, 0x09, 0x2B,
0x2C, 0xD2, 0xC9, 0x8D, 0xB4, 0x0D, 0x00, 0xAB, 0x67, 0x29, 0x28, 0xD8,
0x01, 0xF5, 0x19, 0x04, 0xB6, 0x1D, 0xBE, 0x76, 0xFE, 0x72, 0x5C, 0xC4,
0x85, 0xCA, 0xD2, 0x80, 0x41, 0xDF, 0x05, 0xA8, 0xA3, 0xD5, 0x84, 0x90,
0x4F, 0x0B, 0xF3, 0xE0, 0x3F, 0x9B, 0x19, 0xD2, 0x37, 0x89, 0x3F, 0xF2,
0x7B, 0x52, 0x1C, 0x8C, 0xF6, 0xE1, 0xF7, 0x3C, 0x07, 0x97, 0x8C, 0x0E,
0xA2, 0x59, 0x81, 0x0C, 0xB2, 0x90, 0x3D, 0xD3, 0xE3, 0x59, 0x46, 0xED,
0x0F, 0xA9, 0xA7, 0xDE, 0x80, 0x6B, 0x5A, 0xAA, 0x07, 0xB6, 0x19, 0xCB,
0xBC, 0x57, 0xF3, 0x97, 0x21, 0x7A, 0x0C, 0xB1, 0x2B, 0x74, 0x3E, 0xEB,
0xDA, 0xA7, 0x67, 0x2D, 0x4C, 0xC4, 0x98, 0x9E, 0x36, 0x09, 0x76, 0x66,
0x66, 0xFC, 0x1A, 0x3F, 0xEA, 0x48, 0x54, 0x1C, 0xBE, 0x30, 0xBD, 0x80,
0x50, 0xBF, 0x7C, 0xB5, 0xCE, 0x00, 0xF6, 0x0C, 0x61, 0xD9, 0xE7, 0x24,
0x03, 0xE0, 0xE3, 0x01, 0x81, 0x0E, 0xBD, 0xD8, 0x85, 0x34, 0x88, 0xBD,
0xB2, 0x36, 0xA8, 0x7B, 0x5C, 0x08, 0xE5, 0x44, 0x80, 0x8C, 0x6F, 0xF8,
0x2F, 0xD5, 0x21, 0xCA, 0x1D, 0x1C, 0xD0, 0xFB, 0xC4, 0xB5, 0x87, 0xD1,
0x3A, 0x4E, 0xC7, 0x76, 0xB5, 0x35, 0x48, 0xB5
};
static const unsigned char TA105_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA106_DN[] = {
0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x54, 0x4E, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x2E, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x4E, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x65, 0x20, 0x64, 0x65, 0x20, 0x43, 0x65,
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20,
0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 0x6E, 0x69, 0x71, 0x75, 0x65,
0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54,
0x75, 0x6E, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41
};
static const unsigned char TA106_RSA_N[] = {
0xC3, 0xCD, 0xD3, 0xFC, 0xBD, 0x04, 0x53, 0xDD, 0x0C, 0x20, 0x3A, 0xD5,
0x88, 0x2E, 0x05, 0x4B, 0x41, 0xF5, 0x83, 0x82, 0x7E, 0xF7, 0x59, 0x9F,
0x9E, 0x9E, 0x63, 0xE8, 0x73, 0xDA, 0xF6, 0x06, 0xA9, 0x4F, 0x1F, 0xB4,
0xF9, 0x0B, 0x1F, 0x39, 0x8C, 0x9A, 0x20, 0xD0, 0x7E, 0x06, 0xD4, 0xEC,
0x34, 0xD9, 0x86, 0xBC, 0x75, 0x5B, 0x87, 0x88, 0xF0, 0xD2, 0xD9, 0xD4,
0xA3, 0x0A, 0xB2, 0x6C, 0x1B, 0xEB, 0x49, 0x2C, 0x3E, 0xAC, 0x5D, 0xD8,
0x94, 0x03, 0xA0, 0xEC, 0x34, 0xE5, 0x30, 0xC4, 0x35, 0x7D, 0xFB, 0x26,
0x4D, 0x1B, 0x6E, 0x30, 0x54, 0xD8, 0xF5, 0x80, 0x45, 0x9C, 0x39, 0xAD,
0x9C, 0xC9, 0x25, 0x04, 0x4D, 0x9A, 0x90, 0x3E, 0x4E, 0x40, 0x6E, 0x8A,
0x6B, 0xCD, 0x29, 0x67, 0xC6, 0xCC, 0x2D, 0xE0, 0x74, 0xE8, 0x05, 0x57,
0x0A, 0x48, 0x50, 0xFA, 0x7A, 0x43, 0xDA, 0x7E, 0xEC, 0x5B, 0x9A, 0x0E,
0x62, 0x76, 0xFE, 0xEA, 0x9D, 0x1D, 0x85, 0x72, 0xEC, 0x11, 0xBB, 0x35,
0xE8, 0x1F, 0x27, 0xBF, 0xC1, 0xA1, 0xC7, 0xBB, 0x48, 0x16, 0xDD, 0x56,
0xD7, 0xCC, 0x4E, 0xA0, 0xE1, 0xB9, 0xAC, 0xDB, 0xD5, 0x83, 0x19, 0x1A,
0x85, 0xD1, 0x94, 0x97, 0xD7, 0xCA, 0xA3, 0x65, 0x0B, 0xF3, 0x38, 0xF9,
0x02, 0xAE, 0xDD, 0xF6, 0x67, 0xCF, 0xC9, 0x3F, 0xF5, 0x8A, 0x2C, 0x47,
0x1A, 0x99, 0x6F, 0x05, 0x0D, 0xFD, 0xD0, 0x1D, 0x82, 0x31, 0xFC, 0x29,
0xCC, 0x00, 0x58, 0x97, 0x91, 0x4C, 0x80, 0x00, 0x1C, 0x33, 0x85, 0x96,
0x2F, 0xCB, 0x41, 0xC2, 0x8B, 0x10, 0x84, 0xC3, 0x09, 0x24, 0x89, 0x1F,
0xB5, 0x0F, 0xD9, 0xD9, 0x77, 0x47, 0x18, 0x92, 0x94, 0x60, 0x5C, 0xC7,
0x99, 0x03, 0x3C, 0xFE, 0xF7, 0x95, 0xA7, 0x7D, 0x50, 0xA1, 0x80, 0xC2,
0xA9, 0x83, 0xAD, 0x58, 0x96, 0x55, 0x21, 0xDB, 0x86, 0x59, 0xD4, 0xAF,
0xC6, 0xBC, 0xDD, 0x81, 0x6E, 0x07, 0xDB, 0x60, 0x62, 0xFE, 0xEC, 0x10,
0x6E, 0xDA, 0x68, 0x01, 0xF4, 0x83, 0x1B, 0xA9, 0x3E, 0xA2, 0x5B, 0x23,
0xD7, 0x64, 0xC6, 0xDF, 0xDC, 0xA2, 0x7D, 0xD8, 0x4B, 0xBA, 0x82, 0xD2,
0x51, 0xF8, 0x66, 0xBF, 0x06, 0x46, 0xE4, 0x79, 0x2A, 0x26, 0x36, 0x79,
0x8F, 0x1F, 0x4E, 0x99, 0x1D, 0xB2, 0x8F, 0x0C, 0x0E, 0x1C, 0xFF, 0xC9,
0x5D, 0xC0, 0xFD, 0x90, 0x10, 0xA6, 0xB1, 0x37, 0xF3, 0xCD, 0x3A, 0x24,
0x6E, 0xB4, 0x85, 0x90, 0xBF, 0x80, 0xB9, 0x0C, 0x8C, 0xD5, 0x9B, 0xD6,
0xC8, 0xF1, 0x56, 0x3F, 0x1A, 0x80, 0x89, 0x7A, 0xA9, 0xE2, 0x1B, 0x32,
0x51, 0x2C, 0x3E, 0xF2, 0xDF, 0x7B, 0xF6, 0x5D, 0x7A, 0x29, 0x19, 0x8E,
0xE5, 0xC8, 0xBD, 0x36, 0x71, 0x8B, 0x5D, 0x4C, 0xC2, 0x1D, 0x3F, 0xAD,
0x58, 0xA2, 0xCF, 0x3D, 0x70, 0x4D, 0xA6, 0x50, 0x98, 0x25, 0xDC, 0x23,
0xF9, 0xB8, 0x58, 0x41, 0x08, 0x71, 0xBF, 0x4F, 0xB8, 0x84, 0xA0, 0x8F,
0x00, 0x54, 0x15, 0xFC, 0x91, 0x6D, 0x58, 0xA7, 0x96, 0x3B, 0xEB, 0x4B,
0x96, 0x27, 0xCD, 0x6B, 0xA2, 0xA1, 0x86, 0xAC, 0x0D, 0x7C, 0x54, 0xE6,
0x66, 0x4C, 0x66, 0x5F, 0x90, 0xBE, 0x21, 0x9A, 0x02, 0x46, 0x2D, 0xE4,
0x83, 0xC2, 0x80, 0xB9, 0xCF, 0x4B, 0x3E, 0xE8, 0x7F, 0x3C, 0x01, 0xEC,
0x8F, 0x5E, 0xCD, 0x7F, 0xD2, 0x28, 0x42, 0x01, 0x95, 0x8A, 0xE2, 0x97,
0x3D, 0x10, 0x21, 0x7D, 0xF6, 0x9D, 0x1C, 0xC5, 0x34, 0xA1, 0xEC, 0x2C,
0x0E, 0x0A, 0x52, 0x2C, 0x12, 0x55, 0x70, 0x24, 0x3D, 0xCB, 0xC2, 0x14,
0x35, 0x43, 0x5D, 0x27, 0x4E, 0xBE, 0xC0, 0xBD, 0xAA, 0x7C, 0x96, 0xE7,
0xFC, 0x9E, 0x61, 0xAD, 0x44, 0xD3, 0x00, 0x97
};
static const unsigned char TA106_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA107_DN[] = {
0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41,
0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20,
0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73,
0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41,
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48,
0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x52, 0x53,
0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30,
0x32, 0x31
};
static const unsigned char TA107_RSA_N[] = {
0x8B, 0xC2, 0xE7, 0xAF, 0x65, 0x9B, 0x05, 0x67, 0x96, 0xC9, 0x0D, 0x24,
0xB9, 0xD0, 0x0E, 0x64, 0xFC, 0xCE, 0xE2, 0x24, 0x18, 0x2C, 0x84, 0x7F,
0x77, 0x51, 0xCB, 0x04, 0x11, 0x36, 0xB8, 0x5E, 0xED, 0x69, 0x71, 0xA7,
0x9E, 0xE4, 0x25, 0x09, 0x97, 0x67, 0xC1, 0x47, 0xC2, 0xCF, 0x91, 0x16,
0x36, 0x62, 0x3D, 0x38, 0x04, 0xE1, 0x51, 0x82, 0xFF, 0xAC, 0xD2, 0xB4,
0x69, 0xDD, 0x2E, 0xEC, 0x11, 0xA3, 0x45, 0xEE, 0x6B, 0x6B, 0x3B, 0x4C,
0xBF, 0x8C, 0x8D, 0xA4, 0x1E, 0x9D, 0x11, 0xB9, 0xE9, 0x38, 0xF9, 0x7A,
0x0E, 0x0C, 0x98, 0xE2, 0x23, 0x1D, 0xD1, 0x4E, 0x63, 0xD4, 0xE7, 0xB8,
0x41, 0x44, 0xFB, 0x6B, 0xAF, 0x6B, 0xDA, 0x1F, 0xD3, 0xC5, 0x91, 0x88,
0x5B, 0xA4, 0x89, 0x92, 0xD1, 0x81, 0xE6, 0x8C, 0x39, 0x58, 0xA0, 0xD6,
0x69, 0x43, 0xA9, 0xAD, 0x98, 0x52, 0x58, 0x6E, 0xDB, 0x0A, 0xFB, 0x6B,
0xCF, 0x68, 0xFA, 0xE3, 0xA4, 0x5E, 0x3A, 0x45, 0x73, 0x98, 0x07, 0xEA,
0x5F, 0x02, 0x72, 0xDE, 0x0C, 0xA5, 0xB3, 0x9F, 0xAE, 0xA9, 0x1D, 0xB7,
0x1D, 0xB3, 0xFC, 0x8A, 0x59, 0xE7, 0x6E, 0x72, 0x65, 0xAD, 0xF5, 0x30,
0x94, 0x23, 0x07, 0xF3, 0x82, 0x16, 0x4B, 0x35, 0x98, 0x9C, 0x53, 0xBB,
0x2F, 0xCA, 0xE4, 0x5A, 0xD9, 0xC7, 0x8D, 0x1D, 0xFC, 0x98, 0x99, 0xFB,
0x2C, 0xA4, 0x82, 0x6B, 0xF0, 0x2A, 0x1F, 0x8E, 0x0B, 0x5F, 0x71, 0x5C,
0x5C, 0xAE, 0x42, 0x7B, 0x29, 0x89, 0x81, 0xCB, 0x03, 0xA3, 0x99, 0xCA,
0x88, 0x9E, 0x0B, 0x40, 0x09, 0x41, 0x33, 0xDB, 0xE6, 0x58, 0x7A, 0xFD,
0xAE, 0x99, 0x70, 0xC0, 0x5A, 0x0F, 0xD6, 0x13, 0x86, 0x71, 0x2F, 0x76,
0x69, 0xFC, 0x90, 0xDD, 0xDB, 0x2D, 0x6E, 0xD1, 0xF2, 0x9B, 0xF5, 0x1A,
0x6B, 0x9E, 0x6F, 0x15, 0x8C, 0x7A, 0xF0, 0x4B, 0x28, 0xA0, 0x22, 0x38,
0x80, 0x24, 0x6C, 0x36, 0xA4, 0x3B, 0xF2, 0x30, 0x91, 0xF3, 0x78, 0x13,
0xCF, 0xC1, 0x3F, 0x35, 0xAB, 0xF1, 0x1D, 0x11, 0x23, 0xB5, 0x43, 0x22,
0x9E, 0x01, 0x92, 0xB7, 0x18, 0x02, 0xE5, 0x11, 0xD1, 0x82, 0xDB, 0x15,
0x00, 0xCC, 0x61, 0x37, 0xC1, 0x2A, 0x7C, 0x9A, 0xE1, 0xD0, 0xBA, 0xB3,
0x50, 0x46, 0xEE, 0x82, 0xAC, 0x9D, 0x31, 0xF8, 0xFB, 0x23, 0xE2, 0x03,
0x00, 0x48, 0x70, 0xA3, 0x09, 0x26, 0x79, 0x15, 0x53, 0x60, 0xF3, 0x38,
0x5C, 0xAD, 0x38, 0xEA, 0x81, 0x00, 0x63, 0x14, 0xB9, 0x33, 0x5E, 0xDD,
0x0B, 0xDB, 0xA0, 0x45, 0x07, 0x1A, 0x33, 0x09, 0xF8, 0x4D, 0xB4, 0xA7,
0x02, 0xA6, 0x69, 0xF4, 0xC2, 0x59, 0x05, 0x88, 0x65, 0x85, 0x56, 0xAE,
0x4B, 0xCB, 0xE0, 0xDE, 0x3C, 0x7D, 0x2D, 0x1A, 0xC8, 0xE9, 0xFB, 0x1F,
0xA3, 0x61, 0x4A, 0xD6, 0x2A, 0x13, 0xAD, 0x77, 0x4C, 0x1A, 0x18, 0x9B,
0x91, 0x0F, 0x58, 0xD8, 0x06, 0x54, 0xC5, 0x97, 0xF8, 0xAA, 0x3F, 0x20,
0x8A, 0xA6, 0x85, 0xA6, 0x77, 0xF6, 0xA6, 0xFC, 0x1C, 0xE2, 0xEE, 0x6E,
0x94, 0x33, 0x2A, 0x83, 0x50, 0x84, 0x0A, 0xE5, 0x4F, 0x86, 0xF8, 0x50,
0x45, 0x78, 0x00, 0x81, 0xEB, 0x5B, 0x68, 0xE3, 0x26, 0x8D, 0xCC, 0x7B,
0x5C, 0x51, 0xF4, 0x14, 0x2C, 0x40, 0xBE, 0x1A, 0x60, 0x1D, 0x7A, 0x72,
0x61, 0x1D, 0x1F, 0x63, 0x2D, 0x88, 0xAA, 0xCE, 0xA2, 0x45, 0x90, 0x08,
0xFC, 0x6B, 0xBE, 0xB3, 0x50, 0x2A, 0x5A, 0xFD, 0xA8, 0x48, 0x18, 0x46,
0xD6, 0x90, 0x40, 0x92, 0x90, 0x0A, 0x84, 0x5E, 0x68, 0x31, 0xF8, 0xEB,
0xED, 0x0D, 0xD3, 0x1D, 0xC6, 0x7D, 0x99, 0x18, 0x55, 0x56, 0x27, 0x65,
0x2E, 0x8D, 0x45, 0xC5, 0x24, 0xEC, 0xCE, 0xE3
};
static const unsigned char TA107_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA108_DN[] = {
0x30, 0x6C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x47, 0x52, 0x31, 0x37, 0x30, 0x35, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x2E, 0x48, 0x65, 0x6C, 0x6C, 0x65, 0x6E, 0x69, 0x63, 0x20, 0x41,
0x63, 0x61, 0x64, 0x65, 0x6D, 0x69, 0x63, 0x20, 0x61, 0x6E, 0x64, 0x20,
0x52, 0x65, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x49, 0x6E, 0x73,
0x74, 0x69, 0x74, 0x75, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x43, 0x41,
0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x48,
0x41, 0x52, 0x49, 0x43, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x45, 0x43,
0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30,
0x32, 0x31
};
static const unsigned char TA108_EC_Q[] = {
0x04, 0x38, 0x08, 0xFE, 0xB1, 0xA0, 0x96, 0xD2, 0x7A, 0xAC, 0xAF, 0x49,
0x3A, 0xD0, 0xC0, 0xE0, 0xC3, 0x3B, 0x28, 0xAA, 0xF1, 0x72, 0x6D, 0x65,
0x00, 0x47, 0x88, 0x84, 0xFC, 0x9A, 0x26, 0x6B, 0xAA, 0x4B, 0xBA, 0x6C,
0x04, 0x0A, 0x88, 0x5E, 0x17, 0xF2, 0x55, 0x87, 0xFC, 0x30, 0xB0, 0x34,
0xE2, 0x34, 0x58, 0x57, 0x1A, 0x84, 0x53, 0xE9, 0x30, 0xD9, 0xA9, 0xF2,
0x96, 0x74, 0xC3, 0x51, 0x1F, 0x58, 0x49, 0x31, 0xCC, 0x98, 0x4E, 0x60,
0x11, 0x87, 0x75, 0xD3, 0x72, 0x94, 0x90, 0x4F, 0x9B, 0x10, 0x25, 0x2A,
0xA8, 0x78, 0x2D, 0xBE, 0x90, 0x41, 0x58, 0x90, 0x15, 0x72, 0xA7, 0xA1,
0xB7
};
static const unsigned char TA109_DN[] = {
0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x45, 0x53, 0x31, 0x42, 0x30, 0x40, 0x06, 0x03, 0x55, 0x04, 0x03,
0x0C, 0x39, 0x41, 0x75, 0x74, 0x6F, 0x72, 0x69, 0x64, 0x61, 0x64, 0x20,
0x64, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
0x63, 0x69, 0x6F, 0x6E, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72,
0x6F, 0x66, 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x43, 0x49,
0x46, 0x20, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38
};
static const unsigned char TA109_RSA_N[] = {
0xCA, 0x96, 0x6B, 0x8E, 0xEA, 0xF8, 0xFB, 0xF1, 0xA2, 0x35, 0xE0, 0x7F,
0x4C, 0xDA, 0xE0, 0xC3, 0x52, 0xD7, 0x7D, 0xB6, 0x10, 0xC8, 0x02, 0x5E,
0xB3, 0x43, 0x2A, 0xC4, 0x4F, 0x6A, 0xB2, 0xCA, 0x1C, 0x5D, 0x28, 0x9A,
0x78, 0x11, 0x1A, 0x69, 0x59, 0x57, 0xAF, 0xB5, 0x20, 0x42, 0xE4, 0x8B,
0x0F, 0xE6, 0xDF, 0x5B, 0xA6, 0x03, 0x92, 0x2F, 0xF5, 0x11, 0xE4, 0x62,
0xD7, 0x32, 0x71, 0x38, 0xD9, 0x04, 0x0C, 0x71, 0xAB, 0x3D, 0x51, 0x7E,
0x0F, 0x07, 0xDF, 0x63, 0x05, 0x5C, 0xE9, 0xBF, 0x94, 0x6F, 0xC1, 0x29,
0x82, 0xC0, 0xB4, 0xDA, 0x51, 0xB0, 0xC1, 0x3C, 0xBB, 0xAD, 0x37, 0x4A,
0x5C, 0xCA, 0xF1, 0x4B, 0x36, 0x0E, 0x24, 0xAB, 0xBF, 0xC3, 0x84, 0x77,
0xFD, 0xA8, 0x50, 0xF4, 0xB1, 0xE7, 0xC6, 0x2F, 0xD2, 0x2D, 0x59, 0x8D,
0x7A, 0x0A, 0x4E, 0x96, 0x69, 0x52, 0x02, 0xAA, 0x36, 0x98, 0xEC, 0xFC,
0xFA, 0x14, 0x83, 0x0C, 0x37, 0x1F, 0xC9, 0x92, 0x37, 0x7F, 0xD7, 0x81,
0x2D, 0xE5, 0xC4, 0xB9, 0xE0, 0x3E, 0x34, 0xFE, 0x67, 0xF4, 0x3E, 0x66,
0xD1, 0xD3, 0xF4, 0x40, 0xCF, 0x5E, 0x62, 0x34, 0x0F, 0x70, 0x06, 0x3E,
0x20, 0x18, 0x5A, 0xCE, 0xF7, 0x72, 0x1B, 0x25, 0x6C, 0x93, 0x74, 0x14,
0x93, 0xA3, 0x73, 0xB1, 0x0E, 0xAA, 0x87, 0x10, 0x23, 0x59, 0x5F, 0x20,
0x05, 0x19, 0x47, 0xED, 0x68, 0x8E, 0x92, 0x12, 0xCA, 0x5D, 0xFC, 0xD6,
0x2B, 0xB2, 0x92, 0x3C, 0x20, 0xCF, 0xE1, 0x5F, 0xAF, 0x20, 0xBE, 0xA0,
0x76, 0x7F, 0x76, 0xE5, 0xEC, 0x1A, 0x86, 0x61, 0x33, 0x3E, 0xE7, 0x7B,
0xB4, 0x3F, 0xA0, 0x0F, 0x8E, 0xA2, 0xB9, 0x6A, 0x6F, 0xB9, 0x87, 0x26,
0x6F, 0x41, 0x6C, 0x88, 0xA6, 0x50, 0xFD, 0x6A, 0x63, 0x0B, 0xF5, 0x93,
0x16, 0x1B, 0x19, 0x8F, 0xB2, 0xED, 0x9B, 0x9B, 0xC9, 0x90, 0xF5, 0x01,
0x0C, 0xDF, 0x19, 0x3D, 0x0F, 0x3E, 0x38, 0x23, 0xC9, 0x2F, 0x8F, 0x0C,
0xD1, 0x02, 0xFE, 0x1B, 0x55, 0xD6, 0x4E, 0xD0, 0x8D, 0x3C, 0xAF, 0x4F,
0xA4, 0xF3, 0xFE, 0xAF, 0x2A, 0xD3, 0x05, 0x9D, 0x79, 0x08, 0xA1, 0xCB,
0x57, 0x31, 0xB4, 0x9C, 0xC8, 0x90, 0xB2, 0x67, 0xF4, 0x18, 0x16, 0x93,
0x3A, 0xFC, 0x47, 0xD8, 0xD1, 0x78, 0x96, 0x31, 0x1F, 0xBA, 0x2B, 0x0C,
0x5F, 0x5D, 0x99, 0xAD, 0x63, 0x89, 0x5A, 0x24, 0x20, 0x76, 0xD8, 0xDF,
0xFD, 0xAB, 0x4E, 0xA6, 0x22, 0xAA, 0x9D, 0x5E, 0xE6, 0x27, 0x8A, 0x7D,
0x68, 0x29, 0xA3, 0xE7, 0x8A, 0xB8, 0xDA, 0x11, 0xBB, 0x17, 0x2D, 0x99,
0x9D, 0x13, 0x24, 0x46, 0xF7, 0xC5, 0xE2, 0xD8, 0x9F, 0x8E, 0x7F, 0xC7,
0x8F, 0x74, 0x6D, 0x5A, 0xB2, 0xE8, 0x72, 0xF5, 0xAC, 0xEE, 0x24, 0x10,
0xAD, 0x2F, 0x14, 0xDA, 0xFF, 0x2D, 0x9A, 0x46, 0x71, 0x47, 0xBE, 0x42,
0xDF, 0xBB, 0x01, 0xDB, 0xF4, 0x7F, 0xD3, 0x28, 0x8F, 0x31, 0x59, 0x5B,
0xD3, 0xC9, 0x02, 0xA6, 0xB4, 0x52, 0xCA, 0x6E, 0x97, 0xFB, 0x43, 0xC5,
0x08, 0x26, 0x6F, 0x8A, 0xF4, 0xBB, 0xFD, 0x9F, 0x28, 0xAA, 0x0D, 0xD5,
0x45, 0xF3, 0x13, 0x3A, 0x1D, 0xD8, 0xC0, 0x78, 0x8F, 0x41, 0x67, 0x3C,
0x1E, 0x94, 0x64, 0xAE, 0x7B, 0x0B, 0xC5, 0xE8, 0xD9, 0x01, 0x88, 0x39,
0x1A, 0x97, 0x86, 0x64, 0x41, 0xD5, 0x3B, 0x87, 0x0C, 0x6E, 0xFA, 0x0F,
0xC6, 0xBD, 0x48, 0x14, 0xBF, 0x39, 0x4D, 0xD4, 0x9E, 0x41, 0xB6, 0x8F,
0x96, 0x1D, 0x63, 0x96, 0x93, 0xD9, 0x95, 0x06, 0x78, 0x31, 0x68, 0x9E,
0x37, 0x06, 0x3B, 0x80, 0x89, 0x45, 0x61, 0x39, 0x23, 0xC7, 0x1B, 0x44,
0xA3, 0x15, 0xE5, 0x1C, 0xF8, 0x92, 0x30, 0xBB
};
static const unsigned char TA109_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA110_DN[] = {
0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61,
0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1A, 0x30,
0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x76, 0x54, 0x72, 0x75,
0x73, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
0x41
};
static const unsigned char TA110_EC_Q[] = {
0x04, 0x65, 0x50, 0x4A, 0xAE, 0x8C, 0x79, 0x96, 0x4A, 0xAA, 0x1C, 0x08,
0xC3, 0xA3, 0xA2, 0xCD, 0xFE, 0x59, 0x56, 0x41, 0x77, 0xFD, 0x26, 0x94,
0x42, 0xBB, 0x1D, 0xCD, 0x08, 0xDB, 0x73, 0xB2, 0x5B, 0x75, 0xF3, 0xCF,
0x9C, 0x4E, 0x82, 0xF4, 0xBF, 0xF8, 0x61, 0x26, 0x85, 0x6C, 0xD6, 0x85,
0x5B, 0x72, 0x70, 0xD2, 0xFD, 0xDB, 0x62, 0xB4, 0xDF, 0x53, 0x8B, 0xBD,
0xB1, 0x44, 0x58, 0x62, 0x42, 0x09, 0xC7, 0xFA, 0x7F, 0x5B, 0x10, 0xE7,
0xFE, 0x40, 0xFD, 0xC0, 0xD8, 0xC3, 0x2B, 0x32, 0xE7, 0x70, 0xA6, 0xB7,
0xA6, 0x20, 0x55, 0x1D, 0x7B, 0x80, 0x5D, 0x4B, 0x8F, 0x67, 0x4C, 0xF1,
0x10
};
static const unsigned char TA111_DN[] = {
0x30, 0x43, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x13, 0x69, 0x54, 0x72, 0x75, 0x73, 0x43, 0x68, 0x69, 0x6E, 0x61,
0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x31, 0x16, 0x30,
0x14, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0D, 0x76, 0x54, 0x72, 0x75,
0x73, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA111_RSA_N[] = {
0xBD, 0x55, 0x7C, 0x61, 0xD3, 0xB8, 0x1D, 0x04, 0x62, 0x05, 0xA0, 0xAE,
0x6C, 0xB7, 0x70, 0xB4, 0x41, 0xEA, 0x4B, 0x03, 0x5E, 0x10, 0x3F, 0x90,
0x5A, 0x1C, 0x8B, 0x3B, 0xB0, 0x66, 0x8B, 0x6C, 0x48, 0xA6, 0x1C, 0x22,
0xBA, 0xD5, 0x40, 0x92, 0xEE, 0x33, 0xB2, 0x23, 0x59, 0xC9, 0x8E, 0xBC,
0x58, 0xDA, 0x8B, 0x9E, 0xD0, 0x19, 0xF2, 0x2F, 0x59, 0xC6, 0x8C, 0x63,
0x5A, 0xBA, 0x9F, 0xA3, 0x0B, 0xB0, 0xB3, 0x9A, 0x5C, 0xBA, 0x11, 0xB8,
0x12, 0xE9, 0x0C, 0xBB, 0xCF, 0x6E, 0x6C, 0x80, 0x87, 0x29, 0x14, 0x03,
0x2C, 0x8D, 0x24, 0x9A, 0xC8, 0x64, 0x83, 0xB5, 0x6A, 0xAC, 0x13, 0x2C,
0x33, 0xF1, 0x9F, 0xDC, 0x2C, 0x61, 0x3C, 0x1A, 0x3F, 0x70, 0x55, 0x9B,
0xAD, 0x00, 0x52, 0x7F, 0xCF, 0x04, 0xB9, 0xFE, 0x36, 0xFA, 0x9C, 0xC0,
0x16, 0xAE, 0x62, 0xFE, 0x96, 0x4C, 0x43, 0x7E, 0x55, 0x14, 0xBE, 0x1A,
0xB3, 0xD2, 0x6D, 0xC2, 0xAF, 0x76, 0x66, 0x95, 0x6B, 0x2A, 0xB0, 0x94,
0x77, 0x85, 0x5E, 0x04, 0x0F, 0x62, 0x1D, 0x63, 0x75, 0xF7, 0x6B, 0xE7,
0xCB, 0x5B, 0x9A, 0x70, 0xEC, 0x3E, 0x67, 0x05, 0xF0, 0xFE, 0x07, 0x08,
0x80, 0xCF, 0x28, 0xDB, 0x05, 0xC6, 0x14, 0x27, 0x2F, 0x86, 0x7D, 0xF0,
0x27, 0xDE, 0xFF, 0xE6, 0x7E, 0x33, 0x48, 0xE7, 0x0B, 0x1E, 0x58, 0xD1,
0x27, 0x2B, 0x53, 0x0E, 0x57, 0x4A, 0x65, 0xD7, 0xFB, 0xA2, 0x80, 0x60,
0xFC, 0x4C, 0xBC, 0x35, 0x53, 0x01, 0x6A, 0x97, 0x72, 0x82, 0xAF, 0xF1,
0x1D, 0x70, 0xE8, 0x9C, 0xF5, 0xEF, 0x5E, 0xC2, 0x6C, 0xC7, 0x47, 0x7E,
0x5A, 0x94, 0x85, 0x26, 0x4D, 0x3B, 0xBA, 0xEB, 0x4C, 0xE8, 0xB0, 0x09,
0xC2, 0x65, 0xC2, 0x9D, 0x9D, 0x09, 0x9B, 0x4E, 0xB5, 0x97, 0x05, 0xAC,
0xF5, 0x06, 0xA0, 0xF7, 0x36, 0x05, 0x7E, 0xF4, 0x90, 0xB2, 0x6B, 0xC4,
0xB4, 0xF9, 0x64, 0xEA, 0xE9, 0x1A, 0x0A, 0xC8, 0x0D, 0xA8, 0xED, 0x27,
0xC9, 0xD4, 0xE7, 0xB3, 0xB9, 0xAB, 0x82, 0x22, 0x90, 0x27, 0x3D, 0x2A,
0xE8, 0x7C, 0x90, 0xEF, 0xBC, 0x4F, 0xFD, 0xE2, 0x0A, 0x24, 0xA7, 0xDE,
0x65, 0x24, 0xA4, 0x5D, 0xEA, 0xC0, 0x76, 0x30, 0xD3, 0x77, 0x50, 0xF8,
0x0D, 0x04, 0x9B, 0x94, 0x36, 0x01, 0x73, 0xCA, 0x06, 0x58, 0xA6, 0xD3,
0x3B, 0xDC, 0xFA, 0x04, 0x46, 0x13, 0x55, 0x8A, 0xC9, 0x44, 0x47, 0xB8,
0x51, 0x39, 0x1A, 0x2E, 0xE8, 0x34, 0xE2, 0x79, 0xCB, 0x59, 0x4A, 0x0A,
0x7F, 0xBC, 0xA6, 0xEF, 0x1F, 0x03, 0x67, 0x6A, 0x59, 0x2B, 0x25, 0x62,
0x93, 0xD9, 0x53, 0x19, 0x66, 0x3C, 0x27, 0x62, 0x29, 0x86, 0x4D, 0xA4,
0x6B, 0xEE, 0xFF, 0xD4, 0x4E, 0xBA, 0xD5, 0xB4, 0xE2, 0x8E, 0x48, 0x5A,
0x00, 0x19, 0x09, 0xF1, 0x05, 0xD9, 0xCE, 0x91, 0xB1, 0xF7, 0xEB, 0xE9,
0x39, 0x4F, 0xF6, 0x6F, 0x04, 0x43, 0x9A, 0x55, 0xF5, 0x3E, 0x05, 0x14,
0xBD, 0xBF, 0xB3, 0x59, 0xB4, 0xD8, 0x8E, 0x33, 0x84, 0xA3, 0x90, 0x52,
0xAA, 0xB3, 0x02, 0x95, 0x60, 0xF9, 0x0C, 0x4C, 0x68, 0xF9, 0xEE, 0xD5,
0x17, 0x0D, 0xF8, 0x71, 0x57, 0xB5, 0x25, 0xE4, 0x29, 0xEE, 0x65, 0x5D,
0xAF, 0xD1, 0xEE, 0x3C, 0x17, 0x0B, 0x5A, 0x43, 0xC5, 0xA5, 0x86, 0xEA,
0x24, 0x9E, 0xE2, 0x05, 0x07, 0xDC, 0x34, 0x42, 0x12, 0x91, 0xD6, 0x39,
0x74, 0xAE, 0x4C, 0x41, 0x82, 0xDB, 0xF2, 0xA6, 0x48, 0xD1, 0xB3, 0x9B,
0xF3, 0x33, 0xAA, 0xF3, 0xA6, 0xC0, 0xC5, 0x4E, 0xF5, 0xF4, 0x9D, 0x76,
0x63, 0xE6, 0x02, 0xC6, 0x22, 0x4B, 0xC1, 0x95, 0x3F, 0x50, 0x64, 0x2C,
0x54, 0xE5, 0xB6, 0xF0, 0x3C, 0x29, 0xCF, 0x57
};
static const unsigned char TA111_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA112_DN[] = {
0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x20, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65, 0x74, 0x20, 0x53,
0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20, 0x52, 0x65, 0x73, 0x65,
0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x15,
0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0C, 0x49, 0x53, 0x52,
0x47, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x58, 0x32
};
static const unsigned char TA112_EC_Q[] = {
0x04, 0xCD, 0x9B, 0xD5, 0x9F, 0x80, 0x83, 0x0A, 0xEC, 0x09, 0x4A, 0xF3,
0x16, 0x4A, 0x3E, 0x5C, 0xCF, 0x77, 0xAC, 0xDE, 0x67, 0x05, 0x0D, 0x1D,
0x07, 0xB6, 0xDC, 0x16, 0xFB, 0x5A, 0x8B, 0x14, 0xDB, 0xE2, 0x71, 0x60,
0xC4, 0xBA, 0x45, 0x95, 0x11, 0x89, 0x8E, 0xEA, 0x06, 0xDF, 0xF7, 0x2A,
0x16, 0x1C, 0xA4, 0xB9, 0xC5, 0xC5, 0x32, 0xE0, 0x03, 0xE0, 0x1E, 0x82,
0x18, 0x38, 0x8B, 0xD7, 0x45, 0xD8, 0x0A, 0x6A, 0x6E, 0xE6, 0x00, 0x77,
0xFB, 0x02, 0x51, 0x7D, 0x22, 0xD8, 0x0A, 0x6E, 0x9A, 0x5B, 0x77, 0xDF,
0xF0, 0xFA, 0x41, 0xEC, 0x39, 0xDC, 0x75, 0xCA, 0x68, 0x07, 0x0C, 0x1F,
0xEA
};
static const unsigned char TA113_DN[] = {
0x30, 0x4F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x54, 0x57, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1A, 0x43, 0x68, 0x75, 0x6E, 0x67, 0x68, 0x77, 0x61, 0x20, 0x54,
0x65, 0x6C, 0x65, 0x63, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20,
0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04,
0x03, 0x0C, 0x12, 0x48, 0x69, 0x50, 0x4B, 0x49, 0x20, 0x52, 0x6F, 0x6F,
0x74, 0x20, 0x43, 0x41, 0x20, 0x2D, 0x20, 0x47, 0x31
};
static const unsigned char TA113_RSA_N[] = {
0xF4, 0x1E, 0x7F, 0x52, 0x73, 0x32, 0x0C, 0x73, 0xE4, 0xBD, 0x13, 0x74,
0xA3, 0xD4, 0x30, 0xA8, 0xD0, 0xAE, 0x4B, 0xD8, 0xB6, 0xDF, 0x75, 0x47,
0x66, 0xF4, 0x7C, 0xE7, 0x39, 0x04, 0x1E, 0x6A, 0x70, 0x20, 0xD2, 0x5A,
0x47, 0x72, 0x67, 0x55, 0xF4, 0xA5, 0xE8, 0x9D, 0xD5, 0x1E, 0x21, 0xA1,
0xF0, 0x67, 0xBA, 0xCC, 0x21, 0x68, 0xBE, 0x44, 0x53, 0xBF, 0x8D, 0xF9,
0xE2, 0xDC, 0x2F, 0x55, 0xC8, 0x37, 0x3F, 0x1F, 0xA4, 0xC0, 0x9C, 0xB3,
0xE4, 0x77, 0x5C, 0xA0, 0x46, 0xFE, 0x77, 0xFA, 0x1A, 0xA0, 0x38, 0xEA,
0xED, 0x9A, 0x72, 0xDE, 0x2B, 0xBD, 0x94, 0x57, 0x3A, 0xBA, 0xEC, 0x79,
0xE7, 0x5F, 0x7D, 0x42, 0x64, 0x39, 0x7A, 0x26, 0x36, 0xF7, 0x24, 0xF0,
0xD5, 0x2F, 0xBA, 0x95, 0x98, 0x11, 0x66, 0xAD, 0x97, 0x35, 0xD6, 0x75,
0x01, 0x80, 0xE0, 0xAF, 0xF4, 0x84, 0x61, 0x8C, 0x0D, 0x1E, 0x5F, 0x7C,
0x87, 0x96, 0x5E, 0x41, 0xAF, 0xEB, 0x87, 0xEA, 0xF8, 0x5D, 0xF1, 0x2E,
0x88, 0x05, 0x3E, 0x4C, 0x22, 0xBB, 0xDA, 0x1F, 0x2A, 0xDD, 0x52, 0x46,
0x64, 0x39, 0xF3, 0x42, 0xCE, 0xD9, 0x9E, 0x0C, 0xB3, 0xB0, 0x77, 0x97,
0x64, 0x9C, 0xC0, 0xF4, 0xA3, 0x2E, 0x1F, 0x95, 0x07, 0xB0, 0x17, 0xDF,
0x30, 0xDB, 0x00, 0x18, 0x96, 0x4C, 0xA1, 0x81, 0x4B, 0xDD, 0x04, 0x6D,
0x53, 0xA3, 0x3D, 0xFC, 0x07, 0xAC, 0xD4, 0xC5, 0x37, 0x82, 0xEB, 0xE4,
0x95, 0x08, 0x19, 0x28, 0x82, 0xD2, 0x42, 0x3A, 0xA3, 0xD8, 0x53, 0xEC,
0x79, 0x89, 0x60, 0x48, 0x60, 0xC8, 0x72, 0x92, 0x50, 0xDC, 0x03, 0x8F,
0x83, 0x3F, 0xB2, 0x42, 0x57, 0x5A, 0xDB, 0x6A, 0xE9, 0x11, 0x97, 0xDD,
0x85, 0x28, 0xBC, 0x30, 0x4C, 0xAB, 0xE3, 0xC2, 0xB1, 0x45, 0x44, 0x47,
0x1F, 0xE0, 0x8A, 0x16, 0x07, 0x96, 0xD2, 0x21, 0x0F, 0x53, 0xC0, 0xED,
0xA9, 0x7E, 0xD4, 0x4E, 0xEC, 0x9B, 0x09, 0xEC, 0xAF, 0x42, 0xAC, 0x30,
0xD6, 0xBF, 0xD1, 0x10, 0x45, 0xE0, 0xA6, 0x16, 0xB2, 0xA5, 0xC5, 0xD3,
0x4F, 0x73, 0x94, 0x33, 0x71, 0x02, 0xA1, 0x6A, 0xA3, 0xD6, 0x33, 0x97,
0x4F, 0x21, 0x63, 0x1E, 0x5B, 0x8F, 0xD9, 0xC1, 0x5E, 0x45, 0x71, 0x77,
0x0F, 0x81, 0x5D, 0x5F, 0x21, 0x9A, 0xAD, 0x83, 0xCC, 0xFA, 0x5E, 0xD6,
0x8D, 0x23, 0x5F, 0x1B, 0x3D, 0x41, 0xAF, 0x20, 0x75, 0x66, 0x5A, 0x4A,
0xF6, 0x9F, 0xFB, 0xAB, 0x18, 0xF7, 0x71, 0xC0, 0xB6, 0x1D, 0x31, 0xEC,
0x3B, 0x20, 0xEB, 0xCB, 0xE2, 0xB8, 0xF5, 0xAE, 0x92, 0xB2, 0xF7, 0xE1,
0x84, 0x4B, 0xF2, 0xA2, 0xF2, 0x93, 0x9A, 0x22, 0x9E, 0xD3, 0x14, 0x6F,
0x36, 0x54, 0xBD, 0x1F, 0x5E, 0x59, 0x15, 0xB9, 0x73, 0xA8, 0xC1, 0x7C,
0x6F, 0x7B, 0x62, 0xE9, 0x16, 0x6C, 0x47, 0x5A, 0x65, 0xF3, 0x0E, 0x11,
0x9B, 0x46, 0xD9, 0xFD, 0x6D, 0xDC, 0xD6, 0x9C, 0xC0, 0xB4, 0x7D, 0xA5,
0xB0, 0xDD, 0x3F, 0x56, 0x6F, 0xA1, 0xF9, 0xF6, 0xE4, 0x12, 0x48, 0xFD,
0x06, 0x7F, 0x12, 0x57, 0xB6, 0xA9, 0x23, 0x4F, 0x5B, 0x03, 0xC3, 0xE0,
0x71, 0x2A, 0x23, 0xB7, 0xF7, 0xB0, 0xB1, 0x3B, 0xBC, 0x98, 0xBD, 0xD6,
0x98, 0xA8, 0x0C, 0x6B, 0xF6, 0x8E, 0x12, 0x67, 0xA6, 0xF2, 0xB2, 0x58,
0xE4, 0x02, 0x09, 0x13, 0x3C, 0xA9, 0xBB, 0x10, 0xB4, 0xD2, 0x30, 0x45,
0xF1, 0xEC, 0xF7, 0x00, 0x11, 0xDF, 0x65, 0xF8, 0xDC, 0x2B, 0x43, 0x55,
0xBF, 0x16, 0x97, 0xC4, 0x0F, 0xD5, 0x2C, 0x61, 0x84, 0xAA, 0x72, 0x86,
0xFE, 0xE6, 0x3A, 0x7E, 0xC2, 0x3F, 0x7D, 0xEE, 0xFC, 0x2F, 0x14, 0x3E,
0xE6, 0x85, 0xDD, 0x50, 0x6F, 0xB7, 0x49, 0xED
};
static const unsigned char TA113_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA114_DN[] = {
0x30, 0x50, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
0x1B, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E, 0x20,
0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20,
0x2D, 0x20, 0x52, 0x34, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
0x0A, 0x13, 0x0A, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67,
0x6E, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0A,
0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x53, 0x69, 0x67, 0x6E
};
static const unsigned char TA114_EC_Q[] = {
0x04, 0xB8, 0xC6, 0x79, 0xD3, 0x8F, 0x6C, 0x25, 0x0E, 0x9F, 0x2E, 0x39,
0x19, 0x1C, 0x03, 0xA4, 0xAE, 0x9A, 0xE5, 0x39, 0x07, 0x09, 0x16, 0xCA,
0x63, 0xB1, 0xB9, 0x86, 0xF8, 0x8A, 0x57, 0xC1, 0x57, 0xCE, 0x42, 0xFA,
0x73, 0xA1, 0xF7, 0x65, 0x42, 0xFF, 0x1E, 0xC1, 0x00, 0xB2, 0x6E, 0x73,
0x0E, 0xFF, 0xC7, 0x21, 0xE5, 0x18, 0xA4, 0xAA, 0xD9, 0x71, 0x3F, 0xA8,
0xD4, 0xB9, 0xCE, 0x8C, 0x1D
};
static const unsigned char TA115_DN[] = {
0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20,
0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52,
0x31
};
static const unsigned char TA115_RSA_N[] = {
0xB6, 0x11, 0x02, 0x8B, 0x1E, 0xE3, 0xA1, 0x77, 0x9B, 0x3B, 0xDC, 0xBF,
0x94, 0x3E, 0xB7, 0x95, 0xA7, 0x40, 0x3C, 0xA1, 0xFD, 0x82, 0xF9, 0x7D,
0x32, 0x06, 0x82, 0x71, 0xF6, 0xF6, 0x8C, 0x7F, 0xFB, 0xE8, 0xDB, 0xBC,
0x6A, 0x2E, 0x97, 0x97, 0xA3, 0x8C, 0x4B, 0xF9, 0x2B, 0xF6, 0xB1, 0xF9,
0xCE, 0x84, 0x1D, 0xB1, 0xF9, 0xC5, 0x97, 0xDE, 0xEF, 0xB9, 0xF2, 0xA3,
0xE9, 0xBC, 0x12, 0x89, 0x5E, 0xA7, 0xAA, 0x52, 0xAB, 0xF8, 0x23, 0x27,
0xCB, 0xA4, 0xB1, 0x9C, 0x63, 0xDB, 0xD7, 0x99, 0x7E, 0xF0, 0x0A, 0x5E,
0xEB, 0x68, 0xA6, 0xF4, 0xC6, 0x5A, 0x47, 0x0D, 0x4D, 0x10, 0x33, 0xE3,
0x4E, 0xB1, 0x13, 0xA3, 0xC8, 0x18, 0x6C, 0x4B, 0xEC, 0xFC, 0x09, 0x90,
0xDF, 0x9D, 0x64, 0x29, 0x25, 0x23, 0x07, 0xA1, 0xB4, 0xD2, 0x3D, 0x2E,
0x60, 0xE0, 0xCF, 0xD2, 0x09, 0x87, 0xBB, 0xCD, 0x48, 0xF0, 0x4D, 0xC2,
0xC2, 0x7A, 0x88, 0x8A, 0xBB, 0xBA, 0xCF, 0x59, 0x19, 0xD6, 0xAF, 0x8F,
0xB0, 0x07, 0xB0, 0x9E, 0x31, 0xF1, 0x82, 0xC1, 0xC0, 0xDF, 0x2E, 0xA6,
0x6D, 0x6C, 0x19, 0x0E, 0xB5, 0xD8, 0x7E, 0x26, 0x1A, 0x45, 0x03, 0x3D,
0xB0, 0x79, 0xA4, 0x94, 0x28, 0xAD, 0x0F, 0x7F, 0x26, 0xE5, 0xA8, 0x08,
0xFE, 0x96, 0xE8, 0x3C, 0x68, 0x94, 0x53, 0xEE, 0x83, 0x3A, 0x88, 0x2B,
0x15, 0x96, 0x09, 0xB2, 0xE0, 0x7A, 0x8C, 0x2E, 0x75, 0xD6, 0x9C, 0xEB,
0xA7, 0x56, 0x64, 0x8F, 0x96, 0x4F, 0x68, 0xAE, 0x3D, 0x97, 0xC2, 0x84,
0x8F, 0xC0, 0xBC, 0x40, 0xC0, 0x0B, 0x5C, 0xBD, 0xF6, 0x87, 0xB3, 0x35,
0x6C, 0xAC, 0x18, 0x50, 0x7F, 0x84, 0xE0, 0x4C, 0xCD, 0x92, 0xD3, 0x20,
0xE9, 0x33, 0xBC, 0x52, 0x99, 0xAF, 0x32, 0xB5, 0x29, 0xB3, 0x25, 0x2A,
0xB4, 0x48, 0xF9, 0x72, 0xE1, 0xCA, 0x64, 0xF7, 0xE6, 0x82, 0x10, 0x8D,
0xE8, 0x9D, 0xC2, 0x8A, 0x88, 0xFA, 0x38, 0x66, 0x8A, 0xFC, 0x63, 0xF9,
0x01, 0xF9, 0x78, 0xFD, 0x7B, 0x5C, 0x77, 0xFA, 0x76, 0x87, 0xFA, 0xEC,
0xDF, 0xB1, 0x0E, 0x79, 0x95, 0x57, 0xB4, 0xBD, 0x26, 0xEF, 0xD6, 0x01,
0xD1, 0xEB, 0x16, 0x0A, 0xBB, 0x8E, 0x0B, 0xB5, 0xC5, 0xC5, 0x8A, 0x55,
0xAB, 0xD3, 0xAC, 0xEA, 0x91, 0x4B, 0x29, 0xCC, 0x19, 0xA4, 0x32, 0x25,
0x4E, 0x2A, 0xF1, 0x65, 0x44, 0xD0, 0x02, 0xCE, 0xAA, 0xCE, 0x49, 0xB4,
0xEA, 0x9F, 0x7C, 0x83, 0xB0, 0x40, 0x7B, 0xE7, 0x43, 0xAB, 0xA7, 0x6C,
0xA3, 0x8F, 0x7D, 0x89, 0x81, 0xFA, 0x4C, 0xA5, 0xFF, 0xD5, 0x8E, 0xC3,
0xCE, 0x4B, 0xE0, 0xB5, 0xD8, 0xB3, 0x8E, 0x45, 0xCF, 0x76, 0xC0, 0xED,
0x40, 0x2B, 0xFD, 0x53, 0x0F, 0xB0, 0xA7, 0xD5, 0x3B, 0x0D, 0xB1, 0x8A,
0xA2, 0x03, 0xDE, 0x31, 0xAD, 0xCC, 0x77, 0xEA, 0x6F, 0x7B, 0x3E, 0xD6,
0xDF, 0x91, 0x22, 0x12, 0xE6, 0xBE, 0xFA, 0xD8, 0x32, 0xFC, 0x10, 0x63,
0x14, 0x51, 0x72, 0xDE, 0x5D, 0xD6, 0x16, 0x93, 0xBD, 0x29, 0x68, 0x33,
0xEF, 0x3A, 0x66, 0xEC, 0x07, 0x8A, 0x26, 0xDF, 0x13, 0xD7, 0x57, 0x65,
0x78, 0x27, 0xDE, 0x5E, 0x49, 0x14, 0x00, 0xA2, 0x00, 0x7F, 0x9A, 0xA8,
0x21, 0xB6, 0xA9, 0xB1, 0x95, 0xB0, 0xA5, 0xB9, 0x0D, 0x16, 0x11, 0xDA,
0xC7, 0x6C, 0x48, 0x3C, 0x40, 0xE0, 0x7E, 0x0D, 0x5A, 0xCD, 0x56, 0x3C,
0xD1, 0x97, 0x05, 0xB9, 0xCB, 0x4B, 0xED, 0x39, 0x4B, 0x9C, 0xC4, 0x3F,
0xD2, 0x55, 0x13, 0x6E, 0x24, 0xB0, 0xD6, 0x71, 0xFA, 0xF4, 0xC1, 0xBA,
0xCC, 0xED, 0x1B, 0xF5, 0xFE, 0x81, 0x41, 0xD8, 0x00, 0x98, 0x3D, 0x3A,
0xC8, 0xAE, 0x7A, 0x98, 0x37, 0x18, 0x05, 0x95
};
static const unsigned char TA115_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA116_DN[] = {
0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20,
0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52,
0x32
};
static const unsigned char TA116_RSA_N[] = {
0xCE, 0xDE, 0xFD, 0xA6, 0xFB, 0xEC, 0xEC, 0x14, 0x34, 0x3C, 0x07, 0x06,
0x5A, 0x6C, 0x59, 0xF7, 0x19, 0x35, 0xDD, 0xF7, 0xC1, 0x9D, 0x55, 0xAA,
0xD3, 0xCD, 0x3B, 0xA4, 0x93, 0x72, 0xEF, 0x0A, 0xFA, 0x6D, 0x9D, 0xF6,
0xF0, 0x85, 0x80, 0x5B, 0xA1, 0x48, 0x52, 0x9F, 0x39, 0xC5, 0xB7, 0xEE,
0x28, 0xAC, 0xEF, 0xCB, 0x76, 0x68, 0x14, 0xB9, 0xDF, 0xAD, 0x01, 0x6C,
0x99, 0x1F, 0xC4, 0x22, 0x1D, 0x9F, 0xFE, 0x72, 0x77, 0xE0, 0x2C, 0x5B,
0xAF, 0xE4, 0x04, 0xBF, 0x4F, 0x72, 0xA0, 0x1A, 0x34, 0x98, 0xE8, 0x39,
0x68, 0xEC, 0x95, 0x25, 0x7B, 0x76, 0xA1, 0xE6, 0x69, 0xB9, 0x85, 0x19,
0xBD, 0x89, 0x8C, 0xFE, 0xAD, 0xED, 0x36, 0xEA, 0x73, 0xBC, 0xFF, 0x83,
0xE2, 0xCB, 0x7D, 0xC1, 0xD2, 0xCE, 0x4A, 0xB3, 0x8D, 0x05, 0x9E, 0x8B,
0x49, 0x93, 0xDF, 0xC1, 0x5B, 0xD0, 0x6E, 0x5E, 0xF0, 0x2E, 0x30, 0x2E,
0x82, 0xFC, 0xFA, 0xBC, 0xB4, 0x17, 0x0A, 0x48, 0xE5, 0x88, 0x9B, 0xC5,
0x9B, 0x6B, 0xDE, 0xB0, 0xCA, 0xB4, 0x03, 0xF0, 0xDA, 0xF4, 0x90, 0xB8,
0x65, 0x64, 0xF7, 0x5C, 0x4C, 0xAD, 0xE8, 0x7E, 0x66, 0x5E, 0x99, 0xD7,
0xB8, 0xC2, 0x3E, 0xC8, 0xD0, 0x13, 0x9D, 0xAD, 0xEE, 0xE4, 0x45, 0x7B,
0x89, 0x55, 0xF7, 0x8A, 0x1F, 0x62, 0x52, 0x84, 0x12, 0xB3, 0xC2, 0x40,
0x97, 0xE3, 0x8A, 0x1F, 0x47, 0x91, 0xA6, 0x74, 0x5A, 0xD2, 0xF8, 0xB1,
0x63, 0x28, 0x10, 0xB8, 0xB3, 0x09, 0xB8, 0x56, 0x77, 0x40, 0xA2, 0x26,
0x98, 0x79, 0xC6, 0xFE, 0xDF, 0x25, 0xEE, 0x3E, 0xE5, 0xA0, 0x7F, 0xD4,
0x61, 0x0F, 0x51, 0x4B, 0x3C, 0x3F, 0x8C, 0xDA, 0xE1, 0x70, 0x74, 0xD8,
0xC2, 0x68, 0xA1, 0xF9, 0xC1, 0x0C, 0xE9, 0xA1, 0xE2, 0x7F, 0xBB, 0x55,
0x3C, 0x76, 0x06, 0xEE, 0x6A, 0x4E, 0xCC, 0x92, 0x88, 0x30, 0x4D, 0x9A,
0xBD, 0x4F, 0x0B, 0x48, 0x9A, 0x84, 0xB5, 0x98, 0xA3, 0xD5, 0xFB, 0x73,
0xC1, 0x57, 0x61, 0xDD, 0x28, 0x56, 0x75, 0x13, 0xAE, 0x87, 0x8E, 0xE7,
0x0C, 0x51, 0x09, 0x10, 0x75, 0x88, 0x4C, 0xBC, 0x8D, 0xF9, 0x7B, 0x3C,
0xD4, 0x22, 0x48, 0x1F, 0x2A, 0xDC, 0xEB, 0x6B, 0xBB, 0x44, 0xB1, 0xCB,
0x33, 0x71, 0x32, 0x46, 0xAF, 0xAD, 0x4A, 0xF1, 0x8C, 0xE8, 0x74, 0x3A,
0xAC, 0xE7, 0x1A, 0x22, 0x73, 0x80, 0xD2, 0x30, 0xF7, 0x25, 0x42, 0xC7,
0x22, 0x3B, 0x3B, 0x12, 0xAD, 0x96, 0x2E, 0xC6, 0xC3, 0x76, 0x07, 0xAA,
0x20, 0xB7, 0x35, 0x49, 0x57, 0xE9, 0x92, 0x49, 0xE8, 0x76, 0x16, 0x72,
0x31, 0x67, 0x2B, 0x96, 0x7E, 0x8A, 0xA3, 0xC7, 0x94, 0x56, 0x22, 0xBF,
0x6A, 0x4B, 0x7E, 0x01, 0x21, 0xB2, 0x23, 0x32, 0xDF, 0xE4, 0x9A, 0x44,
0x6D, 0x59, 0x5B, 0x5D, 0xF5, 0x00, 0xA0, 0x1C, 0x9B, 0xC6, 0x78, 0x97,
0x8D, 0x90, 0xFF, 0x9B, 0xC8, 0xAA, 0xB4, 0xAF, 0x11, 0x51, 0x39, 0x5E,
0xD9, 0xFB, 0x67, 0xAD, 0xD5, 0x5B, 0x11, 0x9D, 0x32, 0x9A, 0x1B, 0xBD,
0xD5, 0xBA, 0x5B, 0xA5, 0xC9, 0xCB, 0x25, 0x69, 0x53, 0x55, 0x27, 0x5C,
0xE0, 0xCA, 0x36, 0xCB, 0x88, 0x61, 0xFB, 0x1E, 0xB7, 0xD0, 0xCB, 0xEE,
0x16, 0xFB, 0xD3, 0xA6, 0x4C, 0xDE, 0x92, 0xA5, 0xD4, 0xE2, 0xDF, 0xF5,
0x06, 0x54, 0xDE, 0x2E, 0x9D, 0x4B, 0xB4, 0x93, 0x30, 0xAA, 0x81, 0xCE,
0xDD, 0x1A, 0xDC, 0x51, 0x73, 0x0D, 0x4F, 0x70, 0xE9, 0xE5, 0xB6, 0x16,
0x21, 0x19, 0x79, 0xB2, 0xE6, 0x89, 0x0B, 0x75, 0x64, 0xCA, 0xD5, 0xAB,
0xBC, 0x09, 0xC1, 0x18, 0xA1, 0xFF, 0xD4, 0x54, 0xA1, 0x85, 0x3C, 0xFD,
0x14, 0x24, 0x03, 0xB2, 0x87, 0xD3, 0xA4, 0xB7
};
static const unsigned char TA116_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA117_DN[] = {
0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20,
0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52,
0x33
};
static const unsigned char TA117_EC_Q[] = {
0x04, 0x1F, 0x4F, 0x33, 0x87, 0x33, 0x29, 0x8A, 0xA1, 0x84, 0xDE, 0xCB,
0xC7, 0x21, 0x58, 0x41, 0x89, 0xEA, 0x56, 0x9D, 0x2B, 0x4B, 0x85, 0xC6,
0x1D, 0x4C, 0x27, 0xBC, 0x7F, 0x26, 0x51, 0x72, 0x6F, 0xE2, 0x9F, 0xD6,
0xA3, 0xCA, 0xCC, 0x45, 0x14, 0x46, 0x8B, 0xAD, 0xEF, 0x7E, 0x86, 0x8C,
0xEC, 0xB1, 0x7E, 0x2F, 0xFF, 0xA9, 0x71, 0x9D, 0x18, 0x84, 0x45, 0x04,
0x41, 0x55, 0x6E, 0x2B, 0xEA, 0x26, 0x7F, 0xBB, 0x90, 0x01, 0xE3, 0x4B,
0x19, 0xBA, 0xE4, 0x54, 0x96, 0x45, 0x09, 0xB1, 0xD5, 0x6C, 0x91, 0x44,
0xAD, 0x84, 0x13, 0x8E, 0x9A, 0x8C, 0x0D, 0x80, 0x0C, 0x32, 0xF6, 0xE0,
0x27
};
static const unsigned char TA118_DN[] = {
0x30, 0x47, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x19, 0x47, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x54, 0x72, 0x75,
0x73, 0x74, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20,
0x4C, 0x4C, 0x43, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x0B, 0x47, 0x54, 0x53, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52,
0x34
};
static const unsigned char TA118_EC_Q[] = {
0x04, 0xF3, 0x74, 0x73, 0xA7, 0x68, 0x8B, 0x60, 0xAE, 0x43, 0xB8, 0x35,
0xC5, 0x81, 0x30, 0x7B, 0x4B, 0x49, 0x9D, 0xFB, 0xC1, 0x61, 0xCE, 0xE6,
0xDE, 0x46, 0xBD, 0x6B, 0xD5, 0x61, 0x18, 0x35, 0xAE, 0x40, 0xDD, 0x73,
0xF7, 0x89, 0x91, 0x30, 0x5A, 0xEB, 0x3C, 0xEE, 0x85, 0x7C, 0xA2, 0x40,
0x76, 0x3B, 0xA9, 0xC6, 0xB8, 0x47, 0xD8, 0x2A, 0xE7, 0x92, 0x91, 0x6A,
0x73, 0xE9, 0xB1, 0x72, 0x39, 0x9F, 0x29, 0x9F, 0xA2, 0x98, 0xD3, 0x5F,
0x5E, 0x58, 0x86, 0x65, 0x0F, 0xA1, 0x84, 0x65, 0x06, 0xD1, 0xDC, 0x8B,
0xC9, 0xC7, 0x73, 0xC8, 0x8C, 0x6A, 0x2F, 0xE5, 0xC4, 0xAB, 0xD1, 0x1D,
0x8A
};
static const unsigned char TA119_DN[] = {
0x30, 0x44, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x46, 0x49, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x11, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20, 0x46, 0x69, 0x6E, 0x6C,
0x61, 0x6E, 0x64, 0x20, 0x4F, 0x79, 0x6A, 0x31, 0x19, 0x30, 0x17, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x10, 0x54, 0x65, 0x6C, 0x69, 0x61, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x76, 0x32
};
static const unsigned char TA119_RSA_N[] = {
0xB2, 0xD0, 0x3F, 0x07, 0xBC, 0xE2, 0x7B, 0xD0, 0x6B, 0x99, 0xF8, 0xE2,
0x77, 0x69, 0xE7, 0xCE, 0x9D, 0xA4, 0x03, 0xBC, 0x82, 0x6D, 0xA1, 0xFE,
0x81, 0x65, 0x1F, 0x4C, 0x27, 0xAC, 0x8E, 0x00, 0xBA, 0x16, 0x7B, 0xEB,
0x30, 0x6A, 0x00, 0xC0, 0xB3, 0x74, 0x68, 0x7E, 0xB2, 0xAF, 0xC7, 0xD5,
0x62, 0xB3, 0x7A, 0x3F, 0x50, 0xCA, 0x8C, 0x36, 0x44, 0x24, 0x63, 0xD2,
0x36, 0xE9, 0x0C, 0x85, 0xF6, 0x43, 0x76, 0xD5, 0x4C, 0xA1, 0x60, 0x72,
0x67, 0xE2, 0x28, 0x33, 0xA5, 0xCB, 0x31, 0xB8, 0x3A, 0x22, 0x23, 0x34,
0xB8, 0x7D, 0xBD, 0x56, 0x22, 0x40, 0x9D, 0xEA, 0xF4, 0x7B, 0x03, 0xAD,
0x68, 0xFC, 0xB2, 0x81, 0x4F, 0x98, 0xD0, 0x74, 0xEA, 0x8D, 0xE5, 0x7D,
0xCD, 0x63, 0xC3, 0xA3, 0xF6, 0xDE, 0x92, 0xC2, 0x58, 0x19, 0xE0, 0x96,
0xBB, 0xC5, 0xC4, 0xA9, 0x3D, 0xA5, 0x74, 0x96, 0xFE, 0xAF, 0xF9, 0x89,
0xAA, 0xBD, 0x95, 0x17, 0x54, 0xD8, 0x78, 0x44, 0xF1, 0x0C, 0x77, 0x15,
0x92, 0xE0, 0x98, 0x42, 0xA7, 0xA4, 0xD6, 0xAA, 0x20, 0x92, 0xCD, 0xC1,
0xA0, 0xB3, 0x96, 0xB2, 0x3A, 0x84, 0x42, 0x8D, 0x7D, 0xD5, 0x95, 0xE4,
0xD6, 0xDB, 0xE9, 0x62, 0xC4, 0x58, 0xB3, 0x79, 0xC5, 0x8C, 0xD3, 0x35,
0x33, 0x83, 0x9F, 0x75, 0xA1, 0x52, 0x27, 0x61, 0x38, 0xF1, 0x59, 0x3D,
0x8E, 0x50, 0xE0, 0xBD, 0x79, 0x3C, 0xE7, 0x6C, 0x96, 0xFE, 0x5E, 0xD9,
0x02, 0x65, 0xB4, 0x8E, 0x5C, 0xD0, 0x11, 0x34, 0xDF, 0x5D, 0xBF, 0x52,
0xA7, 0x81, 0x00, 0xC3, 0x7F, 0x99, 0x45, 0x99, 0x15, 0xD5, 0x17, 0xC8,
0x0A, 0x53, 0xEC, 0x63, 0xF3, 0x99, 0x7D, 0xCC, 0x69, 0x12, 0x86, 0xC2,
0x17, 0xF0, 0x01, 0x9E, 0xBF, 0x84, 0xBC, 0xD1, 0x52, 0xCB, 0x1B, 0x92,
0x66, 0xCE, 0xA4, 0x53, 0xE5, 0xA1, 0xBF, 0xC4, 0xDB, 0x09, 0xD6, 0xE6,
0x89, 0x56, 0x2B, 0xC8, 0xE3, 0x7C, 0xDE, 0xE3, 0xFF, 0x89, 0xE5, 0x35,
0x6E, 0x28, 0xE8, 0x6C, 0x0B, 0x23, 0x51, 0xA9, 0x25, 0x05, 0xEB, 0x48,
0xF8, 0xDD, 0xB1, 0xCA, 0xFA, 0x6C, 0x08, 0x51, 0xEF, 0xB7, 0x18, 0x6C,
0x44, 0xCA, 0x26, 0xE1, 0x73, 0xC6, 0x89, 0x06, 0x81, 0xE5, 0x8A, 0xAC,
0xB0, 0xE2, 0x29, 0xC6, 0xB9, 0x24, 0xB3, 0x6B, 0x44, 0x11, 0xF4, 0xA5,
0x43, 0xC2, 0x4C, 0x43, 0xE5, 0x70, 0x36, 0x8C, 0xB6, 0x33, 0x57, 0x7A,
0x95, 0x2E, 0x82, 0xA0, 0xF4, 0x5C, 0x10, 0xB3, 0x61, 0x83, 0xF6, 0x02,
0x05, 0x86, 0x2E, 0x7C, 0x2D, 0x6C, 0xDC, 0x03, 0x46, 0x6E, 0x35, 0x93,
0xD5, 0x7A, 0x95, 0x2F, 0xDE, 0x20, 0xD8, 0x5B, 0x7E, 0x94, 0x90, 0x04,
0x6A, 0xBA, 0x59, 0x3D, 0x04, 0x05, 0x75, 0x9D, 0x37, 0xA2, 0x0E, 0x2E,
0x3D, 0xEB, 0xC1, 0xA4, 0x52, 0x83, 0xFE, 0xD0, 0x6B, 0xD4, 0x66, 0x8E,
0xDC, 0xC6, 0xE9, 0x12, 0x4E, 0x1D, 0x2A, 0x57, 0xAA, 0x10, 0xBC, 0x7C,
0x5E, 0x82, 0x7D, 0xA6, 0xA6, 0xC9, 0xF2, 0x2D, 0xB9, 0xF5, 0x17, 0x27,
0xAD, 0xD1, 0x0E, 0x89, 0x54, 0x2B, 0x95, 0xFA, 0xC0, 0xAD, 0x1D, 0x98,
0x14, 0x78, 0x33, 0x42, 0x86, 0x0A, 0xA9, 0x73, 0xB5, 0xFB, 0x74, 0x0D,
0xB7, 0x1B, 0x30, 0x19, 0xC4, 0x5A, 0x0E, 0x1C, 0x27, 0xB7, 0xDA, 0x18,
0xD0, 0xFF, 0x8A, 0xC8, 0x05, 0xBA, 0xF1, 0xAA, 0x1C, 0xA2, 0x37, 0xB7,
0xE6, 0x48, 0xA4, 0x46, 0x2C, 0x94, 0xEA, 0xA8, 0x76, 0x62, 0x47, 0x8B,
0x10, 0x53, 0x07, 0x48, 0x57, 0x6C, 0xE2, 0x92, 0x4D, 0xB6, 0xAE, 0x05,
0xCB, 0xDC, 0xC1, 0x4A, 0x5E, 0x8F, 0xAC, 0x3D, 0x19, 0x4E, 0xC2, 0xED,
0x60, 0x75, 0x2B, 0xDB, 0xC1, 0xCA, 0x42, 0xD5
};
static const unsigned char TA119_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA120_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D,
0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30,
0x32, 0x30
};
static const unsigned char TA120_EC_Q[] = {
0x04, 0xC6, 0xCB, 0xC7, 0x28, 0xD1, 0xFB, 0x84, 0xF5, 0x9A, 0xEF, 0x42,
0x14, 0x20, 0xE1, 0x43, 0x6B, 0x6E, 0x75, 0xAD, 0xFC, 0x2B, 0x03, 0x84,
0xD4, 0x76, 0x93, 0x25, 0xD7, 0x59, 0x3B, 0x41, 0x65, 0x6B, 0x1E, 0xE6,
0x34, 0x2A, 0xBB, 0x74, 0xF6, 0x12, 0xCE, 0xE8, 0x6D, 0xE7, 0xAB, 0xE4,
0x3C, 0x4E, 0x3F, 0x44, 0x08, 0x8B, 0xCD, 0x16, 0x71, 0xCB, 0xBF, 0x92,
0x99, 0xF4, 0xA4, 0xD7, 0x3C, 0x50, 0x54, 0x52, 0x90, 0x85, 0x83, 0x78,
0x94, 0x67, 0x67, 0xA3, 0x1C, 0x09, 0x19, 0x3D, 0x75, 0x34, 0x85, 0xDE,
0xED, 0x60, 0x7D, 0xC7, 0x0C, 0xB4, 0x41, 0x52, 0xB9, 0x6E, 0xE5, 0xEE,
0x42
};
static const unsigned char TA121_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D,
0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x31, 0x20, 0x32, 0x30,
0x32, 0x30
};
static const unsigned char TA121_EC_Q[] = {
0x04, 0xF1, 0x0B, 0xDD, 0x86, 0x43, 0x20, 0x19, 0xDF, 0x97, 0x85, 0xE8,
0x22, 0x4A, 0x9B, 0xCF, 0x9D, 0x98, 0xBF, 0xB4, 0x05, 0x26, 0xC9, 0xCB,
0xE3, 0xA6, 0xD2, 0x8F, 0xC5, 0x9E, 0x78, 0x7B, 0x31, 0x89, 0xA9, 0x89,
0xAD, 0x27, 0x3C, 0x65, 0x10, 0x82, 0xFC, 0xDF, 0xC3, 0x9D, 0x4E, 0xF0,
0x33, 0x23, 0xC4, 0xD2, 0x32, 0xF5, 0x1C, 0xB0, 0xDF, 0x33, 0x17, 0x5D,
0xC5, 0xF0, 0xB1, 0x8A, 0xF9, 0xEF, 0xB9, 0xB7, 0x14, 0xCA, 0x29, 0x4A,
0xC2, 0x0F, 0xA9, 0x7F, 0x75, 0x65, 0x49, 0x2A, 0x30, 0x67, 0xF4, 0x64,
0xF7, 0xD6, 0x1A, 0x77, 0xDA, 0xC3, 0xC2, 0x97, 0x61, 0x42, 0x7B, 0x49,
0xAD
};
static const unsigned char TA122_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x1D, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20,
0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x50, 0x33, 0x38, 0x34,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35
};
static const unsigned char TA122_EC_Q[] = {
0x04, 0xC1, 0x44, 0xA1, 0xCF, 0x11, 0x97, 0x50, 0x9A, 0xDE, 0x23, 0x82,
0x35, 0x07, 0xCD, 0xD0, 0xCB, 0x18, 0x9D, 0xD2, 0xF1, 0x7F, 0x77, 0x35,
0x4F, 0x3B, 0xDD, 0x94, 0x72, 0x52, 0xED, 0xC2, 0x3B, 0xF8, 0xEC, 0xFA,
0x7B, 0x6B, 0x58, 0x20, 0xEC, 0x99, 0xAE, 0xC9, 0xFC, 0x68, 0xB3, 0x75,
0xB9, 0xDB, 0x09, 0xEC, 0xC8, 0x13, 0xF5, 0x4E, 0xC6, 0x0A, 0x1D, 0x66,
0x30, 0x4C, 0xBB, 0x1F, 0x47, 0x0A, 0x3C, 0x61, 0x10, 0x42, 0x29, 0x7C,
0xA5, 0x08, 0x0E, 0xE0, 0x22, 0xE9, 0xD3, 0x35, 0x68, 0xCE, 0x9B, 0x63,
0x9F, 0x84, 0xB5, 0x99, 0x4D, 0x58, 0xA0, 0x8E, 0xF5, 0x54, 0xE7, 0x95,
0xC9
};
static const unsigned char TA123_DN[] = {
0x30, 0x4D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0E, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x2C, 0x20,
0x49, 0x6E, 0x63, 0x2E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x1C, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20,
0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x34, 0x30, 0x39, 0x36, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x47, 0x35
};
static const unsigned char TA123_RSA_N[] = {
0xB3, 0xD0, 0xF4, 0xC9, 0x79, 0x11, 0x9D, 0xFD, 0xFC, 0x66, 0x81, 0xE7,
0xCC, 0xD5, 0xE4, 0xBC, 0xEC, 0x81, 0x3E, 0x6A, 0x35, 0x8E, 0x2E, 0xB7,
0xE7, 0xDE, 0xAF, 0xF9, 0x07, 0x4D, 0xCF, 0x30, 0x9D, 0xEA, 0x09, 0x0B,
0x99, 0xBD, 0x6C, 0x57, 0xDA, 0x18, 0x4A, 0xB8, 0x78, 0xAC, 0x3A, 0x39,
0xA8, 0xA6, 0x48, 0xAC, 0x2E, 0x72, 0xE5, 0xBD, 0xEB, 0xF1, 0x1A, 0xCD,
0xE7, 0xA4, 0x03, 0xA9, 0x3F, 0x11, 0xB4, 0xD8, 0x2F, 0x89, 0x16, 0xFB,
0x94, 0x01, 0x3D, 0xBB, 0x2F, 0xF8, 0x13, 0x05, 0xA1, 0x78, 0x1C, 0x8E,
0x28, 0xE0, 0x45, 0xE0, 0x83, 0xF4, 0x59, 0x1B, 0x95, 0xB3, 0xAE, 0x7E,
0x03, 0x45, 0xE5, 0xBE, 0xC2, 0x42, 0xFE, 0xEE, 0xF2, 0x3C, 0xB6, 0x85,
0x13, 0x98, 0x32, 0x9D, 0x16, 0xA8, 0x29, 0xC2, 0x0B, 0x1C, 0x38, 0xDC,
0x9F, 0x31, 0x77, 0x5C, 0xBF, 0x27, 0xA3, 0xFC, 0x27, 0xAC, 0xB7, 0x2B,
0xBD, 0x74, 0x9B, 0x17, 0x2D, 0xF2, 0x81, 0xDA, 0x5D, 0xB0, 0xE1, 0x23,
0x17, 0x3E, 0x88, 0x4A, 0x12, 0x23, 0xD0, 0xEA, 0xCF, 0x9D, 0xDE, 0x03,
0x17, 0xB1, 0x42, 0x4A, 0xA0, 0x16, 0x4C, 0xA4, 0x6D, 0x93, 0xE9, 0x3F,
0x3A, 0xEE, 0x3A, 0x7C, 0x9D, 0x58, 0x9D, 0xF4, 0x4E, 0x8F, 0xFC, 0x3B,
0x23, 0xC8, 0x6D, 0xB8, 0xE2, 0x05, 0xDA, 0xCC, 0xEB, 0xEC, 0xC3, 0x31,
0xF4, 0xD7, 0xA7, 0x29, 0x54, 0x80, 0xCF, 0x44, 0x5B, 0x4C, 0x6F, 0x30,
0x9E, 0xF3, 0xCC, 0xDD, 0x1F, 0x94, 0x43, 0x9D, 0x4D, 0x7F, 0x70, 0x70,
0x0D, 0xD4, 0x3A, 0xD1, 0x37, 0xF0, 0x6C, 0x9D, 0x9B, 0xC0, 0x14, 0x93,
0x58, 0xEF, 0xCD, 0x41, 0x38, 0x75, 0xBC, 0x13, 0x03, 0x95, 0x7C, 0x7F,
0xE3, 0x5C, 0xE9, 0xD5, 0x0D, 0xD5, 0xE2, 0x7C, 0x10, 0x62, 0xAA, 0x6B,
0xF0, 0x3D, 0x76, 0xF3, 0x3F, 0xA3, 0xE8, 0xB0, 0xC1, 0xFD, 0xEF, 0xAA,
0x57, 0x4D, 0xAC, 0x86, 0xA7, 0x18, 0xB4, 0x29, 0xC1, 0x2C, 0x0E, 0xBF,
0x64, 0xBE, 0x29, 0x8C, 0xD8, 0x02, 0x2D, 0xCD, 0x5C, 0x2F, 0xF2, 0x7F,
0xEF, 0x15, 0xF4, 0x0C, 0x15, 0xAC, 0x0A, 0xB0, 0xF1, 0xD3, 0x0D, 0x4F,
0x6A, 0x4D, 0x77, 0x97, 0x01, 0xA0, 0xF1, 0x66, 0xB7, 0xB7, 0xCE, 0xEF,
0xCE, 0xEC, 0xEC, 0xA5, 0x75, 0xCA, 0xAC, 0xE3, 0xE1, 0x63, 0xF7, 0xB8,
0xA1, 0x04, 0xC8, 0xBC, 0x7B, 0x3F, 0x5D, 0x2D, 0x16, 0x22, 0x56, 0xED,
0x48, 0x49, 0xFE, 0xA7, 0x2F, 0x79, 0x30, 0x25, 0x9B, 0xBA, 0x6B, 0x2D,
0x3F, 0x9D, 0x3B, 0xC4, 0x17, 0xE7, 0x1D, 0x2E, 0xFB, 0xF2, 0xCF, 0xA6,
0xFC, 0xE3, 0x14, 0x2C, 0x96, 0x98, 0x21, 0x8C, 0xB4, 0x91, 0xE9, 0x19,
0x60, 0x83, 0xF2, 0x30, 0x2B, 0x06, 0x73, 0x50, 0xD5, 0x98, 0x3B, 0x06,
0xE9, 0xC7, 0x8A, 0x0C, 0x60, 0x8C, 0x28, 0xF8, 0x52, 0x9B, 0x6E, 0xE1,
0xF6, 0x4D, 0xBB, 0x06, 0x24, 0x9B, 0xD7, 0x2B, 0x26, 0x3F, 0xFD, 0x2A,
0x2F, 0x71, 0xF5, 0xD6, 0x24, 0xBE, 0x7F, 0x31, 0x9E, 0x0F, 0x6D, 0xE8,
0x8F, 0x4F, 0x4D, 0xA3, 0x3F, 0xFF, 0x35, 0xEA, 0xDF, 0x49, 0x5E, 0x41,
0x8F, 0x86, 0xF9, 0xF1, 0x77, 0x79, 0x4B, 0x1B, 0xB4, 0xA3, 0x5E, 0x2F,
0xFB, 0x46, 0x02, 0xD0, 0x66, 0x13, 0x5E, 0x5E, 0x85, 0x4F, 0xCE, 0xD8,
0x70, 0x88, 0x7B, 0xCE, 0x01, 0xB5, 0x96, 0x97, 0xD7, 0xCD, 0x7D, 0xFD,
0x82, 0xF8, 0xC2, 0x24, 0xC1, 0xCA, 0x01, 0x39, 0x4F, 0x8D, 0xA2, 0xC1,
0x14, 0x40, 0x1F, 0x9C, 0x66, 0xD5, 0x0C, 0x09, 0x46, 0xD6, 0xF2, 0xD0,
0xD1, 0x48, 0x76, 0x56, 0x3A, 0x43, 0xCB, 0xB6, 0x0A, 0x11, 0x39, 0xBA,
0x8C, 0x13, 0x6C, 0x06, 0xB5, 0x9E, 0xCF, 0xEB
};
static const unsigned char TA123_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA124_DN[] = {
0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31,
0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65,
0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x52, 0x31
};
static const unsigned char TA124_RSA_N[] = {
0xD0, 0x36, 0xD4, 0x1F, 0xEA, 0xDD, 0xAB, 0xE4, 0xD1, 0xB6, 0xE6, 0xFB,
0x22, 0xC0, 0xDD, 0x13, 0x0D, 0x6A, 0x7B, 0x22, 0x13, 0x1C, 0x97, 0x3C,
0x68, 0x63, 0x66, 0x32, 0x9C, 0x03, 0xB5, 0x8D, 0xA4, 0x81, 0x83, 0xDA,
0x78, 0x30, 0x11, 0xCF, 0xDC, 0xB2, 0x2B, 0xBE, 0x92, 0xBF, 0x8E, 0xE4,
0xC4, 0x13, 0xBE, 0xA4, 0x68, 0x4C, 0xDA, 0x02, 0x68, 0x16, 0x74, 0xBE,
0xB2, 0xDD, 0x04, 0xE4, 0x6B, 0x2A, 0xDD, 0x37, 0x1F, 0x60, 0x2C, 0xDB,
0xF5, 0xF7, 0xA1, 0x7C, 0x95, 0xB7, 0x0C, 0x70, 0x86, 0x2E, 0xF1, 0x3A,
0xEF, 0x52, 0xF7, 0xCC, 0xD3, 0x9B, 0xF9, 0x8B, 0xBE, 0x0E, 0xDF, 0x31,
0xB7, 0x9D, 0x68, 0x5C, 0x92, 0xA6, 0xF5, 0xE5, 0xF3, 0x0A, 0x34, 0xB5,
0xFF, 0x7B, 0xA2, 0xE4, 0x87, 0xA1, 0xC6, 0xAF, 0x17, 0x00, 0xEF, 0x03,
0x91, 0xED, 0xA9, 0x1C, 0x4E, 0x71, 0x3D, 0xD2, 0x8B, 0x6C, 0x89, 0xF4,
0x78, 0x86, 0xE6, 0x6A, 0x49, 0xA0, 0xCE, 0xB5, 0xD2, 0xB0, 0xAB, 0x9B,
0xF6, 0xF4, 0xD4, 0x2E, 0xE3, 0x72, 0xF9, 0x36, 0xC6, 0xEB, 0x15, 0xB7,
0x25, 0x8C, 0x3A, 0xFC, 0x25, 0x0D, 0xB3, 0x22, 0x73, 0x21, 0x74, 0xC8,
0x4A, 0x96, 0x61, 0x92, 0xF5, 0x2F, 0x0B, 0x18, 0xA5, 0xF4, 0xAD, 0xE2,
0xEE, 0x41, 0xBD, 0x01, 0x79, 0xFA, 0x96, 0x8C, 0x8D, 0x17, 0x02, 0x30,
0xB4, 0xF9, 0xAF, 0x78, 0x1A, 0x8C, 0xB4, 0x36, 0x10, 0x10, 0x07, 0x05,
0x70, 0xD0, 0xF4, 0x31, 0x90, 0x8A, 0x51, 0xC5, 0x86, 0x26, 0x79, 0xB2,
0x11, 0x88, 0x5E, 0xC5, 0xF0, 0x0A, 0x54, 0xCD, 0x49, 0xA6, 0xBF, 0x02,
0x9C, 0xD2, 0x44, 0xA7, 0xED, 0xE3, 0x78, 0xEF, 0x46, 0x5E, 0x6D, 0x71,
0xD1, 0x79, 0x70, 0x1C, 0x46, 0x5F, 0x51, 0xE9, 0xC9, 0x37, 0xDC, 0x5F,
0x7E, 0x69, 0x7B, 0x41, 0xDF, 0x34, 0x45, 0xE0, 0x3B, 0x84, 0xF4, 0xA1,
0x8A, 0x0A, 0x36, 0x9E, 0x37, 0xCC, 0x62, 0x52, 0xE1, 0x89, 0x0D, 0x28,
0xF9, 0x7A, 0x23, 0xB1, 0x0D, 0x3D, 0x3D, 0x9A, 0xFD, 0x9D, 0x81, 0xEF,
0x2C, 0x90, 0xC0, 0x7B, 0x44, 0x4E, 0xBB, 0x49, 0xE0, 0x0E, 0x4A, 0x56,
0x92, 0xBC, 0xCB, 0xB5, 0xDD, 0x79, 0x17, 0x89, 0x91, 0xDE, 0x61, 0x89,
0x74, 0x92, 0xA8, 0xE3, 0x32, 0x85, 0xBE, 0x4E, 0x85, 0xA4, 0x4B, 0x59,
0xCB, 0x2B, 0xC5, 0x78, 0x8E, 0x71, 0x54, 0xD0, 0x02, 0x37, 0x99, 0x8C,
0xE5, 0x49, 0xEA, 0xE0, 0x54, 0x72, 0xA4, 0x11, 0x06, 0x2F, 0x0B, 0x8C,
0xC1, 0x5B, 0xBE, 0xB5, 0xA1, 0xB0, 0x53, 0x6E, 0x9C, 0xB8, 0x60, 0x91,
0x1F, 0x59, 0x6B, 0xF9, 0x2D, 0xF4, 0x94, 0x0A, 0x97, 0xB5, 0xEC, 0xC5,
0x76, 0x03, 0x54, 0x1B, 0x65, 0x52, 0xBA, 0x4C, 0x92, 0x56, 0x51, 0x35,
0xA0, 0x40, 0xD8, 0x29, 0xDB, 0xAE, 0x52, 0x76, 0x3B, 0x2D, 0x30, 0x40,
0x9B, 0x8A, 0xD0, 0x42, 0x56, 0xB4, 0xB7, 0x88, 0x01, 0xA4, 0x87, 0x3B,
0x53, 0x96, 0xCD, 0xA3, 0x16, 0x8F, 0xF3, 0x66, 0xAA, 0x17, 0xB1, 0xC7,
0x60, 0xE0, 0xC1, 0x43, 0x05, 0x0C, 0xEE, 0x9B, 0x5B, 0x60, 0x6F, 0x06,
0x5C, 0x87, 0x5B, 0x27, 0xF9, 0x40, 0x11, 0x9E, 0x9C, 0x33, 0xC1, 0xB7,
0xE5, 0x35, 0x57, 0x05, 0x7F, 0x27, 0xCE, 0x17, 0x20, 0x8C, 0x1C, 0xFC,
0xF1, 0xFB, 0xDA, 0x31, 0x29, 0x49, 0xED, 0xF5, 0x0B, 0x84, 0xA7, 0x4F,
0xC1, 0xF6, 0x4E, 0xC2, 0x28, 0x9C, 0xFA, 0xEE, 0xE0, 0xAF, 0x07, 0xFB,
0x33, 0x11, 0x7A, 0x21, 0x4F, 0x0B, 0x21, 0x10, 0xB6, 0x40, 0x3A, 0xAB,
0x22, 0x3A, 0x04, 0x9C, 0x8B, 0x9B, 0x84, 0x86, 0x72, 0x9A, 0xD2, 0xA7,
0xA5, 0xC4, 0xB4, 0x75, 0x91, 0xA9, 0x2B, 0x23
};
static const unsigned char TA124_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA125_DN[] = {
0x30, 0x3D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x43, 0x65, 0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x31,
0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x43, 0x65,
0x72, 0x74, 0x61, 0x69, 0x6E, 0x6C, 0x79, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x45, 0x31
};
static const unsigned char TA125_EC_Q[] = {
0x04, 0xDE, 0x6F, 0xF8, 0x7F, 0x1C, 0xDF, 0xED, 0xF9, 0x47, 0x87, 0x86,
0xB1, 0xA4, 0xC0, 0x8A, 0xF8, 0x82, 0x97, 0x80, 0xEA, 0x8F, 0xC8, 0x4A,
0x5E, 0x2A, 0x7D, 0x88, 0x68, 0xA7, 0x01, 0x62, 0x14, 0x91, 0x24, 0x7A,
0x5C, 0x9E, 0xA3, 0x17, 0x7D, 0x8A, 0x86, 0x21, 0x34, 0x18, 0x50, 0x1B,
0x10, 0xDE, 0xD0, 0x37, 0x4B, 0x26, 0xC7, 0x19, 0x60, 0x80, 0xE9, 0x34,
0xBD, 0x60, 0x19, 0x36, 0x40, 0xD6, 0x29, 0x87, 0x09, 0x3C, 0x91, 0x7A,
0xF6, 0xBC, 0x13, 0x23, 0xDD, 0x59, 0x4E, 0x04, 0x5E, 0xCF, 0xC8, 0x02,
0x1C, 0x18, 0x53, 0xC1, 0x31, 0xD8, 0xDA, 0x20, 0xE9, 0x44, 0x8D, 0xE4,
0x76
};
static const unsigned char TA126_DN[] = {
0x30, 0x61, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4A, 0x50, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1C, 0x53, 0x45, 0x43, 0x4F, 0x4D, 0x20, 0x54, 0x72, 0x75, 0x73,
0x74, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73, 0x20, 0x43, 0x4F,
0x2E, 0x2C, 0x4C, 0x54, 0x44, 0x2E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03,
0x55, 0x04, 0x03, 0x13, 0x22, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x75, 0x6E, 0x69, 0x63, 0x61, 0x74,
0x69, 0x6F, 0x6E, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x43, 0x41, 0x31
};
static const unsigned char TA126_EC_Q[] = {
0x04, 0xA4, 0xA5, 0x6F, 0x60, 0x03, 0x03, 0xC3, 0xBD, 0x31, 0xF4, 0xD3,
0x17, 0x9C, 0x2B, 0x84, 0x75, 0xAC, 0xE5, 0xFD, 0x3D, 0x57, 0x6E, 0xD7,
0x63, 0xBF, 0xE6, 0x04, 0x89, 0x92, 0x8E, 0x81, 0x9C, 0xE3, 0xE9, 0x47,
0x6E, 0xCA, 0x90, 0x12, 0xC8, 0x13, 0xE0, 0xA7, 0x9D, 0xF7, 0x65, 0x74,
0x1F, 0x6C, 0x10, 0xB2, 0xE8, 0xE4, 0xE9, 0xEF, 0x6D, 0x85, 0x32, 0x99,
0x44, 0xB1, 0x5E, 0xFD, 0xCC, 0x76, 0x10, 0xD8, 0x5B, 0xBD, 0xA2, 0xC6,
0xF9, 0xD6, 0x42, 0xE4, 0x57, 0x76, 0xDC, 0x90, 0xC2, 0x35, 0xA9, 0x4B,
0x88, 0x3C, 0x12, 0x47, 0x6D, 0x5C, 0xFF, 0x49, 0x4F, 0x1A, 0x4A, 0x50,
0xB1
};
static const unsigned char TA127_DN[] = {
0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45,
0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55,
0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47,
0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
0x41, 0x31
};
static const unsigned char TA127_RSA_N[] = {
0xF1, 0x66, 0x08, 0xBD, 0xD9, 0xC5, 0x15, 0x61, 0xCB, 0x84, 0x04, 0x41,
0xA5, 0x69, 0x37, 0x77, 0x1D, 0xC1, 0xB0, 0x7B, 0xFA, 0xC3, 0x77, 0x48,
0x90, 0x13, 0x72, 0x64, 0xD1, 0xB8, 0x7C, 0x90, 0x35, 0x9D, 0x18, 0x79,
0x88, 0xE3, 0x97, 0x01, 0x3C, 0x47, 0x81, 0xF2, 0x0E, 0xA2, 0x98, 0x0D,
0x9E, 0x3F, 0x37, 0xE0, 0x19, 0xB2, 0x90, 0xF2, 0x46, 0x1C, 0x92, 0xB1,
0x3A, 0x61, 0xCE, 0xFA, 0xB7, 0x46, 0x9E, 0x03, 0x86, 0xD7, 0x33, 0x6E,
0xED, 0xF7, 0x45, 0x8C, 0x76, 0x37, 0xDE, 0x6E, 0x96, 0x91, 0xF7, 0xD7,
0x7E, 0x2B, 0x87, 0x17, 0xD5, 0x8B, 0x35, 0xEE, 0x84, 0x91, 0x72, 0x57,
0xDC, 0x60, 0xC3, 0xC3, 0xB9, 0xE7, 0xC7, 0x67, 0x24, 0x23, 0x4F, 0x63,
0x0A, 0x63, 0xF6, 0x66, 0x7D, 0x4B, 0x55, 0xA7, 0x3F, 0x78, 0x64, 0x49,
0x69, 0x12, 0x97, 0xE0, 0x4C, 0x0D, 0xD3, 0x09, 0xA0, 0x32, 0x30, 0x3A,
0xFA, 0x9F, 0xC0, 0xF2, 0x9C, 0xC5, 0x12, 0x2A, 0x2E, 0x1C, 0xB5, 0x04,
0x33, 0xDA, 0xA4, 0x38, 0x11, 0x6A, 0xDE, 0xC6, 0x18, 0xF6, 0x47, 0x3A,
0x22, 0x41, 0x87, 0x22, 0xFC, 0xC4, 0x89, 0x28, 0x54, 0xD8, 0x8C, 0xA5,
0x30, 0x0A, 0xF8, 0x17, 0x16, 0xCA, 0xAC, 0x37, 0xFD, 0x79, 0xA7, 0x91,
0x17, 0x78, 0x38, 0x99, 0xAD, 0x58, 0xED, 0xB2, 0xDE, 0xCC, 0x89, 0x7D,
0x03, 0x9C, 0xB3, 0x89, 0x65, 0xE7, 0xE3, 0x3B, 0xB1, 0x22, 0x86, 0x8F,
0x06, 0x6D, 0x78, 0x07, 0xFD, 0x91, 0x12, 0x7F, 0xB0, 0x6B, 0x1C, 0x89,
0x0D, 0xF9, 0xB8, 0xCB, 0x74, 0x5B, 0x07, 0xC2, 0xC8, 0xF4, 0x35, 0xD1,
0x64, 0x63, 0x7A, 0xE9, 0x6E, 0x9A, 0x28, 0xD6, 0x30, 0xBD, 0xE6, 0x1B,
0xDD, 0x15, 0xAF, 0x84, 0xEA, 0x9C, 0xC7, 0xCA, 0xF5, 0x0E, 0xEA, 0xF2,
0x5D, 0x29, 0x87, 0x8F, 0x69, 0x73, 0x39, 0xBE, 0x2E, 0x24, 0x6F, 0x45,
0x21, 0xAC, 0xC5, 0xD4, 0x69, 0x25, 0x06, 0x83, 0xAD, 0x7A, 0x48, 0x85,
0x13, 0x2C, 0x0D, 0x06, 0xB8, 0x6C, 0x79, 0x56, 0xFC, 0xA3, 0x67, 0x32,
0x81, 0xF5, 0x57, 0xA5, 0xCA, 0x57, 0x42, 0x69, 0xE9, 0x5C, 0x24, 0x61,
0xEF, 0xE2, 0x30, 0x18, 0x4E, 0x44, 0x98, 0x55, 0x6F, 0x7A, 0xC2, 0x93,
0xD8, 0x19, 0xB6, 0xDE, 0x7C, 0x47, 0x8A, 0x11, 0x4E, 0x49, 0x47, 0xDB,
0x28, 0x94, 0x02, 0x0B, 0x94, 0x4A, 0x2C, 0xF9, 0x12, 0xD0, 0x4F, 0xE8,
0x31, 0x7E, 0x6C, 0x7A, 0xBF, 0xA6, 0x3F, 0x9B, 0x39, 0x3D, 0x02, 0x16,
0xA3, 0x18, 0xB3, 0x67, 0xAC, 0x5B, 0x3F, 0x2C, 0x83, 0x2B, 0x67, 0x39,
0x81, 0x5C, 0xB9, 0x7E, 0x94, 0xD5, 0x64, 0xDD, 0x9E, 0x8F, 0x6E, 0xAE,
0xE8, 0x7C, 0x5B, 0xB4, 0xD7, 0x6A, 0x47, 0x48, 0xD7, 0x7E, 0xB3, 0xD4,
0x2D, 0x8E, 0x56, 0x76, 0x4E, 0xCF, 0x69, 0xF1, 0x6E, 0x44, 0x6C, 0xD4,
0x24, 0xEA, 0x8D, 0x24, 0xA1, 0x18, 0xBF, 0xBD, 0x57, 0xFE, 0xA9, 0x99,
0x35, 0xB5, 0xDB, 0x10, 0x77, 0xB8, 0x3D, 0x48, 0xBA, 0xD6, 0xC1, 0xE7,
0xF1, 0x23, 0x3E, 0xD7, 0xDF, 0x85, 0x9D, 0x27, 0x3C, 0xD4, 0x40, 0xBD,
0x0A, 0x0C, 0xBD, 0xF5, 0xE7, 0x8D, 0x25, 0xD6, 0x81, 0x74, 0x87, 0x46,
0xD4, 0x29, 0x75, 0xA2, 0x42, 0x6C, 0xF7, 0x73, 0x89, 0xE7, 0x7D, 0xBF,
0x7A, 0x4A, 0x1F, 0xD3, 0x22, 0xC9, 0x15, 0x55, 0xCF, 0xDF, 0x6F, 0x7C,
0x55, 0xD0, 0xA4, 0x8B, 0x07, 0x11, 0x37, 0x5F, 0x83, 0xA6, 0x26, 0x57,
0xA6, 0x01, 0x5B, 0x7E, 0xFE, 0x58, 0x68, 0x07, 0xA9, 0xE9, 0x7A, 0xD9,
0xB9, 0xE8, 0xFF, 0x50, 0x1F, 0xAB, 0xC2, 0xB4, 0xC0, 0xCE, 0xE8, 0xEA,
0xFD, 0x0F, 0xBD, 0x8D, 0x4D, 0xB8, 0xBC, 0x71
};
static const unsigned char TA127_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA128_DN[] = {
0x30, 0x54, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1D, 0x42, 0x45, 0x49, 0x4A, 0x49, 0x4E, 0x47, 0x20, 0x43, 0x45,
0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x20, 0x41, 0x55,
0x54, 0x48, 0x4F, 0x52, 0x49, 0x54, 0x59, 0x31, 0x1D, 0x30, 0x1B, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0C, 0x14, 0x42, 0x4A, 0x43, 0x41, 0x20, 0x47,
0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
0x41, 0x32
};
static const unsigned char TA128_EC_Q[] = {
0x04, 0x9D, 0xCB, 0x80, 0x91, 0x8D, 0x53, 0x67, 0xB5, 0xB9, 0x50, 0xB1,
0x03, 0xF8, 0xE5, 0x49, 0x1F, 0x41, 0x22, 0x09, 0xB0, 0x51, 0x52, 0x58,
0xD6, 0x2B, 0x34, 0x8F, 0xC5, 0x12, 0x46, 0x14, 0xC5, 0x8B, 0x2F, 0x2C,
0x84, 0xFF, 0x2C, 0x6E, 0xA8, 0xD5, 0xF1, 0x09, 0xE3, 0x03, 0x21, 0x14,
0xC4, 0x43, 0x3D, 0x7C, 0xC1, 0x2C, 0xC4, 0x4B, 0x6A, 0x4A, 0xCD, 0xE9,
0x87, 0xE0, 0x7D, 0xF6, 0x22, 0xBE, 0xFA, 0x4A, 0x51, 0xB8, 0x30, 0x8A,
0xFD, 0xE1, 0xDE, 0x18, 0x12, 0x0A, 0xF6, 0x47, 0xB7, 0xE7, 0x17, 0xBF,
0x27, 0x8A, 0xD4, 0x41, 0x4C, 0x96, 0x3C, 0x60, 0x96, 0xC1, 0xFD, 0x15,
0x1C
};
static const unsigned char TA129_DN[] = {
0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69,
0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20,
0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x45, 0x34,
0x36
};
static const unsigned char TA129_EC_Q[] = {
0x04, 0x76, 0xFA, 0x99, 0xA9, 0x6E, 0x20, 0xED, 0xF9, 0xD7, 0x77, 0xE3,
0x07, 0x3B, 0xA8, 0xDB, 0x3D, 0x5F, 0x38, 0xE8, 0xAB, 0x55, 0xA6, 0x56,
0x4F, 0xD6, 0x48, 0xEA, 0xEC, 0x7F, 0x2D, 0xAA, 0xC3, 0xB2, 0xC5, 0x79,
0xEC, 0x99, 0x61, 0x7F, 0x10, 0x79, 0xC7, 0x02, 0x5A, 0xF9, 0x04, 0x37,
0xF5, 0x34, 0x35, 0x2B, 0x77, 0xCE, 0x7F, 0x20, 0x8F, 0x52, 0xA3, 0x00,
0x89, 0xEC, 0xD5, 0xA7, 0xA2, 0x6D, 0x5B, 0xE3, 0x4B, 0x92, 0x93, 0xA0,
0x80, 0xF5, 0x01, 0x94, 0xDC, 0xF0, 0x68, 0x07, 0x1E, 0xCD, 0xEE, 0xFE,
0x25, 0x52, 0xB5, 0x20, 0x43, 0x1C, 0x1B, 0xFE, 0xEB, 0x19, 0xCE, 0x43,
0xA3
};
static const unsigned char TA130_DN[] = {
0x30, 0x5F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x47, 0x42, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0F, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20, 0x4C, 0x69,
0x6D, 0x69, 0x74, 0x65, 0x64, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x2D, 0x53, 0x65, 0x63, 0x74, 0x69, 0x67, 0x6F, 0x20,
0x50, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x74, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6F, 0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x34,
0x36
};
static const unsigned char TA130_RSA_N[] = {
0x93, 0xBE, 0xD5, 0x36, 0x52, 0x75, 0xD8, 0x01, 0x23, 0xA0, 0x1C, 0x47,
0x42, 0x49, 0xEE, 0x63, 0xB6, 0xB7, 0x21, 0xFD, 0xC4, 0x95, 0xD5, 0x48,
0x2B, 0x26, 0x7C, 0x14, 0x53, 0x10, 0xDA, 0x79, 0xFD, 0x2B, 0xB7, 0x2D,
0xA4, 0xD4, 0x2C, 0xFA, 0xEA, 0x32, 0xDD, 0x49, 0xC2, 0xB9, 0xBD, 0x0F,
0x48, 0x3D, 0x7B, 0x5A, 0x98, 0x54, 0xAF, 0x9E, 0x5D, 0x31, 0x74, 0x4F,
0x07, 0xFC, 0x50, 0x21, 0xDD, 0xA4, 0xCF, 0x68, 0x4F, 0x1B, 0x12, 0x63,
0x6D, 0x25, 0x99, 0x4C, 0x2A, 0x99, 0xF3, 0x48, 0x30, 0x61, 0xFA, 0x81,
0x7C, 0x1E, 0xA7, 0x08, 0x4A, 0xDC, 0x3E, 0x2B, 0x1C, 0x1F, 0x18, 0x4C,
0x71, 0xAA, 0x35, 0x8C, 0xAD, 0xF8, 0x6E, 0xE8, 0x3B, 0x4A, 0xD9, 0xE5,
0x94, 0x02, 0xD6, 0x89, 0x84, 0x13, 0xAA, 0x6D, 0xC8, 0x4F, 0x33, 0xCC,
0x50, 0x96, 0x37, 0x92, 0x33, 0xDC, 0x5F, 0x88, 0xE7, 0x9F, 0x54, 0xD9,
0x48, 0xF0, 0x98, 0x43, 0xD6, 0x66, 0xFD, 0x9F, 0x17, 0x38, 0x43, 0xC5,
0x01, 0x51, 0x0B, 0xD7, 0xE3, 0x23, 0x0F, 0x14, 0x5D, 0x5B, 0x14, 0xE7,
0x4B, 0xBE, 0xDD, 0xF4, 0xC8, 0xDA, 0x03, 0x37, 0xD1, 0xD6, 0x39, 0xA1,
0x21, 0x51, 0x30, 0x83, 0xB0, 0x6D, 0xD7, 0x30, 0x4E, 0x96, 0x5B, 0x91,
0xF0, 0x70, 0x24, 0xAB, 0xBF, 0x45, 0x81, 0x64, 0x43, 0x0D, 0xBD, 0x21,
0x3A, 0x2F, 0x3C, 0xE9, 0x9E, 0x0D, 0xCB, 0x20, 0xB5, 0x42, 0x27, 0xCC,
0xDA, 0x6F, 0x9B, 0xEE, 0x64, 0x30, 0x90, 0x39, 0xCD, 0x93, 0x65, 0x81,
0x21, 0x31, 0xB5, 0x23, 0x50, 0x33, 0x37, 0x22, 0xE3, 0x38, 0xED, 0xF8,
0x31, 0x30, 0xCC, 0x45, 0xFE, 0x62, 0xF9, 0xD1, 0x5D, 0x32, 0x79, 0x42,
0x87, 0xDF, 0x6A, 0xCC, 0x56, 0x19, 0x40, 0x4D, 0xCE, 0xAA, 0xBB, 0xF9,
0xB5, 0x76, 0x49, 0x94, 0xF1, 0x27, 0xF8, 0x91, 0xA5, 0x83, 0xE5, 0x06,
0xB3, 0x63, 0x0E, 0x80, 0xDC, 0xE0, 0x12, 0x55, 0x80, 0xA6, 0x3B, 0x66,
0xB4, 0x39, 0x87, 0x2D, 0xC8, 0xF0, 0xD0, 0xD1, 0x14, 0xE9, 0xE4, 0x0D,
0x4D, 0x0E, 0xF6, 0x5D, 0x57, 0x72, 0xC5, 0x3B, 0x1C, 0x47, 0x56, 0x9D,
0xE2, 0xD5, 0xFB, 0x81, 0x61, 0x8C, 0xCC, 0x4D, 0x80, 0x90, 0x34, 0x5B,
0xB7, 0xD7, 0x14, 0x75, 0xDC, 0xD8, 0x04, 0x48, 0x9F, 0xC0, 0xC1, 0x28,
0x88, 0xB4, 0xE9, 0x1C, 0xCA, 0xA7, 0xB1, 0xF1, 0x56, 0xB7, 0x7B, 0x49,
0x4C, 0x59, 0xE5, 0x20, 0x15, 0xA8, 0x84, 0x02, 0x29, 0xFA, 0x38, 0x94,
0x69, 0x9A, 0x49, 0x06, 0x8F, 0xCD, 0x1F, 0x79, 0x14, 0x17, 0x12, 0x0C,
0x83, 0x7A, 0xDE, 0x1F, 0xB1, 0x97, 0xEE, 0xF9, 0x97, 0x78, 0x28, 0xA4,
0xC8, 0x44, 0x92, 0xE9, 0x7D, 0x26, 0x05, 0xA6, 0x58, 0x72, 0x9B, 0x79,
0x13, 0xD8, 0x11, 0x5F, 0xAE, 0xC5, 0x38, 0x62, 0x34, 0x68, 0xB2, 0x86,
0x30, 0x8E, 0xF8, 0x90, 0x61, 0x9E, 0x32, 0x6C, 0xF5, 0x07, 0x36, 0xCD,
0xA2, 0x4C, 0x6E, 0xEC, 0x8A, 0x36, 0xED, 0xF2, 0xE6, 0x99, 0x15, 0x44,
0x70, 0xC3, 0x7C, 0xBC, 0x9C, 0x39, 0xC0, 0xB4, 0xE1, 0x6B, 0xF7, 0x83,
0x25, 0x23, 0x57, 0xD9, 0x12, 0x80, 0xE5, 0x49, 0xF0, 0x75, 0x0F, 0xEF,
0x8D, 0xEB, 0x1C, 0x9B, 0x54, 0x28, 0xB4, 0x21, 0x3C, 0xFC, 0x7C, 0x0A,
0xFF, 0xEF, 0x7B, 0x6B, 0x75, 0xFF, 0x8B, 0x1D, 0xA0, 0x19, 0x05, 0xAB,
0xFA, 0xF8, 0x2B, 0x81, 0x42, 0xE8, 0x38, 0xBA, 0xBB, 0xFB, 0xAA, 0xFD,
0x3D, 0xE0, 0xF3, 0xCA, 0xDF, 0x4E, 0x97, 0x97, 0x29, 0xED, 0xF3, 0x18,
0x56, 0xE9, 0xA5, 0x96, 0xAC, 0xBD, 0xC3, 0x90, 0x98, 0xB2, 0xE0, 0xF9,
0xA2, 0xD4, 0xA6, 0x47, 0x43, 0x7C, 0x6D, 0xCF
};
static const unsigned char TA130_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA131_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20,
0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32
};
static const unsigned char TA131_RSA_N[] = {
0xD0, 0xA4, 0x09, 0x72, 0x4F, 0x40, 0x88, 0x12, 0x61, 0x3E, 0x35, 0x23,
0x9E, 0xEE, 0xF6, 0x74, 0xCF, 0x2F, 0x7B, 0x58, 0x3D, 0xCE, 0x3C, 0x0D,
0x10, 0x28, 0x90, 0x2F, 0x97, 0xF7, 0x8C, 0x48, 0xD8, 0xA0, 0xD8, 0x25,
0xB1, 0x4C, 0xB0, 0x11, 0x4C, 0x17, 0x73, 0x50, 0xD0, 0x22, 0x4A, 0x63,
0xBB, 0x81, 0xD3, 0x29, 0x6E, 0xD5, 0xB5, 0x09, 0x3E, 0x26, 0x18, 0x7F,
0xB2, 0x12, 0x7F, 0x93, 0x98, 0xB7, 0xAF, 0xF0, 0x36, 0xBF, 0xF2, 0xEE,
0x18, 0x9E, 0x9C, 0x3B, 0x52, 0xC5, 0x47, 0x19, 0x5D, 0x74, 0xF3, 0x64,
0x66, 0xD5, 0x5D, 0xC7, 0x68, 0xB4, 0xBF, 0x1B, 0x1C, 0x06, 0xA3, 0xBC,
0x8F, 0x40, 0x23, 0xB6, 0x1E, 0xC6, 0x84, 0xBD, 0x51, 0xC4, 0x1B, 0x39,
0xC1, 0x95, 0xD2, 0x29, 0xEC, 0x4B, 0xAE, 0x7B, 0x2D, 0xBF, 0x39, 0xFD,
0xB4, 0x62, 0xDE, 0x96, 0x7B, 0x41, 0xC6, 0x9C, 0xA0, 0xE0, 0x06, 0x72,
0xFB, 0xF0, 0x07, 0x97, 0x09, 0x39, 0x81, 0x74, 0xAF, 0xF7, 0x34, 0x59,
0x11, 0x57, 0x0A, 0xC2, 0x5B, 0xC1, 0x24, 0xF4, 0x31, 0x73, 0x30, 0x82,
0xC6, 0x9D, 0xBA, 0x02, 0xF7, 0x3E, 0x7C, 0x44, 0x5F, 0x83, 0x0D, 0xF3,
0xF1, 0xDD, 0x20, 0x69, 0x16, 0x09, 0x50, 0xE2, 0xD4, 0x55, 0xB6, 0xE0,
0x80, 0x72, 0x76, 0x6E, 0x4C, 0x47, 0xB7, 0x75, 0x55, 0x59, 0xB4, 0x53,
0x74, 0xD9, 0x94, 0xC6, 0x41, 0xAD, 0x58, 0x8A, 0x31, 0x66, 0x0F, 0x1E,
0xA2, 0x1B, 0x29, 0x40, 0x4E, 0x2F, 0xDF, 0x7B, 0xE6, 0x16, 0x2C, 0x2D,
0xFC, 0xBF, 0xEC, 0xF3, 0xB4, 0xFA, 0xBE, 0x18, 0xF6, 0x9B, 0x49, 0xD4,
0xEE, 0x05, 0x6E, 0xD9, 0x34, 0xF3, 0x9C, 0xF1, 0xEC, 0x01, 0x8B, 0xD1,
0x20, 0xC6, 0x0F, 0xA0, 0xB5, 0xBC, 0x17, 0x4E, 0x48, 0x7B, 0x51, 0xC2,
0xFC, 0xE9, 0x5C, 0x69, 0x37, 0x47, 0x66, 0xB3, 0x68, 0xF8, 0x15, 0x28,
0xF0, 0xB9, 0xD3, 0xA4, 0x15, 0xCC, 0x5A, 0x4F, 0xBA, 0x52, 0x70, 0xA3,
0x12, 0x45, 0xDD, 0xC6, 0xBA, 0x4E, 0xFB, 0xC2, 0xD0, 0xF7, 0xA8, 0x52,
0x27, 0x6D, 0x6E, 0x79, 0xB5, 0x8C, 0xFC, 0x7B, 0x8C, 0xC1, 0x16, 0x4C,
0xEE, 0x80, 0x7F, 0xBE, 0xF0, 0x76, 0xBE, 0x41, 0x53, 0x12, 0x33, 0xAE,
0x5A, 0x38, 0x42, 0xAB, 0xD7, 0x0F, 0x3E, 0x41, 0x8D, 0x76, 0x07, 0x32,
0xD5, 0xAB, 0x89, 0xF6, 0x4E, 0x67, 0xD9, 0xB1, 0x42, 0x75, 0x23, 0x6E,
0xF3, 0xCD, 0x42, 0xB2, 0xFC, 0x55, 0xF5, 0x53, 0x87, 0x17, 0x3B, 0xC0,
0x33, 0x58, 0xF1, 0x52, 0xD2, 0xF9, 0x80, 0xA4, 0xF0, 0xE8, 0xF0, 0x3B,
0x8B, 0x38, 0xCC, 0xA4, 0xC6, 0x90, 0x7F, 0x0F, 0x9C, 0xFD, 0x8B, 0xD1,
0xA3, 0xCF, 0xDA, 0x83, 0xA7, 0x69, 0xC9, 0x50, 0x36, 0xD5, 0x5C, 0x05,
0xD2, 0x0A, 0x41, 0x74, 0xDB, 0x63, 0x11, 0x37, 0xC1, 0xA5, 0xA0, 0x96,
0x4B, 0x1E, 0x8C, 0x16, 0x12, 0x77, 0xAE, 0x94, 0x34, 0x7B, 0x1E, 0x7F,
0xC2, 0x66, 0x00, 0xE4, 0xAA, 0x83, 0xEA, 0x8A, 0x90, 0xAD, 0xCE, 0x36,
0x44, 0x4D, 0xD1, 0x51, 0xE9, 0xBC, 0x1F, 0xF3, 0x6A, 0x05, 0xFD, 0xC0,
0x74, 0x1F, 0x25, 0x19, 0x40, 0x51, 0x6E, 0xEA, 0x82, 0x51, 0x40, 0xDF,
0x9B, 0xB9, 0x08, 0x2A, 0x06, 0x02, 0xD5, 0x23, 0x1C, 0x13, 0xD6, 0xE9,
0xDB, 0xDB, 0xC6, 0xB0, 0x7A, 0xCB, 0x7B, 0x27, 0x9B, 0xFB, 0xE0, 0xD5,
0x46, 0x24, 0xED, 0x10, 0x4B, 0x63, 0x4B, 0xA5, 0x05, 0x8F, 0xBA, 0xB8,
0x1D, 0x2B, 0xA6, 0xFA, 0x91, 0xE2, 0x92, 0x52, 0xBD, 0xEC, 0xEB, 0x67,
0x97, 0x6D, 0x9A, 0x2D, 0x9F, 0x81, 0x32, 0x05, 0x67, 0x32, 0xFB, 0x48,
0x08, 0x3F, 0xD9, 0x25, 0xB8, 0x04, 0x25, 0x2F
};
static const unsigned char TA131_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA132_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x0F, 0x53, 0x53, 0x4C, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55,
0x04, 0x03, 0x0C, 0x1C, 0x53, 0x53, 0x4C, 0x2E, 0x63, 0x6F, 0x6D, 0x20,
0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x32, 0x32
};
static const unsigned char TA132_EC_Q[] = {
0x04, 0x45, 0x29, 0x35, 0x73, 0xFA, 0xC2, 0xB8, 0x23, 0xCE, 0x14, 0x7D,
0xA8, 0xB1, 0x4D, 0xA0, 0x5B, 0x36, 0xEE, 0x2A, 0x2C, 0x53, 0xC3, 0x60,
0x09, 0x35, 0xB2, 0x24, 0x66, 0x26, 0x69, 0xC0, 0xB3, 0x95, 0xD6, 0x5D,
0x92, 0x40, 0x19, 0x0E, 0xC6, 0xA5, 0x13, 0x70, 0xF4, 0xEF, 0x12, 0x51,
0x28, 0x5D, 0xE7, 0xCC, 0xBD, 0xF9, 0x3C, 0x85, 0xC1, 0xCF, 0x94, 0x90,
0xC9, 0x2B, 0xCE, 0x92, 0x42, 0x58, 0x59, 0x67, 0xFD, 0x94, 0x27, 0x10,
0x64, 0x8C, 0x4F, 0x04, 0xB1, 0x4D, 0x49, 0xE4, 0x7B, 0x4F, 0x9B, 0xF5,
0xE7, 0x08, 0xF8, 0x03, 0x88, 0xF7, 0xA7, 0xC3, 0x92, 0x4B, 0x19, 0x54,
0x81
};
static const unsigned char TA133_DN[] = {
0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65,
0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
0x41, 0x20, 0x45, 0x43, 0x43, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30,
0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C,
0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
0x04, 0x06, 0x13, 0x02, 0x44, 0x45
};
static const unsigned char TA133_EC_Q[] = {
0x04, 0x96, 0x86, 0x58, 0x28, 0x37, 0x0A, 0x67, 0xD0, 0xA0, 0xDE, 0x24,
0x19, 0x19, 0xE1, 0xE4, 0x05, 0x07, 0x1F, 0x97, 0xED, 0xE8, 0x64, 0x82,
0xB9, 0xF6, 0xC4, 0x71, 0x50, 0xCE, 0x8A, 0x0C, 0xFF, 0xD7, 0xB5, 0x76,
0xBB, 0xA1, 0x6C, 0x93, 0x6C, 0x83, 0xA2, 0x68, 0x6E, 0xA5, 0xD9, 0xBE,
0x2C, 0x88, 0x95, 0x41, 0xCD, 0x5D, 0xDD, 0xB1, 0xCA, 0x83, 0x63, 0x83,
0xCC, 0xC0, 0xBE, 0x74, 0xD9, 0xE0, 0x9D, 0xA4, 0xEE, 0x4A, 0x4E, 0x56,
0xE0, 0x98, 0x29, 0x41, 0x93, 0x52, 0x10, 0xD5, 0x24, 0x38, 0x02, 0x32,
0x67, 0xF1, 0x94, 0x12, 0x6F, 0xEF, 0xD7, 0xC5, 0xDE, 0x2E, 0xFD, 0x19,
0x80
};
static const unsigned char TA134_DN[] = {
0x30, 0x4C, 0x31, 0x2E, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
0x25, 0x41, 0x74, 0x6F, 0x73, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65,
0x64, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43,
0x41, 0x20, 0x52, 0x53, 0x41, 0x20, 0x54, 0x4C, 0x53, 0x20, 0x32, 0x30,
0x32, 0x31, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C,
0x04, 0x41, 0x74, 0x6F, 0x73, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
0x04, 0x06, 0x13, 0x02, 0x44, 0x45
};
static const unsigned char TA134_RSA_N[] = {
0xB6, 0x80, 0x0E, 0xC4, 0x79, 0xBD, 0x05, 0x8C, 0x7D, 0xB0, 0xA3, 0x9D,
0x4D, 0x22, 0x4D, 0xCB, 0xF0, 0x41, 0x97, 0x4D, 0x59, 0xE0, 0xD1, 0xFE,
0x56, 0x8C, 0x97, 0xF2, 0xD7, 0xBD, 0x8F, 0x6C, 0xB7, 0x23, 0x8F, 0x5F,
0xD5, 0xC4, 0xD8, 0x41, 0xCB, 0xF2, 0x02, 0x1E, 0x71, 0xE5, 0xE9, 0xF6,
0x5E, 0xCB, 0x08, 0x2A, 0x5E, 0x30, 0xF2, 0x2D, 0x66, 0xC7, 0x84, 0x1B,
0x64, 0x57, 0x38, 0x9D, 0x75, 0x2D, 0x56, 0xC6, 0x2F, 0x61, 0xEF, 0x96,
0xFC, 0x20, 0x46, 0xBD, 0xEB, 0xD4, 0x7B, 0x3F, 0x3F, 0x7C, 0x47, 0x38,
0x04, 0xA9, 0x1B, 0xAA, 0x52, 0xDF, 0x13, 0x37, 0xD3, 0x15, 0x15, 0x4E,
0xBD, 0x5F, 0x7C, 0xAF, 0xAD, 0x63, 0xC7, 0x79, 0xDC, 0x08, 0x7B, 0xD5,
0xA0, 0xE5, 0xF7, 0x5B, 0x75, 0xAC, 0x80, 0x55, 0x99, 0x92, 0x61, 0x9B,
0xCD, 0x2A, 0x17, 0x7D, 0xDB, 0x8F, 0xF4, 0xB5, 0x6A, 0xEA, 0x17, 0x4A,
0x64, 0x28, 0x66, 0x15, 0x29, 0x6C, 0x02, 0xF1, 0x6B, 0xD5, 0xBA, 0xA3,
0x33, 0xDC, 0x5A, 0x67, 0xA7, 0x05, 0xE2, 0xBF, 0x65, 0xB6, 0x16, 0xB0,
0x10, 0xED, 0xCD, 0x50, 0x33, 0xC9, 0x70, 0x50, 0xEC, 0x19, 0x8E, 0xB0,
0xC7, 0xF2, 0x74, 0x5B, 0x6B, 0x44, 0xC6, 0x7D, 0x96, 0xB9, 0x98, 0x08,
0x59, 0x66, 0xDE, 0x29, 0x01, 0x9B, 0xF4, 0x2A, 0x6D, 0xD3, 0x15, 0x3A,
0x90, 0x6A, 0x67, 0xF1, 0xB4, 0x6B, 0x66, 0xD9, 0x21, 0xEB, 0xCA, 0xD9,
0x62, 0x7C, 0x46, 0x10, 0x5C, 0xDE, 0x75, 0x49, 0x67, 0x9E, 0x42, 0xF9,
0xFE, 0x75, 0xA9, 0xA3, 0xAD, 0xFF, 0x76, 0x0A, 0x67, 0x40, 0xE3, 0xC5,
0xF7, 0x8D, 0xC7, 0x85, 0x9A, 0x59, 0x9E, 0x62, 0x9A, 0x6A, 0xED, 0x45,
0x87, 0x98, 0x67, 0xB2, 0xD5, 0x4A, 0x3C, 0xD7, 0xB4, 0x3B, 0x00, 0x0D,
0xC0, 0x8F, 0x1F, 0xE1, 0x40, 0xC4, 0xAE, 0x6C, 0x21, 0xDC, 0x49, 0x7E,
0x7E, 0xCA, 0xB2, 0x8D, 0x6D, 0xB6, 0xBF, 0x93, 0x2F, 0xA1, 0x5C, 0x3E,
0x8F, 0xCA, 0xED, 0x80, 0x8E, 0x58, 0xE1, 0xDB, 0x57, 0xCF, 0x85, 0x36,
0x38, 0xB2, 0x71, 0xA4, 0x09, 0x8C, 0x92, 0x89, 0x08, 0x88, 0x48, 0xF1,
0x40, 0x63, 0x18, 0xB2, 0x5B, 0x8C, 0x5A, 0xE3, 0xC3, 0xD3, 0x17, 0xAA,
0xAB, 0x19, 0xA3, 0x2C, 0x1B, 0xE4, 0xD5, 0xC6, 0xE2, 0x66, 0x7A, 0xD7,
0x82, 0x19, 0xA6, 0x3B, 0x16, 0x2C, 0x2F, 0x71, 0x87, 0x5F, 0x45, 0x9E,
0x95, 0x73, 0x93, 0xC2, 0x42, 0x81, 0x21, 0x13, 0x96, 0xD7, 0x9D, 0xBB,
0x93, 0x68, 0x15, 0xFA, 0x9D, 0xA4, 0x1D, 0x8C, 0xF2, 0x81, 0xE0, 0x58,
0x06, 0xBD, 0xC9, 0xB6, 0xE3, 0xF6, 0x89, 0x5D, 0x89, 0xF9, 0xAC, 0x44,
0xA1, 0xCB, 0x6B, 0xFA, 0x16, 0xF1, 0xC7, 0x50, 0x3D, 0x24, 0xDA, 0xF7,
0xC3, 0xE4, 0x87, 0xD5, 0x56, 0xF1, 0x4F, 0x90, 0x30, 0xFA, 0x45, 0x09,
0x59, 0xDA, 0x34, 0xCE, 0xE0, 0x13, 0x1C, 0x04, 0x7C, 0x00, 0xD4, 0x9B,
0x86, 0xA4, 0x40, 0xBC, 0xD9, 0xDC, 0x4C, 0x57, 0x7E, 0xAE, 0xB7, 0x33,
0xB6, 0x5E, 0x76, 0xE1, 0x65, 0x8B, 0x66, 0xDF, 0x8D, 0xCA, 0xD7, 0x98,
0xAF, 0xCE, 0x36, 0x98, 0x8C, 0x9C, 0x83, 0x99, 0x03, 0x70, 0xF3, 0xAF,
0x74, 0xED, 0xC6, 0x0E, 0x36, 0xE7, 0xBD, 0xEC, 0xC1, 0x73, 0xA7, 0x94,
0x5A, 0xCB, 0x92, 0x64, 0x82, 0xA6, 0x00, 0xC1, 0x70, 0xA1, 0x6E, 0x2C,
0x29, 0xE1, 0x58, 0x57, 0xEC, 0x5A, 0x7C, 0x99, 0x6B, 0x25, 0xA4, 0x90,
0x3A, 0x80, 0xF4, 0x20, 0x9D, 0x9A, 0xCE, 0xC7, 0x2D, 0xF9, 0xB2, 0x4B,
0x29, 0x95, 0x83, 0xE9, 0x35, 0x8D, 0xA7, 0x49, 0x48, 0xA7, 0x0F, 0x4C,
0x19, 0x91, 0xD0, 0xF5, 0xBF, 0x10, 0xE0, 0x71
};
static const unsigned char TA134_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA135_DN[] = {
0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20,
0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73,
0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73,
0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x33
};
static const unsigned char TA135_RSA_N[] = {
0xC0, 0x31, 0x82, 0x61, 0x92, 0xE4, 0x94, 0x1B, 0x0A, 0x2A, 0x65, 0xD0,
0xBE, 0x06, 0xA9, 0x87, 0x3B, 0x51, 0x12, 0xEA, 0x70, 0x41, 0xAE, 0xE2,
0xFB, 0x74, 0xEA, 0x0A, 0x8D, 0xB9, 0xB3, 0x4C, 0xDC, 0x8F, 0xB7, 0x13,
0x52, 0x4F, 0x54, 0x18, 0xE1, 0x2C, 0x73, 0x95, 0x91, 0xC5, 0x66, 0x3B,
0x6A, 0xCF, 0xAC, 0x63, 0x6D, 0x87, 0x53, 0xF0, 0xF7, 0xF1, 0x39, 0xB7,
0xA0, 0x43, 0x63, 0xB0, 0xC4, 0x03, 0x5D, 0x57, 0xA9, 0xE7, 0x44, 0xCE,
0xC4, 0xA1, 0x83, 0x65, 0xF6, 0x50, 0x3E, 0xB1, 0x7E, 0x16, 0xB8, 0x3A,
0x8A, 0x02, 0xD0, 0x96, 0x1F, 0x00, 0xCD, 0x05, 0x21, 0xEF, 0x06, 0x6D,
0xDD, 0x21, 0x9C, 0x19, 0x43, 0x45, 0xA1, 0xC5, 0xE8, 0x80, 0xCA, 0xC2,
0xAD, 0x40, 0x62, 0x17, 0x06, 0xC6, 0xAA, 0xBC, 0xF3, 0xD6, 0xE6, 0xFC,
0x50, 0x7E, 0x66, 0x42, 0x1F, 0x3C, 0x8B, 0xA6, 0x79, 0x79, 0x86, 0x40,
0x35, 0x9F, 0x20, 0xEF, 0x3F, 0xEB, 0x8B, 0x47, 0x1F, 0x8F, 0x8E, 0xC5,
0xD4, 0x8E, 0xB6, 0x2C, 0xC9, 0x44, 0x04, 0xE3, 0xD4, 0x43, 0x75, 0x3F,
0xD5, 0x3F, 0xAF, 0x1C, 0xCC, 0x7E, 0x46, 0x5F, 0xAC, 0xDF, 0x64, 0x10,
0x8A, 0xEF, 0x46, 0xF0, 0x90, 0xF0, 0x0F, 0x2D, 0xF4, 0x88, 0x0B, 0xB1,
0x29, 0xAA, 0xAF, 0x85, 0xAA, 0x49, 0x58, 0xA8, 0xBF, 0x63, 0xA0, 0x38,
0x91, 0xE6, 0xB3, 0xE6, 0x77, 0x68, 0xC4, 0xF9, 0x2A, 0x19, 0x84, 0xBB,
0x0E, 0xE1, 0xF5, 0xAF, 0x89, 0xEC, 0xA5, 0x2F, 0x50, 0x20, 0x74, 0x1E,
0x12, 0x41, 0x73, 0x1E, 0x24, 0xD9, 0xCA, 0xCE, 0x2C, 0xA1, 0x59, 0x35,
0xC0, 0xC8, 0x1D, 0x46, 0x27, 0x61, 0x5A, 0x8F, 0xF9, 0x4D, 0xD3, 0x72,
0x79, 0x66, 0x1E, 0x9F, 0x15, 0x90, 0x21, 0x2D, 0xFD, 0xED, 0x8B, 0x56,
0x70, 0x03, 0x4A, 0x49, 0x3E, 0x7F, 0x69, 0x31, 0x12, 0x69, 0xC7, 0x1E,
0x5C, 0xCA, 0x7A, 0x13, 0x8B, 0xE8, 0xE6, 0xF5, 0x60, 0x0F, 0xCC, 0x93,
0x2C, 0x84, 0x7F, 0xF1, 0xFC, 0x6A, 0xFC, 0x9B, 0x47, 0x9D, 0xDB, 0xAD,
0x88, 0x3D, 0xF3, 0x76, 0x75, 0x33, 0xD7, 0x4B, 0xA4, 0xC8, 0x8B, 0xF9,
0xF5, 0x43, 0x58, 0x4F, 0xCB, 0xC8, 0x03, 0x54, 0x8F, 0xA5, 0x85, 0x78,
0x04, 0x1A, 0xF3, 0x73, 0xF2, 0xD7, 0x87, 0x1D, 0x41, 0x9F, 0xE7, 0xD8,
0x17, 0xCE, 0x1A, 0x9C, 0x0F, 0x4A, 0xFC, 0xDC, 0x44, 0x68, 0x54, 0x68,
0xE2, 0x41, 0x3C, 0xFE, 0x2C, 0x84, 0x86, 0x37, 0x3C, 0xCD, 0x3F, 0x2F,
0xA2, 0xDB, 0xE7, 0xF7, 0x54, 0x03, 0x5F, 0x59, 0xD3, 0xF7, 0x91, 0x78,
0xC7, 0x8B, 0x77, 0x6A, 0x16, 0xE5, 0x49, 0x85, 0x90, 0x45, 0x72, 0x70,
0x2F, 0x91, 0x5D, 0xF8, 0x3E, 0x65, 0x40, 0x0B, 0x19, 0x99, 0xC9, 0x26,
0x20, 0x5A, 0x68, 0xC1, 0x35, 0xBF, 0x4F, 0xA7, 0x51, 0xF1, 0xD8, 0x11,
0x2B, 0x5B, 0xE0, 0x9A, 0x9E, 0x28, 0x3B, 0x0A, 0x3A, 0x0A, 0x1F, 0xC1,
0x81, 0xE5, 0x2E, 0xF0, 0xA6, 0xB9, 0x69, 0xA5, 0x88, 0x94, 0xE6, 0x6B,
0x13, 0x7F, 0xD1, 0x64, 0x3F, 0x3D, 0x9C, 0x70, 0x46, 0xE5, 0xA2, 0x85,
0x7B, 0x58, 0x84, 0x27, 0xDC, 0xC4, 0x80, 0x3E, 0x67, 0x9A, 0x9A, 0xC7,
0x9A, 0x31, 0x0E, 0x30, 0xEC, 0xE6, 0x17, 0x40, 0x95, 0xD9, 0x45, 0xED,
0x01, 0x96, 0xAA, 0xBF, 0x0C, 0xF3, 0x4B, 0xD1, 0x63, 0xF7, 0x13, 0x58,
0xC0, 0xB8, 0xF3, 0xFA, 0x67, 0xDD, 0x9B, 0x7D, 0x6D, 0x4A, 0xFF, 0x32,
0x4C, 0xB5, 0x25, 0x3B, 0xFF, 0x1C, 0x67, 0x0F, 0x85, 0x22, 0x59, 0x05,
0x91, 0x91, 0x41, 0x77, 0x81, 0xD0, 0x85, 0x4C, 0x87, 0x10, 0x71, 0xFF,
0x9E, 0x43, 0x1B, 0xAE, 0x95, 0x75, 0x2D, 0x81
};
static const unsigned char TA135_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA136_DN[] = {
0x30, 0x5A, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x43, 0x4E, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1C, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73, 0x69, 0x61, 0x20,
0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x69, 0x65, 0x73,
0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03,
0x55, 0x04, 0x03, 0x0C, 0x1B, 0x54, 0x72, 0x75, 0x73, 0x74, 0x41, 0x73,
0x69, 0x61, 0x20, 0x47, 0x6C, 0x6F, 0x62, 0x61, 0x6C, 0x20, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x47, 0x34
};
static const unsigned char TA136_EC_Q[] = {
0x04, 0xF1, 0xB3, 0xCD, 0x38, 0xE4, 0x25, 0x43, 0xE5, 0xDE, 0x19, 0x09,
0xBB, 0x81, 0x79, 0xA2, 0x15, 0x5F, 0x15, 0x63, 0x01, 0xDE, 0xC2, 0xAB,
0xDD, 0xB3, 0xA6, 0x1B, 0x67, 0x4B, 0x80, 0x83, 0xAF, 0x99, 0xCB, 0xAC,
0x17, 0xDB, 0x2B, 0x96, 0xCA, 0x7C, 0x52, 0x55, 0xE2, 0x1A, 0xE1, 0x3D,
0x56, 0xF0, 0x2F, 0x16, 0x08, 0xFA, 0x15, 0xBC, 0x9B, 0xBB, 0x47, 0xE6,
0x3F, 0xEE, 0xA8, 0xE1, 0x4C, 0x8C, 0xF5, 0xD3, 0x36, 0xF9, 0x38, 0x5D,
0xAB, 0x70, 0x9A, 0x47, 0x0D, 0xE2, 0x81, 0x41, 0x06, 0xEB, 0x49, 0xF9,
0xB0, 0x29, 0xDD, 0x33, 0xEC, 0x50, 0xA5, 0x7F, 0x79, 0x29, 0xB8, 0x20,
0x98
};
static const unsigned char TA137_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31,
0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F,
0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C,
0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31
};
static const unsigned char TA137_EC_Q[] = {
0x04, 0x4B, 0x36, 0xE9, 0xAE, 0x57, 0x5E, 0xA8, 0x70, 0xD7, 0xD0, 0x8F,
0x74, 0x62, 0x77, 0xC3, 0x5E, 0x7A, 0xAA, 0xE5, 0xB6, 0xA2, 0xF1, 0x78,
0xFD, 0x02, 0x7E, 0x57, 0xDD, 0x91, 0x79, 0x9C, 0x6C, 0xB9, 0x52, 0x88,
0x54, 0xBC, 0x2F, 0x04, 0xBE, 0xB8, 0xCD, 0xF6, 0x10, 0xD1, 0x29, 0xEC,
0xB5, 0xD0, 0xA0, 0xC3, 0xF0, 0x89, 0x70, 0x19, 0xBB, 0x51, 0x65, 0xC5,
0x43, 0x9C, 0xC3, 0x9B, 0x63, 0x9D, 0x20, 0x83, 0x3E, 0x06, 0x0B, 0xA6,
0x42, 0x44, 0x85, 0x11, 0xA7, 0x4A, 0x3A, 0x2D, 0xE9, 0xD6, 0x68, 0x2F,
0x48, 0x4E, 0x53, 0x2B, 0x07, 0x3F, 0x4D, 0xBD, 0xB9, 0xAC, 0x77, 0x39,
0x57
};
static const unsigned char TA138_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31,
0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F,
0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C,
0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x45, 0x43, 0x43,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32
};
static const unsigned char TA138_EC_Q[] = {
0x04, 0x78, 0x30, 0x81, 0xE8, 0x63, 0x1E, 0xE5, 0xEB, 0x71, 0x51, 0x0F,
0xF7, 0x07, 0x07, 0xCA, 0x39, 0x99, 0x7C, 0x4E, 0xD5, 0x0F, 0xCC, 0x30,
0x30, 0x0B, 0x8F, 0x66, 0x93, 0x3E, 0xCF, 0xBD, 0xC5, 0x86, 0xBD, 0xF9,
0xB1, 0xB7, 0xB4, 0x3E, 0xB4, 0x07, 0xC8, 0xF3, 0x96, 0x31, 0xF3, 0xED,
0xA4, 0x4F, 0xF8, 0xA3, 0x4E, 0x8D, 0x29, 0x15, 0x58, 0xB8, 0xD5, 0x6F,
0x7F, 0xEE, 0x6C, 0x22, 0xB5, 0xB0, 0xAF, 0x48, 0x45, 0x0A, 0xBD, 0xA8,
0x49, 0x94, 0xBF, 0x84, 0x43, 0xB0, 0xDB, 0x84, 0x4A, 0x03, 0x23, 0x19,
0x67, 0x6A, 0x6F, 0xC1, 0x6E, 0xBC, 0x06, 0x39, 0x37, 0xD1, 0x88, 0x22,
0xF7
};
static const unsigned char TA139_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31,
0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F,
0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C,
0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x31
};
static const unsigned char TA139_RSA_N[] = {
0xB0, 0x48, 0x65, 0xA3, 0x0D, 0x1D, 0x42, 0xE3, 0x91, 0x6D, 0x9D, 0x84,
0xA4, 0x61, 0x96, 0x12, 0xC2, 0xED, 0xC3, 0xDA, 0x23, 0x34, 0x19, 0x76,
0xF6, 0xEA, 0xFD, 0x55, 0x5A, 0xF6, 0x55, 0x01, 0x53, 0x0F, 0xF2, 0xCC,
0x8C, 0x97, 0x4F, 0xB9, 0x50, 0xCB, 0xB3, 0x01, 0x44, 0x56, 0x96, 0xFD,
0x9B, 0x28, 0xEC, 0x7B, 0x74, 0x0B, 0xE7, 0x42, 0x6B, 0x55, 0xCE, 0xC9,
0x61, 0xB2, 0xE8, 0xAD, 0x40, 0x3C, 0xBA, 0xB9, 0x41, 0x0A, 0x05, 0x4F,
0x1B, 0x26, 0x85, 0x8F, 0x43, 0xB5, 0x40, 0xB5, 0x85, 0xD1, 0xD4, 0x71,
0xDC, 0x83, 0x41, 0xF3, 0xF6, 0x45, 0xC7, 0x80, 0xA2, 0x84, 0x50, 0x97,
0x46, 0xCE, 0xA0, 0x0C, 0xC4, 0x60, 0x56, 0x04, 0x1D, 0x07, 0x5B, 0x46,
0xA5, 0x0E, 0xB2, 0x4B, 0xA4, 0x0E, 0xA5, 0x7C, 0xEE, 0xF8, 0xD4, 0x62,
0x03, 0xB9, 0x93, 0x6A, 0x8A, 0x14, 0xB8, 0x70, 0xF8, 0x2E, 0x82, 0x46,
0x38, 0x23, 0x0E, 0x74, 0xC7, 0x6B, 0x41, 0xB7, 0xD0, 0x29, 0xA3, 0x9D,
0x80, 0xB0, 0x7E, 0x77, 0x93, 0x63, 0x42, 0xFB, 0x34, 0x83, 0x3B, 0x73,
0xA3, 0x5A, 0x21, 0x36, 0xEB, 0x47, 0xFA, 0x18, 0x17, 0xD9, 0xBA, 0x66,
0xC2, 0x93, 0xA4, 0x8F, 0xFC, 0x5D, 0xA4, 0xAD, 0xFC, 0x50, 0x6A, 0x95,
0xAC, 0xBC, 0x24, 0x33, 0xD1, 0xBD, 0x88, 0x7F, 0x86, 0xF5, 0xF5, 0xB2,
0x73, 0x2A, 0x8F, 0x7C, 0xAF, 0x08, 0xF2, 0x1A, 0x98, 0x3F, 0xA9, 0x81,
0x65, 0x3F, 0xC1, 0x8C, 0x89, 0xC5, 0x96, 0x30, 0x9A, 0x0A, 0xCF, 0xF4,
0xD4, 0xC8, 0x34, 0xED, 0x9D, 0x2F, 0xBC, 0x8D, 0x38, 0x86, 0x53, 0xEE,
0x97, 0x9F, 0xA9, 0xB2, 0x63, 0x94, 0x17, 0x8D, 0x0F, 0xDC, 0x66, 0x2A,
0x7C, 0x52, 0x51, 0x75, 0xCB, 0x99, 0x8E, 0xE8, 0x3D, 0x5C, 0xBF, 0x9E,
0x3B, 0x28, 0x8D, 0x83, 0x02, 0x0F, 0xA9, 0x9F, 0x72, 0xE2, 0x2C, 0x2B,
0xB3, 0xDC, 0x66, 0x97, 0x00, 0x40, 0xD0, 0xA4, 0x54, 0x8E, 0x9B, 0x5D,
0x7B, 0x45, 0x36, 0x26, 0xD6, 0x72, 0x43, 0xEB, 0xCF, 0xC0, 0xEA, 0x0D,
0xDC, 0xCE, 0x12, 0xE6, 0x7D, 0x38, 0x9F, 0x05, 0x27, 0xA8, 0x97, 0x3E,
0xE9, 0x51, 0xC6, 0x6C, 0x05, 0x28, 0xC1, 0x02, 0x0F, 0xE9, 0x18, 0x6D,
0xEC, 0xBD, 0x9C, 0x06, 0xD4, 0xA7, 0x49, 0xF4, 0x54, 0x05, 0x6B, 0x6C,
0x30, 0xF1, 0xEB, 0x03, 0xD5, 0xEA, 0x3D, 0x6A, 0x76, 0xC2, 0xCB, 0x1A,
0x28, 0x49, 0x4D, 0x7F, 0x64, 0xE0, 0xFA, 0x2B, 0xDA, 0x73, 0x83, 0x81,
0xFF, 0x91, 0x03, 0xBD, 0x94, 0xBB, 0xE4, 0xB8, 0x8E, 0x9C, 0x32, 0x63,
0xCD, 0x9F, 0xBB, 0x68, 0x81, 0xB1, 0x84, 0x5B, 0xAF, 0x36, 0xBF, 0x77,
0xEE, 0x1D, 0x7F, 0xF7, 0x49, 0x9B, 0x52, 0xEC, 0xD2, 0x77, 0x5A, 0x7D,
0x91, 0x9D, 0x4D, 0xC2, 0x39, 0x2D, 0xE4, 0xBA, 0x82, 0xF8, 0x6F, 0xF2,
0x4E, 0x1E, 0x0F, 0x4E, 0xE6, 0x3F, 0x59, 0xA5, 0x23, 0xDC, 0x3D, 0x87,
0xA8, 0x28, 0x58, 0x28, 0xD1, 0xF1, 0x1B, 0x36, 0xDB, 0x4F, 0xC4, 0xFF,
0xE1, 0x8C, 0x5B, 0x72, 0x8C, 0xC7, 0x26, 0x03, 0x27, 0xA3, 0x39, 0x0A,
0x01, 0xAA, 0xC0, 0xB2, 0x31, 0x60, 0x83, 0x22, 0xA1, 0x4F, 0x12, 0x09,
0x01, 0x11, 0xAF, 0x34, 0xD4, 0xCF, 0xD7, 0xAE, 0x62, 0xD3, 0x05, 0x07,
0xB4, 0x31, 0x75, 0xE0, 0x0D, 0x6D, 0x57, 0x4F, 0x69, 0x87, 0xF9, 0x57,
0xA9, 0xBA, 0x15, 0xF6, 0xC8, 0x52, 0x6D, 0xA1, 0xCB, 0x9C, 0x1F, 0xE5,
0xFC, 0x78, 0xA8, 0x35, 0x9A, 0x9F, 0x41, 0x14, 0xCE, 0xA5, 0xB4, 0xCE,
0x94, 0x08, 0x1C, 0x09, 0xAD, 0x56, 0xE5, 0xDA, 0xB6, 0x49, 0x9A, 0x4A,
0xEA, 0x63, 0x18, 0x53, 0x9C, 0x2C, 0x2E, 0xC3
};
static const unsigned char TA139_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA140_DN[] = {
0x30, 0x4E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x55, 0x53, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x09, 0x43, 0x6F, 0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x31,
0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x43, 0x6F,
0x6D, 0x6D, 0x53, 0x63, 0x6F, 0x70, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C,
0x69, 0x63, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x52, 0x53, 0x41,
0x20, 0x52, 0x6F, 0x6F, 0x74, 0x2D, 0x30, 0x32
};
static const unsigned char TA140_RSA_N[] = {
0xE1, 0xFA, 0x0E, 0xFB, 0x68, 0x00, 0x12, 0xC8, 0x4D, 0xD5, 0xAC, 0x22,
0xC4, 0x35, 0x01, 0x3B, 0xC5, 0x54, 0xE5, 0x59, 0x76, 0x63, 0xA5, 0x7F,
0xEB, 0xC1, 0xC4, 0x6A, 0x98, 0xBD, 0x32, 0x8D, 0x17, 0x80, 0xEB, 0x5D,
0xBA, 0xD1, 0x62, 0x3D, 0x25, 0x23, 0x19, 0x35, 0x14, 0xE9, 0x7F, 0x89,
0xA7, 0x1B, 0x62, 0x3C, 0xD6, 0x50, 0xE7, 0x34, 0x95, 0x03, 0x32, 0xB1,
0xB4, 0x93, 0x22, 0x3D, 0xA7, 0xE2, 0xB1, 0xED, 0xE6, 0x7B, 0x4E, 0x2E,
0x87, 0x9B, 0x0D, 0x33, 0x75, 0x0A, 0xDE, 0xAA, 0x35, 0xE7, 0x7E, 0xE5,
0x36, 0x98, 0xA2, 0xAE, 0x25, 0x9E, 0x95, 0xB3, 0x32, 0x96, 0xA4, 0x2B,
0x58, 0x1E, 0xEF, 0x3F, 0xFE, 0x62, 0x34, 0x48, 0x51, 0xD1, 0xB4, 0x8D,
0x42, 0xAD, 0x60, 0xDA, 0x49, 0x6A, 0x95, 0x70, 0xDD, 0xD2, 0x00, 0xE2,
0xCC, 0x57, 0x63, 0x02, 0x7B, 0x96, 0xDD, 0x49, 0x97, 0x5B, 0x92, 0x4E,
0x95, 0xD3, 0xF9, 0xCB, 0x29, 0x1F, 0x18, 0x4A, 0xF8, 0x01, 0x2A, 0xD2,
0x63, 0x09, 0x6E, 0x24, 0xE9, 0x89, 0xD2, 0xE5, 0xC7, 0x22, 0x4C, 0xDC,
0x73, 0x86, 0x47, 0x00, 0xAA, 0x0D, 0x88, 0x8E, 0xAE, 0x85, 0x7D, 0x4A,
0xE9, 0xBB, 0x33, 0x4F, 0x0E, 0x52, 0x70, 0x9D, 0x95, 0xE3, 0x7C, 0x6D,
0x96, 0x5B, 0x2D, 0x3D, 0x5F, 0xA1, 0x83, 0x46, 0x5D, 0xB6, 0xE3, 0x25,
0xB8, 0x7C, 0xA7, 0x19, 0x80, 0x1C, 0xEA, 0x65, 0x43, 0xDC, 0x91, 0x79,
0x36, 0x2C, 0x74, 0x7C, 0xF2, 0x67, 0x06, 0xC9, 0x89, 0xC9, 0xDB, 0xBF,
0xDA, 0x68, 0xBF, 0x23, 0xED, 0xDC, 0x6B, 0xAD, 0x28, 0x83, 0x79, 0x2F,
0xEC, 0x38, 0xA5, 0x0D, 0x37, 0x01, 0x67, 0x27, 0x9A, 0xE9, 0x33, 0xD9,
0x33, 0x5F, 0x37, 0xA1, 0xC5, 0xF0, 0xAB, 0x3D, 0xFA, 0x78, 0xB0, 0xE7,
0x2C, 0x9F, 0xF6, 0x3E, 0x9F, 0x60, 0xE0, 0xEF, 0x48, 0xE9, 0x90, 0x45,
0x1E, 0x05, 0x51, 0x78, 0x1A, 0x2C, 0x12, 0x2C, 0x5C, 0x28, 0xAC, 0x0D,
0xA2, 0x23, 0x9E, 0x34, 0x8F, 0x05, 0xE6, 0xA2, 0x33, 0xCE, 0x11, 0x77,
0x13, 0xD4, 0x0E, 0xA4, 0x1E, 0x42, 0x1F, 0x86, 0xCD, 0x70, 0xFE, 0xD9,
0x2E, 0x15, 0x3D, 0x1D, 0xBB, 0xB8, 0xF2, 0x53, 0x57, 0xDB, 0xCC, 0xC6,
0x74, 0x29, 0x9C, 0x18, 0xB3, 0x36, 0x75, 0x38, 0x2E, 0x0F, 0x54, 0xA1,
0xF8, 0x92, 0x1F, 0x89, 0x96, 0x4F, 0xBB, 0xD4, 0xEE, 0x9D, 0xE9, 0x3B,
0x36, 0x42, 0xB5, 0x0A, 0x3B, 0x2A, 0xD4, 0x64, 0x79, 0x36, 0x10, 0xE1,
0xF9, 0x91, 0x03, 0x2B, 0x7B, 0x20, 0x54, 0xCD, 0x0D, 0x19, 0x1A, 0xC8,
0x41, 0x32, 0x34, 0xD1, 0xB0, 0x99, 0xE1, 0x90, 0x1E, 0x01, 0x40, 0x36,
0xB5, 0xB7, 0xFA, 0xA9, 0xE5, 0x77, 0x75, 0xA4, 0x22, 0x81, 0x5D, 0xB0,
0x8B, 0xE4, 0x27, 0x12, 0x0F, 0x54, 0x88, 0xC6, 0xDB, 0x85, 0x74, 0xE6,
0xB7, 0xC0, 0xD7, 0xA6, 0x29, 0xFA, 0xDB, 0xDE, 0xF3, 0x93, 0x97, 0x27,
0x04, 0x55, 0x2F, 0x0A, 0x6F, 0x37, 0xC5, 0x3D, 0x13, 0xAF, 0x0A, 0x00,
0xA9, 0x2C, 0x8B, 0x1C, 0x81, 0x28, 0xD7, 0xEF, 0x86, 0x31, 0xA9, 0xAE,
0xF2, 0x6E, 0xB8, 0xCA, 0x6A, 0x2C, 0x54, 0x47, 0xD8, 0x2A, 0x88, 0x2E,
0xAF, 0xC1, 0x07, 0x10, 0x78, 0xAC, 0x11, 0xA2, 0x2F, 0x42, 0xF0, 0x37,
0xC5, 0xF2, 0xB8, 0x56, 0xDD, 0x0E, 0x62, 0x2D, 0xCE, 0x2D, 0x56, 0x7E,
0x55, 0xF2, 0xA7, 0x44, 0xF6, 0x2B, 0x32, 0xF4, 0x23, 0xA8, 0x47, 0xE8,
0xD4, 0x2A, 0x01, 0x78, 0xCF, 0x6A, 0xC3, 0x37, 0xA8, 0x9E, 0x65, 0xD2,
0x2C, 0xE5, 0xFA, 0xBA, 0x33, 0xC1, 0x06, 0x44, 0xF6, 0xE6, 0xCF, 0xA5,
0x0D, 0xA7, 0x66, 0x08, 0x34, 0x8A, 0x2C, 0xF3
};
static const unsigned char TA140_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA141_DN[] = {
0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54,
0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72,
0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B,
0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20,
0x54, 0x4C, 0x53, 0x20, 0x45, 0x43, 0x43, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x32, 0x30, 0x32, 0x30
};
static const unsigned char TA141_EC_Q[] = {
0x04, 0xCE, 0xBF, 0xFE, 0x57, 0xA8, 0xBF, 0xD5, 0xAA, 0xF7, 0x10, 0x9A,
0xCD, 0xBC, 0xD1, 0x11, 0xA2, 0xBD, 0x67, 0x42, 0xCC, 0x90, 0xEB, 0x15,
0x18, 0x90, 0xD9, 0xA2, 0xCD, 0x0C, 0x2A, 0x25, 0xEB, 0x3E, 0x4F, 0xCE,
0xB5, 0xD2, 0x8F, 0x0F, 0xF3, 0x35, 0xDA, 0x43, 0x8B, 0x02, 0x80, 0xBE,
0x6F, 0x51, 0x24, 0x1D, 0x0F, 0x6B, 0x2B, 0xCA, 0x9F, 0xC2, 0x6F, 0x50,
0x32, 0xE5, 0x37, 0x20, 0xB6, 0x20, 0xFF, 0x88, 0x0D, 0x0F, 0x6D, 0x49,
0xBB, 0xDB, 0x06, 0xA4, 0x87, 0x90, 0x92, 0x94, 0xF4, 0x09, 0xD0, 0xCF,
0x7F, 0xC8, 0x80, 0x0B, 0xC1, 0x97, 0xB3, 0xBB, 0x35, 0x27, 0xC9, 0xC2,
0x1B
};
static const unsigned char TA142_DN[] = {
0x30, 0x63, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x1E, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x65, 0x20, 0x54,
0x65, 0x6C, 0x65, 0x6B, 0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72,
0x69, 0x74, 0x79, 0x20, 0x47, 0x6D, 0x62, 0x48, 0x31, 0x2B, 0x30, 0x29,
0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x22, 0x54, 0x65, 0x6C, 0x65, 0x6B,
0x6F, 0x6D, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x20,
0x54, 0x4C, 0x53, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6F, 0x6F, 0x74,
0x20, 0x32, 0x30, 0x32, 0x33
};
static const unsigned char TA142_RSA_N[] = {
0xED, 0x35, 0xA1, 0x81, 0x80, 0xF3, 0xCB, 0x4A, 0x69, 0x5B, 0xC2, 0xFB,
0x51, 0x83, 0xAE, 0x26, 0xFD, 0xE1, 0x6E, 0xF3, 0x81, 0x12, 0x7D, 0x71,
0x40, 0xFF, 0x87, 0x75, 0x42, 0x29, 0x21, 0xED, 0x81, 0x52, 0x2C, 0xDF,
0x12, 0xC1, 0x19, 0x84, 0x89, 0xC1, 0xBD, 0xC5, 0x28, 0xD5, 0xD5, 0x4B,
0x6C, 0x44, 0xD6, 0x4C, 0xDB, 0x07, 0x96, 0x4A, 0x55, 0x7A, 0xCA, 0x36,
0x82, 0x04, 0x36, 0xA8, 0xA5, 0xFC, 0x27, 0xF6, 0x49, 0xF1, 0xD5, 0x72,
0x9E, 0x91, 0xF9, 0x23, 0xD6, 0x70, 0x7B, 0xBB, 0xF5, 0x9B, 0xC1, 0xEC,
0x93, 0xCF, 0x19, 0xEA, 0x65, 0x7E, 0x88, 0x70, 0xA0, 0x73, 0xFC, 0xF6,
0xFF, 0xB5, 0x56, 0x62, 0xE1, 0x73, 0x6A, 0x34, 0x98, 0x3E, 0x82, 0xB8,
0xAC, 0x95, 0x53, 0xF4, 0x01, 0xA0, 0x27, 0x07, 0x72, 0xA3, 0x00, 0x53,
0xA0, 0xE4, 0xB2, 0xAB, 0x83, 0x38, 0x57, 0x33, 0x25, 0x94, 0x9F, 0xBE,
0x48, 0x1D, 0x98, 0xE1, 0xA3, 0xBA, 0x9E, 0x5C, 0xCD, 0x04, 0x71, 0x51,
0x7D, 0x75, 0x78, 0xAB, 0xF3, 0x59, 0xAA, 0xC4, 0xE0, 0x60, 0xBE, 0x8F,
0x83, 0x52, 0xB8, 0x75, 0x1A, 0x41, 0x35, 0xED, 0xBC, 0xF3, 0x3A, 0x63,
0xE9, 0xA9, 0x14, 0x45, 0xD7, 0xE6, 0x52, 0xD1, 0x6E, 0xD2, 0xDE, 0xBC,
0xE3, 0xF5, 0x0B, 0x3B, 0xE6, 0xE0, 0xC4, 0xBD, 0x43, 0x64, 0x13, 0xA6,
0xCE, 0xF4, 0x98, 0x37, 0x6C, 0x8A, 0x95, 0xA8, 0x97, 0xC8, 0x47, 0x0F,
0xF0, 0x5E, 0x10, 0x8B, 0xE7, 0x1D, 0x1C, 0xFE, 0xB1, 0x3B, 0xA0, 0x05,
0x33, 0x68, 0x05, 0x41, 0x82, 0xC1, 0x03, 0x2B, 0x01, 0xC8, 0xE7, 0x8F,
0x4D, 0xAB, 0xE8, 0xB5, 0xF6, 0xCD, 0x6B, 0x44, 0xB5, 0xE7, 0xDD, 0x8B,
0xEC, 0xEA, 0x25, 0xB4, 0x00, 0x22, 0x57, 0x4D, 0xB0, 0xB1, 0xB2, 0x31,
0xC1, 0x16, 0xCE, 0xFF, 0xFD, 0x14, 0x84, 0xB7, 0x47, 0xFA, 0xB2, 0xF1,
0x70, 0xDE, 0xDB, 0x8B, 0x6C, 0x36, 0x58, 0xA4, 0x7C, 0xB3, 0x11, 0xD1,
0xC3, 0x77, 0x7F, 0x5F, 0xB6, 0x25, 0xE0, 0x0D, 0xC5, 0xD2, 0xB3, 0xF9,
0xB8, 0xB8, 0x77, 0xDB, 0x37, 0x71, 0x71, 0x47, 0xE3, 0x60, 0x18, 0x4F,
0x24, 0xB6, 0x75, 0x37, 0x78, 0xB9, 0xA3, 0x62, 0xAF, 0xBD, 0xC9, 0x72,
0x8E, 0x2F, 0xCC, 0xBB, 0xAE, 0xDB, 0xE4, 0x15, 0x52, 0x19, 0x07, 0x33,
0xFB, 0x6A, 0xB7, 0x2D, 0x4B, 0x90, 0x28, 0x82, 0x73, 0xFE, 0x18, 0x8B,
0x35, 0x8D, 0xDB, 0xA7, 0x04, 0x6A, 0xBE, 0xEA, 0xC1, 0x4D, 0x36, 0x3B,
0x16, 0x36, 0x91, 0x32, 0xEF, 0xB6, 0x40, 0x89, 0x91, 0x43, 0xE0, 0xF2,
0xA2, 0xAB, 0x04, 0x2E, 0xE6, 0xF2, 0x4C, 0x0E, 0x16, 0x34, 0x20, 0xAC,
0x87, 0xC1, 0x2D, 0x7E, 0xC9, 0x66, 0x47, 0x17, 0x14, 0x11, 0xA4, 0xF3,
0xF7, 0xA1, 0x24, 0x89, 0xAB, 0xD8, 0x1A, 0xC8, 0xA1, 0x5C, 0xB1, 0xA3,
0xF7, 0x8C, 0x6D, 0xC8, 0x01, 0xC9, 0x4F, 0xC9, 0xEC, 0xC4, 0xFC, 0xAC,
0x51, 0x33, 0xD1, 0xC8, 0x83, 0xD1, 0xC9, 0x9F, 0x1D, 0xD4, 0x47, 0x34,
0x29, 0x3E, 0xCB, 0xB0, 0x0E, 0xFA, 0x83, 0x0B, 0x28, 0x58, 0xE5, 0x29,
0xDC, 0x3F, 0x7C, 0xA8, 0x9F, 0xC9, 0xB6, 0x0A, 0xBB, 0xA6, 0xE8, 0x46,
0x16, 0x0F, 0x96, 0xE5, 0x7B, 0xE4, 0x6A, 0x7A, 0x48, 0x6D, 0x76, 0x98,
0x05, 0xA5, 0xDC, 0x6D, 0x1E, 0x42, 0x1E, 0x42, 0xDA, 0x1A, 0xE0, 0x52,
0xF7, 0xB5, 0x83, 0xC0, 0x1A, 0x7B, 0x78, 0x35, 0x2C, 0x38, 0xF5, 0x1F,
0xFD, 0x49, 0xA3, 0x2E, 0xD2, 0x59, 0x63, 0xBF, 0x80, 0xB0, 0x8C, 0x93,
0x73, 0xCB, 0x35, 0xA6, 0x99, 0x95, 0x22, 0x61, 0x65, 0x03, 0x60, 0xFB,
0x2F, 0x93, 0x4B, 0xFA, 0x9A, 0x9C, 0x80, 0x3B
};
static const unsigned char TA142_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA143_DN[] = {
0x30, 0x6E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x45, 0x53, 0x31, 0x1C, 0x30, 0x1A, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x0C, 0x13, 0x46, 0x69, 0x72, 0x6D, 0x61, 0x70, 0x72, 0x6F, 0x66, 0x65,
0x73, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x20, 0x53, 0x41, 0x31, 0x18, 0x30,
0x16, 0x06, 0x03, 0x55, 0x04, 0x61, 0x0C, 0x0F, 0x56, 0x41, 0x54, 0x45,
0x53, 0x2D, 0x41, 0x36, 0x32, 0x36, 0x33, 0x34, 0x30, 0x36, 0x38, 0x31,
0x27, 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1E, 0x46, 0x49,
0x52, 0x4D, 0x41, 0x50, 0x52, 0x4F, 0x46, 0x45, 0x53, 0x49, 0x4F, 0x4E,
0x41, 0x4C, 0x20, 0x43, 0x41, 0x20, 0x52, 0x4F, 0x4F, 0x54, 0x2D, 0x41,
0x20, 0x57, 0x45, 0x42
};
static const unsigned char TA143_EC_Q[] = {
0x04, 0x47, 0x53, 0xEA, 0x2C, 0x11, 0xA4, 0x77, 0xC7, 0x2A, 0xEA, 0xF3,
0xD6, 0x5F, 0x7B, 0xD3, 0x04, 0x91, 0x5C, 0xFA, 0x88, 0xC6, 0x22, 0xB9,
0x83, 0x10, 0x62, 0x77, 0x84, 0x33, 0x2D, 0xE9, 0x03, 0x88, 0xD4, 0xE0,
0x33, 0xF7, 0xED, 0x77, 0x2C, 0x4A, 0x60, 0xEA, 0xE4, 0x6F, 0xAD, 0x6D,
0xB4, 0xF8, 0x4C, 0x8A, 0xA4, 0xE4, 0x1F, 0xCA, 0xEA, 0x4F, 0x38, 0x4A,
0x2E, 0x82, 0x73, 0x2B, 0xC7, 0x66, 0x9B, 0x0A, 0x8C, 0x40, 0x9C, 0x7C,
0x8A, 0xF6, 0xF2, 0x39, 0x60, 0xB2, 0xDE, 0xCB, 0xEC, 0xB8, 0xE4, 0x6F,
0xEA, 0x9B, 0x5D, 0xB7, 0x53, 0x90, 0x18, 0x32, 0x55, 0xC5, 0x20, 0xB7,
0x94
};
static const unsigned char TA144_DN[] = {
0x30, 0x50, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x54, 0x57, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x09, 0x54, 0x41, 0x49, 0x57, 0x41, 0x4E, 0x2D, 0x43, 0x41, 0x31,
0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x52, 0x6F,
0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03, 0x55,
0x04, 0x03, 0x13, 0x12, 0x54, 0x57, 0x43, 0x41, 0x20, 0x43, 0x59, 0x42,
0x45, 0x52, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41
};
static const unsigned char TA144_RSA_N[] = {
0xC6, 0xF8, 0xCA, 0x1E, 0xD9, 0x09, 0x20, 0x7E, 0x1D, 0x6C, 0x4E, 0xCE,
0x8F, 0xE3, 0x47, 0x33, 0x44, 0x9C, 0xC7, 0xC9, 0x69, 0xAA, 0x3A, 0x5B,
0x78, 0xEE, 0x70, 0xD2, 0x92, 0xF8, 0x04, 0xB3, 0x52, 0x52, 0x1D, 0x67,
0x72, 0x28, 0xA1, 0xDF, 0x8B, 0x5D, 0x95, 0x0A, 0xFE, 0xEA, 0xCD, 0xED,
0xF7, 0x29, 0xCE, 0xF0, 0x6F, 0x7F, 0xAC, 0xCD, 0x3D, 0xEF, 0xB3, 0x1C,
0x45, 0x6A, 0xF7, 0x28, 0x90, 0xF1, 0x61, 0x57, 0xC5, 0x0C, 0xC4, 0xA3,
0x50, 0x5D, 0xDE, 0xD4, 0xB5, 0xCB, 0x19, 0xCA, 0x80, 0xB9, 0x75, 0xCE,
0x29, 0xCE, 0xD2, 0x85, 0x22, 0xEC, 0x02, 0x63, 0xCC, 0x44, 0x30, 0x20,
0xDA, 0xEA, 0x91, 0x5B, 0x56, 0xE6, 0x1D, 0x1C, 0xD5, 0x9D, 0x66, 0xC7,
0x3F, 0xDF, 0x86, 0xCA, 0x4B, 0x53, 0xC4, 0xD9, 0x8D, 0xB2, 0x1D, 0xEA,
0xF8, 0xDC, 0x27, 0x53, 0xA3, 0x47, 0xE1, 0x61, 0xCC, 0x7D, 0xB5, 0xB0,
0xF8, 0xEE, 0x73, 0x91, 0xC5, 0xCE, 0x73, 0x6F, 0xCE, 0xEE, 0x10, 0x1F,
0x1A, 0x06, 0xCF, 0xE9, 0x27, 0x60, 0xC5, 0x4F, 0x19, 0xE4, 0xEB, 0xCE,
0x22, 0x26, 0x45, 0xD7, 0x60, 0x99, 0xDD, 0xCE, 0x4F, 0x37, 0xE0, 0x7F,
0xE7, 0x63, 0xAD, 0xB0, 0xB8, 0x59, 0xB8, 0xD0, 0x06, 0x68, 0x35, 0x60,
0xD3, 0x36, 0xAE, 0x71, 0x43, 0x04, 0xF1, 0x69, 0x65, 0x78, 0x7C, 0xF3,
0x1F, 0xF3, 0xCA, 0x28, 0x9F, 0x5A, 0x20, 0x95, 0x66, 0xB4, 0xCD, 0xB7,
0xEE, 0x8F, 0x78, 0xA4, 0x45, 0x18, 0xE9, 0x26, 0x2F, 0x8D, 0x9B, 0x29,
0x28, 0xB1, 0xA4, 0xB7, 0x3A, 0x6D, 0xB9, 0xD4, 0x1C, 0x38, 0x72, 0x45,
0x58, 0xB1, 0x5E, 0xEB, 0xF0, 0x28, 0x9B, 0xB7, 0x82, 0xCA, 0xFD, 0xCF,
0xD6, 0x33, 0x0F, 0x9F, 0xFB, 0x97, 0x9E, 0xB1, 0x1C, 0x9C, 0x9E, 0xEA,
0x5F, 0x5E, 0xDB, 0xAA, 0xDD, 0x54, 0xE9, 0x30, 0x21, 0x28, 0x6D, 0x8E,
0x79, 0xF3, 0x75, 0x92, 0x8C, 0x26, 0xFE, 0xDC, 0xC5, 0xF6, 0xC3, 0xB0,
0xDF, 0x44, 0x59, 0x43, 0xA3, 0xB6, 0x03, 0x28, 0xF6, 0x08, 0x30, 0xAA,
0x0D, 0x33, 0xE1, 0xEF, 0x9C, 0xA9, 0x07, 0x22, 0xE3, 0x59, 0x5B, 0x40,
0x8F, 0xDA, 0x88, 0xB7, 0x69, 0x08, 0xA8, 0xB7, 0x23, 0x2E, 0x44, 0x09,
0x59, 0x37, 0x5B, 0xC7, 0xE3, 0x17, 0xF2, 0x22, 0xEB, 0x6E, 0x39, 0x52,
0xC5, 0xDE, 0x54, 0xA7, 0x98, 0xC9, 0x4B, 0x20, 0x95, 0xDC, 0x46, 0x89,
0x5F, 0xB4, 0x12, 0xF9, 0x85, 0x29, 0x8E, 0xEB, 0xC8, 0x27, 0x15, 0x20,
0xC0, 0x4B, 0xD4, 0xCC, 0x7C, 0x0C, 0x6C, 0x34, 0x0C, 0x26, 0x9B, 0x26,
0x31, 0xA6, 0x3C, 0xA7, 0xF6, 0xD9, 0xD0, 0x4B, 0xA2, 0x64, 0xFF, 0x3B,
0x99, 0x41, 0x72, 0xC1, 0xE0, 0x70, 0x97, 0xF1, 0x24, 0xBB, 0x2B, 0xC4,
0x74, 0x22, 0xB1, 0xAC, 0x6B, 0x22, 0x32, 0x24, 0xD3, 0x78, 0x2A, 0xC0,
0xC0, 0xA1, 0x2F, 0xF1, 0x52, 0x05, 0xC9, 0x3F, 0xEF, 0x76, 0x66, 0xE2,
0x45, 0xD8, 0x0D, 0x3D, 0xAD, 0x95, 0xC8, 0xC7, 0x89, 0x26, 0xC8, 0x0F,
0xAE, 0xA7, 0x03, 0x2E, 0xFB, 0xC1, 0x5F, 0xFA, 0x20, 0xE1, 0x70, 0xAD,
0xB0, 0x65, 0x20, 0x37, 0x33, 0x60, 0xB0, 0xD5, 0xAF, 0xD7, 0x0C, 0x1C,
0xC2, 0x90, 0x70, 0xD7, 0x4A, 0x18, 0xBC, 0x7E, 0x01, 0xB0, 0xB0, 0xEB,
0x15, 0x1E, 0x44, 0x06, 0xCD, 0xA4, 0x4F, 0xE8, 0x0C, 0xD1, 0xC3, 0x20,
0x10, 0xE1, 0x54, 0x65, 0x9E, 0xB6, 0x51, 0xD0, 0x1A, 0x76, 0x6B, 0x42,
0x5A, 0x58, 0x76, 0x34, 0xEA, 0xB7, 0x37, 0x19, 0xAE, 0x2E, 0x75, 0xF9,
0x96, 0xE5, 0xC1, 0x59, 0xF7, 0x94, 0x57, 0x29, 0x25, 0x8D, 0x3A, 0x4C,
0xAB, 0x4D, 0x9A, 0x41, 0xD0, 0x5F, 0x26, 0x03
};
static const unsigned char TA144_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA145_DN[] = {
0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74,
0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20,
0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x32
};
static const unsigned char TA145_RSA_N[] = {
0xBA, 0x39, 0xC1, 0x37, 0x7A, 0x68, 0x45, 0x2B, 0x14, 0xB4, 0xEB, 0xE4,
0x13, 0xEB, 0x57, 0x75, 0x23, 0x4D, 0x8F, 0x24, 0x2D, 0x16, 0xE8, 0xAE,
0x8E, 0xC9, 0x7D, 0xA4, 0x57, 0x3B, 0x2A, 0x76, 0x25, 0x33, 0x83, 0x6C,
0xEA, 0x32, 0x8A, 0x94, 0x9B, 0x4E, 0x3C, 0x96, 0xE4, 0xFD, 0x51, 0xBF,
0x99, 0xC9, 0x93, 0x7E, 0xBF, 0xF9, 0xAD, 0xA7, 0xB2, 0x48, 0x2B, 0x07,
0x1C, 0x27, 0xF5, 0x4C, 0xBC, 0x70, 0x12, 0x77, 0xA4, 0x85, 0x54, 0xB5,
0xFD, 0x90, 0x7A, 0xE4, 0xA3, 0xE4, 0x51, 0x58, 0x03, 0xCD, 0x10, 0x79,
0x79, 0xEE, 0x6B, 0x93, 0x1F, 0x64, 0x8E, 0x6B, 0x64, 0xAB, 0xA3, 0x13,
0xE3, 0x71, 0xFE, 0x7D, 0xAB, 0x9C, 0xDD, 0x27, 0x53, 0x37, 0xB3, 0xAA,
0x18, 0xC2, 0x59, 0x26, 0xEC, 0x5B, 0x1F, 0xD2, 0xE6, 0x65, 0x7C, 0xEF,
0x93, 0xBD, 0xD8, 0x58, 0x5C, 0x0B, 0xC0, 0xE3, 0x65, 0x6F, 0x3C, 0xC7,
0xCA, 0x59, 0xE3, 0xFE, 0x6E, 0x5F, 0xAC, 0x83, 0xBE, 0xFD, 0x5D, 0x25,
0x4E, 0x2A, 0x29, 0x3B, 0xD6, 0x0B, 0xAB, 0x17, 0x32, 0x78, 0xA4, 0xE1,
0x3E, 0x94, 0x46, 0xBE, 0x62, 0x6E, 0x9B, 0xDE, 0x46, 0xA8, 0xB1, 0x16,
0xE7, 0x85, 0x6E, 0xF4, 0x08, 0x40, 0x45, 0x11, 0xA0, 0x9E, 0x54, 0x44,
0x84, 0xF7, 0xD8, 0x36, 0xCE, 0xF5, 0x50, 0x47, 0xDC, 0x2C, 0x30, 0x9B,
0xEE, 0xC0, 0xF5, 0x96, 0xD2, 0xFE, 0x09, 0x86, 0xC7, 0x06, 0x59, 0xAE,
0x4F, 0xAE, 0x8E, 0x11, 0x98, 0x7B, 0xF3, 0x0B, 0x52, 0xAA, 0x62, 0x26,
0xAA, 0x21, 0xDF, 0x8E, 0x25, 0x33, 0x79, 0x97, 0x16, 0x49, 0x8D, 0xF5,
0x3E, 0xD5, 0x47, 0x9F, 0x37, 0x31, 0x49, 0x33, 0x72, 0x05, 0x4D, 0x0C,
0xB6, 0x55, 0x8C, 0xF1, 0x57, 0x8F, 0x8A, 0x87, 0xD1, 0xAD, 0xC5, 0x11,
0x12, 0x39, 0xA0, 0xAD
};
static const unsigned char TA145_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA146_DN[] = {
0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74,
0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20,
0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x34
};
static const unsigned char TA146_RSA_N[] = {
0xC5, 0xD2, 0x7A, 0xA1, 0xD6, 0x8A, 0xBF, 0x16, 0x31, 0xD0, 0x98, 0xD1,
0x3A, 0x94, 0xFC, 0x5A, 0xB8, 0x6E, 0x22, 0xC1, 0x62, 0xF7, 0xA7, 0x0A,
0x27, 0xEF, 0x50, 0xF6, 0x2E, 0xB1, 0x9E, 0x68, 0x12, 0xF0, 0x6C, 0x24,
0x63, 0x39, 0xF1, 0xF0, 0xDF, 0x10, 0xC6, 0xDE, 0xB7, 0x52, 0x20, 0xD5,
0x52, 0x5B, 0x42, 0x99, 0x9E, 0xF3, 0xA0, 0xBE, 0x52, 0x1F, 0x5F, 0xCC,
0x67, 0x6D, 0xA7, 0x2E, 0x50, 0xA2, 0xC1, 0x97, 0x8D, 0xB6, 0xF8, 0x95,
0xF5, 0xB0, 0xBA, 0xDC, 0x9D, 0xE0, 0xBE, 0xCB, 0xDF, 0xF7, 0x38, 0xF2,
0x47, 0xF5, 0xA6, 0x9A, 0x92, 0x95, 0x2A, 0x62, 0x59, 0x50, 0x0B, 0xA2,
0xB1, 0x35, 0xE7, 0x65, 0xB2, 0x61, 0xB2, 0xEA, 0x92, 0x71, 0x69, 0xE4,
0x29, 0xF0, 0x4F, 0x81, 0x81, 0x04, 0x3C, 0xB2, 0xA5, 0x5B, 0xD4, 0xC5,
0xA8, 0x59, 0x67, 0x7B, 0x55, 0x1C, 0x49, 0xAB, 0x7A, 0x9D, 0xC2, 0xE7,
0x73, 0x4D, 0xEF, 0xCD, 0x09, 0xC2, 0xC4, 0x57, 0x12, 0xDB, 0x01, 0x0E,
0x23, 0x79, 0x09, 0x07, 0x3B, 0xA2, 0xE8, 0xFC, 0x8A, 0xCF, 0x8F, 0xC0,
0x46, 0x24, 0x9C, 0x38, 0x27, 0xE0, 0x83, 0x9D, 0x1B, 0xA0, 0xBF, 0x78,
0x15, 0x10, 0xEB, 0x86, 0x4E, 0x0A, 0x5A, 0xFD, 0xDF, 0xDA, 0x2C, 0x82,
0x7E, 0xEE, 0xCA, 0xF6, 0x29, 0xE1, 0xFA, 0x71, 0xA1, 0xF7, 0x88, 0x68,
0x9C, 0x9C, 0xF0, 0x8D, 0xBE, 0x0F, 0x49, 0x91, 0xD8, 0xEA, 0x3A, 0xF9,
0xFD, 0xD0, 0x68, 0x71, 0xDB, 0xE9, 0xB5, 0x2B, 0x4E, 0x82, 0x92, 0x6F,
0x66, 0x1F, 0xE0, 0xF0, 0xDC, 0x4C, 0xEC, 0xCA, 0xD1, 0xEA, 0xBA, 0x74,
0x06, 0xF9, 0xB3, 0x84, 0x90, 0x94, 0xD1, 0x5F, 0x8E, 0x73, 0x19, 0x10,
0x5D, 0x02, 0xE5, 0x70, 0xA5, 0xC0, 0x10, 0xD0, 0x10, 0x7C, 0x6F, 0xC5,
0x58, 0x49, 0xB4, 0xB0, 0x6E, 0x9A, 0xDA, 0x7D, 0x95, 0xF5, 0xCC, 0xDA,
0x02, 0xAF, 0xB8, 0x2C, 0x7D, 0x79, 0x8F, 0xBE, 0x43, 0xF1, 0xF9, 0x28,
0x28, 0x8D, 0x09, 0x43, 0xF8, 0x08, 0xDD, 0x6B, 0xC8, 0x8B, 0x2C, 0x24,
0xB1, 0x8D, 0x52, 0x07, 0xBD, 0x78, 0x9B, 0xCB, 0xCA, 0x68, 0xB2, 0xA4,
0xDD, 0x0C, 0x4C, 0x79, 0x60, 0xC6, 0x99, 0xD1, 0x93, 0xF1, 0x30, 0x1A,
0x07, 0xD3, 0xAE, 0x22, 0xC2, 0xEA, 0xCE, 0xF1, 0x84, 0x09, 0xCC, 0xE0,
0x14, 0x6E, 0x7F, 0x3F, 0x7E, 0xD2, 0x82, 0x85, 0xAC, 0xDC, 0xA9, 0x16,
0x4E, 0x85, 0xA0, 0x60, 0xCB, 0xF6, 0x9C, 0xD7, 0xC8, 0xB3, 0x8E, 0xED,
0xC6, 0x9B, 0x98, 0x75, 0x0D, 0x55, 0xE8, 0x5F, 0xE5, 0x95, 0x8B, 0x02,
0xA4, 0xAE, 0x43, 0x29, 0x28, 0x11, 0xA4, 0xE6, 0x12, 0x30, 0x01, 0x4B,
0x75, 0x6B, 0x1E, 0x66, 0x9D, 0x79, 0x2F, 0xA5, 0x76, 0x2F, 0x1D, 0x40,
0xB4, 0x6D, 0xC9, 0x7D, 0x79, 0x08, 0xEC, 0xD1, 0x6A, 0xB6, 0x5D, 0x2A,
0xB2, 0xA5, 0x66, 0xBD, 0x6B, 0x85, 0xF4, 0x74, 0x56, 0xC3, 0xF5, 0xE7,
0x75, 0x52, 0x28, 0x2C, 0xA5, 0xFF, 0x66, 0x47, 0xA5, 0xD4, 0xFE, 0xFE,
0x9E, 0x54, 0xBF, 0x65, 0x7E, 0x01, 0xD6, 0x30, 0x8F, 0xA5, 0x36, 0x9C,
0xA2, 0x50, 0x1C, 0xEE, 0x38, 0x80, 0x01, 0x48, 0xC6, 0xC7, 0x74, 0xF4,
0xC6, 0xAC, 0xC3, 0x40, 0x49, 0x16, 0x61, 0x74, 0x2C, 0xAF, 0x8C, 0x6F,
0x35, 0xED, 0x7B, 0x18, 0x00, 0x5B, 0x36, 0x3C, 0x9C, 0x50, 0x0D, 0xCA,
0x92, 0x33, 0x10, 0xF1, 0x26, 0x49, 0x6D, 0xDF, 0x75, 0x24, 0x37, 0x82,
0x22, 0xD7, 0xE8, 0x96, 0xFD, 0x15, 0x4B, 0x02, 0x96, 0x3E, 0x07, 0x72,
0x95, 0x7E, 0xAB, 0x3D, 0x4C, 0x2E, 0xD7, 0xCA, 0xF0, 0xDF, 0xE0, 0x58,
0x3F, 0x2D, 0x2F, 0x04, 0x9A, 0x38, 0xA3, 0x01
};
static const unsigned char TA146_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA147_DN[] = {
0x30, 0x51, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4A, 0x50, 0x31, 0x23, 0x30, 0x21, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x1A, 0x43, 0x79, 0x62, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74,
0x20, 0x4A, 0x61, 0x70, 0x61, 0x6E, 0x20, 0x43, 0x6F, 0x2E, 0x2C, 0x20,
0x4C, 0x74, 0x64, 0x2E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x14, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x53, 0x69, 0x67,
0x6E, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x31, 0x35
};
static const unsigned char TA147_EC_Q[] = {
0x04, 0x0B, 0x50, 0x74, 0x8D, 0x64, 0x32, 0x99, 0x99, 0xB3, 0xD2, 0x60,
0x08, 0xB8, 0x22, 0x8E, 0x46, 0x74, 0x2C, 0x78, 0xC0, 0x2B, 0x44, 0x2D,
0x6D, 0x5F, 0x1D, 0xC9, 0xAE, 0x4B, 0x52, 0x20, 0x83, 0x3D, 0xB8, 0x14,
0x6D, 0x53, 0x87, 0x60, 0x9E, 0x5F, 0x6C, 0x85, 0xDB, 0x06, 0x14, 0x95,
0xE0, 0xC7, 0x28, 0xFF, 0x9D, 0x5F, 0xE4, 0xAA, 0xF1, 0xB3, 0x8B, 0x6D,
0xED, 0x4F, 0x2F, 0x4B, 0xC9, 0x4A, 0x94, 0x91, 0x64, 0x75, 0xFE, 0x01,
0xEC, 0xC1, 0xD8, 0xEB, 0x7A, 0x94, 0x78, 0x56, 0x18, 0x43, 0x5F, 0x6B,
0x81, 0xCB, 0xF6, 0xBC, 0xDA, 0xB4, 0x0C, 0xB6, 0x29, 0x93, 0x08, 0x69,
0x8F
};
static const unsigned char TA148_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D,
0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x42, 0x52, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30,
0x32, 0x33
};
static const unsigned char TA148_RSA_N[] = {
0xAE, 0xFF, 0x09, 0x59, 0x91, 0x80, 0x0A, 0x4A, 0x68, 0xE6, 0x24, 0x3F,
0xB8, 0xA7, 0xE4, 0xC8, 0x3A, 0x0A, 0x3A, 0x16, 0xCD, 0xC9, 0x23, 0x61,
0xA0, 0x93, 0x71, 0xF2, 0xAB, 0x8B, 0x73, 0x8F, 0xA0, 0x67, 0x65, 0x60,
0xD2, 0x54, 0x6B, 0x63, 0x51, 0x6F, 0x49, 0x33, 0xE0, 0x72, 0x07, 0x13,
0x7D, 0x38, 0xCD, 0x06, 0x92, 0x07, 0x29, 0x52, 0x6B, 0x4E, 0x77, 0x6C,
0x04, 0xD3, 0x95, 0xFA, 0xDD, 0x4C, 0x8C, 0xD9, 0x5D, 0xC1, 0x61, 0x7D,
0x4B, 0xE7, 0x28, 0xB3, 0x44, 0x81, 0x7B, 0x51, 0xAF, 0xDD, 0x33, 0xB1,
0x68, 0x7C, 0xD6, 0x4E, 0x4C, 0xFE, 0x2B, 0x68, 0xB9, 0xCA, 0x66, 0x69,
0xC4, 0xEC, 0x5E, 0x57, 0x7F, 0xF7, 0x0D, 0xC7, 0x9C, 0x36, 0x36, 0xE5,
0x07, 0x60, 0xAC, 0xC0, 0x4C, 0xEA, 0x08, 0x6C, 0xEF, 0x06, 0x7C, 0x4F,
0x5B, 0x28, 0x7A, 0x08, 0xFC, 0x93, 0x5D, 0x9B, 0xF6, 0x9C, 0xB4, 0x8B,
0x86, 0xBA, 0x21, 0xB9, 0xF4, 0xF0, 0xE8, 0x59, 0x5A, 0x28, 0xA1, 0x34,
0x84, 0x1A, 0x25, 0x91, 0xB6, 0xB5, 0x8F, 0xEF, 0xB2, 0xF9, 0x80, 0xFA,
0xF9, 0x3D, 0x3C, 0x11, 0x72, 0xD8, 0xE3, 0x2F, 0x86, 0x76, 0xC5, 0x79,
0x2C, 0xC1, 0xA9, 0x90, 0x93, 0x46, 0x98, 0x67, 0xCB, 0x83, 0x6A, 0xA0,
0x50, 0x23, 0xA7, 0x3B, 0xF6, 0x81, 0x39, 0xE0, 0xED, 0xF0, 0xB9, 0xBF,
0x65, 0xF1, 0xD8, 0xCB, 0x7A, 0xFB, 0xEF, 0x73, 0x03, 0xCE, 0x00, 0xF4,
0x7D, 0xD7, 0xE0, 0x5D, 0x3B, 0x66, 0xB8, 0xDC, 0x8E, 0xBA, 0x83, 0xCB,
0x87, 0x76, 0x03, 0xFC, 0x25, 0xD9, 0xE7, 0x23, 0x6F, 0x06, 0xFD, 0x67,
0xF3, 0xE0, 0xFF, 0x84, 0xBC, 0x47, 0xBF, 0xB5, 0x16, 0x18, 0x46, 0x69,
0x14, 0xCC, 0x05, 0xF7, 0xDB, 0xD3, 0x49, 0xAC, 0x6B, 0xCC, 0xAB, 0xE4,
0xB5, 0x0B, 0x43, 0x24, 0x5E, 0x4B, 0x6B, 0x4D, 0x67, 0xDF, 0xD6, 0xB5,
0x3E, 0x4F, 0x78, 0x1F, 0x94, 0x71, 0x24, 0xEA, 0xDE, 0x70, 0xFC, 0xF1,
0x93, 0xFE, 0x9E, 0x93, 0x5A, 0xE4, 0x94, 0x5A, 0x97, 0x54, 0x0C, 0x35,
0x7B, 0x5F, 0x6C, 0xEE, 0x00, 0x1F, 0x24, 0xEC, 0x03, 0xBA, 0x02, 0xF5,
0x76, 0xF4, 0x9F, 0xD4, 0x9A, 0xED, 0x85, 0x2C, 0x38, 0x22, 0x2F, 0xC7,
0xD8, 0x2F, 0x76, 0x11, 0x4F, 0xFD, 0x6C, 0x5C, 0xE8, 0xF5, 0x8E, 0x27,
0x87, 0x7F, 0x19, 0x4A, 0x21, 0x47, 0x90, 0x1D, 0x79, 0x8D, 0x1C, 0x5B,
0xF8, 0xCF, 0x4A, 0x85, 0xE4, 0xED, 0xB3, 0x5B, 0x8D, 0xBE, 0xC4, 0x64,
0x28, 0x5D, 0x41, 0xC4, 0x6E, 0xAC, 0x38, 0x5A, 0x4F, 0x23, 0x74, 0x74,
0xA9, 0x12, 0xC3, 0xF6, 0xD2, 0xB9, 0x11, 0x15, 0x33, 0x07, 0x91, 0xD8,
0x3B, 0x37, 0x3A, 0x63, 0x30, 0x06, 0xD1, 0xC5, 0x22, 0x36, 0x28, 0x62,
0x23, 0x10, 0xE0, 0x46, 0xCC, 0x97, 0xAC, 0xD6, 0x2B, 0x5D, 0x64, 0x24,
0xD5, 0xEE, 0x1C, 0x0E, 0xDE, 0xFB, 0x08, 0x5A, 0x75, 0x2A, 0xF6, 0x63,
0x6D, 0xCE, 0x0B, 0x42, 0xBE, 0xD1, 0xBA, 0x70, 0x1C, 0x9C, 0x21, 0xE5,
0x0F, 0x31, 0x69, 0x17, 0xD7, 0xFC, 0x0A, 0xB4, 0xDE, 0xED, 0x80, 0x9C,
0xCB, 0x92, 0xB4, 0x8B, 0xF5, 0xDE, 0x59, 0xA2, 0x58, 0x09, 0xA5, 0x63,
0x47, 0x0B, 0xE1, 0x41, 0x32, 0x34, 0x41, 0xD9, 0x9A, 0xB1, 0xD9, 0xA8,
0xB0, 0x1B, 0x5A, 0xDE, 0x0D, 0x0D, 0xF4, 0xE2, 0xB2, 0x5D, 0x35, 0x80,
0xB9, 0x81, 0xD4, 0x84, 0x69, 0x91, 0x02, 0xCB, 0x75, 0xD0, 0x8D, 0xC5,
0xB5, 0x3D, 0x09, 0x91, 0x09, 0x8F, 0x14, 0xA1, 0x14, 0x74, 0x79, 0x3E,
0xD6, 0xC9, 0x15, 0x1D, 0xA4, 0x59, 0x59, 0x22, 0xDC, 0xF6, 0x8A, 0x45,
0x3D, 0x3C, 0x12, 0xD6, 0x3E, 0x5D, 0x32, 0x2F
};
static const unsigned char TA148_RSA_E[] = {
0x01, 0x00, 0x01
};
static const unsigned char TA149_DN[] = {
0x30, 0x48, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x44, 0x45, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A,
0x13, 0x0C, 0x44, 0x2D, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6D,
0x62, 0x48, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x19, 0x44, 0x2D, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x45, 0x56, 0x20,
0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x20, 0x32, 0x30,
0x32, 0x33
};
static const unsigned char TA149_RSA_N[] = {
0xD8, 0x8E, 0xA3, 0x89, 0x80, 0x0B, 0xB2, 0x57, 0x52, 0xDC, 0xA9, 0x53,
0x4C, 0x37, 0xB9, 0x7F, 0x63, 0x17, 0x13, 0xEF, 0xA7, 0x5B, 0x23, 0x5B,
0x69, 0x75, 0xB0, 0x99, 0x0A, 0x17, 0xC1, 0x8B, 0xC4, 0xDB, 0xA8, 0xE0,
0xCC, 0x31, 0xBA, 0xC2, 0xF2, 0xCD, 0x5D, 0xE9, 0xB7, 0xF8, 0x1D, 0xAF,
0x6A, 0xC4, 0x95, 0x87, 0xD7, 0x47, 0xC9, 0x95, 0xD8, 0x82, 0x04, 0x50,
0x3D, 0x81, 0x08, 0xFF, 0xE4, 0x3D, 0xB3, 0xB1, 0xD6, 0xC5, 0xB2, 0xFD,
0x88, 0x09, 0xDB, 0x9C, 0x84, 0xEC, 0x25, 0x17, 0x14, 0x87, 0x7F, 0x30,
0x78, 0x9B, 0x6A, 0x58, 0xC9, 0xB6, 0x73, 0x28, 0x3C, 0x34, 0xF7, 0x99,
0xF7, 0x7F, 0xD3, 0xA6, 0xF8, 0x1C, 0x45, 0x7C, 0xAD, 0x2C, 0x8C, 0x94,
0x3F, 0xD8, 0x67, 0x10, 0x53, 0x7E, 0x22, 0xCD, 0x4E, 0x25, 0x51, 0xF0,
0x25, 0x24, 0x35, 0x11, 0x5E, 0x10, 0xC6, 0xEC, 0x87, 0x66, 0x89, 0x81,
0x68, 0xBA, 0xCC, 0x2B, 0x9D, 0x47, 0x73, 0x1F, 0xBD, 0xCD, 0x91, 0xA4,
0x72, 0x6A, 0x9C, 0xA2, 0x1B, 0x18, 0xA0, 0x6F, 0xEC, 0x50, 0xF4, 0x7D,
0x40, 0xC2, 0xA8, 0x30, 0xCF, 0xBD, 0x73, 0xC8, 0x13, 0x2B, 0x10, 0x13,
0x1E, 0x8B, 0x9A, 0xA8, 0x3A, 0x94, 0x73, 0xD3, 0x18, 0x69, 0x0A, 0x4A,
0xFF, 0xC1, 0x01, 0x03, 0xFF, 0x79, 0x7F, 0xB5, 0x48, 0x7F, 0x7B, 0xEE,
0xE8, 0x29, 0x6F, 0x36, 0x4C, 0x95, 0x61, 0x86, 0xD8, 0xF9, 0xA2, 0x73,
0x8A, 0xEE, 0xAE, 0x2F, 0x96, 0xEE, 0x68, 0xCD, 0x3D, 0x4D, 0x28, 0x42,
0xF9, 0x45, 0x2B, 0x32, 0x1B, 0x46, 0x55, 0x16, 0x6A, 0xA6, 0x4B, 0x29,
0xF9, 0xBB, 0x95, 0x56, 0xBF, 0x46, 0x1D, 0xEC, 0x1D, 0x93, 0x1D, 0xC0,
0x65, 0xB2, 0x1F, 0xA1, 0x43, 0xAE, 0x56, 0x9E, 0xA0, 0xB1, 0x8F, 0x6B,
0x12, 0xB7, 0x60, 0x6D, 0x78, 0x0B, 0xCA, 0x8A, 0x5C, 0xED, 0x1E, 0x96,
0x0E, 0x83, 0xA6, 0x48, 0x95, 0x8D, 0x3B, 0xA3, 0x21, 0xC4, 0xAE, 0x58,
0xC6, 0x00, 0xB2, 0x84, 0xB4, 0x23, 0xA4, 0x96, 0x86, 0x35, 0xB8, 0xD8,
0x9E, 0xD8, 0xAC, 0x34, 0x49, 0x98, 0x63, 0x95, 0xC5, 0xCB, 0x6D, 0x48,
0x47, 0xE2, 0xF2, 0x2E, 0x18, 0x1E, 0xD0, 0x31, 0xAB, 0xDD, 0x74, 0xEC,
0xF9, 0xDC, 0x8C, 0xB8, 0x1C, 0x8E, 0x68, 0x23, 0xBA, 0xD0, 0xF3, 0x50,
0xDC, 0xCF, 0x65, 0x8F, 0x73, 0x3A, 0x32, 0xC7, 0x7C, 0xFE, 0xCA, 0x82,
0x22, 0x4F, 0xBE, 0x8E, 0x62, 0x47, 0x66, 0xE5, 0xCD, 0x87, 0xE2, 0xE8,
0xD5, 0x0F, 0x18, 0x9F, 0xE5, 0x04, 0x72, 0x4B, 0x46, 0x3C, 0x10, 0xF2,
0x44, 0xC2, 0x64, 0x56, 0x71, 0x4E, 0x75, 0xE8, 0x9C, 0xC9, 0x26, 0x74,
0xC5, 0x7D, 0x59, 0xD1, 0x0A, 0x5B, 0x0F, 0x6D, 0xFE, 0x9E, 0x75, 0x1C,
0x18, 0xC6, 0x1A, 0x3A, 0x7C, 0xD8, 0x0D, 0x04, 0xCC, 0xCD, 0xB7, 0x45,
0x65, 0x7A, 0xB1, 0x8F, 0xB8, 0xAE, 0x84, 0x48, 0x3E, 0xB3, 0x7A, 0x4D,
0xA8, 0x03, 0xE2, 0xE2, 0x7E, 0x01, 0x16, 0x59, 0x68, 0x18, 0x43, 0x33,
0xB0, 0xD2, 0xDC, 0xB0, 0x1A, 0x43, 0x35, 0xEE, 0xA5, 0xDA, 0xA9, 0x46,
0x5C, 0xAE, 0x86, 0x81, 0x41, 0x01, 0x4A, 0x74, 0x26, 0xEC, 0x9F, 0x06,
0xBF, 0xC2, 0x05, 0x37, 0x64, 0x75, 0x78, 0x29, 0x68, 0xFD, 0xC5, 0xF5,
0xEB, 0xFE, 0x47, 0xF9, 0xE4, 0x85, 0xB0, 0xE1, 0x7B, 0x31, 0x9D, 0xA6,
0x7F, 0x72, 0xA3, 0xB9, 0xC4, 0x2C, 0x2E, 0xCC, 0x99, 0x57, 0x0E, 0x21,
0x0C, 0x45, 0x01, 0x94, 0x65, 0xEB, 0x65, 0x09, 0xC6, 0x63, 0x22, 0x0B,
0x33, 0x49, 0x92, 0x48, 0x3C, 0xFC, 0xCD, 0xCE, 0xB0, 0x3E, 0x8E, 0x9E,
0x8B, 0xF8, 0xFE, 0x49, 0xC5, 0x35, 0x72, 0x47
};
static const unsigned char TA149_RSA_E[] = {
0x01, 0x00, 0x01
};
static const br_x509_trust_anchor TAs[150] = {
{
{ (unsigned char *)TA0_DN, sizeof TA0_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA0_RSA_N, sizeof TA0_RSA_N,
(unsigned char *)TA0_RSA_E, sizeof TA0_RSA_E,
} }
}
},
{
{ (unsigned char *)TA1_DN, sizeof TA1_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA1_RSA_N, sizeof TA1_RSA_N,
(unsigned char *)TA1_RSA_E, sizeof TA1_RSA_E,
} }
}
},
{
{ (unsigned char *)TA2_DN, sizeof TA2_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA2_RSA_N, sizeof TA2_RSA_N,
(unsigned char *)TA2_RSA_E, sizeof TA2_RSA_E,
} }
}
},
{
{ (unsigned char *)TA3_DN, sizeof TA3_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA3_RSA_N, sizeof TA3_RSA_N,
(unsigned char *)TA3_RSA_E, sizeof TA3_RSA_E,
} }
}
},
{
{ (unsigned char *)TA4_DN, sizeof TA4_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA4_RSA_N, sizeof TA4_RSA_N,
(unsigned char *)TA4_RSA_E, sizeof TA4_RSA_E,
} }
}
},
{
{ (unsigned char *)TA5_DN, sizeof TA5_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA5_RSA_N, sizeof TA5_RSA_N,
(unsigned char *)TA5_RSA_E, sizeof TA5_RSA_E,
} }
}
},
{
{ (unsigned char *)TA6_DN, sizeof TA6_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA6_RSA_N, sizeof TA6_RSA_N,
(unsigned char *)TA6_RSA_E, sizeof TA6_RSA_E,
} }
}
},
{
{ (unsigned char *)TA7_DN, sizeof TA7_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA7_RSA_N, sizeof TA7_RSA_N,
(unsigned char *)TA7_RSA_E, sizeof TA7_RSA_E,
} }
}
},
{
{ (unsigned char *)TA8_DN, sizeof TA8_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA8_RSA_N, sizeof TA8_RSA_N,
(unsigned char *)TA8_RSA_E, sizeof TA8_RSA_E,
} }
}
},
{
{ (unsigned char *)TA9_DN, sizeof TA9_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA9_RSA_N, sizeof TA9_RSA_N,
(unsigned char *)TA9_RSA_E, sizeof TA9_RSA_E,
} }
}
},
{
{ (unsigned char *)TA10_DN, sizeof TA10_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA10_RSA_N, sizeof TA10_RSA_N,
(unsigned char *)TA10_RSA_E, sizeof TA10_RSA_E,
} }
}
},
{
{ (unsigned char *)TA11_DN, sizeof TA11_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA11_RSA_N, sizeof TA11_RSA_N,
(unsigned char *)TA11_RSA_E, sizeof TA11_RSA_E,
} }
}
},
{
{ (unsigned char *)TA12_DN, sizeof TA12_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA12_RSA_N, sizeof TA12_RSA_N,
(unsigned char *)TA12_RSA_E, sizeof TA12_RSA_E,
} }
}
},
{
{ (unsigned char *)TA13_DN, sizeof TA13_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA13_RSA_N, sizeof TA13_RSA_N,
(unsigned char *)TA13_RSA_E, sizeof TA13_RSA_E,
} }
}
},
{
{ (unsigned char *)TA14_DN, sizeof TA14_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA14_RSA_N, sizeof TA14_RSA_N,
(unsigned char *)TA14_RSA_E, sizeof TA14_RSA_E,
} }
}
},
{
{ (unsigned char *)TA15_DN, sizeof TA15_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA15_RSA_N, sizeof TA15_RSA_N,
(unsigned char *)TA15_RSA_E, sizeof TA15_RSA_E,
} }
}
},
{
{ (unsigned char *)TA16_DN, sizeof TA16_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA16_RSA_N, sizeof TA16_RSA_N,
(unsigned char *)TA16_RSA_E, sizeof TA16_RSA_E,
} }
}
},
{
{ (unsigned char *)TA17_DN, sizeof TA17_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA17_EC_Q, sizeof TA17_EC_Q,
} }
}
},
{
{ (unsigned char *)TA18_DN, sizeof TA18_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA18_RSA_N, sizeof TA18_RSA_N,
(unsigned char *)TA18_RSA_E, sizeof TA18_RSA_E,
} }
}
},
{
{ (unsigned char *)TA19_DN, sizeof TA19_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA19_RSA_N, sizeof TA19_RSA_N,
(unsigned char *)TA19_RSA_E, sizeof TA19_RSA_E,
} }
}
},
{
{ (unsigned char *)TA20_DN, sizeof TA20_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA20_RSA_N, sizeof TA20_RSA_N,
(unsigned char *)TA20_RSA_E, sizeof TA20_RSA_E,
} }
}
},
{
{ (unsigned char *)TA21_DN, sizeof TA21_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA21_RSA_N, sizeof TA21_RSA_N,
(unsigned char *)TA21_RSA_E, sizeof TA21_RSA_E,
} }
}
},
{
{ (unsigned char *)TA22_DN, sizeof TA22_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA22_RSA_N, sizeof TA22_RSA_N,
(unsigned char *)TA22_RSA_E, sizeof TA22_RSA_E,
} }
}
},
{
{ (unsigned char *)TA23_DN, sizeof TA23_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA23_RSA_N, sizeof TA23_RSA_N,
(unsigned char *)TA23_RSA_E, sizeof TA23_RSA_E,
} }
}
},
{
{ (unsigned char *)TA24_DN, sizeof TA24_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA24_RSA_N, sizeof TA24_RSA_N,
(unsigned char *)TA24_RSA_E, sizeof TA24_RSA_E,
} }
}
},
{
{ (unsigned char *)TA25_DN, sizeof TA25_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA25_RSA_N, sizeof TA25_RSA_N,
(unsigned char *)TA25_RSA_E, sizeof TA25_RSA_E,
} }
}
},
{
{ (unsigned char *)TA26_DN, sizeof TA26_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA26_RSA_N, sizeof TA26_RSA_N,
(unsigned char *)TA26_RSA_E, sizeof TA26_RSA_E,
} }
}
},
{
{ (unsigned char *)TA27_DN, sizeof TA27_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA27_RSA_N, sizeof TA27_RSA_N,
(unsigned char *)TA27_RSA_E, sizeof TA27_RSA_E,
} }
}
},
{
{ (unsigned char *)TA28_DN, sizeof TA28_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA28_RSA_N, sizeof TA28_RSA_N,
(unsigned char *)TA28_RSA_E, sizeof TA28_RSA_E,
} }
}
},
{
{ (unsigned char *)TA29_DN, sizeof TA29_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA29_RSA_N, sizeof TA29_RSA_N,
(unsigned char *)TA29_RSA_E, sizeof TA29_RSA_E,
} }
}
},
{
{ (unsigned char *)TA30_DN, sizeof TA30_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA30_RSA_N, sizeof TA30_RSA_N,
(unsigned char *)TA30_RSA_E, sizeof TA30_RSA_E,
} }
}
},
{
{ (unsigned char *)TA31_DN, sizeof TA31_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA31_EC_Q, sizeof TA31_EC_Q,
} }
}
},
{
{ (unsigned char *)TA32_DN, sizeof TA32_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA32_RSA_N, sizeof TA32_RSA_N,
(unsigned char *)TA32_RSA_E, sizeof TA32_RSA_E,
} }
}
},
{
{ (unsigned char *)TA33_DN, sizeof TA33_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA33_RSA_N, sizeof TA33_RSA_N,
(unsigned char *)TA33_RSA_E, sizeof TA33_RSA_E,
} }
}
},
{
{ (unsigned char *)TA34_DN, sizeof TA34_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA34_RSA_N, sizeof TA34_RSA_N,
(unsigned char *)TA34_RSA_E, sizeof TA34_RSA_E,
} }
}
},
{
{ (unsigned char *)TA35_DN, sizeof TA35_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA35_RSA_N, sizeof TA35_RSA_N,
(unsigned char *)TA35_RSA_E, sizeof TA35_RSA_E,
} }
}
},
{
{ (unsigned char *)TA36_DN, sizeof TA36_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA36_RSA_N, sizeof TA36_RSA_N,
(unsigned char *)TA36_RSA_E, sizeof TA36_RSA_E,
} }
}
},
{
{ (unsigned char *)TA37_DN, sizeof TA37_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA37_RSA_N, sizeof TA37_RSA_N,
(unsigned char *)TA37_RSA_E, sizeof TA37_RSA_E,
} }
}
},
{
{ (unsigned char *)TA38_DN, sizeof TA38_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA38_RSA_N, sizeof TA38_RSA_N,
(unsigned char *)TA38_RSA_E, sizeof TA38_RSA_E,
} }
}
},
{
{ (unsigned char *)TA39_DN, sizeof TA39_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA39_RSA_N, sizeof TA39_RSA_N,
(unsigned char *)TA39_RSA_E, sizeof TA39_RSA_E,
} }
}
},
{
{ (unsigned char *)TA40_DN, sizeof TA40_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA40_RSA_N, sizeof TA40_RSA_N,
(unsigned char *)TA40_RSA_E, sizeof TA40_RSA_E,
} }
}
},
{
{ (unsigned char *)TA41_DN, sizeof TA41_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA41_RSA_N, sizeof TA41_RSA_N,
(unsigned char *)TA41_RSA_E, sizeof TA41_RSA_E,
} }
}
},
{
{ (unsigned char *)TA42_DN, sizeof TA42_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA42_RSA_N, sizeof TA42_RSA_N,
(unsigned char *)TA42_RSA_E, sizeof TA42_RSA_E,
} }
}
},
{
{ (unsigned char *)TA43_DN, sizeof TA43_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA43_RSA_N, sizeof TA43_RSA_N,
(unsigned char *)TA43_RSA_E, sizeof TA43_RSA_E,
} }
}
},
{
{ (unsigned char *)TA44_DN, sizeof TA44_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA44_RSA_N, sizeof TA44_RSA_N,
(unsigned char *)TA44_RSA_E, sizeof TA44_RSA_E,
} }
}
},
{
{ (unsigned char *)TA45_DN, sizeof TA45_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA45_RSA_N, sizeof TA45_RSA_N,
(unsigned char *)TA45_RSA_E, sizeof TA45_RSA_E,
} }
}
},
{
{ (unsigned char *)TA46_DN, sizeof TA46_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA46_RSA_N, sizeof TA46_RSA_N,
(unsigned char *)TA46_RSA_E, sizeof TA46_RSA_E,
} }
}
},
{
{ (unsigned char *)TA47_DN, sizeof TA47_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA47_RSA_N, sizeof TA47_RSA_N,
(unsigned char *)TA47_RSA_E, sizeof TA47_RSA_E,
} }
}
},
{
{ (unsigned char *)TA48_DN, sizeof TA48_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA48_RSA_N, sizeof TA48_RSA_N,
(unsigned char *)TA48_RSA_E, sizeof TA48_RSA_E,
} }
}
},
{
{ (unsigned char *)TA49_DN, sizeof TA49_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA49_RSA_N, sizeof TA49_RSA_N,
(unsigned char *)TA49_RSA_E, sizeof TA49_RSA_E,
} }
}
},
{
{ (unsigned char *)TA50_DN, sizeof TA50_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA50_RSA_N, sizeof TA50_RSA_N,
(unsigned char *)TA50_RSA_E, sizeof TA50_RSA_E,
} }
}
},
{
{ (unsigned char *)TA51_DN, sizeof TA51_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA51_EC_Q, sizeof TA51_EC_Q,
} }
}
},
{
{ (unsigned char *)TA52_DN, sizeof TA52_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA52_RSA_N, sizeof TA52_RSA_N,
(unsigned char *)TA52_RSA_E, sizeof TA52_RSA_E,
} }
}
},
{
{ (unsigned char *)TA53_DN, sizeof TA53_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA53_EC_Q, sizeof TA53_EC_Q,
} }
}
},
{
{ (unsigned char *)TA54_DN, sizeof TA54_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA54_RSA_N, sizeof TA54_RSA_N,
(unsigned char *)TA54_RSA_E, sizeof TA54_RSA_E,
} }
}
},
{
{ (unsigned char *)TA55_DN, sizeof TA55_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA55_RSA_N, sizeof TA55_RSA_N,
(unsigned char *)TA55_RSA_E, sizeof TA55_RSA_E,
} }
}
},
{
{ (unsigned char *)TA56_DN, sizeof TA56_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA56_RSA_N, sizeof TA56_RSA_N,
(unsigned char *)TA56_RSA_E, sizeof TA56_RSA_E,
} }
}
},
{
{ (unsigned char *)TA57_DN, sizeof TA57_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA57_EC_Q, sizeof TA57_EC_Q,
} }
}
},
{
{ (unsigned char *)TA58_DN, sizeof TA58_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA58_EC_Q, sizeof TA58_EC_Q,
} }
}
},
{
{ (unsigned char *)TA59_DN, sizeof TA59_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA59_RSA_N, sizeof TA59_RSA_N,
(unsigned char *)TA59_RSA_E, sizeof TA59_RSA_E,
} }
}
},
{
{ (unsigned char *)TA60_DN, sizeof TA60_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA60_RSA_N, sizeof TA60_RSA_N,
(unsigned char *)TA60_RSA_E, sizeof TA60_RSA_E,
} }
}
},
{
{ (unsigned char *)TA61_DN, sizeof TA61_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA61_RSA_N, sizeof TA61_RSA_N,
(unsigned char *)TA61_RSA_E, sizeof TA61_RSA_E,
} }
}
},
{
{ (unsigned char *)TA62_DN, sizeof TA62_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA62_EC_Q, sizeof TA62_EC_Q,
} }
}
},
{
{ (unsigned char *)TA63_DN, sizeof TA63_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA63_RSA_N, sizeof TA63_RSA_N,
(unsigned char *)TA63_RSA_E, sizeof TA63_RSA_E,
} }
}
},
{
{ (unsigned char *)TA64_DN, sizeof TA64_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA64_RSA_N, sizeof TA64_RSA_N,
(unsigned char *)TA64_RSA_E, sizeof TA64_RSA_E,
} }
}
},
{
{ (unsigned char *)TA65_DN, sizeof TA65_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA65_RSA_N, sizeof TA65_RSA_N,
(unsigned char *)TA65_RSA_E, sizeof TA65_RSA_E,
} }
}
},
{
{ (unsigned char *)TA66_DN, sizeof TA66_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA66_RSA_N, sizeof TA66_RSA_N,
(unsigned char *)TA66_RSA_E, sizeof TA66_RSA_E,
} }
}
},
{
{ (unsigned char *)TA67_DN, sizeof TA67_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA67_RSA_N, sizeof TA67_RSA_N,
(unsigned char *)TA67_RSA_E, sizeof TA67_RSA_E,
} }
}
},
{
{ (unsigned char *)TA68_DN, sizeof TA68_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA68_EC_Q, sizeof TA68_EC_Q,
} }
}
},
{
{ (unsigned char *)TA69_DN, sizeof TA69_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA69_RSA_N, sizeof TA69_RSA_N,
(unsigned char *)TA69_RSA_E, sizeof TA69_RSA_E,
} }
}
},
{
{ (unsigned char *)TA70_DN, sizeof TA70_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA70_RSA_N, sizeof TA70_RSA_N,
(unsigned char *)TA70_RSA_E, sizeof TA70_RSA_E,
} }
}
},
{
{ (unsigned char *)TA71_DN, sizeof TA71_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA71_RSA_N, sizeof TA71_RSA_N,
(unsigned char *)TA71_RSA_E, sizeof TA71_RSA_E,
} }
}
},
{
{ (unsigned char *)TA72_DN, sizeof TA72_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA72_RSA_N, sizeof TA72_RSA_N,
(unsigned char *)TA72_RSA_E, sizeof TA72_RSA_E,
} }
}
},
{
{ (unsigned char *)TA73_DN, sizeof TA73_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp256r1,
(unsigned char *)TA73_EC_Q, sizeof TA73_EC_Q,
} }
}
},
{
{ (unsigned char *)TA74_DN, sizeof TA74_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA74_EC_Q, sizeof TA74_EC_Q,
} }
}
},
{
{ (unsigned char *)TA75_DN, sizeof TA75_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA75_RSA_N, sizeof TA75_RSA_N,
(unsigned char *)TA75_RSA_E, sizeof TA75_RSA_E,
} }
}
},
{
{ (unsigned char *)TA76_DN, sizeof TA76_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA76_RSA_N, sizeof TA76_RSA_N,
(unsigned char *)TA76_RSA_E, sizeof TA76_RSA_E,
} }
}
},
{
{ (unsigned char *)TA77_DN, sizeof TA77_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA77_RSA_N, sizeof TA77_RSA_N,
(unsigned char *)TA77_RSA_E, sizeof TA77_RSA_E,
} }
}
},
{
{ (unsigned char *)TA78_DN, sizeof TA78_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA78_EC_Q, sizeof TA78_EC_Q,
} }
}
},
{
{ (unsigned char *)TA79_DN, sizeof TA79_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA79_RSA_N, sizeof TA79_RSA_N,
(unsigned char *)TA79_RSA_E, sizeof TA79_RSA_E,
} }
}
},
{
{ (unsigned char *)TA80_DN, sizeof TA80_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA80_EC_Q, sizeof TA80_EC_Q,
} }
}
},
{
{ (unsigned char *)TA81_DN, sizeof TA81_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA81_RSA_N, sizeof TA81_RSA_N,
(unsigned char *)TA81_RSA_E, sizeof TA81_RSA_E,
} }
}
},
{
{ (unsigned char *)TA82_DN, sizeof TA82_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA82_EC_Q, sizeof TA82_EC_Q,
} }
}
},
{
{ (unsigned char *)TA83_DN, sizeof TA83_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA83_RSA_N, sizeof TA83_RSA_N,
(unsigned char *)TA83_RSA_E, sizeof TA83_RSA_E,
} }
}
},
{
{ (unsigned char *)TA84_DN, sizeof TA84_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA84_RSA_N, sizeof TA84_RSA_N,
(unsigned char *)TA84_RSA_E, sizeof TA84_RSA_E,
} }
}
},
{
{ (unsigned char *)TA85_DN, sizeof TA85_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA85_RSA_N, sizeof TA85_RSA_N,
(unsigned char *)TA85_RSA_E, sizeof TA85_RSA_E,
} }
}
},
{
{ (unsigned char *)TA86_DN, sizeof TA86_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA86_RSA_N, sizeof TA86_RSA_N,
(unsigned char *)TA86_RSA_E, sizeof TA86_RSA_E,
} }
}
},
{
{ (unsigned char *)TA87_DN, sizeof TA87_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA87_EC_Q, sizeof TA87_EC_Q,
} }
}
},
{
{ (unsigned char *)TA88_DN, sizeof TA88_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA88_RSA_N, sizeof TA88_RSA_N,
(unsigned char *)TA88_RSA_E, sizeof TA88_RSA_E,
} }
}
},
{
{ (unsigned char *)TA89_DN, sizeof TA89_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA89_EC_Q, sizeof TA89_EC_Q,
} }
}
},
{
{ (unsigned char *)TA90_DN, sizeof TA90_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA90_RSA_N, sizeof TA90_RSA_N,
(unsigned char *)TA90_RSA_E, sizeof TA90_RSA_E,
} }
}
},
{
{ (unsigned char *)TA91_DN, sizeof TA91_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA91_EC_Q, sizeof TA91_EC_Q,
} }
}
},
{
{ (unsigned char *)TA92_DN, sizeof TA92_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA92_RSA_N, sizeof TA92_RSA_N,
(unsigned char *)TA92_RSA_E, sizeof TA92_RSA_E,
} }
}
},
{
{ (unsigned char *)TA93_DN, sizeof TA93_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp256r1,
(unsigned char *)TA93_EC_Q, sizeof TA93_EC_Q,
} }
}
},
{
{ (unsigned char *)TA94_DN, sizeof TA94_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA94_RSA_N, sizeof TA94_RSA_N,
(unsigned char *)TA94_RSA_E, sizeof TA94_RSA_E,
} }
}
},
{
{ (unsigned char *)TA95_DN, sizeof TA95_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA95_RSA_N, sizeof TA95_RSA_N,
(unsigned char *)TA95_RSA_E, sizeof TA95_RSA_E,
} }
}
},
{
{ (unsigned char *)TA96_DN, sizeof TA96_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp256r1,
(unsigned char *)TA96_EC_Q, sizeof TA96_EC_Q,
} }
}
},
{
{ (unsigned char *)TA97_DN, sizeof TA97_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA97_EC_Q, sizeof TA97_EC_Q,
} }
}
},
{
{ (unsigned char *)TA98_DN, sizeof TA98_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA98_RSA_N, sizeof TA98_RSA_N,
(unsigned char *)TA98_RSA_E, sizeof TA98_RSA_E,
} }
}
},
{
{ (unsigned char *)TA99_DN, sizeof TA99_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA99_EC_Q, sizeof TA99_EC_Q,
} }
}
},
{
{ (unsigned char *)TA100_DN, sizeof TA100_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA100_RSA_N, sizeof TA100_RSA_N,
(unsigned char *)TA100_RSA_E, sizeof TA100_RSA_E,
} }
}
},
{
{ (unsigned char *)TA101_DN, sizeof TA101_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA101_EC_Q, sizeof TA101_EC_Q,
} }
}
},
{
{ (unsigned char *)TA102_DN, sizeof TA102_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA102_RSA_N, sizeof TA102_RSA_N,
(unsigned char *)TA102_RSA_E, sizeof TA102_RSA_E,
} }
}
},
{
{ (unsigned char *)TA103_DN, sizeof TA103_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA103_RSA_N, sizeof TA103_RSA_N,
(unsigned char *)TA103_RSA_E, sizeof TA103_RSA_E,
} }
}
},
{
{ (unsigned char *)TA104_DN, sizeof TA104_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA104_EC_Q, sizeof TA104_EC_Q,
} }
}
},
{
{ (unsigned char *)TA105_DN, sizeof TA105_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA105_RSA_N, sizeof TA105_RSA_N,
(unsigned char *)TA105_RSA_E, sizeof TA105_RSA_E,
} }
}
},
{
{ (unsigned char *)TA106_DN, sizeof TA106_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA106_RSA_N, sizeof TA106_RSA_N,
(unsigned char *)TA106_RSA_E, sizeof TA106_RSA_E,
} }
}
},
{
{ (unsigned char *)TA107_DN, sizeof TA107_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA107_RSA_N, sizeof TA107_RSA_N,
(unsigned char *)TA107_RSA_E, sizeof TA107_RSA_E,
} }
}
},
{
{ (unsigned char *)TA108_DN, sizeof TA108_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA108_EC_Q, sizeof TA108_EC_Q,
} }
}
},
{
{ (unsigned char *)TA109_DN, sizeof TA109_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA109_RSA_N, sizeof TA109_RSA_N,
(unsigned char *)TA109_RSA_E, sizeof TA109_RSA_E,
} }
}
},
{
{ (unsigned char *)TA110_DN, sizeof TA110_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA110_EC_Q, sizeof TA110_EC_Q,
} }
}
},
{
{ (unsigned char *)TA111_DN, sizeof TA111_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA111_RSA_N, sizeof TA111_RSA_N,
(unsigned char *)TA111_RSA_E, sizeof TA111_RSA_E,
} }
}
},
{
{ (unsigned char *)TA112_DN, sizeof TA112_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA112_EC_Q, sizeof TA112_EC_Q,
} }
}
},
{
{ (unsigned char *)TA113_DN, sizeof TA113_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA113_RSA_N, sizeof TA113_RSA_N,
(unsigned char *)TA113_RSA_E, sizeof TA113_RSA_E,
} }
}
},
{
{ (unsigned char *)TA114_DN, sizeof TA114_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp256r1,
(unsigned char *)TA114_EC_Q, sizeof TA114_EC_Q,
} }
}
},
{
{ (unsigned char *)TA115_DN, sizeof TA115_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA115_RSA_N, sizeof TA115_RSA_N,
(unsigned char *)TA115_RSA_E, sizeof TA115_RSA_E,
} }
}
},
{
{ (unsigned char *)TA116_DN, sizeof TA116_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA116_RSA_N, sizeof TA116_RSA_N,
(unsigned char *)TA116_RSA_E, sizeof TA116_RSA_E,
} }
}
},
{
{ (unsigned char *)TA117_DN, sizeof TA117_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA117_EC_Q, sizeof TA117_EC_Q,
} }
}
},
{
{ (unsigned char *)TA118_DN, sizeof TA118_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA118_EC_Q, sizeof TA118_EC_Q,
} }
}
},
{
{ (unsigned char *)TA119_DN, sizeof TA119_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA119_RSA_N, sizeof TA119_RSA_N,
(unsigned char *)TA119_RSA_E, sizeof TA119_RSA_E,
} }
}
},
{
{ (unsigned char *)TA120_DN, sizeof TA120_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA120_EC_Q, sizeof TA120_EC_Q,
} }
}
},
{
{ (unsigned char *)TA121_DN, sizeof TA121_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA121_EC_Q, sizeof TA121_EC_Q,
} }
}
},
{
{ (unsigned char *)TA122_DN, sizeof TA122_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA122_EC_Q, sizeof TA122_EC_Q,
} }
}
},
{
{ (unsigned char *)TA123_DN, sizeof TA123_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA123_RSA_N, sizeof TA123_RSA_N,
(unsigned char *)TA123_RSA_E, sizeof TA123_RSA_E,
} }
}
},
{
{ (unsigned char *)TA124_DN, sizeof TA124_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA124_RSA_N, sizeof TA124_RSA_N,
(unsigned char *)TA124_RSA_E, sizeof TA124_RSA_E,
} }
}
},
{
{ (unsigned char *)TA125_DN, sizeof TA125_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA125_EC_Q, sizeof TA125_EC_Q,
} }
}
},
{
{ (unsigned char *)TA126_DN, sizeof TA126_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA126_EC_Q, sizeof TA126_EC_Q,
} }
}
},
{
{ (unsigned char *)TA127_DN, sizeof TA127_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA127_RSA_N, sizeof TA127_RSA_N,
(unsigned char *)TA127_RSA_E, sizeof TA127_RSA_E,
} }
}
},
{
{ (unsigned char *)TA128_DN, sizeof TA128_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA128_EC_Q, sizeof TA128_EC_Q,
} }
}
},
{
{ (unsigned char *)TA129_DN, sizeof TA129_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA129_EC_Q, sizeof TA129_EC_Q,
} }
}
},
{
{ (unsigned char *)TA130_DN, sizeof TA130_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA130_RSA_N, sizeof TA130_RSA_N,
(unsigned char *)TA130_RSA_E, sizeof TA130_RSA_E,
} }
}
},
{
{ (unsigned char *)TA131_DN, sizeof TA131_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA131_RSA_N, sizeof TA131_RSA_N,
(unsigned char *)TA131_RSA_E, sizeof TA131_RSA_E,
} }
}
},
{
{ (unsigned char *)TA132_DN, sizeof TA132_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA132_EC_Q, sizeof TA132_EC_Q,
} }
}
},
{
{ (unsigned char *)TA133_DN, sizeof TA133_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA133_EC_Q, sizeof TA133_EC_Q,
} }
}
},
{
{ (unsigned char *)TA134_DN, sizeof TA134_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA134_RSA_N, sizeof TA134_RSA_N,
(unsigned char *)TA134_RSA_E, sizeof TA134_RSA_E,
} }
}
},
{
{ (unsigned char *)TA135_DN, sizeof TA135_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA135_RSA_N, sizeof TA135_RSA_N,
(unsigned char *)TA135_RSA_E, sizeof TA135_RSA_E,
} }
}
},
{
{ (unsigned char *)TA136_DN, sizeof TA136_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA136_EC_Q, sizeof TA136_EC_Q,
} }
}
},
{
{ (unsigned char *)TA137_DN, sizeof TA137_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA137_EC_Q, sizeof TA137_EC_Q,
} }
}
},
{
{ (unsigned char *)TA138_DN, sizeof TA138_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA138_EC_Q, sizeof TA138_EC_Q,
} }
}
},
{
{ (unsigned char *)TA139_DN, sizeof TA139_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA139_RSA_N, sizeof TA139_RSA_N,
(unsigned char *)TA139_RSA_E, sizeof TA139_RSA_E,
} }
}
},
{
{ (unsigned char *)TA140_DN, sizeof TA140_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA140_RSA_N, sizeof TA140_RSA_N,
(unsigned char *)TA140_RSA_E, sizeof TA140_RSA_E,
} }
}
},
{
{ (unsigned char *)TA141_DN, sizeof TA141_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA141_EC_Q, sizeof TA141_EC_Q,
} }
}
},
{
{ (unsigned char *)TA142_DN, sizeof TA142_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA142_RSA_N, sizeof TA142_RSA_N,
(unsigned char *)TA142_RSA_E, sizeof TA142_RSA_E,
} }
}
},
{
{ (unsigned char *)TA143_DN, sizeof TA143_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA143_EC_Q, sizeof TA143_EC_Q,
} }
}
},
{
{ (unsigned char *)TA144_DN, sizeof TA144_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA144_RSA_N, sizeof TA144_RSA_N,
(unsigned char *)TA144_RSA_E, sizeof TA144_RSA_E,
} }
}
},
{
{ (unsigned char *)TA145_DN, sizeof TA145_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA145_RSA_N, sizeof TA145_RSA_N,
(unsigned char *)TA145_RSA_E, sizeof TA145_RSA_E,
} }
}
},
{
{ (unsigned char *)TA146_DN, sizeof TA146_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA146_RSA_N, sizeof TA146_RSA_N,
(unsigned char *)TA146_RSA_E, sizeof TA146_RSA_E,
} }
}
},
{
{ (unsigned char *)TA147_DN, sizeof TA147_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_EC,
{ .ec = {
BR_EC_secp384r1,
(unsigned char *)TA147_EC_Q, sizeof TA147_EC_Q,
} }
}
},
{
{ (unsigned char *)TA148_DN, sizeof TA148_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA148_RSA_N, sizeof TA148_RSA_N,
(unsigned char *)TA148_RSA_E, sizeof TA148_RSA_E,
} }
}
},
{
{ (unsigned char *)TA149_DN, sizeof TA149_DN },
BR_X509_TA_CA,
{
BR_KEYTYPE_RSA,
{ .rsa = {
(unsigned char *)TA149_RSA_N, sizeof TA149_RSA_N,
(unsigned char *)TA149_RSA_E, sizeof TA149_RSA_E,
} }
}
}
};
#define TAs_NUM 150
#define BR_ENABLE_INTRINSICS 1
#ifndef BearSSLSingleUnit_fdefine
#define BearSSLSingleUnit_fdefine
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Implementation Notes
* ====================
*
* The combined CTR + CBC-MAC functions can only handle full blocks,
* so some buffering is necessary.
*
* - 'ptr' contains a value from 0 to 15, which is the number of bytes
* accumulated in buf[] that still needs to be processed with the
* current CBC-MAC computation.
*
* - When processing the message itself, CTR encryption/decryption is
* also done at the same time. The first 'ptr' bytes of buf[] then
* contains the plaintext bytes, while the last '16 - ptr' bytes of
* buf[] are the remnants of the stream block, to be used against
* the next input bytes, when available. When 'ptr' is 0, the
* contents of buf[] are to be ignored.
*
* - The current counter and running CBC-MAC values are kept in 'ctr'
* and 'cbcmac', respectively.
*/
/* see bearssl_block.h */
void
br_ccm_init(br_ccm_context *ctx, const br_block_ctrcbc_class **bctx)
{
ctx->bctx = bctx;
}
/* see bearssl_block.h */
int
br_ccm_reset(br_ccm_context *ctx, const void *nonce, size_t nonce_len,
uint64_t aad_len, uint64_t data_len, size_t tag_len)
{
unsigned char tmp[16];
unsigned u, q;
if (nonce_len < 7 || nonce_len > 13) {
return 0;
}
if (tag_len < 4 || tag_len > 16 || (tag_len & 1) != 0) {
return 0;
}
q = 15 - (unsigned)nonce_len;
ctx->tag_len = tag_len;
/*
* Block B0, to start CBC-MAC.
*/
tmp[0] = (aad_len > 0 ? 0x40 : 0x00)
| (((unsigned)tag_len - 2) << 2)
| (q - 1);
memcpy(tmp + 1, nonce, nonce_len);
for (u = 0; u < q; u ++) {
tmp[15 - u] = (unsigned char)data_len;
data_len >>= 8;
}
if (data_len != 0) {
/*
* If the data length was not entirely consumed in the
* loop above, then it exceeds the maximum limit of
* q bytes (when encoded).
*/
return 0;
}
/*
* Start CBC-MAC.
*/
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, tmp, sizeof tmp);
/*
* Assemble AAD length header.
*/
if ((aad_len >> 32) != 0) {
ctx->buf[0] = 0xFF;
ctx->buf[1] = 0xFF;
br_enc64be(ctx->buf + 2, aad_len);
ctx->ptr = 10;
} else if (aad_len >= 0xFF00) {
ctx->buf[0] = 0xFF;
ctx->buf[1] = 0xFE;
br_enc32be(ctx->buf + 2, (uint32_t)aad_len);
ctx->ptr = 6;
} else if (aad_len > 0) {
br_enc16be(ctx->buf, (unsigned)aad_len);
ctx->ptr = 2;
} else {
ctx->ptr = 0;
}
/*
* Make initial counter value and compute tag mask.
*/
ctx->ctr[0] = q - 1;
memcpy(ctx->ctr + 1, nonce, nonce_len);
memset(ctx->ctr + 1 + nonce_len, 0, q);
memset(ctx->tagmask, 0, sizeof ctx->tagmask);
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr,
ctx->tagmask, sizeof ctx->tagmask);
return 1;
}
/* see bearssl_block.h */
void
br_ccm_aad_inject(br_ccm_context *ctx, const void *data, size_t len)
{
const unsigned char *dbuf;
size_t ptr;
dbuf = (unsigned char*)data;
/*
* Complete partial block, if needed.
*/
ptr = ctx->ptr;
if (ptr != 0) {
size_t clen;
clen = (sizeof ctx->buf) - ptr;
if (clen > len) {
memcpy(ctx->buf + ptr, dbuf, len);
ctx->ptr = ptr + len;
return;
}
memcpy(ctx->buf + ptr, dbuf, clen);
dbuf += clen;
len -= clen;
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
ctx->buf, sizeof ctx->buf);
}
/*
* Process complete blocks.
*/
ptr = len & 15;
len -= ptr;
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, dbuf, len);
dbuf += len;
/*
* Copy last partial block in the context buffer.
*/
memcpy(ctx->buf, dbuf, ptr);
ctx->ptr = ptr;
}
/* see bearssl_block.h */
void
br_ccm_flip(br_ccm_context *ctx)
{
size_t ptr;
/*
* Complete AAD partial block with zeros, if necessary.
*/
ptr = ctx->ptr;
if (ptr != 0) {
memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr);
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
ctx->buf, sizeof ctx->buf);
ctx->ptr = 0;
}
/*
* Counter was already set by br_ccm_reset().
*/
}
/* see bearssl_block.h */
void
br_ccm_run(br_ccm_context *ctx, int encrypt, void *data, size_t len)
{
unsigned char *dbuf;
size_t ptr;
dbuf = (unsigned char*)data;
/*
* Complete a partial block, if any: ctx->buf[] contains
* ctx->ptr plaintext bytes (already reported), and the other
* bytes are CTR stream output.
*/
ptr = ctx->ptr;
if (ptr != 0) {
size_t clen;
size_t u;
clen = (sizeof ctx->buf) - ptr;
if (clen > len) {
clen = len;
}
if (encrypt) {
for (u = 0; u < clen; u ++) {
unsigned w, x;
w = ctx->buf[ptr + u];
x = dbuf[u];
ctx->buf[ptr + u] = x;
dbuf[u] = w ^ x;
}
} else {
for (u = 0; u < clen; u ++) {
unsigned w;
w = ctx->buf[ptr + u] ^ dbuf[u];
dbuf[u] = w;
ctx->buf[ptr + u] = w;
}
}
dbuf += clen;
len -= clen;
ptr += clen;
if (ptr < sizeof ctx->buf) {
ctx->ptr = ptr;
return;
}
(*ctx->bctx)->mac(ctx->bctx,
ctx->cbcmac, ctx->buf, sizeof ctx->buf);
}
/*
* Process all complete blocks. Note that the ctrcbc API is for
* encrypt-then-MAC (CBC-MAC is computed over the encrypted
* blocks) while CCM uses MAC-and-encrypt (CBC-MAC is computed
* over the plaintext blocks). Therefore, we need to use the
* _decryption_ function for encryption, and the encryption
* function for decryption (this works because CTR encryption
* and decryption are identical, so the choice really is about
* computing the CBC-MAC before or after XORing with the CTR
* stream).
*/
ptr = len & 15;
len -= ptr;
if (encrypt) {
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
dbuf, len);
} else {
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
dbuf, len);
}
dbuf += len;
/*
* If there is some remaining data, then we need to compute an
* extra block of CTR stream.
*/
if (ptr != 0) {
size_t u;
memset(ctx->buf, 0, sizeof ctx->buf);
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr,
ctx->buf, sizeof ctx->buf);
if (encrypt) {
for (u = 0; u < ptr; u ++) {
unsigned w, x;
w = ctx->buf[u];
x = dbuf[u];
ctx->buf[u] = x;
dbuf[u] = w ^ x;
}
} else {
for (u = 0; u < ptr; u ++) {
unsigned w;
w = ctx->buf[u] ^ dbuf[u];
dbuf[u] = w;
ctx->buf[u] = w;
}
}
}
ctx->ptr = ptr;
}
/* see bearssl_block.h */
size_t
br_ccm_get_tag(br_ccm_context *ctx, void *tag)
{
size_t ptr;
size_t u;
/*
* If there is some buffered data, then we need to pad it with
* zeros and finish up CBC-MAC.
*/
ptr = ctx->ptr;
if (ptr != 0) {
memset(ctx->buf + ptr, 0, (sizeof ctx->buf) - ptr);
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
ctx->buf, sizeof ctx->buf);
}
/*
* XOR the tag mask into the CBC-MAC output.
*/
for (u = 0; u < ctx->tag_len; u ++) {
ctx->cbcmac[u] ^= ctx->tagmask[u];
}
memcpy(tag, ctx->cbcmac, ctx->tag_len);
return ctx->tag_len;
}
/* see bearssl_block.h */
uint32_t
br_ccm_check_tag(br_ccm_context *ctx, const void *tag)
{
unsigned char tmp[16];
size_t u, tag_len;
uint32_t z;
tag_len = br_ccm_get_tag(ctx, tmp);
z = 0;
for (u = 0; u < tag_len; u ++) {
z |= tmp[u] ^ ((const unsigned char *)tag)[u];
}
return EQ0(z);
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Implementation Notes
* ====================
*
* The combined CTR + CBC-MAC functions can only handle full blocks,
* so some buffering is necessary. Moreover, EAX has a special padding
* rule for CBC-MAC, which implies that we cannot compute the MAC over
* the last received full block until we know whether we are at the
* end of the data or not.
*
* - 'ptr' contains a value from 1 to 16, which is the number of bytes
* accumulated in buf[] that still needs to be processed with the
* current OMAC computation. Beware that this can go to 16: a
* complete block cannot be processed until it is known whether it
* is the last block or not. However, it can never be 0, because
* OMAC^t works on an input that is at least one-block long.
*
* - When processing the message itself, CTR encryption/decryption is
* also done at the same time. The first 'ptr' bytes of buf[] then
* contains the encrypted bytes, while the last '16 - ptr' bytes of
* buf[] are the remnants of the stream block, to be used against
* the next input bytes, when available.
*
* - The current counter and running CBC-MAC values are kept in 'ctr'
* and 'cbcmac', respectively.
*
* - The derived keys for padding are kept in L2 and L4 (double and
* quadruple of Enc_K(0^n), in GF(2^128), respectively).
*/
/*
* Start an OMAC computation; the first block is the big-endian
* representation of the provided value ('val' must fit on one byte).
* We make it a delayed block because it may also be the last one,
*/
static void
omac_start(br_eax_context *ctx, unsigned val)
{
memset(ctx->cbcmac, 0, sizeof ctx->cbcmac);
memset(ctx->buf, 0, sizeof ctx->buf);
ctx->buf[15] = val;
ctx->ptr = 16;
}
/*
* Double a value in finite field GF(2^128), defined with modulus
* X^128+X^7+X^2+X+1.
*/
static void
double_gf128(unsigned char *dst, const unsigned char *src)
{
unsigned cc;
int i;
cc = 0x87 & -((unsigned)src[0] >> 7);
for (i = 15; i >= 0; i --) {
unsigned z;
z = (src[i] << 1) ^ cc;
cc = z >> 8;
dst[i] = (unsigned char)z;
}
}
/*
* Apply padding to the last block, currently in ctx->buf (with
* ctx->ptr bytes), and finalize OMAC computation.
*/
static void
do_pad(br_eax_context *ctx)
{
unsigned char *pad;
size_t ptr, u;
ptr = ctx->ptr;
if (ptr == 16) {
pad = ctx->L2;
} else {
ctx->buf[ptr ++] = 0x80;
memset(ctx->buf + ptr, 0x00, 16 - ptr);
pad = ctx->L4;
}
for (u = 0; u < sizeof ctx->buf; u ++) {
ctx->buf[u] ^= pad[u];
}
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, ctx->buf, sizeof ctx->buf);
}
/*
* Apply CBC-MAC on the provided data, with buffering management.
*
* Upon entry, two situations are acceptable:
*
* ctx->ptr == 0: there is no data to process in ctx->buf
* ctx->ptr == 16: there is a full block of unprocessed data in ctx->buf
*
* Upon exit, ctx->ptr may be zero only if it was already zero on entry,
* and len == 0. In all other situations, ctx->ptr will be non-zero on
* exit (and may have value 16).
*/
static void
do_cbcmac_chunk(br_eax_context *ctx, const void *data, size_t len)
{
size_t ptr;
if (len == 0) {
return;
}
ptr = len & (size_t)15;
if (ptr == 0) {
len -= 16;
ptr = 16;
} else {
len -= ptr;
}
if (ctx->ptr == 16) {
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
ctx->buf, sizeof ctx->buf);
}
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac, data, len);
memcpy(ctx->buf, (const unsigned char *)data + len, ptr);
ctx->ptr = ptr;
}
/* see bearssl_aead.h */
void
br_eax_init(br_eax_context *ctx, const br_block_ctrcbc_class **bctx)
{
unsigned char tmp[16], iv[16];
ctx->vtable = &br_eax_vtable;
ctx->bctx = bctx;
/*
* Encrypt a whole-zero block to compute L2 and L4.
*/
memset(tmp, 0, sizeof tmp);
memset(iv, 0, sizeof iv);
(*bctx)->ctr(bctx, iv, tmp, sizeof tmp);
double_gf128(ctx->L2, tmp);
double_gf128(ctx->L4, ctx->L2);
}
/* see bearssl_aead.h */
void
br_eax_capture(const br_eax_context *ctx, br_eax_state *st)
{
/*
* We capture the three OMAC* states _after_ processing the
* initial block (assuming that nonce, message and AAD are
* all non-empty).
*/
int i;
memset(st->st, 0, sizeof st->st);
for (i = 0; i < 3; i ++) {
unsigned char tmp[16];
memset(tmp, 0, sizeof tmp);
tmp[15] = (unsigned char)i;
(*ctx->bctx)->mac(ctx->bctx, st->st[i], tmp, sizeof tmp);
}
}
/* see bearssl_aead.h */
void
br_eax_reset(br_eax_context *ctx, const void *nonce, size_t len)
{
/*
* Process nonce with OMAC^0.
*/
omac_start(ctx, 0);
do_cbcmac_chunk(ctx, nonce, len);
do_pad(ctx);
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
/*
* Start OMAC^1 for the AAD ("header" in the EAX specification).
*/
omac_start(ctx, 1);
/*
* We use ctx->head[0] as temporary flag to mark that we are
* using a "normal" reset().
*/
ctx->head[0] = 0;
}
/* see bearssl_aead.h */
void
br_eax_reset_pre_aad(br_eax_context *ctx, const br_eax_state *st,
const void *nonce, size_t len)
{
if (len == 0) {
omac_start(ctx, 0);
} else {
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
ctx->ptr = 0;
do_cbcmac_chunk(ctx, nonce, len);
}
do_pad(ctx);
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
memcpy(ctx->cbcmac, st->st[1], sizeof ctx->cbcmac);
ctx->ptr = 0;
memcpy(ctx->ctr, st->st[2], sizeof ctx->ctr);
/*
* We use ctx->head[0] as a flag to indicate that we use a
* a recorded state, with ctx->ctr containing the preprocessed
* first block for OMAC^2.
*/
ctx->head[0] = 1;
}
/* see bearssl_aead.h */
void
br_eax_reset_post_aad(br_eax_context *ctx, const br_eax_state *st,
const void *nonce, size_t len)
{
if (len == 0) {
omac_start(ctx, 0);
} else {
memcpy(ctx->cbcmac, st->st[0], sizeof ctx->cbcmac);
ctx->ptr = 0;
do_cbcmac_chunk(ctx, nonce, len);
}
do_pad(ctx);
memcpy(ctx->nonce, ctx->cbcmac, sizeof ctx->cbcmac);
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
memcpy(ctx->head, st->st[1], sizeof ctx->head);
memcpy(ctx->cbcmac, st->st[2], sizeof ctx->cbcmac);
ctx->ptr = 0;
}
/* see bearssl_aead.h */
void
br_eax_aad_inject(br_eax_context *ctx, const void *data, size_t len)
{
size_t ptr;
ptr = ctx->ptr;
/*
* If there is a partial block, first complete it.
*/
if (ptr < 16) {
size_t clen;
clen = 16 - ptr;
if (len <= clen) {
memcpy(ctx->buf + ptr, data, len);
ctx->ptr = ptr + len;
return;
}
memcpy(ctx->buf + ptr, data, clen);
data = (const unsigned char *)data + clen;
len -= clen;
}
/*
* We now have a full block in buf[], and this is not the last
* block.
*/
do_cbcmac_chunk(ctx, data, len);
}
/* see bearssl_aead.h */
void
br_eax_flip(br_eax_context *ctx)
{
int from_capture;
/*
* ctx->head[0] may be non-zero if the context was reset with
* a pre-AAD captured state. In that case, ctx->ctr[] contains
* the state for OMAC^2 _after_ processing the first block.
*/
from_capture = ctx->head[0];
/*
* Complete the OMAC computation on the AAD.
*/
do_pad(ctx);
memcpy(ctx->head, ctx->cbcmac, sizeof ctx->cbcmac);
/*
* Start OMAC^2 for the encrypted data.
* If the context was initialized from a captured state, then
* the OMAC^2 value is in the ctr[] array.
*/
if (from_capture) {
memcpy(ctx->cbcmac, ctx->ctr, sizeof ctx->cbcmac);
ctx->ptr = 0;
} else {
omac_start(ctx, 2);
}
/*
* Initial counter value for CTR is the processed nonce.
*/
memcpy(ctx->ctr, ctx->nonce, sizeof ctx->nonce);
}
/* see bearssl_aead.h */
void
br_eax_run(br_eax_context *ctx, int encrypt, void *data, size_t len)
{
unsigned char *dbuf;
size_t ptr;
/*
* Ensure that there is actual data to process.
*/
if (len == 0) {
return;
}
dbuf = (unsigned char*)data;
ptr = ctx->ptr;
/*
* We may have ptr == 0 here if we initialized from a captured
* state. In that case, there is no partially consumed block
* or unprocessed data.
*/
if (ptr != 0 && ptr != 16) {
/*
* We have a partially consumed block.
*/
size_t u, clen;
clen = 16 - ptr;
if (len <= clen) {
clen = len;
}
if (encrypt) {
for (u = 0; u < clen; u ++) {
ctx->buf[ptr + u] ^= dbuf[u];
}
memcpy(dbuf, ctx->buf + ptr, clen);
} else {
for (u = 0; u < clen; u ++) {
unsigned dx, sx;
sx = ctx->buf[ptr + u];
dx = dbuf[u];
ctx->buf[ptr + u] = dx;
dbuf[u] = sx ^ dx;
}
}
if (len <= clen) {
ctx->ptr = ptr + clen;
return;
}
dbuf += clen;
len -= clen;
}
/*
* We now have a complete encrypted block in buf[] that must still
* be processed with OMAC, and this is not the final buf.
* Exception: when ptr == 0, no block has been produced yet.
*/
if (ptr != 0) {
(*ctx->bctx)->mac(ctx->bctx, ctx->cbcmac,
ctx->buf, sizeof ctx->buf);
}
/*
* Do CTR encryption or decryption and CBC-MAC for all full blocks
* except the last.
*/
ptr = len & (size_t)15;
if (ptr == 0) {
len -= 16;
ptr = 16;
} else {
len -= ptr;
}
if (encrypt) {
(*ctx->bctx)->encrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
dbuf, len);
} else {
(*ctx->bctx)->decrypt(ctx->bctx, ctx->ctr, ctx->cbcmac,
dbuf, len);
}
dbuf += len;
/*
* Compute next block of CTR stream, and use it to finish
* encrypting or decrypting the data.
*/
memset(ctx->buf, 0, sizeof ctx->buf);
(*ctx->bctx)->ctr(ctx->bctx, ctx->ctr, ctx->buf, sizeof ctx->buf);
if (encrypt) {
size_t u;
for (u = 0; u < ptr; u ++) {
ctx->buf[u] ^= dbuf[u];
}
memcpy(dbuf, ctx->buf, ptr);
} else {
size_t u;
for (u = 0; u < ptr; u ++) {
unsigned dx, sx;
sx = ctx->buf[u];
dx = dbuf[u];
ctx->buf[u] = dx;
dbuf[u] = sx ^ dx;
}
}
ctx->ptr = ptr;
}
/*
* Complete tag computation. The final tag is written in ctx->cbcmac.
*/
static void
do_final(br_eax_context *ctx)
{
size_t u;
do_pad(ctx);
/*
* Authentication tag is the XOR of the three OMAC outputs for
* the nonce, AAD and encrypted data.
*/
for (u = 0; u < 16; u ++) {
ctx->cbcmac[u] ^= ctx->nonce[u] ^ ctx->head[u];
}
}
/* see bearssl_aead.h */
void
br_eax_get_tag(br_eax_context *ctx, void *tag)
{
do_final(ctx);
memcpy(tag, ctx->cbcmac, sizeof ctx->cbcmac);
}
/* see bearssl_aead.h */
void
br_eax_get_tag_trunc(br_eax_context *ctx, void *tag, size_t len)
{
do_final(ctx);
memcpy(tag, ctx->cbcmac, len);
}
/* see bearssl_aead.h */
uint32_t
br_eax_check_tag_trunc(br_eax_context *ctx, const void *tag, size_t len)
{
unsigned char tmp[16];
size_t u;
int x;
br_eax_get_tag(ctx, tmp);
x = 0;
for (u = 0; u < len; u ++) {
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
}
return EQ0(x);
}
/* see bearssl_aead.h */
uint32_t
br_eax_check_tag(br_eax_context *ctx, const void *tag)
{
return br_eax_check_tag_trunc(ctx, tag, 16);
}
/* see bearssl_aead.h */
const br_aead_class br_eax_vtable = {
16,
(void (*)(const br_aead_class **, const void *, size_t))
&br_eax_reset,
(void (*)(const br_aead_class **, const void *, size_t))
&br_eax_aad_inject,
(void (*)(const br_aead_class **))
&br_eax_flip,
(void (*)(const br_aead_class **, int, void *, size_t))
&br_eax_run,
(void (*)(const br_aead_class **, void *))
&br_eax_get_tag,
(uint32_t (*)(const br_aead_class **, const void *))
&br_eax_check_tag,
(void (*)(const br_aead_class **, void *, size_t))
&br_eax_get_tag_trunc,
(uint32_t (*)(const br_aead_class **, const void *, size_t))
&br_eax_check_tag_trunc
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Implementation Notes
* ====================
*
* Since CTR and GHASH implementations can handle only full blocks, a
* 16-byte buffer (buf[]) is maintained in the context:
*
* - When processing AAD, buf[] contains the 0-15 unprocessed bytes.
*
* - When doing CTR encryption / decryption, buf[] contains the AES output
* for the last partial block, to be used with the next few bytes of
* data, as well as the already encrypted bytes. For instance, if the
* processed data length so far is 21 bytes, then buf[0..4] contains
* the five last encrypted bytes, and buf[5..15] contains the next 11
* AES output bytes to be XORed with the next 11 bytes of input.
*
* The recorded AES output bytes are used to complete the block when
* the corresponding bytes are obtained. Note that buf[] always
* contains the _encrypted_ bytes, whether we apply encryption or
* decryption: these bytes are used as input to GHASH when the block
* is complete.
*
* In both cases, the low bits of the data length counters (count_aad,
* count_ctr) are used to work out the current situation.
*/
/* see bearssl_aead.h */
void
br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh)
{
unsigned char iv[12];
ctx->vtable = &br_gcm_vtable;
ctx->bctx = bctx;
ctx->gh = gh;
/*
* The GHASH key h[] is the raw encryption of the all-zero
* block. Since we only have a CTR implementation, we use it
* with an all-zero IV and a zero counter, to CTR-encrypt an
* all-zero block.
*/
memset(ctx->h, 0, sizeof ctx->h);
memset(iv, 0, sizeof iv);
(*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h);
}
/* see bearssl_aead.h */
void
br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len)
{
/*
* If the provided nonce is 12 bytes, then this is the initial
* IV for CTR mode; it will be used with a counter that starts
* at 2 (value 1 is for encrypting the GHASH output into the tag).
*
* If the provided nonce has any other length, then it is hashed
* (with GHASH) into a 16-byte value that will be the IV for CTR
* (both 12-byte IV and 32-bit counter).
*/
if (len == 12) {
memcpy(ctx->j0_1, iv, 12);
ctx->j0_2 = 1;
} else {
unsigned char ty[16], tmp[16];
memset(ty, 0, sizeof ty);
ctx->gh(ty, ctx->h, iv, len);
memset(tmp, 0, 8);
br_enc64be(tmp + 8, (uint64_t)len << 3);
ctx->gh(ty, ctx->h, tmp, 16);
memcpy(ctx->j0_1, ty, 12);
ctx->j0_2 = br_dec32be(ty + 12);
}
ctx->jc = ctx->j0_2 + 1;
memset(ctx->y, 0, sizeof ctx->y);
ctx->count_aad = 0;
ctx->count_ctr = 0;
}
/* see bearssl_aead.h */
void
br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len)
{
size_t ptr, dlen;
ptr = (size_t)ctx->count_aad & (size_t)15;
if (ptr != 0) {
/*
* If there is a partial block, then we first try to
* complete it.
*/
size_t clen;
clen = 16 - ptr;
if (len < clen) {
memcpy(ctx->buf + ptr, data, len);
ctx->count_aad += (uint64_t)len;
return;
}
memcpy(ctx->buf + ptr, data, clen);
ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
data = (const unsigned char *)data + clen;
len -= clen;
ctx->count_aad += (uint64_t)clen;
}
/*
* Now AAD is aligned on a 16-byte block (with regards to GHASH).
* We process all complete blocks, and save the last partial
* block.
*/
dlen = len & ~(size_t)15;
ctx->gh(ctx->y, ctx->h, data, dlen);
memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen);
ctx->count_aad += (uint64_t)len;
}
/* see bearssl_aead.h */
void
br_gcm_flip(br_gcm_context *ctx)
{
/*
* We complete the GHASH computation if there is a partial block.
* The GHASH implementation automatically applies padding with
* zeros.
*/
size_t ptr;
ptr = (size_t)ctx->count_aad & (size_t)15;
if (ptr != 0) {
ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
}
}
/* see bearssl_aead.h */
void
br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len)
{
unsigned char *buf;
size_t ptr, dlen;
buf = (unsigned char*)data;
ptr = (size_t)ctx->count_ctr & (size_t)15;
if (ptr != 0) {
/*
* If we have a partial block, then we try to complete it.
*/
size_t u, clen;
clen = 16 - ptr;
if (len < clen) {
clen = len;
}
for (u = 0; u < clen; u ++) {
unsigned x, y;
x = buf[u];
y = x ^ ctx->buf[ptr + u];
ctx->buf[ptr + u] = encrypt ? y : x;
buf[u] = y;
}
ctx->count_ctr += (uint64_t)clen;
buf += clen;
len -= clen;
if (ptr + clen < 16) {
return;
}
ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
}
/*
* Process full blocks.
*/
dlen = len & ~(size_t)15;
if (!encrypt) {
ctx->gh(ctx->y, ctx->h, buf, dlen);
}
ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen);
if (encrypt) {
ctx->gh(ctx->y, ctx->h, buf, dlen);
}
buf += dlen;
len -= dlen;
ctx->count_ctr += (uint64_t)dlen;
if (len > 0) {
/*
* There is a partial block.
*/
size_t u;
memset(ctx->buf, 0, sizeof ctx->buf);
ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1,
ctx->jc, ctx->buf, 16);
for (u = 0; u < len; u ++) {
unsigned x, y;
x = buf[u];
y = x ^ ctx->buf[u];
ctx->buf[u] = encrypt ? y : x;
buf[u] = y;
}
ctx->count_ctr += (uint64_t)len;
}
}
/* see bearssl_aead.h */
void
br_gcm_get_tag(br_gcm_context *ctx, void *tag)
{
size_t ptr;
unsigned char tmp[16];
ptr = (size_t)ctx->count_ctr & (size_t)15;
if (ptr > 0) {
/*
* There is a partial block: encrypted/decrypted data has
* been produced, but the encrypted bytes must still be
* processed by GHASH.
*/
ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
}
/*
* Final block for GHASH: the AAD and plaintext lengths (in bits).
*/
br_enc64be(tmp, ctx->count_aad << 3);
br_enc64be(tmp + 8, ctx->count_ctr << 3);
ctx->gh(ctx->y, ctx->h, tmp, 16);
/*
* Tag is the GHASH output XORed with the encryption of the
* nonce with the initial counter value.
*/
memcpy(tag, ctx->y, 16);
(*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16);
}
/* see bearssl_aead.h */
void
br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len)
{
unsigned char tmp[16];
br_gcm_get_tag(ctx, tmp);
memcpy(tag, tmp, len);
}
/* see bearssl_aead.h */
uint32_t
br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len)
{
unsigned char tmp[16];
size_t u;
int x;
br_gcm_get_tag(ctx, tmp);
x = 0;
for (u = 0; u < len; u ++) {
x |= tmp[u] ^ ((const unsigned char *)tag)[u];
}
return EQ0(x);
}
/* see bearssl_aead.h */
uint32_t
br_gcm_check_tag(br_gcm_context *ctx, const void *tag)
{
return br_gcm_check_tag_trunc(ctx, tag, 16);
}
/* see bearssl_aead.h */
const br_aead_class br_gcm_vtable = {
16,
(void (*)(const br_aead_class **, const void *, size_t))
&br_gcm_reset,
(void (*)(const br_aead_class **, const void *, size_t))
&br_gcm_aad_inject,
(void (*)(const br_aead_class **))
&br_gcm_flip,
(void (*)(const br_aead_class **, int, void *, size_t))
&br_gcm_run,
(void (*)(const br_aead_class **, void *))
&br_gcm_get_tag,
(uint32_t (*)(const br_aead_class **, const void *))
&br_gcm_check_tag,
(void (*)(const br_aead_class **, void *, size_t))
&br_gcm_get_tag_trunc,
(uint32_t (*)(const br_aead_class **, const void *, size_t))
&br_gcm_check_tag_trunc
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_ccopy(uint32_t ctl, void *dst, const void *src, size_t len)
{
unsigned char *d;
const unsigned char *s;
d = (unsigned char*)dst;
s = (const unsigned char*)src;
while (len -- > 0) {
uint32_t x, y;
x = *s ++;
y = *d;
*d = MUX(ctl, x, y);
d ++;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_dec16be(uint16_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = (const unsigned char*)src;
while (num -- > 0) {
*v ++ = br_dec16be(buf);
buf += 2;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_dec16le(uint16_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = (const unsigned char*)src;
while (num -- > 0) {
*v ++ = br_dec16le(buf);
buf += 2;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_dec32be(uint32_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = (const unsigned char*)src;
while (num -- > 0) {
*v ++ = br_dec32be(buf);
buf += 4;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_dec32le(uint32_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = (const unsigned char*)src;
while (num -- > 0) {
*v ++ = br_dec32le(buf);
buf += 4;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_dec64be(uint64_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = (const unsigned char*)src;
while (num -- > 0) {
*v ++ = br_dec64be(buf);
buf += 8;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_dec64le(uint64_t *v, size_t num, const void *src)
{
const unsigned char *buf;
buf = (const unsigned char*)src;
while (num -- > 0) {
*v ++ = br_dec64le(buf);
buf += 8;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_enc16be(void *dst, const uint16_t *v, size_t num)
{
unsigned char *buf;
buf = (unsigned char*)dst;
while (num -- > 0) {
br_enc16be(buf, *v ++);
buf += 2;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_enc16le(void *dst, const uint16_t *v, size_t num)
{
unsigned char *buf;
buf = (unsigned char*)dst;
while (num -- > 0) {
br_enc16le(buf, *v ++);
buf += 2;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_enc32be(void *dst, const uint32_t *v, size_t num)
{
unsigned char *buf;
buf = (unsigned char*)dst;
while (num -- > 0) {
br_enc32be(buf, *v ++);
buf += 4;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_enc32le(void *dst, const uint32_t *v, size_t num)
{
unsigned char *buf;
buf = (unsigned char*)dst;
while (num -- > 0) {
br_enc32le(buf, *v ++);
buf += 4;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_enc64be(void *dst, const uint64_t *v, size_t num)
{
unsigned char *buf;
buf = (unsigned char*)dst;
while (num -- > 0) {
br_enc64be(buf, *v ++);
buf += 8;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_range_enc64le(void *dst, const uint64_t *v, size_t num)
{
unsigned char *buf;
buf = (unsigned char*)dst;
while (num -- > 0) {
br_enc64le(buf, *v ++);
buf += 8;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/* Automatically generated code; do not modify directly. */
#include
#include
typedef struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} _src_codec_pemdec_ct0_context;
static uint32_t
_src_codec_pemdec_ct0_parse7E_unsigned(const unsigned char **p)
{
uint32_t x;
x = 0;
for (;;) {
unsigned y;
y = *(*p) ++;
x = (x << 7) | (uint32_t)(y & 0x7F);
if (y < 0x80) {
return x;
}
}
}
static int32_t
_src_codec_pemdec_ct0_parse7E_signed(const unsigned char **p)
{
int neg;
uint32_t x;
neg = ((**p) >> 6) & 1;
x = (uint32_t)-neg;
for (;;) {
unsigned y;
y = *(*p) ++;
x = (x << 7) | (uint32_t)(y & 0x7F);
if (y < 0x80) {
if (neg) {
return -(int32_t)~x - 1;
} else {
return (int32_t)x;
}
}
}
}
#define T0_VBYTE(x, n) (unsigned char)((((uint32_t)(x) >> (n)) & 0x7F) | 0x80)
#define T0_FBYTE(x, n) (unsigned char)(((uint32_t)(x) >> (n)) & 0x7F)
#define T0_SBYTE(x) (unsigned char)((((uint32_t)(x) >> 28) + 0xF8) ^ 0xF8)
#define T0_INT1(x) T0_FBYTE(x, 0)
#define T0_INT2(x) T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT3(x) T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT4(x) T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
#define T0_INT5(x) T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
/* static const unsigned char _src_codec_pemdec_ct0_datablock[]; */
void br_pem_decoder_init_main(void *t0ctx);
void br_pem_decoder_run(void *t0ctx);
#define _src_codec_pemdec_cCTX ((br_pem_decoder_context *)(void *)((unsigned char *)t0ctx - offsetof(br_pem_decoder_context, cpu)))
/* see bearssl_pem.h */
void
br_pem_decoder_init(br_pem_decoder_context *ctx)
{
memset(ctx, 0, sizeof *ctx);
ctx->cpu.dp = &ctx->dp_stack[0];
ctx->cpu.rp = &ctx->rp_stack[0];
br_pem_decoder_init_main(&ctx->cpu);
br_pem_decoder_run(&ctx->cpu);
}
/* see bearssl_pem.h */
size_t
br_pem_decoder_push(br_pem_decoder_context *ctx,
const void *data, size_t len)
{
if (ctx->event) {
return 0;
}
ctx->hbuf = (const unsigned char*)data;
ctx->hlen = len;
br_pem_decoder_run(&ctx->cpu);
return len - ctx->hlen;
}
/* see bearssl_pem.h */
int
br_pem_decoder_event(br_pem_decoder_context *ctx)
{
int event;
event = ctx->event;
ctx->event = 0;
return event;
}
static const unsigned char _src_codec_pemdec_ct0_datablock[] = {
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20,
0x00, 0x2D, 0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x00
};
static const unsigned char _src_codec_pemdec_ct0_codeblock[] = {
0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x01, 0x01, 0x07, 0x00, 0x00, 0x01,
0x01, 0x08, 0x00, 0x00, 0x13, 0x13, 0x00, 0x00, 0x01,
T0_INT2(offsetof(br_pem_decoder_context, event)), 0x00, 0x00, 0x01,
T0_INT2(offsetof(br_pem_decoder_context, name)), 0x00, 0x00, 0x05,
0x14, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x03, 0x13, 0x04, 0x76, 0x01,
0x2D, 0x0C, 0x06, 0x05, 0x2E, 0x01, 0x03, 0x2D, 0x00, 0x01, 0x0D, 0x27,
0x05, 0x04, 0x01, 0x03, 0x2D, 0x00, 0x15, 0x2E, 0x01, 0x02, 0x2D, 0x00,
0x01, 0x01, 0x7F, 0x03, 0x00, 0x25, 0x01, 0x00, 0x18, 0x0D, 0x06, 0x03,
0x13, 0x04, 0x3C, 0x01, 0x7F, 0x18, 0x0D, 0x06, 0x13, 0x13, 0x02, 0x00,
0x05, 0x06, 0x2E, 0x01, 0x03, 0x2D, 0x04, 0x03, 0x01, 0x7F, 0x23, 0x01,
0x00, 0x00, 0x04, 0x23, 0x01, 0x01, 0x18, 0x0D, 0x06, 0x09, 0x13, 0x01,
0x00, 0x23, 0x01, 0x00, 0x00, 0x04, 0x14, 0x01, 0x02, 0x18, 0x0D, 0x06,
0x06, 0x13, 0x01, 0x7F, 0x00, 0x04, 0x08, 0x13, 0x01, 0x03, 0x2D, 0x01,
0x00, 0x00, 0x13, 0x01, 0x00, 0x03, 0x00, 0x04, 0xFF, 0x33, 0x01, 0x2C,
0x14, 0x01, 0x2D, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x7F, 0x00, 0x14, 0x31,
0x06, 0x02, 0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01,
0x02, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00,
0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03,
0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02,
0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D,
0x06, 0x04, 0x13, 0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x2E,
0x13, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13, 0x01, 0x03, 0x00,
0x2F, 0x05, 0x04, 0x13, 0x01, 0x03, 0x00, 0x01, 0x3D, 0x0C, 0x06, 0x03,
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x0F, 0x10, 0x06, 0x03, 0x01, 0x03,
0x00, 0x02, 0x00, 0x01, 0x04, 0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14,
0x1D, 0x06, 0x05, 0x13, 0x2E, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06,
0x0A, 0x07, 0x03, 0x00, 0x29, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x04, 0x13,
0x01, 0x03, 0x00, 0x14, 0x01, 0x3D, 0x0D, 0x06, 0x20, 0x13, 0x2F, 0x05,
0x03, 0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x03, 0x10, 0x06, 0x03, 0x01,
0x03, 0x00, 0x02, 0x00, 0x01, 0x0A, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x02,
0x0F, 0x1C, 0x01, 0x01, 0x00, 0x16, 0x14, 0x1D, 0x06, 0x05, 0x13, 0x2E,
0x01, 0x03, 0x00, 0x02, 0x00, 0x01, 0x06, 0x0A, 0x07, 0x03, 0x00, 0x02,
0x00, 0x01, 0x10, 0x0F, 0x1C, 0x02, 0x00, 0x01, 0x08, 0x0F, 0x1C, 0x02,
0x00, 0x1C, 0x01, 0x00, 0x00, 0x00, 0x28, 0x01, 0x01, 0x2D, 0x24, 0x06,
0x02, 0x04, 0x7B, 0x04, 0x75, 0x00, 0x14, 0x12, 0x2A, 0x14, 0x05, 0x04,
0x20, 0x01, 0x7F, 0x00, 0x2C, 0x2A, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x05,
0x13, 0x20, 0x01, 0x00, 0x00, 0x0D, 0x05, 0x05, 0x13, 0x2E, 0x01, 0x00,
0x00, 0x1E, 0x04, 0x5E, 0x00, 0x01, 0x01, 0x27, 0x06, 0x0B, 0x22, 0x01,
0x80, 0x7F, 0x2B, 0x14, 0x06, 0x02, 0x30, 0x00, 0x13, 0x04, 0x6E, 0x00,
0x2C, 0x14, 0x31, 0x05, 0x01, 0x00, 0x13, 0x04, 0x77, 0x00, 0x14, 0x14,
0x01, 0x80, 0x61, 0x0E, 0x1B, 0x01, 0x80, 0x7A, 0x0B, 0x10, 0x06, 0x03,
0x01, 0x20, 0x08, 0x00, 0x01, 0x14, 0x03, 0x00, 0x1B, 0x18, 0x05, 0x05,
0x20, 0x2E, 0x01, 0x00, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0D, 0x06, 0x06,
0x20, 0x02, 0x00, 0x1B, 0x08, 0x00, 0x14, 0x01, 0x0D, 0x0D, 0x06, 0x03,
0x13, 0x04, 0x03, 0x2A, 0x18, 0x1A, 0x1E, 0x1B, 0x1F, 0x1B, 0x04, 0x59,
0x00, 0x19, 0x14, 0x1D, 0x05, 0x01, 0x00, 0x13, 0x11, 0x04, 0x76, 0x00,
0x21, 0x1A, 0x11, 0x00, 0x00, 0x2C, 0x01, 0x0A, 0x0C, 0x06, 0x02, 0x04,
0x78, 0x00, 0x01, 0x01, 0x7F, 0x03, 0x00, 0x2C, 0x14, 0x01, 0x0A, 0x0C,
0x06, 0x09, 0x31, 0x05, 0x04, 0x01, 0x00, 0x03, 0x00, 0x04, 0x70, 0x13,
0x02, 0x00, 0x00, 0x00, 0x14, 0x06, 0x14, 0x1F, 0x14, 0x22, 0x07, 0x17,
0x01, 0x2D, 0x0C, 0x06, 0x08, 0x22, 0x07, 0x1E, 0x01, 0x00, 0x1B, 0x1A,
0x00, 0x04, 0x69, 0x22, 0x1A, 0x00, 0x00, 0x14, 0x01, 0x0A, 0x0C, 0x1B,
0x01, 0x20, 0x0B, 0x10, 0x00
};
static const uint16_t _src_codec_pemdec_ct0_caddr[] = {
0,
5,
10,
15,
19,
24,
29,
67,
149,
384,
396,
431,
450,
460,
479,
523,
534,
539,
549,
574,
601
};
#define _src_codec_pemdec_cT0_INTERPRETED 29
#define _src_codec_pemdec_cT0_ENTER(ip, rp, slot) do { \
const unsigned char *t0_newip; \
uint32_t t0_lnum; \
t0_newip = &_src_codec_pemdec_ct0_codeblock[_src_codec_pemdec_ct0_caddr[(slot) - _src_codec_pemdec_cT0_INTERPRETED]]; \
t0_lnum = _src_codec_pemdec_ct0_parse7E_unsigned(&t0_newip); \
(rp) += t0_lnum; \
*((rp) ++) = (uint32_t)((ip) - &_src_codec_pemdec_ct0_codeblock[0]) + (t0_lnum << 16); \
(ip) = t0_newip; \
} while (0)
#define _src_codec_pemdec_cT0_DEFENTRY(name, slot) \
void \
name(void *ctx) \
{ \
_src_codec_pemdec_ct0_context *t0ctx =(_src_codec_pemdec_ct0_context*)ctx; \
t0ctx->ip = &_src_codec_pemdec_ct0_codeblock[0]; \
_src_codec_pemdec_cT0_ENTER(t0ctx->ip, t0ctx->rp, slot); \
}
_src_codec_pemdec_cT0_DEFENTRY(br_pem_decoder_init_main, 38)
#define T0_NEXT(t0ipp) (*(*(t0ipp)) ++)
void
br_pem_decoder_run(void *t0ctx)
{
uint32_t *dp, *rp;
const unsigned char *ip;
#define T0_LOCAL(x) (*(rp - 2 - (x)))
#define T0_POP() (*-- dp)
#define T0_POPi() (*(int32_t *)(-- dp))
#define T0_PEEK(x) (*(dp - 1 - (x)))
#define T0_PEEKi(x) (*(int32_t *)(dp - 1 - (x)))
#define T0_PUSH(v) do { *dp = (v); dp ++; } while (0)
#define T0_PUSHi(v) do { *(int32_t *)dp = (v); dp ++; } while (0)
#define T0_RPOP() (*-- rp)
#define T0_RPOPi() (*(int32_t *)(-- rp))
#define T0_RPUSH(v) do { *rp = (v); rp ++; } while (0)
#define T0_RPUSHi(v) do { *(int32_t *)rp = (v); rp ++; } while (0)
#define T0_ROLL(x) do { \
size_t t0len = (size_t)(x); \
uint32_t t0tmp = *(dp - 1 - t0len); \
memmove(dp - t0len - 1, dp - t0len, t0len * sizeof *dp); \
*(dp - 1) = t0tmp; \
} while (0)
#define T0_SWAP() do { \
uint32_t t0tmp = *(dp - 2); \
*(dp - 2) = *(dp - 1); \
*(dp - 1) = t0tmp; \
} while (0)
#define T0_ROT() do { \
uint32_t t0tmp = *(dp - 3); \
*(dp - 3) = *(dp - 2); \
*(dp - 2) = *(dp - 1); \
*(dp - 1) = t0tmp; \
} while (0)
#define T0_NROT() do { \
uint32_t t0tmp = *(dp - 1); \
*(dp - 1) = *(dp - 2); \
*(dp - 2) = *(dp - 3); \
*(dp - 3) = t0tmp; \
} while (0)
#define T0_PICK(x) do { \
uint32_t t0depth = (x); \
T0_PUSH(T0_PEEK(t0depth)); \
} while (0)
#define T0_CO() do { \
goto t0_exit; \
} while (0)
#define T0_RET() goto t0_next
dp = ((_src_codec_pemdec_ct0_context *)t0ctx)->dp;
rp = ((_src_codec_pemdec_ct0_context *)t0ctx)->rp;
ip = ((_src_codec_pemdec_ct0_context *)t0ctx)->ip;
goto t0_next;
for (;;) {
uint32_t t0x;
t0_next:
t0x = T0_NEXT(&ip);
if (t0x < _src_codec_pemdec_cT0_INTERPRETED) {
switch (t0x) {
int32_t t0off;
case 0: /* ret */
t0x = T0_RPOP();
rp -= (t0x >> 16);
t0x &= 0xFFFF;
if (t0x == 0) {
ip = NULL;
goto t0_exit;
}
ip = &_src_codec_pemdec_ct0_codeblock[t0x];
break;
case 1: /* literal constant */
T0_PUSHi(_src_codec_pemdec_ct0_parse7E_signed(&ip));
break;
case 2: /* read local */
T0_PUSH(T0_LOCAL(_src_codec_pemdec_ct0_parse7E_unsigned(&ip)));
break;
case 3: /* write local */
T0_LOCAL(_src_codec_pemdec_ct0_parse7E_unsigned(&ip)) = T0_POP();
break;
case 4: /* jump */
t0off = _src_codec_pemdec_ct0_parse7E_signed(&ip);
ip += t0off;
break;
case 5: /* jump if */
t0off = _src_codec_pemdec_ct0_parse7E_signed(&ip);
if (T0_POP()) {
ip += t0off;
}
break;
case 6: /* jump if not */
t0off = _src_codec_pemdec_ct0_parse7E_signed(&ip);
if (!T0_POP()) {
ip += t0off;
}
break;
case 7: {
/* + */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(a + b);
}
break;
case 8: {
/* - */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(a - b);
}
break;
case 9: {
/* < */
int32_t b = T0_POPi();
int32_t a = T0_POPi();
T0_PUSH(-(uint32_t)(a < b));
}
break;
case 10: {
/* << */
int c = (int)T0_POPi();
uint32_t x = T0_POP();
T0_PUSH(x << c);
}
break;
case 11: {
/* <= */
int32_t b = T0_POPi();
int32_t a = T0_POPi();
T0_PUSH(-(uint32_t)(a <= b));
}
break;
case 12: {
/* <> */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(-(uint32_t)(a != b));
}
break;
case 13: {
/* = */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(-(uint32_t)(a == b));
}
break;
case 14: {
/* >= */
int32_t b = T0_POPi();
int32_t a = T0_POPi();
T0_PUSH(-(uint32_t)(a >= b));
}
break;
case 15: {
/* >> */
int c = (int)T0_POPi();
int32_t x = T0_POPi();
T0_PUSHi(x >> c);
}
break;
case 16: {
/* and */
uint32_t b = T0_POP();
uint32_t a = T0_POP();
T0_PUSH(a & b);
}
break;
case 17: {
/* co */
T0_CO();
}
break;
case 18: {
/* data-get8 */
size_t addr = T0_POP();
T0_PUSH(_src_codec_pemdec_ct0_datablock[addr]);
}
break;
case 19: {
/* drop */
(void)T0_POP();
}
break;
case 20: {
/* dup */
T0_PUSH(T0_PEEK(0));
}
break;
case 21: {
/* flush-buf */
if (_src_codec_pemdec_cCTX->ptr > 0) {
if (_src_codec_pemdec_cCTX->dest) {
_src_codec_pemdec_cCTX->dest(_src_codec_pemdec_cCTX->dest_ctx, _src_codec_pemdec_cCTX->buf, _src_codec_pemdec_cCTX->ptr);
}
_src_codec_pemdec_cCTX->ptr = 0;
}
}
break;
case 22: {
/* from-base64 */
uint32_t c = T0_POP();
uint32_t p, q, r, z;
p = c - 0x41;
q = c - 0x61;
r = c - 0x30;
z = ((p + 2) & -LT(p, 26))
| ((q + 28) & -LT(q, 26))
| ((r + 54) & -LT(r, 10))
| (64 & -EQ(c, 0x2B))
| (65 & -EQ(c, 0x2F))
| EQ(c, 0x3D);
T0_PUSHi((int32_t)z - 2);
}
break;
case 23: {
/* get8 */
size_t addr = T0_POP();
T0_PUSH(*((unsigned char *)_src_codec_pemdec_cCTX + addr));
}
break;
case 24: {
/* over */
T0_PUSH(T0_PEEK(1));
}
break;
case 25: {
/* read8-native */
if (_src_codec_pemdec_cCTX->hlen > 0) {
T0_PUSH(*_src_codec_pemdec_cCTX->hbuf ++);
_src_codec_pemdec_cCTX->hlen --;
} else {
T0_PUSHi(-1);
}
}
break;
case 26: {
/* set8 */
size_t addr = T0_POP();
unsigned x = T0_POP();
*((unsigned char *)_src_codec_pemdec_cCTX + addr) = x;
}
break;
case 27: {
/* swap */
T0_SWAP();
}
break;
case 28: {
/* write8 */
unsigned char x = (unsigned char)T0_POP();
_src_codec_pemdec_cCTX->buf[_src_codec_pemdec_cCTX->ptr ++] = x;
if (_src_codec_pemdec_cCTX->ptr == sizeof _src_codec_pemdec_cCTX->buf) {
if (_src_codec_pemdec_cCTX->dest) {
_src_codec_pemdec_cCTX->dest(_src_codec_pemdec_cCTX->dest_ctx, _src_codec_pemdec_cCTX->buf, sizeof _src_codec_pemdec_cCTX->buf);
}
_src_codec_pemdec_cCTX->ptr = 0;
}
}
break;
}
} else {
_src_codec_pemdec_cT0_ENTER(ip, rp, t0x);
}
}
t0_exit:
((_src_codec_pemdec_ct0_context *)t0ctx)->dp = dp;
((_src_codec_pemdec_ct0_context *)t0ctx)->rp = rp;
((_src_codec_pemdec_ct0_context *)t0ctx)->ip = ip;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Get the appropriate Base64 character for a numeric value in the
* 0..63 range. This is constant-time.
*/
static char
b64char(uint32_t x)
{
/*
* Values 0 to 25 map to 0x41..0x5A ('A' to 'Z')
* Values 26 to 51 map to 0x61..0x7A ('a' to 'z')
* Values 52 to 61 map to 0x30..0x39 ('0' to '9')
* Value 62 maps to 0x2B ('+')
* Value 63 maps to 0x2F ('/')
*/
uint32_t a, b, c;
a = x - 26;
b = x - 52;
c = x - 62;
/*
* Looking at bits 8..15 of values a, b and c:
*
* x a b c
* ---------------------
* 0..25 FF FF FF
* 26..51 00 FF FF
* 52..61 00 00 FF
* 62..63 00 00 00
*/
return (char)(((x + 0x41) & ((a & b & c) >> 8))
| ((x + (0x61 - 26)) & ((~a & b & c) >> 8))
| ((x - (52 - 0x30)) & ((~a & ~b & c) >> 8))
| ((0x2B + ((x & 1) << 2)) & (~(a | b | c) >> 8)));
}
/* see bearssl_pem.h */
size_t
br_pem_encode(void *dest, const void *data, size_t len,
const char *banner, unsigned flags)
{
size_t dlen, banner_len, lines;
char *d;
unsigned char *buf;
size_t u;
int off, lim;
banner_len = strlen(banner);
/* FIXME: try to avoid divisions here, as they may pull
an extra libc function. */
if ((flags & BR_PEM_LINE64) != 0) {
lines = (len + 47) / 48;
} else {
lines = (len + 56) / 57;
}
dlen = (banner_len << 1) + 30 + (((len + 2) / 3) << 2)
+ lines + 2;
if ((flags & BR_PEM_CRLF) != 0) {
dlen += lines + 2;
}
if (dest == NULL) {
return dlen;
}
d = (char*)dest;
/*
* We always move the source data to the end of output buffer;
* the encoding process never "catches up" except at the very
* end. This also handles all conditions of partial or total
* overlap.
*/
buf = (unsigned char *)d + dlen - len;
memmove(buf, data, len);
memcpy(d, "-----BEGIN ", 11);
d += 11;
memcpy(d, banner, banner_len);
d += banner_len;
memcpy(d, "-----", 5);
d += 5;
if ((flags & BR_PEM_CRLF) != 0) {
*d ++ = 0x0D;
}
*d ++ = 0x0A;
off = 0;
lim = (flags & BR_PEM_LINE64) != 0 ? 16 : 19;
for (u = 0; (u + 2) < len; u += 3) {
uint32_t w;
w = ((uint32_t)buf[u] << 16)
| ((uint32_t)buf[u + 1] << 8)
| (uint32_t)buf[u + 2];
*d ++ = b64char(w >> 18);
*d ++ = b64char((w >> 12) & 0x3F);
*d ++ = b64char((w >> 6) & 0x3F);
*d ++ = b64char(w & 0x3F);
if (++ off == lim) {
off = 0;
if ((flags & BR_PEM_CRLF) != 0) {
*d ++ = 0x0D;
}
*d ++ = 0x0A;
}
}
if (u < len) {
uint32_t w;
w = (uint32_t)buf[u] << 16;
if (u + 1 < len) {
w |= (uint32_t)buf[u + 1] << 8;
}
*d ++ = b64char(w >> 18);
*d ++ = b64char((w >> 12) & 0x3F);
if (u + 1 < len) {
*d ++ = b64char((w >> 6) & 0x3F);
} else {
*d ++ = 0x3D;
}
*d ++ = 0x3D;
off ++;
}
if (off != 0) {
if ((flags & BR_PEM_CRLF) != 0) {
*d ++ = 0x0D;
}
*d ++ = 0x0A;
}
memcpy(d, "-----END ", 9);
d += 9;
memcpy(d, banner, banner_len);
d += banner_len;
memcpy(d, "-----", 5);
d += 5;
if ((flags & BR_PEM_CRLF) != 0) {
*d ++ = 0x0D;
}
*d ++ = 0x0A;
/* Final zero, not counted in returned length. */
*d ++ = 0x00;
return dlen;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char *
_src_ec_ec_all_m15_capi_generator(int curve, size_t *len)
{
switch (curve) {
case BR_EC_secp256r1:
return br_ec_p256_m15.generator(curve, len);
case BR_EC_curve25519:
return br_ec_c25519_m15.generator(curve, len);
default:
return br_ec_prime_i15.generator(curve, len);
}
}
static const unsigned char *
_src_ec_ec_all_m15_capi_order(int curve, size_t *len)
{
switch (curve) {
case BR_EC_secp256r1:
return br_ec_p256_m15.order(curve, len);
case BR_EC_curve25519:
return br_ec_c25519_m15.order(curve, len);
default:
return br_ec_prime_i15.order(curve, len);
}
}
static size_t
_src_ec_ec_all_m15_capi_xoff(int curve, size_t *len)
{
switch (curve) {
case BR_EC_secp256r1:
return br_ec_p256_m15.xoff(curve, len);
case BR_EC_curve25519:
return br_ec_c25519_m15.xoff(curve, len);
default:
return br_ec_prime_i15.xoff(curve, len);
}
}
static uint32_t
_src_ec_ec_all_m15_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
switch (curve) {
case BR_EC_secp256r1:
return br_ec_p256_m15.mul(G, Glen, kb, kblen, curve);
case BR_EC_curve25519:
return br_ec_c25519_m15.mul(G, Glen, kb, kblen, curve);
default:
return br_ec_prime_i15.mul(G, Glen, kb, kblen, curve);
}
}
static size_t
_src_ec_ec_all_m15_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
switch (curve) {
case BR_EC_secp256r1:
return br_ec_p256_m15.mulgen(R, x, xlen, curve);
case BR_EC_curve25519:
return br_ec_c25519_m15.mulgen(R, x, xlen, curve);
default:
return br_ec_prime_i15.mulgen(R, x, xlen, curve);
}
}
static uint32_t
_src_ec_ec_all_m15_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
switch (curve) {
case BR_EC_secp256r1:
return br_ec_p256_m15.muladd(A, B, len,
x, xlen, y, ylen, curve);
case BR_EC_curve25519:
return br_ec_c25519_m15.muladd(A, B, len,
x, xlen, y, ylen, curve);
default:
return br_ec_prime_i15.muladd(A, B, len,
x, xlen, y, ylen, curve);
}
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_all_m15 = {
(uint32_t)0x23800000,
&_src_ec_ec_all_m15_capi_generator,
&_src_ec_ec_all_m15_capi_order,
&_src_ec_ec_all_m15_capi_xoff,
&_src_ec_ec_all_m15_capi_mul,
&_src_ec_ec_all_m15_capi_mulgen,
&_src_ec_ec_all_m15_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char *
_src_ec_ec_all_m31_capi_generator(int curve, size_t *len)
{
switch (curve) {
case BR_EC_secp256r1:
#if BR_INT128 || BR_UMUL128
return br_ec_p256_m64.generator(curve, len);
#else
return br_ec_p256_m31.generator(curve, len);
#endif
case BR_EC_curve25519:
#if BR_INT128 || BR_UMUL128
return br_ec_c25519_m64.generator(curve, len);
#else
return br_ec_c25519_m31.generator(curve, len);
#endif
default:
return br_ec_prime_i31.generator(curve, len);
}
}
static const unsigned char *
_src_ec_ec_all_m31_capi_order(int curve, size_t *len)
{
switch (curve) {
case BR_EC_secp256r1:
#if BR_INT128 || BR_UMUL128
return br_ec_p256_m64.order(curve, len);
#else
return br_ec_p256_m31.order(curve, len);
#endif
case BR_EC_curve25519:
#if BR_INT128 || BR_UMUL128
return br_ec_c25519_m64.order(curve, len);
#else
return br_ec_c25519_m31.order(curve, len);
#endif
default:
return br_ec_prime_i31.order(curve, len);
}
}
static size_t
_src_ec_ec_all_m31_capi_xoff(int curve, size_t *len)
{
switch (curve) {
case BR_EC_secp256r1:
#if BR_INT128 || BR_UMUL128
return br_ec_p256_m64.xoff(curve, len);
#else
return br_ec_p256_m31.xoff(curve, len);
#endif
case BR_EC_curve25519:
#if BR_INT128 || BR_UMUL128
return br_ec_c25519_m64.xoff(curve, len);
#else
return br_ec_c25519_m31.xoff(curve, len);
#endif
default:
return br_ec_prime_i31.xoff(curve, len);
}
}
static uint32_t
_src_ec_ec_all_m31_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
switch (curve) {
case BR_EC_secp256r1:
#if BR_INT128 || BR_UMUL128
return br_ec_p256_m64.mul(G, Glen, kb, kblen, curve);
#else
return br_ec_p256_m31.mul(G, Glen, kb, kblen, curve);
#endif
case BR_EC_curve25519:
#if BR_INT128 || BR_UMUL128
return br_ec_c25519_m64.mul(G, Glen, kb, kblen, curve);
#else
return br_ec_c25519_m31.mul(G, Glen, kb, kblen, curve);
#endif
default:
return br_ec_prime_i31.mul(G, Glen, kb, kblen, curve);
}
}
static size_t
_src_ec_ec_all_m31_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
switch (curve) {
case BR_EC_secp256r1:
#if BR_INT128 || BR_UMUL128
return br_ec_p256_m64.mulgen(R, x, xlen, curve);
#else
return br_ec_p256_m31.mulgen(R, x, xlen, curve);
#endif
case BR_EC_curve25519:
#if BR_INT128 || BR_UMUL128
return br_ec_c25519_m64.mulgen(R, x, xlen, curve);
#else
return br_ec_c25519_m31.mulgen(R, x, xlen, curve);
#endif
default:
return br_ec_prime_i31.mulgen(R, x, xlen, curve);
}
}
static uint32_t
_src_ec_ec_all_m31_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
switch (curve) {
case BR_EC_secp256r1:
#if BR_INT128 || BR_UMUL128
return br_ec_p256_m64.muladd(A, B, len,
x, xlen, y, ylen, curve);
#else
return br_ec_p256_m31.muladd(A, B, len,
x, xlen, y, ylen, curve);
#endif
case BR_EC_curve25519:
#if BR_INT128 || BR_UMUL128
return br_ec_c25519_m64.muladd(A, B, len,
x, xlen, y, ylen, curve);
#else
return br_ec_c25519_m31.muladd(A, B, len,
x, xlen, y, ylen, curve);
#endif
default:
return br_ec_prime_i31.muladd(A, B, len,
x, xlen, y, ylen, curve);
}
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_all_m31 = {
(uint32_t)0x23800000,
&_src_ec_ec_all_m31_capi_generator,
&_src_ec_ec_all_m31_capi_order,
&_src_ec_ec_all_m31_capi_xoff,
&_src_ec_ec_all_m31_capi_mul,
&_src_ec_ec_all_m31_capi_mulgen,
&_src_ec_ec_all_m31_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Parameters for the field:
* - field modulus p = 2^255-19
* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
*/
static const uint16_t _src_ec_ec_c25519_i15_cC255_P[] = {
0x0110,
0x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF
};
#define _src_ec_ec_c25519_i15_cP0I 0x4A1B
static const uint16_t _src_ec_ec_c25519_i15_cC255_R2[] = {
0x0110,
0x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000
};
/* obsolete
#include
#include
static void
print_int_mont(const char *name, const uint16_t *x)
{
uint16_t y[18];
unsigned char tmp[32];
size_t u;
printf("%s = ", name);
memcpy(y, x, sizeof y);
br_i15_from_monty(y, _src_ec_ec_c25519_i15_cC255_P, _src_ec_ec_c25519_i15_cP0I);
br_i15_encode(tmp, sizeof tmp, y);
for (u = 0; u < sizeof tmp; u ++) {
printf("%02X", tmp[u]);
}
printf("\n");
}
*/
static const uint16_t _src_ec_ec_c25519_i15_cC255_A24[] = {
0x0110,
0x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000
};
static const unsigned char _src_ec_ec_c25519_i15_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_c25519_i15_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const unsigned char *
_src_ec_ec_c25519_i15_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_i15_cGEN;
}
static const unsigned char *
_src_ec_ec_c25519_i15_capi_order(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_i15_cORDER;
}
static size_t
_src_ec_ec_c25519_i15_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 0;
}
static void
_src_ec_ec_c25519_i15_ccswap(uint16_t *a, uint16_t *b, uint32_t ctl)
{
int i;
ctl = -ctl;
for (i = 0; i < 18; i ++) {
uint32_t aw, bw, tw;
aw = a[i];
bw = b[i];
tw = ctl & (aw ^ bw);
a[i] = aw ^ tw;
b[i] = bw ^ tw;
}
}
static void
_src_ec_ec_c25519_i15_cc255_add(uint16_t *d, const uint16_t *a, const uint16_t *b)
{
uint32_t ctl;
uint16_t t[18];
memcpy(t, a, sizeof t);
ctl = br_i15_add(t, b, 1);
ctl |= NOT(br_i15_sub(t, _src_ec_ec_c25519_i15_cC255_P, 0));
br_i15_sub(t, _src_ec_ec_c25519_i15_cC255_P, ctl);
memcpy(d, t, sizeof t);
}
static void
_src_ec_ec_c25519_i15_cc255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b)
{
uint16_t t[18];
memcpy(t, a, sizeof t);
br_i15_add(t, _src_ec_ec_c25519_i15_cC255_P, br_i15_sub(t, b, 1));
memcpy(d, t, sizeof t);
}
static void
_src_ec_ec_c25519_i15_cc255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b)
{
uint16_t t[18];
br_i15_montymul(t, a, b, _src_ec_ec_c25519_i15_cC255_P, _src_ec_ec_c25519_i15_cP0I);
memcpy(d, t, sizeof t);
}
static void
_src_ec_ec_c25519_i15_cbyteswap(unsigned char *G)
{
int i;
for (i = 0; i < 16; i ++) {
unsigned char t;
t = G[i];
G[i] = G[31 - i];
G[31 - i] = t;
}
}
static uint32_t
_src_ec_ec_c25519_i15_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
#define ILEN (18 * sizeof(uint16_t))
/*
* The a[] and b[] arrays have an extra word to allow for
* decoding without using br_i15_decode_reduce().
*/
uint16_t x1[18], x2[18], x3[18], z2[18], z3[18];
uint16_t a[19], aa[18], b[19], bb[18];
uint16_t c[18], d[18], e[18], da[18], cb[18];
unsigned char k[32];
uint32_t swap;
int i;
(void)curve;
/*
* Points are encoded over exactly 32 bytes. Multipliers must fit
* in 32 bytes as well.
* RFC 7748 mandates that the high bit of the last point byte must
* be ignored/cleared.
*/
if (Glen != 32 || kblen > 32) {
return 0;
}
G[31] &= 0x7F;
/*
* Byteswap the point encoding, because it uses little-endian, and
* the generic decoding routine uses big-endian.
*/
_src_ec_ec_c25519_i15_cbyteswap(G);
/*
* Decode the point ('u' coordinate). This should be reduced
* modulo p, but we prefer to avoid the dependency on
* br_i15_decode_reduce(). Instead, we use br_i15_decode_mod()
* with a synthetic modulus of value 2^255 (this must work
* since G was truncated to 255 bits), then use a conditional
* subtraction. We use br_i15_decode_mod() and not
* br_i15_decode(), because the ec_prime_i15 implementation uses
* the former but not the latter.
* br_i15_decode_reduce(a, G, 32, _src_ec_ec_c25519_i15_cC255_P);
*/
br_i15_zero(b, 0x111);
b[18] = 1;
br_i15_decode_mod(a, G, 32, b);
a[0] = 0x110;
br_i15_sub(a, _src_ec_ec_c25519_i15_cC255_P, NOT(br_i15_sub(a, _src_ec_ec_c25519_i15_cC255_P, 0)));
/*
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
* into Montgomery representation.
*/
br_i15_montymul(x1, a, _src_ec_ec_c25519_i15_cC255_R2, _src_ec_ec_c25519_i15_cC255_P, _src_ec_ec_c25519_i15_cP0I);
memcpy(x3, x1, ILEN);
br_i15_zero(z2, _src_ec_ec_c25519_i15_cC255_P[0]);
memcpy(x2, z2, ILEN);
x2[1] = 19;
memcpy(z3, x2, ILEN);
memset(k, 0, (sizeof k) - kblen);
memcpy(k + (sizeof k) - kblen, kb, kblen);
k[31] &= 0xF8;
k[0] &= 0x7F;
k[0] |= 0x40;
/* obsolete
print_int_mont("x1", x1);
*/
swap = 0;
for (i = 254; i >= 0; i --) {
uint32_t kt;
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
swap ^= kt;
_src_ec_ec_c25519_i15_ccswap(x2, x3, swap);
_src_ec_ec_c25519_i15_ccswap(z2, z3, swap);
swap = kt;
/* obsolete
print_int_mont("x2", x2);
print_int_mont("z2", z2);
print_int_mont("x3", x3);
print_int_mont("z3", z3);
*/
_src_ec_ec_c25519_i15_cc255_add(a, x2, z2);
_src_ec_ec_c25519_i15_cc255_mul(aa, a, a);
_src_ec_ec_c25519_i15_cc255_sub(b, x2, z2);
_src_ec_ec_c25519_i15_cc255_mul(bb, b, b);
_src_ec_ec_c25519_i15_cc255_sub(e, aa, bb);
_src_ec_ec_c25519_i15_cc255_add(c, x3, z3);
_src_ec_ec_c25519_i15_cc255_sub(d, x3, z3);
_src_ec_ec_c25519_i15_cc255_mul(da, d, a);
_src_ec_ec_c25519_i15_cc255_mul(cb, c, b);
/* obsolete
print_int_mont("a ", a);
print_int_mont("aa", aa);
print_int_mont("b ", b);
print_int_mont("bb", bb);
print_int_mont("e ", e);
print_int_mont("c ", c);
print_int_mont("d ", d);
print_int_mont("da", da);
print_int_mont("cb", cb);
*/
_src_ec_ec_c25519_i15_cc255_add(x3, da, cb);
_src_ec_ec_c25519_i15_cc255_mul(x3, x3, x3);
_src_ec_ec_c25519_i15_cc255_sub(z3, da, cb);
_src_ec_ec_c25519_i15_cc255_mul(z3, z3, z3);
_src_ec_ec_c25519_i15_cc255_mul(z3, z3, x1);
_src_ec_ec_c25519_i15_cc255_mul(x2, aa, bb);
_src_ec_ec_c25519_i15_cc255_mul(z2, _src_ec_ec_c25519_i15_cC255_A24, e);
_src_ec_ec_c25519_i15_cc255_add(z2, z2, aa);
_src_ec_ec_c25519_i15_cc255_mul(z2, e, z2);
/* obsolete
print_int_mont("x2", x2);
print_int_mont("z2", z2);
print_int_mont("x3", x3);
print_int_mont("z3", z3);
*/
}
_src_ec_ec_c25519_i15_ccswap(x2, x3, swap);
_src_ec_ec_c25519_i15_ccswap(z2, z3, swap);
/*
* Inverse z2 with a modular exponentiation. This is a simple
* square-and-multiply algorithm; we mutualise most non-squarings
* since the exponent contains almost only ones.
*/
memcpy(a, z2, ILEN);
for (i = 0; i < 15; i ++) {
_src_ec_ec_c25519_i15_cc255_mul(a, a, a);
_src_ec_ec_c25519_i15_cc255_mul(a, a, z2);
}
memcpy(b, a, ILEN);
for (i = 0; i < 14; i ++) {
int j;
for (j = 0; j < 16; j ++) {
_src_ec_ec_c25519_i15_cc255_mul(b, b, b);
}
_src_ec_ec_c25519_i15_cc255_mul(b, b, a);
}
for (i = 14; i >= 0; i --) {
_src_ec_ec_c25519_i15_cc255_mul(b, b, b);
if ((0xFFEB >> i) & 1) {
_src_ec_ec_c25519_i15_cc255_mul(b, z2, b);
}
}
_src_ec_ec_c25519_i15_cc255_mul(b, x2, b);
/*
* To avoid a dependency on br_i15_from_monty(), we use a
* Montgomery multiplication with 1.
* memcpy(x2, b, ILEN);
* br_i15_from_monty(x2, _src_ec_ec_c25519_i15_cC255_P, _src_ec_ec_c25519_i15_cP0I);
*/
br_i15_zero(a, _src_ec_ec_c25519_i15_cC255_P[0]);
a[1] = 1;
br_i15_montymul(x2, a, b, _src_ec_ec_c25519_i15_cC255_P, _src_ec_ec_c25519_i15_cP0I);
br_i15_encode(G, 32, x2);
_src_ec_ec_c25519_i15_cbyteswap(G);
return 1;
#undef ILEN
}
static size_t
_src_ec_ec_c25519_i15_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_c25519_i15_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_c25519_i15_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_c25519_i15_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We don't implement this method, since it is used for ECDSA
* only, and there is no ECDSA over Curve25519 (which instead
* uses EdDSA).
*/
(void)A;
(void)B;
(void)len;
(void)x;
(void)xlen;
(void)y;
(void)ylen;
(void)curve;
return 0;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_c25519_i15 = {
(uint32_t)0x20000000,
&_src_ec_ec_c25519_i15_capi_generator,
&_src_ec_ec_c25519_i15_capi_order,
&_src_ec_ec_c25519_i15_capi_xoff,
&_src_ec_ec_c25519_i15_capi_mul,
&_src_ec_ec_c25519_i15_capi_mulgen,
&_src_ec_ec_c25519_i15_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Parameters for the field:
* - field modulus p = 2^255-19
* - R^2 mod p (R = 2^(31k) for the smallest k such that R >= p)
*/
static const uint32_t _src_ec_ec_c25519_i31_cC255_P[] = {
0x00000107,
0x7FFFFFED, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0000007F
};
#define _src_ec_ec_c25519_i31_cP0I 0x286BCA1B
static const uint32_t _src_ec_ec_c25519_i31_cC255_R2[] = {
0x00000107,
0x00000000, 0x02D20000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
static const uint32_t _src_ec_ec_c25519_i31_cC255_A24[] = {
0x00000107,
0x53000000, 0x0000468B, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
/* obsolete
#include
#include
static void
print_int_mont(const char *name, const uint32_t *x)
{
uint32_t y[10];
unsigned char tmp[32];
size_t u;
printf("%s = ", name);
memcpy(y, x, sizeof y);
br_i31_from_monty(y, _src_ec_ec_c25519_i31_cC255_P, _src_ec_ec_c25519_i31_cP0I);
br_i31_encode(tmp, sizeof tmp, y);
for (u = 0; u < sizeof tmp; u ++) {
printf("%02X", tmp[u]);
}
printf("\n");
}
*/
static const unsigned char _src_ec_ec_c25519_i31_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_c25519_i31_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const unsigned char *
_src_ec_ec_c25519_i31_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_i31_cGEN;
}
static const unsigned char *
_src_ec_ec_c25519_i31_capi_order(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_i31_cORDER;
}
static size_t
_src_ec_ec_c25519_i31_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 0;
}
static void
_src_ec_ec_c25519_i31_ccswap(uint32_t *a, uint32_t *b, uint32_t ctl)
{
int i;
ctl = -ctl;
for (i = 0; i < 10; i ++) {
uint32_t aw, bw, tw;
aw = a[i];
bw = b[i];
tw = ctl & (aw ^ bw);
a[i] = aw ^ tw;
b[i] = bw ^ tw;
}
}
static void
_src_ec_ec_c25519_i31_cc255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t ctl;
uint32_t t[10];
memcpy(t, a, sizeof t);
ctl = br_i31_add(t, b, 1);
ctl |= NOT(br_i31_sub(t, _src_ec_ec_c25519_i31_cC255_P, 0));
br_i31_sub(t, _src_ec_ec_c25519_i31_cC255_P, ctl);
memcpy(d, t, sizeof t);
}
static void
_src_ec_ec_c25519_i31_cc255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[10];
memcpy(t, a, sizeof t);
br_i31_add(t, _src_ec_ec_c25519_i31_cC255_P, br_i31_sub(t, b, 1));
memcpy(d, t, sizeof t);
}
static void
_src_ec_ec_c25519_i31_cc255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[10];
br_i31_montymul(t, a, b, _src_ec_ec_c25519_i31_cC255_P, _src_ec_ec_c25519_i31_cP0I);
memcpy(d, t, sizeof t);
}
static void
_src_ec_ec_c25519_i31_cbyteswap(unsigned char *G)
{
int i;
for (i = 0; i < 16; i ++) {
unsigned char t;
t = G[i];
G[i] = G[31 - i];
G[31 - i] = t;
}
}
static uint32_t
_src_ec_ec_c25519_i31_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
uint32_t x1[10], x2[10], x3[10], z2[10], z3[10];
uint32_t a[10], aa[10], b[10], bb[10];
uint32_t c[10], d[10], e[10], da[10], cb[10];
unsigned char k[32];
uint32_t swap;
int i;
(void)curve;
/*
* Points are encoded over exactly 32 bytes. Multipliers must fit
* in 32 bytes as well.
* RFC 7748 mandates that the high bit of the last point byte must
* be ignored/cleared.
*/
if (Glen != 32 || kblen > 32) {
return 0;
}
G[31] &= 0x7F;
/*
* Byteswap the point encoding, because it uses little-endian, and
* the generic decoding routine uses big-endian.
*/
_src_ec_ec_c25519_i31_cbyteswap(G);
/*
* Decode the point ('u' coordinate). This should be reduced
* modulo p, but we prefer to avoid the dependency on
* br_i31_decode_reduce(). Instead, we use br_i31_decode_mod()
* with a synthetic modulus of value 2^255 (this must work
* since G was truncated to 255 bits), then use a conditional
* subtraction. We use br_i31_decode_mod() and not
* br_i31_decode(), because the ec_prime_i31 implementation uses
* the former but not the latter.
* br_i31_decode_reduce(a, G, 32, _src_ec_ec_c25519_i31_cC255_P);
*/
br_i31_zero(b, 0x108);
b[9] = 0x0080;
br_i31_decode_mod(a, G, 32, b);
a[0] = 0x107;
br_i31_sub(a, _src_ec_ec_c25519_i31_cC255_P, NOT(br_i31_sub(a, _src_ec_ec_c25519_i31_cC255_P, 0)));
/*
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
* into Montgomery representation.
*/
br_i31_montymul(x1, a, _src_ec_ec_c25519_i31_cC255_R2, _src_ec_ec_c25519_i31_cC255_P, _src_ec_ec_c25519_i31_cP0I);
memcpy(x3, x1, sizeof x1);
br_i31_zero(z2, _src_ec_ec_c25519_i31_cC255_P[0]);
memcpy(x2, z2, sizeof z2);
x2[1] = 0x13000000;
memcpy(z3, x2, sizeof x2);
/*
* kb[] is in big-endian notation, but possibly shorter than k[].
*/
memset(k, 0, (sizeof k) - kblen);
memcpy(k + (sizeof k) - kblen, kb, kblen);
k[31] &= 0xF8;
k[0] &= 0x7F;
k[0] |= 0x40;
/* obsolete
print_int_mont("x1", x1);
*/
swap = 0;
for (i = 254; i >= 0; i --) {
uint32_t kt;
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
swap ^= kt;
_src_ec_ec_c25519_i31_ccswap(x2, x3, swap);
_src_ec_ec_c25519_i31_ccswap(z2, z3, swap);
swap = kt;
/* obsolete
print_int_mont("x2", x2);
print_int_mont("z2", z2);
print_int_mont("x3", x3);
print_int_mont("z3", z3);
*/
_src_ec_ec_c25519_i31_cc255_add(a, x2, z2);
_src_ec_ec_c25519_i31_cc255_mul(aa, a, a);
_src_ec_ec_c25519_i31_cc255_sub(b, x2, z2);
_src_ec_ec_c25519_i31_cc255_mul(bb, b, b);
_src_ec_ec_c25519_i31_cc255_sub(e, aa, bb);
_src_ec_ec_c25519_i31_cc255_add(c, x3, z3);
_src_ec_ec_c25519_i31_cc255_sub(d, x3, z3);
_src_ec_ec_c25519_i31_cc255_mul(da, d, a);
_src_ec_ec_c25519_i31_cc255_mul(cb, c, b);
/* obsolete
print_int_mont("a ", a);
print_int_mont("aa", aa);
print_int_mont("b ", b);
print_int_mont("bb", bb);
print_int_mont("e ", e);
print_int_mont("c ", c);
print_int_mont("d ", d);
print_int_mont("da", da);
print_int_mont("cb", cb);
*/
_src_ec_ec_c25519_i31_cc255_add(x3, da, cb);
_src_ec_ec_c25519_i31_cc255_mul(x3, x3, x3);
_src_ec_ec_c25519_i31_cc255_sub(z3, da, cb);
_src_ec_ec_c25519_i31_cc255_mul(z3, z3, z3);
_src_ec_ec_c25519_i31_cc255_mul(z3, z3, x1);
_src_ec_ec_c25519_i31_cc255_mul(x2, aa, bb);
_src_ec_ec_c25519_i31_cc255_mul(z2, _src_ec_ec_c25519_i31_cC255_A24, e);
_src_ec_ec_c25519_i31_cc255_add(z2, z2, aa);
_src_ec_ec_c25519_i31_cc255_mul(z2, e, z2);
/* obsolete
print_int_mont("x2", x2);
print_int_mont("z2", z2);
print_int_mont("x3", x3);
print_int_mont("z3", z3);
*/
}
_src_ec_ec_c25519_i31_ccswap(x2, x3, swap);
_src_ec_ec_c25519_i31_ccswap(z2, z3, swap);
/*
* Inverse z2 with a modular exponentiation. This is a simple
* square-and-multiply algorithm; we mutualise most non-squarings
* since the exponent contains almost only ones.
*/
memcpy(a, z2, sizeof z2);
for (i = 0; i < 15; i ++) {
_src_ec_ec_c25519_i31_cc255_mul(a, a, a);
_src_ec_ec_c25519_i31_cc255_mul(a, a, z2);
}
memcpy(b, a, sizeof a);
for (i = 0; i < 14; i ++) {
int j;
for (j = 0; j < 16; j ++) {
_src_ec_ec_c25519_i31_cc255_mul(b, b, b);
}
_src_ec_ec_c25519_i31_cc255_mul(b, b, a);
}
for (i = 14; i >= 0; i --) {
_src_ec_ec_c25519_i31_cc255_mul(b, b, b);
if ((0xFFEB >> i) & 1) {
_src_ec_ec_c25519_i31_cc255_mul(b, z2, b);
}
}
_src_ec_ec_c25519_i31_cc255_mul(b, x2, b);
/*
* To avoid a dependency on br_i31_from_monty(), we use
* a Montgomery multiplication with 1.
* memcpy(x2, b, sizeof b);
* br_i31_from_monty(x2, _src_ec_ec_c25519_i31_cC255_P, _src_ec_ec_c25519_i31_cP0I);
*/
br_i31_zero(a, _src_ec_ec_c25519_i31_cC255_P[0]);
a[1] = 1;
br_i31_montymul(x2, a, b, _src_ec_ec_c25519_i31_cC255_P, _src_ec_ec_c25519_i31_cP0I);
br_i31_encode(G, 32, x2);
_src_ec_ec_c25519_i31_cbyteswap(G);
return 1;
}
static size_t
_src_ec_ec_c25519_i31_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_c25519_i31_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_c25519_i31_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_c25519_i31_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We don't implement this method, since it is used for ECDSA
* only, and there is no ECDSA over Curve25519 (which instead
* uses EdDSA).
*/
(void)A;
(void)B;
(void)len;
(void)x;
(void)xlen;
(void)y;
(void)ylen;
(void)curve;
return 0;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_c25519_i31 = {
(uint32_t)0x20000000,
&_src_ec_ec_c25519_i31_capi_generator,
&_src_ec_ec_c25519_i31_capi_order,
&_src_ec_ec_c25519_i31_capi_xoff,
&_src_ec_ec_c25519_i31_capi_mul,
&_src_ec_ec_c25519_i31_capi_mulgen,
&_src_ec_ec_c25519_i31_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* obsolete
#include
#include
static void
print_int(const char *name, const uint32_t *x)
{
size_t u;
unsigned char tmp[36];
printf("%s = ", name);
for (u = 0; u < 20; u ++) {
if (x[u] > 0x1FFF) {
printf("INVALID:");
for (u = 0; u < 20; u ++) {
printf(" %04X", x[u]);
}
printf("\n");
return;
}
}
memset(tmp, 0, sizeof tmp);
for (u = 0; u < 20; u ++) {
uint32_t w;
int j, k;
w = x[u];
j = 13 * (int)u;
k = j & 7;
if (k != 0) {
w <<= k;
j -= k;
}
k = j >> 3;
tmp[35 - k] |= (unsigned char)w;
tmp[34 - k] |= (unsigned char)(w >> 8);
tmp[33 - k] |= (unsigned char)(w >> 16);
tmp[32 - k] |= (unsigned char)(w >> 24);
}
for (u = 4; u < 36; u ++) {
printf("%02X", tmp[u]);
}
printf("\n");
}
*/
/*
* If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
* that right-shifting a signed negative integer copies the sign bit
* (arithmetic right-shift). This is "implementation-defined behaviour",
* i.e. it is not undefined, but it may differ between compilers. Each
* compiler is supposed to document its behaviour in that respect. GCC
* explicitly defines that an arithmetic right shift is used. We expect
* all other compilers to do the same, because underlying CPU offer an
* arithmetic right shift opcode that could not be used otherwise.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#endif
/*
* Convert an integer from unsigned little-endian encoding to a sequence of
* 13-bit words in little-endian order. The final "partial" word is
* returned.
*/
static uint32_t
le8_to_le13(uint32_t *dst, const unsigned char *src, size_t len)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
acc |= (uint32_t)(*src ++) << acc_len;
acc_len += 8;
if (acc_len >= 13) {
*dst ++ = acc & 0x1FFF;
acc >>= 13;
acc_len -= 13;
}
}
return acc;
}
/*
* Convert an integer (13-bit words, little-endian) to unsigned
* little-endian encoding. The total encoding length is provided; all
* the destination bytes will be filled.
*/
static void
le13_to_le8(unsigned char *dst, size_t len, const uint32_t *src)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
if (acc_len < 8) {
acc |= (*src ++) << acc_len;
acc_len += 13;
}
*dst ++ = (unsigned char)acc;
acc >>= 8;
acc_len -= 8;
}
}
/*
* Normalise an array of words to a strict 13 bits per word. Returned
* value is the resulting carry. The source (w) and destination (d)
* arrays may be identical, but shall not overlap partially.
*/
static inline uint32_t
_src_ec_ec_c25519_m15_cnorm13(uint32_t *d, const uint32_t *w, size_t len)
{
size_t u;
uint32_t cc;
cc = 0;
for (u = 0; u < len; u ++) {
int32_t z;
z = w[u] + cc;
d[u] = z & 0x1FFF;
cc = ARSH(z, 13);
}
return cc;
}
/*
* _src_ec_ec_c25519_m15_cmul20() multiplies two 260-bit integers together. Each word must fit
* on 13 bits; source operands use 20 words, destination operand
* receives 40 words. All overlaps allowed.
*
* _src_ec_ec_c25519_m15_csquare20() computes the square of a 260-bit integer. Each word must
* fit on 13 bits; source operand uses 20 words, destination operand
* receives 40 words. All overlaps allowed.
*/
#if BR_SLOW_MUL15
static void
_src_ec_ec_c25519_m15_cmul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* Two-level Karatsuba: turns a 20x20 multiplication into
* nine 5x5 multiplications. We use 13-bit words but do not
* propagate carries immediately, so words may expand:
*
* - First Karatsuba decomposition turns the 20x20 mul on
* 13-bit words into three 10x10 muls, two on 13-bit words
* and one on 14-bit words.
*
* - Second Karatsuba decomposition further splits these into:
*
* * four 5x5 muls on 13-bit words
* * four 5x5 muls on 14-bit words
* * one 5x5 mul on 15-bit words
*
* Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit
* or 15-bit words, respectively.
*/
uint32_t u[45], v[45], w[90];
uint32_t cc;
int i;
#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
(dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \
+ (s2w)[5 * (s2_off) + 0]; \
(dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \
+ (s2w)[5 * (s2_off) + 1]; \
(dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \
+ (s2w)[5 * (s2_off) + 2]; \
(dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \
+ (s2w)[5 * (s2_off) + 3]; \
(dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \
+ (s2w)[5 * (s2_off) + 4]; \
} while (0)
#define ZADDT(dw, d_off, sw, s_off) do { \
(dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \
(dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \
(dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \
(dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \
(dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \
} while (0)
#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
(dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \
+ (s2w)[5 * (s2_off) + 0]; \
(dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \
+ (s2w)[5 * (s2_off) + 1]; \
(dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \
+ (s2w)[5 * (s2_off) + 2]; \
(dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \
+ (s2w)[5 * (s2_off) + 3]; \
(dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \
+ (s2w)[5 * (s2_off) + 4]; \
} while (0)
#define CPR1(w, cprcc) do { \
uint32_t cprz = (w) + cprcc; \
(w) = cprz & 0x1FFF; \
cprcc = cprz >> 13; \
} while (0)
#define CPR(dw, d_off) do { \
uint32_t cprcc; \
cprcc = 0; \
CPR1((dw)[(d_off) + 0], cprcc); \
CPR1((dw)[(d_off) + 1], cprcc); \
CPR1((dw)[(d_off) + 2], cprcc); \
CPR1((dw)[(d_off) + 3], cprcc); \
CPR1((dw)[(d_off) + 4], cprcc); \
CPR1((dw)[(d_off) + 5], cprcc); \
CPR1((dw)[(d_off) + 6], cprcc); \
CPR1((dw)[(d_off) + 7], cprcc); \
CPR1((dw)[(d_off) + 8], cprcc); \
(dw)[(d_off) + 9] = cprcc; \
} while (0)
memcpy(u, a, 20 * sizeof *a);
ZADD(u, 4, a, 0, a, 1);
ZADD(u, 5, a, 2, a, 3);
ZADD(u, 6, a, 0, a, 2);
ZADD(u, 7, a, 1, a, 3);
ZADD(u, 8, u, 6, u, 7);
memcpy(v, b, 20 * sizeof *b);
ZADD(v, 4, b, 0, b, 1);
ZADD(v, 5, b, 2, b, 3);
ZADD(v, 6, b, 0, b, 2);
ZADD(v, 7, b, 1, b, 3);
ZADD(v, 8, v, 6, v, 7);
/*
* Do the eight first 8x8 muls. Source words are at most 16382
* each, so we can add product results together "as is" in 32-bit
* words.
*/
for (i = 0; i < 40; i += 5) {
w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]);
w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1])
+ MUL15(u[i + 1], v[i + 0]);
w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2])
+ MUL15(u[i + 1], v[i + 1])
+ MUL15(u[i + 2], v[i + 0]);
w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3])
+ MUL15(u[i + 1], v[i + 2])
+ MUL15(u[i + 2], v[i + 1])
+ MUL15(u[i + 3], v[i + 0]);
w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4])
+ MUL15(u[i + 1], v[i + 3])
+ MUL15(u[i + 2], v[i + 2])
+ MUL15(u[i + 3], v[i + 1])
+ MUL15(u[i + 4], v[i + 0]);
w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4])
+ MUL15(u[i + 2], v[i + 3])
+ MUL15(u[i + 3], v[i + 2])
+ MUL15(u[i + 4], v[i + 1]);
w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4])
+ MUL15(u[i + 3], v[i + 3])
+ MUL15(u[i + 4], v[i + 2]);
w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4])
+ MUL15(u[i + 4], v[i + 3]);
w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]);
w[(i << 1) + 9] = 0;
}
/*
* For the 9th multiplication, source words are up to 32764,
* so we must do some carry propagation. If we add up to
* 4 products and the carry is no more than 524224, then the
* result fits in 32 bits, and the next carry will be no more
* than 524224 (because 4*(32764^2)+524224 < 8192*524225).
*
* We thus just skip one of the products in the middle word,
* then do a carry propagation (this reduces words to 13 bits
* each, except possibly the last, which may use up to 17 bits
* or so), then add the missing product.
*/
w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]);
w[80 + 1] = MUL15(u[40 + 0], v[40 + 1])
+ MUL15(u[40 + 1], v[40 + 0]);
w[80 + 2] = MUL15(u[40 + 0], v[40 + 2])
+ MUL15(u[40 + 1], v[40 + 1])
+ MUL15(u[40 + 2], v[40 + 0]);
w[80 + 3] = MUL15(u[40 + 0], v[40 + 3])
+ MUL15(u[40 + 1], v[40 + 2])
+ MUL15(u[40 + 2], v[40 + 1])
+ MUL15(u[40 + 3], v[40 + 0]);
w[80 + 4] = MUL15(u[40 + 0], v[40 + 4])
+ MUL15(u[40 + 1], v[40 + 3])
+ MUL15(u[40 + 2], v[40 + 2])
+ MUL15(u[40 + 3], v[40 + 1]);
/* + MUL15(u[40 + 4], v[40 + 0]) */
w[80 + 5] = MUL15(u[40 + 1], v[40 + 4])
+ MUL15(u[40 + 2], v[40 + 3])
+ MUL15(u[40 + 3], v[40 + 2])
+ MUL15(u[40 + 4], v[40 + 1]);
w[80 + 6] = MUL15(u[40 + 2], v[40 + 4])
+ MUL15(u[40 + 3], v[40 + 3])
+ MUL15(u[40 + 4], v[40 + 2]);
w[80 + 7] = MUL15(u[40 + 3], v[40 + 4])
+ MUL15(u[40 + 4], v[40 + 3]);
w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]);
CPR(w, 80);
w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]);
/*
* The products on 14-bit words in slots 6 and 7 yield values
* up to 5*(16382^2) each, and we need to subtract two such
* values from the higher word. We need the subtraction to fit
* in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit.
* However, 10*(16382^2) does not fit. So we must perform a
* bit of reduction here.
*/
CPR(w, 60);
CPR(w, 70);
/*
* Recompose results.
*/
/* 0..1*0..1 into 0..3 */
ZSUB2F(w, 8, w, 0, w, 2);
ZSUB2F(w, 9, w, 1, w, 3);
ZADDT(w, 1, w, 8);
ZADDT(w, 2, w, 9);
/* 2..3*2..3 into 4..7 */
ZSUB2F(w, 10, w, 4, w, 6);
ZSUB2F(w, 11, w, 5, w, 7);
ZADDT(w, 5, w, 10);
ZADDT(w, 6, w, 11);
/* (0..1+2..3)*(0..1+2..3) into 12..15 */
ZSUB2F(w, 16, w, 12, w, 14);
ZSUB2F(w, 17, w, 13, w, 15);
ZADDT(w, 13, w, 16);
ZADDT(w, 14, w, 17);
/* first-level recomposition */
ZSUB2F(w, 12, w, 0, w, 4);
ZSUB2F(w, 13, w, 1, w, 5);
ZSUB2F(w, 14, w, 2, w, 6);
ZSUB2F(w, 15, w, 3, w, 7);
ZADDT(w, 2, w, 12);
ZADDT(w, 3, w, 13);
ZADDT(w, 4, w, 14);
ZADDT(w, 5, w, 15);
/*
* Perform carry propagation to bring all words down to 13 bits.
*/
cc = _src_ec_ec_c25519_m15_cnorm13(d, w, 40);
d[39] += (cc << 13);
#undef ZADD
#undef ZADDT
#undef ZSUB2F
#undef CPR1
#undef CPR
}
static inline void
_src_ec_ec_c25519_m15_csquare20(uint32_t *d, const uint32_t *a)
{
_src_ec_ec_c25519_m15_cmul20(d, a, a);
}
#else
static void
_src_ec_ec_c25519_m15_cmul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[39];
t[ 0] = MUL15(a[ 0], b[ 0]);
t[ 1] = MUL15(a[ 0], b[ 1])
+ MUL15(a[ 1], b[ 0]);
t[ 2] = MUL15(a[ 0], b[ 2])
+ MUL15(a[ 1], b[ 1])
+ MUL15(a[ 2], b[ 0]);
t[ 3] = MUL15(a[ 0], b[ 3])
+ MUL15(a[ 1], b[ 2])
+ MUL15(a[ 2], b[ 1])
+ MUL15(a[ 3], b[ 0]);
t[ 4] = MUL15(a[ 0], b[ 4])
+ MUL15(a[ 1], b[ 3])
+ MUL15(a[ 2], b[ 2])
+ MUL15(a[ 3], b[ 1])
+ MUL15(a[ 4], b[ 0]);
t[ 5] = MUL15(a[ 0], b[ 5])
+ MUL15(a[ 1], b[ 4])
+ MUL15(a[ 2], b[ 3])
+ MUL15(a[ 3], b[ 2])
+ MUL15(a[ 4], b[ 1])
+ MUL15(a[ 5], b[ 0]);
t[ 6] = MUL15(a[ 0], b[ 6])
+ MUL15(a[ 1], b[ 5])
+ MUL15(a[ 2], b[ 4])
+ MUL15(a[ 3], b[ 3])
+ MUL15(a[ 4], b[ 2])
+ MUL15(a[ 5], b[ 1])
+ MUL15(a[ 6], b[ 0]);
t[ 7] = MUL15(a[ 0], b[ 7])
+ MUL15(a[ 1], b[ 6])
+ MUL15(a[ 2], b[ 5])
+ MUL15(a[ 3], b[ 4])
+ MUL15(a[ 4], b[ 3])
+ MUL15(a[ 5], b[ 2])
+ MUL15(a[ 6], b[ 1])
+ MUL15(a[ 7], b[ 0]);
t[ 8] = MUL15(a[ 0], b[ 8])
+ MUL15(a[ 1], b[ 7])
+ MUL15(a[ 2], b[ 6])
+ MUL15(a[ 3], b[ 5])
+ MUL15(a[ 4], b[ 4])
+ MUL15(a[ 5], b[ 3])
+ MUL15(a[ 6], b[ 2])
+ MUL15(a[ 7], b[ 1])
+ MUL15(a[ 8], b[ 0]);
t[ 9] = MUL15(a[ 0], b[ 9])
+ MUL15(a[ 1], b[ 8])
+ MUL15(a[ 2], b[ 7])
+ MUL15(a[ 3], b[ 6])
+ MUL15(a[ 4], b[ 5])
+ MUL15(a[ 5], b[ 4])
+ MUL15(a[ 6], b[ 3])
+ MUL15(a[ 7], b[ 2])
+ MUL15(a[ 8], b[ 1])
+ MUL15(a[ 9], b[ 0]);
t[10] = MUL15(a[ 0], b[10])
+ MUL15(a[ 1], b[ 9])
+ MUL15(a[ 2], b[ 8])
+ MUL15(a[ 3], b[ 7])
+ MUL15(a[ 4], b[ 6])
+ MUL15(a[ 5], b[ 5])
+ MUL15(a[ 6], b[ 4])
+ MUL15(a[ 7], b[ 3])
+ MUL15(a[ 8], b[ 2])
+ MUL15(a[ 9], b[ 1])
+ MUL15(a[10], b[ 0]);
t[11] = MUL15(a[ 0], b[11])
+ MUL15(a[ 1], b[10])
+ MUL15(a[ 2], b[ 9])
+ MUL15(a[ 3], b[ 8])
+ MUL15(a[ 4], b[ 7])
+ MUL15(a[ 5], b[ 6])
+ MUL15(a[ 6], b[ 5])
+ MUL15(a[ 7], b[ 4])
+ MUL15(a[ 8], b[ 3])
+ MUL15(a[ 9], b[ 2])
+ MUL15(a[10], b[ 1])
+ MUL15(a[11], b[ 0]);
t[12] = MUL15(a[ 0], b[12])
+ MUL15(a[ 1], b[11])
+ MUL15(a[ 2], b[10])
+ MUL15(a[ 3], b[ 9])
+ MUL15(a[ 4], b[ 8])
+ MUL15(a[ 5], b[ 7])
+ MUL15(a[ 6], b[ 6])
+ MUL15(a[ 7], b[ 5])
+ MUL15(a[ 8], b[ 4])
+ MUL15(a[ 9], b[ 3])
+ MUL15(a[10], b[ 2])
+ MUL15(a[11], b[ 1])
+ MUL15(a[12], b[ 0]);
t[13] = MUL15(a[ 0], b[13])
+ MUL15(a[ 1], b[12])
+ MUL15(a[ 2], b[11])
+ MUL15(a[ 3], b[10])
+ MUL15(a[ 4], b[ 9])
+ MUL15(a[ 5], b[ 8])
+ MUL15(a[ 6], b[ 7])
+ MUL15(a[ 7], b[ 6])
+ MUL15(a[ 8], b[ 5])
+ MUL15(a[ 9], b[ 4])
+ MUL15(a[10], b[ 3])
+ MUL15(a[11], b[ 2])
+ MUL15(a[12], b[ 1])
+ MUL15(a[13], b[ 0]);
t[14] = MUL15(a[ 0], b[14])
+ MUL15(a[ 1], b[13])
+ MUL15(a[ 2], b[12])
+ MUL15(a[ 3], b[11])
+ MUL15(a[ 4], b[10])
+ MUL15(a[ 5], b[ 9])
+ MUL15(a[ 6], b[ 8])
+ MUL15(a[ 7], b[ 7])
+ MUL15(a[ 8], b[ 6])
+ MUL15(a[ 9], b[ 5])
+ MUL15(a[10], b[ 4])
+ MUL15(a[11], b[ 3])
+ MUL15(a[12], b[ 2])
+ MUL15(a[13], b[ 1])
+ MUL15(a[14], b[ 0]);
t[15] = MUL15(a[ 0], b[15])
+ MUL15(a[ 1], b[14])
+ MUL15(a[ 2], b[13])
+ MUL15(a[ 3], b[12])
+ MUL15(a[ 4], b[11])
+ MUL15(a[ 5], b[10])
+ MUL15(a[ 6], b[ 9])
+ MUL15(a[ 7], b[ 8])
+ MUL15(a[ 8], b[ 7])
+ MUL15(a[ 9], b[ 6])
+ MUL15(a[10], b[ 5])
+ MUL15(a[11], b[ 4])
+ MUL15(a[12], b[ 3])
+ MUL15(a[13], b[ 2])
+ MUL15(a[14], b[ 1])
+ MUL15(a[15], b[ 0]);
t[16] = MUL15(a[ 0], b[16])
+ MUL15(a[ 1], b[15])
+ MUL15(a[ 2], b[14])
+ MUL15(a[ 3], b[13])
+ MUL15(a[ 4], b[12])
+ MUL15(a[ 5], b[11])
+ MUL15(a[ 6], b[10])
+ MUL15(a[ 7], b[ 9])
+ MUL15(a[ 8], b[ 8])
+ MUL15(a[ 9], b[ 7])
+ MUL15(a[10], b[ 6])
+ MUL15(a[11], b[ 5])
+ MUL15(a[12], b[ 4])
+ MUL15(a[13], b[ 3])
+ MUL15(a[14], b[ 2])
+ MUL15(a[15], b[ 1])
+ MUL15(a[16], b[ 0]);
t[17] = MUL15(a[ 0], b[17])
+ MUL15(a[ 1], b[16])
+ MUL15(a[ 2], b[15])
+ MUL15(a[ 3], b[14])
+ MUL15(a[ 4], b[13])
+ MUL15(a[ 5], b[12])
+ MUL15(a[ 6], b[11])
+ MUL15(a[ 7], b[10])
+ MUL15(a[ 8], b[ 9])
+ MUL15(a[ 9], b[ 8])
+ MUL15(a[10], b[ 7])
+ MUL15(a[11], b[ 6])
+ MUL15(a[12], b[ 5])
+ MUL15(a[13], b[ 4])
+ MUL15(a[14], b[ 3])
+ MUL15(a[15], b[ 2])
+ MUL15(a[16], b[ 1])
+ MUL15(a[17], b[ 0]);
t[18] = MUL15(a[ 0], b[18])
+ MUL15(a[ 1], b[17])
+ MUL15(a[ 2], b[16])
+ MUL15(a[ 3], b[15])
+ MUL15(a[ 4], b[14])
+ MUL15(a[ 5], b[13])
+ MUL15(a[ 6], b[12])
+ MUL15(a[ 7], b[11])
+ MUL15(a[ 8], b[10])
+ MUL15(a[ 9], b[ 9])
+ MUL15(a[10], b[ 8])
+ MUL15(a[11], b[ 7])
+ MUL15(a[12], b[ 6])
+ MUL15(a[13], b[ 5])
+ MUL15(a[14], b[ 4])
+ MUL15(a[15], b[ 3])
+ MUL15(a[16], b[ 2])
+ MUL15(a[17], b[ 1])
+ MUL15(a[18], b[ 0]);
t[19] = MUL15(a[ 0], b[19])
+ MUL15(a[ 1], b[18])
+ MUL15(a[ 2], b[17])
+ MUL15(a[ 3], b[16])
+ MUL15(a[ 4], b[15])
+ MUL15(a[ 5], b[14])
+ MUL15(a[ 6], b[13])
+ MUL15(a[ 7], b[12])
+ MUL15(a[ 8], b[11])
+ MUL15(a[ 9], b[10])
+ MUL15(a[10], b[ 9])
+ MUL15(a[11], b[ 8])
+ MUL15(a[12], b[ 7])
+ MUL15(a[13], b[ 6])
+ MUL15(a[14], b[ 5])
+ MUL15(a[15], b[ 4])
+ MUL15(a[16], b[ 3])
+ MUL15(a[17], b[ 2])
+ MUL15(a[18], b[ 1])
+ MUL15(a[19], b[ 0]);
t[20] = MUL15(a[ 1], b[19])
+ MUL15(a[ 2], b[18])
+ MUL15(a[ 3], b[17])
+ MUL15(a[ 4], b[16])
+ MUL15(a[ 5], b[15])
+ MUL15(a[ 6], b[14])
+ MUL15(a[ 7], b[13])
+ MUL15(a[ 8], b[12])
+ MUL15(a[ 9], b[11])
+ MUL15(a[10], b[10])
+ MUL15(a[11], b[ 9])
+ MUL15(a[12], b[ 8])
+ MUL15(a[13], b[ 7])
+ MUL15(a[14], b[ 6])
+ MUL15(a[15], b[ 5])
+ MUL15(a[16], b[ 4])
+ MUL15(a[17], b[ 3])
+ MUL15(a[18], b[ 2])
+ MUL15(a[19], b[ 1]);
t[21] = MUL15(a[ 2], b[19])
+ MUL15(a[ 3], b[18])
+ MUL15(a[ 4], b[17])
+ MUL15(a[ 5], b[16])
+ MUL15(a[ 6], b[15])
+ MUL15(a[ 7], b[14])
+ MUL15(a[ 8], b[13])
+ MUL15(a[ 9], b[12])
+ MUL15(a[10], b[11])
+ MUL15(a[11], b[10])
+ MUL15(a[12], b[ 9])
+ MUL15(a[13], b[ 8])
+ MUL15(a[14], b[ 7])
+ MUL15(a[15], b[ 6])
+ MUL15(a[16], b[ 5])
+ MUL15(a[17], b[ 4])
+ MUL15(a[18], b[ 3])
+ MUL15(a[19], b[ 2]);
t[22] = MUL15(a[ 3], b[19])
+ MUL15(a[ 4], b[18])
+ MUL15(a[ 5], b[17])
+ MUL15(a[ 6], b[16])
+ MUL15(a[ 7], b[15])
+ MUL15(a[ 8], b[14])
+ MUL15(a[ 9], b[13])
+ MUL15(a[10], b[12])
+ MUL15(a[11], b[11])
+ MUL15(a[12], b[10])
+ MUL15(a[13], b[ 9])
+ MUL15(a[14], b[ 8])
+ MUL15(a[15], b[ 7])
+ MUL15(a[16], b[ 6])
+ MUL15(a[17], b[ 5])
+ MUL15(a[18], b[ 4])
+ MUL15(a[19], b[ 3]);
t[23] = MUL15(a[ 4], b[19])
+ MUL15(a[ 5], b[18])
+ MUL15(a[ 6], b[17])
+ MUL15(a[ 7], b[16])
+ MUL15(a[ 8], b[15])
+ MUL15(a[ 9], b[14])
+ MUL15(a[10], b[13])
+ MUL15(a[11], b[12])
+ MUL15(a[12], b[11])
+ MUL15(a[13], b[10])
+ MUL15(a[14], b[ 9])
+ MUL15(a[15], b[ 8])
+ MUL15(a[16], b[ 7])
+ MUL15(a[17], b[ 6])
+ MUL15(a[18], b[ 5])
+ MUL15(a[19], b[ 4]);
t[24] = MUL15(a[ 5], b[19])
+ MUL15(a[ 6], b[18])
+ MUL15(a[ 7], b[17])
+ MUL15(a[ 8], b[16])
+ MUL15(a[ 9], b[15])
+ MUL15(a[10], b[14])
+ MUL15(a[11], b[13])
+ MUL15(a[12], b[12])
+ MUL15(a[13], b[11])
+ MUL15(a[14], b[10])
+ MUL15(a[15], b[ 9])
+ MUL15(a[16], b[ 8])
+ MUL15(a[17], b[ 7])
+ MUL15(a[18], b[ 6])
+ MUL15(a[19], b[ 5]);
t[25] = MUL15(a[ 6], b[19])
+ MUL15(a[ 7], b[18])
+ MUL15(a[ 8], b[17])
+ MUL15(a[ 9], b[16])
+ MUL15(a[10], b[15])
+ MUL15(a[11], b[14])
+ MUL15(a[12], b[13])
+ MUL15(a[13], b[12])
+ MUL15(a[14], b[11])
+ MUL15(a[15], b[10])
+ MUL15(a[16], b[ 9])
+ MUL15(a[17], b[ 8])
+ MUL15(a[18], b[ 7])
+ MUL15(a[19], b[ 6]);
t[26] = MUL15(a[ 7], b[19])
+ MUL15(a[ 8], b[18])
+ MUL15(a[ 9], b[17])
+ MUL15(a[10], b[16])
+ MUL15(a[11], b[15])
+ MUL15(a[12], b[14])
+ MUL15(a[13], b[13])
+ MUL15(a[14], b[12])
+ MUL15(a[15], b[11])
+ MUL15(a[16], b[10])
+ MUL15(a[17], b[ 9])
+ MUL15(a[18], b[ 8])
+ MUL15(a[19], b[ 7]);
t[27] = MUL15(a[ 8], b[19])
+ MUL15(a[ 9], b[18])
+ MUL15(a[10], b[17])
+ MUL15(a[11], b[16])
+ MUL15(a[12], b[15])
+ MUL15(a[13], b[14])
+ MUL15(a[14], b[13])
+ MUL15(a[15], b[12])
+ MUL15(a[16], b[11])
+ MUL15(a[17], b[10])
+ MUL15(a[18], b[ 9])
+ MUL15(a[19], b[ 8]);
t[28] = MUL15(a[ 9], b[19])
+ MUL15(a[10], b[18])
+ MUL15(a[11], b[17])
+ MUL15(a[12], b[16])
+ MUL15(a[13], b[15])
+ MUL15(a[14], b[14])
+ MUL15(a[15], b[13])
+ MUL15(a[16], b[12])
+ MUL15(a[17], b[11])
+ MUL15(a[18], b[10])
+ MUL15(a[19], b[ 9]);
t[29] = MUL15(a[10], b[19])
+ MUL15(a[11], b[18])
+ MUL15(a[12], b[17])
+ MUL15(a[13], b[16])
+ MUL15(a[14], b[15])
+ MUL15(a[15], b[14])
+ MUL15(a[16], b[13])
+ MUL15(a[17], b[12])
+ MUL15(a[18], b[11])
+ MUL15(a[19], b[10]);
t[30] = MUL15(a[11], b[19])
+ MUL15(a[12], b[18])
+ MUL15(a[13], b[17])
+ MUL15(a[14], b[16])
+ MUL15(a[15], b[15])
+ MUL15(a[16], b[14])
+ MUL15(a[17], b[13])
+ MUL15(a[18], b[12])
+ MUL15(a[19], b[11]);
t[31] = MUL15(a[12], b[19])
+ MUL15(a[13], b[18])
+ MUL15(a[14], b[17])
+ MUL15(a[15], b[16])
+ MUL15(a[16], b[15])
+ MUL15(a[17], b[14])
+ MUL15(a[18], b[13])
+ MUL15(a[19], b[12]);
t[32] = MUL15(a[13], b[19])
+ MUL15(a[14], b[18])
+ MUL15(a[15], b[17])
+ MUL15(a[16], b[16])
+ MUL15(a[17], b[15])
+ MUL15(a[18], b[14])
+ MUL15(a[19], b[13]);
t[33] = MUL15(a[14], b[19])
+ MUL15(a[15], b[18])
+ MUL15(a[16], b[17])
+ MUL15(a[17], b[16])
+ MUL15(a[18], b[15])
+ MUL15(a[19], b[14]);
t[34] = MUL15(a[15], b[19])
+ MUL15(a[16], b[18])
+ MUL15(a[17], b[17])
+ MUL15(a[18], b[16])
+ MUL15(a[19], b[15]);
t[35] = MUL15(a[16], b[19])
+ MUL15(a[17], b[18])
+ MUL15(a[18], b[17])
+ MUL15(a[19], b[16]);
t[36] = MUL15(a[17], b[19])
+ MUL15(a[18], b[18])
+ MUL15(a[19], b[17]);
t[37] = MUL15(a[18], b[19])
+ MUL15(a[19], b[18]);
t[38] = MUL15(a[19], b[19]);
d[39] = _src_ec_ec_c25519_m15_cnorm13(d, t, 39);
}
static void
_src_ec_ec_c25519_m15_csquare20(uint32_t *d, const uint32_t *a)
{
uint32_t t[39];
t[ 0] = MUL15(a[ 0], a[ 0]);
t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1);
t[ 2] = MUL15(a[ 1], a[ 1])
+ ((MUL15(a[ 0], a[ 2])) << 1);
t[ 3] = ((MUL15(a[ 0], a[ 3])
+ MUL15(a[ 1], a[ 2])) << 1);
t[ 4] = MUL15(a[ 2], a[ 2])
+ ((MUL15(a[ 0], a[ 4])
+ MUL15(a[ 1], a[ 3])) << 1);
t[ 5] = ((MUL15(a[ 0], a[ 5])
+ MUL15(a[ 1], a[ 4])
+ MUL15(a[ 2], a[ 3])) << 1);
t[ 6] = MUL15(a[ 3], a[ 3])
+ ((MUL15(a[ 0], a[ 6])
+ MUL15(a[ 1], a[ 5])
+ MUL15(a[ 2], a[ 4])) << 1);
t[ 7] = ((MUL15(a[ 0], a[ 7])
+ MUL15(a[ 1], a[ 6])
+ MUL15(a[ 2], a[ 5])
+ MUL15(a[ 3], a[ 4])) << 1);
t[ 8] = MUL15(a[ 4], a[ 4])
+ ((MUL15(a[ 0], a[ 8])
+ MUL15(a[ 1], a[ 7])
+ MUL15(a[ 2], a[ 6])
+ MUL15(a[ 3], a[ 5])) << 1);
t[ 9] = ((MUL15(a[ 0], a[ 9])
+ MUL15(a[ 1], a[ 8])
+ MUL15(a[ 2], a[ 7])
+ MUL15(a[ 3], a[ 6])
+ MUL15(a[ 4], a[ 5])) << 1);
t[10] = MUL15(a[ 5], a[ 5])
+ ((MUL15(a[ 0], a[10])
+ MUL15(a[ 1], a[ 9])
+ MUL15(a[ 2], a[ 8])
+ MUL15(a[ 3], a[ 7])
+ MUL15(a[ 4], a[ 6])) << 1);
t[11] = ((MUL15(a[ 0], a[11])
+ MUL15(a[ 1], a[10])
+ MUL15(a[ 2], a[ 9])
+ MUL15(a[ 3], a[ 8])
+ MUL15(a[ 4], a[ 7])
+ MUL15(a[ 5], a[ 6])) << 1);
t[12] = MUL15(a[ 6], a[ 6])
+ ((MUL15(a[ 0], a[12])
+ MUL15(a[ 1], a[11])
+ MUL15(a[ 2], a[10])
+ MUL15(a[ 3], a[ 9])
+ MUL15(a[ 4], a[ 8])
+ MUL15(a[ 5], a[ 7])) << 1);
t[13] = ((MUL15(a[ 0], a[13])
+ MUL15(a[ 1], a[12])
+ MUL15(a[ 2], a[11])
+ MUL15(a[ 3], a[10])
+ MUL15(a[ 4], a[ 9])
+ MUL15(a[ 5], a[ 8])
+ MUL15(a[ 6], a[ 7])) << 1);
t[14] = MUL15(a[ 7], a[ 7])
+ ((MUL15(a[ 0], a[14])
+ MUL15(a[ 1], a[13])
+ MUL15(a[ 2], a[12])
+ MUL15(a[ 3], a[11])
+ MUL15(a[ 4], a[10])
+ MUL15(a[ 5], a[ 9])
+ MUL15(a[ 6], a[ 8])) << 1);
t[15] = ((MUL15(a[ 0], a[15])
+ MUL15(a[ 1], a[14])
+ MUL15(a[ 2], a[13])
+ MUL15(a[ 3], a[12])
+ MUL15(a[ 4], a[11])
+ MUL15(a[ 5], a[10])
+ MUL15(a[ 6], a[ 9])
+ MUL15(a[ 7], a[ 8])) << 1);
t[16] = MUL15(a[ 8], a[ 8])
+ ((MUL15(a[ 0], a[16])
+ MUL15(a[ 1], a[15])
+ MUL15(a[ 2], a[14])
+ MUL15(a[ 3], a[13])
+ MUL15(a[ 4], a[12])
+ MUL15(a[ 5], a[11])
+ MUL15(a[ 6], a[10])
+ MUL15(a[ 7], a[ 9])) << 1);
t[17] = ((MUL15(a[ 0], a[17])
+ MUL15(a[ 1], a[16])
+ MUL15(a[ 2], a[15])
+ MUL15(a[ 3], a[14])
+ MUL15(a[ 4], a[13])
+ MUL15(a[ 5], a[12])
+ MUL15(a[ 6], a[11])
+ MUL15(a[ 7], a[10])
+ MUL15(a[ 8], a[ 9])) << 1);
t[18] = MUL15(a[ 9], a[ 9])
+ ((MUL15(a[ 0], a[18])
+ MUL15(a[ 1], a[17])
+ MUL15(a[ 2], a[16])
+ MUL15(a[ 3], a[15])
+ MUL15(a[ 4], a[14])
+ MUL15(a[ 5], a[13])
+ MUL15(a[ 6], a[12])
+ MUL15(a[ 7], a[11])
+ MUL15(a[ 8], a[10])) << 1);
t[19] = ((MUL15(a[ 0], a[19])
+ MUL15(a[ 1], a[18])
+ MUL15(a[ 2], a[17])
+ MUL15(a[ 3], a[16])
+ MUL15(a[ 4], a[15])
+ MUL15(a[ 5], a[14])
+ MUL15(a[ 6], a[13])
+ MUL15(a[ 7], a[12])
+ MUL15(a[ 8], a[11])
+ MUL15(a[ 9], a[10])) << 1);
t[20] = MUL15(a[10], a[10])
+ ((MUL15(a[ 1], a[19])
+ MUL15(a[ 2], a[18])
+ MUL15(a[ 3], a[17])
+ MUL15(a[ 4], a[16])
+ MUL15(a[ 5], a[15])
+ MUL15(a[ 6], a[14])
+ MUL15(a[ 7], a[13])
+ MUL15(a[ 8], a[12])
+ MUL15(a[ 9], a[11])) << 1);
t[21] = ((MUL15(a[ 2], a[19])
+ MUL15(a[ 3], a[18])
+ MUL15(a[ 4], a[17])
+ MUL15(a[ 5], a[16])
+ MUL15(a[ 6], a[15])
+ MUL15(a[ 7], a[14])
+ MUL15(a[ 8], a[13])
+ MUL15(a[ 9], a[12])
+ MUL15(a[10], a[11])) << 1);
t[22] = MUL15(a[11], a[11])
+ ((MUL15(a[ 3], a[19])
+ MUL15(a[ 4], a[18])
+ MUL15(a[ 5], a[17])
+ MUL15(a[ 6], a[16])
+ MUL15(a[ 7], a[15])
+ MUL15(a[ 8], a[14])
+ MUL15(a[ 9], a[13])
+ MUL15(a[10], a[12])) << 1);
t[23] = ((MUL15(a[ 4], a[19])
+ MUL15(a[ 5], a[18])
+ MUL15(a[ 6], a[17])
+ MUL15(a[ 7], a[16])
+ MUL15(a[ 8], a[15])
+ MUL15(a[ 9], a[14])
+ MUL15(a[10], a[13])
+ MUL15(a[11], a[12])) << 1);
t[24] = MUL15(a[12], a[12])
+ ((MUL15(a[ 5], a[19])
+ MUL15(a[ 6], a[18])
+ MUL15(a[ 7], a[17])
+ MUL15(a[ 8], a[16])
+ MUL15(a[ 9], a[15])
+ MUL15(a[10], a[14])
+ MUL15(a[11], a[13])) << 1);
t[25] = ((MUL15(a[ 6], a[19])
+ MUL15(a[ 7], a[18])
+ MUL15(a[ 8], a[17])
+ MUL15(a[ 9], a[16])
+ MUL15(a[10], a[15])
+ MUL15(a[11], a[14])
+ MUL15(a[12], a[13])) << 1);
t[26] = MUL15(a[13], a[13])
+ ((MUL15(a[ 7], a[19])
+ MUL15(a[ 8], a[18])
+ MUL15(a[ 9], a[17])
+ MUL15(a[10], a[16])
+ MUL15(a[11], a[15])
+ MUL15(a[12], a[14])) << 1);
t[27] = ((MUL15(a[ 8], a[19])
+ MUL15(a[ 9], a[18])
+ MUL15(a[10], a[17])
+ MUL15(a[11], a[16])
+ MUL15(a[12], a[15])
+ MUL15(a[13], a[14])) << 1);
t[28] = MUL15(a[14], a[14])
+ ((MUL15(a[ 9], a[19])
+ MUL15(a[10], a[18])
+ MUL15(a[11], a[17])
+ MUL15(a[12], a[16])
+ MUL15(a[13], a[15])) << 1);
t[29] = ((MUL15(a[10], a[19])
+ MUL15(a[11], a[18])
+ MUL15(a[12], a[17])
+ MUL15(a[13], a[16])
+ MUL15(a[14], a[15])) << 1);
t[30] = MUL15(a[15], a[15])
+ ((MUL15(a[11], a[19])
+ MUL15(a[12], a[18])
+ MUL15(a[13], a[17])
+ MUL15(a[14], a[16])) << 1);
t[31] = ((MUL15(a[12], a[19])
+ MUL15(a[13], a[18])
+ MUL15(a[14], a[17])
+ MUL15(a[15], a[16])) << 1);
t[32] = MUL15(a[16], a[16])
+ ((MUL15(a[13], a[19])
+ MUL15(a[14], a[18])
+ MUL15(a[15], a[17])) << 1);
t[33] = ((MUL15(a[14], a[19])
+ MUL15(a[15], a[18])
+ MUL15(a[16], a[17])) << 1);
t[34] = MUL15(a[17], a[17])
+ ((MUL15(a[15], a[19])
+ MUL15(a[16], a[18])) << 1);
t[35] = ((MUL15(a[16], a[19])
+ MUL15(a[17], a[18])) << 1);
t[36] = MUL15(a[18], a[18])
+ ((MUL15(a[17], a[19])) << 1);
t[37] = ((MUL15(a[18], a[19])) << 1);
t[38] = MUL15(a[19], a[19]);
d[39] = _src_ec_ec_c25519_m15_cnorm13(d, t, 39);
}
#endif
/*
* Perform a "final reduction" in field F255 (field for Curve25519)
* The source value must be less than twice the modulus. If the value
* is not lower than the modulus, then the modulus is subtracted and
* this function returns 1; otherwise, it leaves it untouched and it
* returns 0.
*/
static uint32_t
_src_ec_ec_c25519_m15_creduce_final_f255(uint32_t *d)
{
uint32_t t[20];
uint32_t cc;
int i;
memcpy(t, d, sizeof t);
cc = 19;
for (i = 0; i < 20; i ++) {
uint32_t w;
w = t[i] + cc;
cc = w >> 13;
t[i] = w & 0x1FFF;
}
cc = t[19] >> 8;
t[19] &= 0xFF;
CCOPY(cc, d, t, sizeof t);
return cc;
}
static void
_src_ec_ec_c25519_m15_cf255_mulgen(uint32_t *d, const uint32_t *a, const uint32_t *b, int square)
{
uint32_t t[40], cc, w;
/*
* Compute raw multiplication. All result words fit in 13 bits
* each; upper word (t[39]) must fit on 5 bits, since the product
* of two 256-bit integers must fit on 512 bits.
*/
if (square) {
_src_ec_ec_c25519_m15_csquare20(t, a);
} else {
_src_ec_ec_c25519_m15_cmul20(t, a, b);
}
/*
* Modular reduction: each high word is added where necessary.
* Since the modulus is 2^255-19 and word 20 corresponds to
* offset 20*13 = 260, word 20+k must be added to word k with
* a factor of 19*2^5 = 608. The extra bits in word 19 are also
* added that way.
*/
cc = MUL15(t[19] >> 8, 19);
t[19] &= 0xFF;
#define MM1(x) do { \
w = t[x] + cc + MUL15(t[(x) + 20], 608); \
t[x] = w & 0x1FFF; \
cc = w >> 13; \
} while (0)
MM1( 0);
MM1( 1);
MM1( 2);
MM1( 3);
MM1( 4);
MM1( 5);
MM1( 6);
MM1( 7);
MM1( 8);
MM1( 9);
MM1(10);
MM1(11);
MM1(12);
MM1(13);
MM1(14);
MM1(15);
MM1(16);
MM1(17);
MM1(18);
MM1(19);
#undef MM1
cc = MUL15(w >> 8, 19);
t[19] &= 0xFF;
#define MM2(x) do { \
w = t[x] + cc; \
d[x] = w & 0x1FFF; \
cc = w >> 13; \
} while (0)
MM2( 0);
MM2( 1);
MM2( 2);
MM2( 3);
MM2( 4);
MM2( 5);
MM2( 6);
MM2( 7);
MM2( 8);
MM2( 9);
MM2(10);
MM2(11);
MM2(12);
MM2(13);
MM2(14);
MM2(15);
MM2(16);
MM2(17);
MM2(18);
MM2(19);
#undef MM2
}
/*
* Perform a multiplication of two integers modulo 2^255-19.
* Operands are arrays of 20 words, each containing 13 bits of data, in
* little-endian order. Input value may be up to 2^256-1; on output, value
* fits on 256 bits and is lower than twice the modulus.
*
* _src_ec_ec_c25519_m15_cf255_mul() is the general multiplication, _src_ec_ec_c25519_m15_cf255_square() is specialised
* for squarings.
*/
#define _src_ec_ec_c25519_m15_cf255_mul(d, a, b) _src_ec_ec_c25519_m15_cf255_mulgen(d, a, b, 0)
#define _src_ec_ec_c25519_m15_cf255_square(d, a) _src_ec_ec_c25519_m15_cf255_mulgen(d, a, a, 1)
/*
* Add two values in F255. Partial reduction is performed (down to less
* than twice the modulus).
*/
static void
_src_ec_ec_c25519_m15_cf255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
int i;
uint32_t cc, w;
cc = 0;
for (i = 0; i < 20; i ++) {
w = a[i] + b[i] + cc;
d[i] = w & 0x1FFF;
cc = w >> 13;
}
cc = MUL15(w >> 8, 19);
d[19] &= 0xFF;
for (i = 0; i < 20; i ++) {
w = d[i] + cc;
d[i] = w & 0x1FFF;
cc = w >> 13;
}
}
/*
* Subtract one value from another in F255. Partial reduction is
* performed (down to less than twice the modulus).
*/
static void
_src_ec_ec_c25519_m15_cf255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* We actually compute a - b + 2*p, so that the final value is
* necessarily positive.
*/
int i;
uint32_t cc, w;
cc = (uint32_t)-38;
for (i = 0; i < 20; i ++) {
w = a[i] - b[i] + cc;
d[i] = w & 0x1FFF;
cc = ARSH(w, 13);
}
cc = MUL15((w + 0x200) >> 8, 19);
d[19] &= 0xFF;
for (i = 0; i < 20; i ++) {
w = d[i] + cc;
d[i] = w & 0x1FFF;
cc = w >> 13;
}
}
/*
* Multiply an integer by the 'A24' constant (121665). Partial reduction
* is performed (down to less than twice the modulus).
*/
static void
_src_ec_ec_c25519_m15_cf255_mul_a24(uint32_t *d, const uint32_t *a)
{
int i;
uint32_t cc, w;
cc = 0;
for (i = 0; i < 20; i ++) {
w = MUL15(a[i], 121665) + cc;
d[i] = w & 0x1FFF;
cc = w >> 13;
}
cc = MUL15(w >> 8, 19);
d[19] &= 0xFF;
for (i = 0; i < 20; i ++) {
w = d[i] + cc;
d[i] = w & 0x1FFF;
cc = w >> 13;
}
}
static const unsigned char _src_ec_ec_c25519_m15_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_c25519_m15_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const unsigned char *
_src_ec_ec_c25519_m15_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m15_cGEN;
}
static const unsigned char *
_src_ec_ec_c25519_m15_capi_order(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m15_cORDER;
}
static size_t
_src_ec_ec_c25519_m15_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 0;
}
static void
_src_ec_ec_c25519_m15_ccswap(uint32_t *a, uint32_t *b, uint32_t ctl)
{
int i;
ctl = -ctl;
for (i = 0; i < 20; i ++) {
uint32_t aw, bw, tw;
aw = a[i];
bw = b[i];
tw = ctl & (aw ^ bw);
a[i] = aw ^ tw;
b[i] = bw ^ tw;
}
}
static uint32_t
_src_ec_ec_c25519_m15_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
uint32_t x1[20], x2[20], x3[20], z2[20], z3[20];
uint32_t a[20], aa[20], b[20], bb[20];
uint32_t c[20], d[20], e[20], da[20], cb[20];
unsigned char k[32];
uint32_t swap;
int i;
(void)curve;
/*
* Points are encoded over exactly 32 bytes. Multipliers must fit
* in 32 bytes as well.
* RFC 7748 mandates that the high bit of the last point byte must
* be ignored/cleared.
*/
if (Glen != 32 || kblen > 32) {
return 0;
}
G[31] &= 0x7F;
/*
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
* into Montgomery representation.
*/
x1[19] = le8_to_le13(x1, G, 32);
memcpy(x3, x1, sizeof x1);
memset(z2, 0, sizeof z2);
memset(x2, 0, sizeof x2);
x2[0] = 1;
memset(z3, 0, sizeof z3);
z3[0] = 1;
memset(k, 0, (sizeof k) - kblen);
memcpy(k + (sizeof k) - kblen, kb, kblen);
k[31] &= 0xF8;
k[0] &= 0x7F;
k[0] |= 0x40;
/* obsolete
print_int("x1", x1);
*/
swap = 0;
for (i = 254; i >= 0; i --) {
uint32_t kt;
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
swap ^= kt;
_src_ec_ec_c25519_m15_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m15_ccswap(z2, z3, swap);
swap = kt;
/* obsolete
print_int("x2", x2);
print_int("z2", z2);
print_int("x3", x3);
print_int("z3", z3);
*/
_src_ec_ec_c25519_m15_cf255_add(a, x2, z2);
_src_ec_ec_c25519_m15_cf255_square(aa, a);
_src_ec_ec_c25519_m15_cf255_sub(b, x2, z2);
_src_ec_ec_c25519_m15_cf255_square(bb, b);
_src_ec_ec_c25519_m15_cf255_sub(e, aa, bb);
_src_ec_ec_c25519_m15_cf255_add(c, x3, z3);
_src_ec_ec_c25519_m15_cf255_sub(d, x3, z3);
_src_ec_ec_c25519_m15_cf255_mul(da, d, a);
_src_ec_ec_c25519_m15_cf255_mul(cb, c, b);
/* obsolete
print_int("a ", a);
print_int("aa", aa);
print_int("b ", b);
print_int("bb", bb);
print_int("e ", e);
print_int("c ", c);
print_int("d ", d);
print_int("da", da);
print_int("cb", cb);
*/
_src_ec_ec_c25519_m15_cf255_add(x3, da, cb);
_src_ec_ec_c25519_m15_cf255_square(x3, x3);
_src_ec_ec_c25519_m15_cf255_sub(z3, da, cb);
_src_ec_ec_c25519_m15_cf255_square(z3, z3);
_src_ec_ec_c25519_m15_cf255_mul(z3, z3, x1);
_src_ec_ec_c25519_m15_cf255_mul(x2, aa, bb);
_src_ec_ec_c25519_m15_cf255_mul_a24(z2, e);
_src_ec_ec_c25519_m15_cf255_add(z2, z2, aa);
_src_ec_ec_c25519_m15_cf255_mul(z2, e, z2);
/* obsolete
print_int("x2", x2);
print_int("z2", z2);
print_int("x3", x3);
print_int("z3", z3);
*/
}
_src_ec_ec_c25519_m15_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m15_ccswap(z2, z3, swap);
/*
* Inverse z2 with a modular exponentiation. This is a simple
* square-and-multiply algorithm; we mutualise most non-squarings
* since the exponent contains almost only ones.
*/
memcpy(a, z2, sizeof z2);
for (i = 0; i < 15; i ++) {
_src_ec_ec_c25519_m15_cf255_square(a, a);
_src_ec_ec_c25519_m15_cf255_mul(a, a, z2);
}
memcpy(b, a, sizeof a);
for (i = 0; i < 14; i ++) {
int j;
for (j = 0; j < 16; j ++) {
_src_ec_ec_c25519_m15_cf255_square(b, b);
}
_src_ec_ec_c25519_m15_cf255_mul(b, b, a);
}
for (i = 14; i >= 0; i --) {
_src_ec_ec_c25519_m15_cf255_square(b, b);
if ((0xFFEB >> i) & 1) {
_src_ec_ec_c25519_m15_cf255_mul(b, z2, b);
}
}
_src_ec_ec_c25519_m15_cf255_mul(x2, x2, b);
_src_ec_ec_c25519_m15_creduce_final_f255(x2);
le13_to_le8(G, 32, x2);
return 1;
}
static size_t
_src_ec_ec_c25519_m15_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_c25519_m15_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_c25519_m15_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_c25519_m15_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We don't implement this method, since it is used for ECDSA
* only, and there is no ECDSA over Curve25519 (which instead
* uses EdDSA).
*/
(void)A;
(void)B;
(void)len;
(void)x;
(void)xlen;
(void)y;
(void)ylen;
(void)curve;
return 0;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_c25519_m15 = {
(uint32_t)0x20000000,
&_src_ec_ec_c25519_m15_capi_generator,
&_src_ec_ec_c25519_m15_capi_order,
&_src_ec_ec_c25519_m15_capi_xoff,
&_src_ec_ec_c25519_m15_capi_mul,
&_src_ec_ec_c25519_m15_capi_mulgen,
&_src_ec_ec_c25519_m15_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* obsolete
#include
#include
static void
print_int(const char *name, const uint32_t *x)
{
size_t u;
unsigned char tmp[40];
printf("%s = ", name);
for (u = 0; u < 9; u ++) {
if (x[u] > 0x3FFFFFFF) {
printf("INVALID:");
for (u = 0; u < 9; u ++) {
printf(" %08X", x[u]);
}
printf("\n");
return;
}
}
memset(tmp, 0, sizeof tmp);
for (u = 0; u < 9; u ++) {
uint64_t w;
int j, k;
w = x[u];
j = 30 * (int)u;
k = j & 7;
if (k != 0) {
w <<= k;
j -= k;
}
k = j >> 3;
for (j = 0; j < 8; j ++) {
tmp[39 - k - j] |= (unsigned char)w;
w >>= 8;
}
}
for (u = 8; u < 40; u ++) {
printf("%02X", tmp[u]);
}
printf("\n");
}
*/
/*
* If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
* that right-shifting a signed negative integer copies the sign bit
* (arithmetic right-shift). This is "implementation-defined behaviour",
* i.e. it is not undefined, but it may differ between compilers. Each
* compiler is supposed to document its behaviour in that respect. GCC
* explicitly defines that an arithmetic right shift is used. We expect
* all other compilers to do the same, because underlying CPU offer an
* arithmetic right shift opcode that could not be used otherwise.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#endif
/*
* Convert an integer from unsigned little-endian encoding to a sequence of
* 30-bit words in little-endian order. The final "partial" word is
* returned.
*/
static uint32_t
le8_to_le30(uint32_t *dst, const unsigned char *src, size_t len)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
uint32_t b;
b = *src ++;
if (acc_len < 22) {
acc |= b << acc_len;
acc_len += 8;
} else {
*dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF;
acc = b >> (30 - acc_len);
acc_len -= 22;
}
}
return acc;
}
/*
* Convert an integer (30-bit words, little-endian) to unsigned
* little-endian encoding. The total encoding length is provided; all
* the destination bytes will be filled.
*/
static void
le30_to_le8(unsigned char *dst, size_t len, const uint32_t *src)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
if (acc_len < 8) {
uint32_t w;
w = *src ++;
*dst ++ = (unsigned char)(acc | (w << acc_len));
acc = w >> (8 - acc_len);
acc_len += 22;
} else {
*dst ++ = (unsigned char)acc;
acc >>= 8;
acc_len -= 8;
}
}
}
/*
* Multiply two integers. Source integers are represented as arrays of
* nine 30-bit words, for values up to 2^270-1. Result is encoded over
* 18 words of 30 bits each.
*/
static void
_src_ec_ec_c25519_m31_cmul9(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* Maximum intermediate result is no more than
* 10376293531797946367, which fits in 64 bits. Reason:
*
* 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406
* 10376293531797946367 < 9663676407 * 2^30
*
* Thus, adding together 9 products of 30-bit integers, with
* a carry of at most 9663676406, yields an integer that fits
* on 64 bits and generates a carry of at most 9663676406.
*/
uint64_t t[17];
uint64_t cc;
int i;
t[ 0] = MUL31(a[0], b[0]);
t[ 1] = MUL31(a[0], b[1])
+ MUL31(a[1], b[0]);
t[ 2] = MUL31(a[0], b[2])
+ MUL31(a[1], b[1])
+ MUL31(a[2], b[0]);
t[ 3] = MUL31(a[0], b[3])
+ MUL31(a[1], b[2])
+ MUL31(a[2], b[1])
+ MUL31(a[3], b[0]);
t[ 4] = MUL31(a[0], b[4])
+ MUL31(a[1], b[3])
+ MUL31(a[2], b[2])
+ MUL31(a[3], b[1])
+ MUL31(a[4], b[0]);
t[ 5] = MUL31(a[0], b[5])
+ MUL31(a[1], b[4])
+ MUL31(a[2], b[3])
+ MUL31(a[3], b[2])
+ MUL31(a[4], b[1])
+ MUL31(a[5], b[0]);
t[ 6] = MUL31(a[0], b[6])
+ MUL31(a[1], b[5])
+ MUL31(a[2], b[4])
+ MUL31(a[3], b[3])
+ MUL31(a[4], b[2])
+ MUL31(a[5], b[1])
+ MUL31(a[6], b[0]);
t[ 7] = MUL31(a[0], b[7])
+ MUL31(a[1], b[6])
+ MUL31(a[2], b[5])
+ MUL31(a[3], b[4])
+ MUL31(a[4], b[3])
+ MUL31(a[5], b[2])
+ MUL31(a[6], b[1])
+ MUL31(a[7], b[0]);
t[ 8] = MUL31(a[0], b[8])
+ MUL31(a[1], b[7])
+ MUL31(a[2], b[6])
+ MUL31(a[3], b[5])
+ MUL31(a[4], b[4])
+ MUL31(a[5], b[3])
+ MUL31(a[6], b[2])
+ MUL31(a[7], b[1])
+ MUL31(a[8], b[0]);
t[ 9] = MUL31(a[1], b[8])
+ MUL31(a[2], b[7])
+ MUL31(a[3], b[6])
+ MUL31(a[4], b[5])
+ MUL31(a[5], b[4])
+ MUL31(a[6], b[3])
+ MUL31(a[7], b[2])
+ MUL31(a[8], b[1]);
t[10] = MUL31(a[2], b[8])
+ MUL31(a[3], b[7])
+ MUL31(a[4], b[6])
+ MUL31(a[5], b[5])
+ MUL31(a[6], b[4])
+ MUL31(a[7], b[3])
+ MUL31(a[8], b[2]);
t[11] = MUL31(a[3], b[8])
+ MUL31(a[4], b[7])
+ MUL31(a[5], b[6])
+ MUL31(a[6], b[5])
+ MUL31(a[7], b[4])
+ MUL31(a[8], b[3]);
t[12] = MUL31(a[4], b[8])
+ MUL31(a[5], b[7])
+ MUL31(a[6], b[6])
+ MUL31(a[7], b[5])
+ MUL31(a[8], b[4]);
t[13] = MUL31(a[5], b[8])
+ MUL31(a[6], b[7])
+ MUL31(a[7], b[6])
+ MUL31(a[8], b[5]);
t[14] = MUL31(a[6], b[8])
+ MUL31(a[7], b[7])
+ MUL31(a[8], b[6]);
t[15] = MUL31(a[7], b[8])
+ MUL31(a[8], b[7]);
t[16] = MUL31(a[8], b[8]);
/*
* Propagate carries.
*/
cc = 0;
for (i = 0; i < 17; i ++) {
uint64_t w;
w = t[i] + cc;
d[i] = (uint32_t)w & 0x3FFFFFFF;
cc = w >> 30;
}
d[17] = (uint32_t)cc;
}
/*
* Square a 270-bit integer, represented as an array of nine 30-bit words.
* Result uses 18 words of 30 bits each.
*/
static void
_src_ec_ec_c25519_m31_csquare9(uint32_t *d, const uint32_t *a)
{
uint64_t t[17];
uint64_t cc;
int i;
t[ 0] = MUL31(a[0], a[0]);
t[ 1] = ((MUL31(a[0], a[1])) << 1);
t[ 2] = MUL31(a[1], a[1])
+ ((MUL31(a[0], a[2])) << 1);
t[ 3] = ((MUL31(a[0], a[3])
+ MUL31(a[1], a[2])) << 1);
t[ 4] = MUL31(a[2], a[2])
+ ((MUL31(a[0], a[4])
+ MUL31(a[1], a[3])) << 1);
t[ 5] = ((MUL31(a[0], a[5])
+ MUL31(a[1], a[4])
+ MUL31(a[2], a[3])) << 1);
t[ 6] = MUL31(a[3], a[3])
+ ((MUL31(a[0], a[6])
+ MUL31(a[1], a[5])
+ MUL31(a[2], a[4])) << 1);
t[ 7] = ((MUL31(a[0], a[7])
+ MUL31(a[1], a[6])
+ MUL31(a[2], a[5])
+ MUL31(a[3], a[4])) << 1);
t[ 8] = MUL31(a[4], a[4])
+ ((MUL31(a[0], a[8])
+ MUL31(a[1], a[7])
+ MUL31(a[2], a[6])
+ MUL31(a[3], a[5])) << 1);
t[ 9] = ((MUL31(a[1], a[8])
+ MUL31(a[2], a[7])
+ MUL31(a[3], a[6])
+ MUL31(a[4], a[5])) << 1);
t[10] = MUL31(a[5], a[5])
+ ((MUL31(a[2], a[8])
+ MUL31(a[3], a[7])
+ MUL31(a[4], a[6])) << 1);
t[11] = ((MUL31(a[3], a[8])
+ MUL31(a[4], a[7])
+ MUL31(a[5], a[6])) << 1);
t[12] = MUL31(a[6], a[6])
+ ((MUL31(a[4], a[8])
+ MUL31(a[5], a[7])) << 1);
t[13] = ((MUL31(a[5], a[8])
+ MUL31(a[6], a[7])) << 1);
t[14] = MUL31(a[7], a[7])
+ ((MUL31(a[6], a[8])) << 1);
t[15] = ((MUL31(a[7], a[8])) << 1);
t[16] = MUL31(a[8], a[8]);
/*
* Propagate carries.
*/
cc = 0;
for (i = 0; i < 17; i ++) {
uint64_t w;
w = t[i] + cc;
d[i] = (uint32_t)w & 0x3FFFFFFF;
cc = w >> 30;
}
d[17] = (uint32_t)cc;
}
/*
* Perform a "final reduction" in field F255 (field for Curve25519)
* The source value must be less than twice the modulus. If the value
* is not lower than the modulus, then the modulus is subtracted and
* this function returns 1; otherwise, it leaves it untouched and it
* returns 0.
*/
static uint32_t
_src_ec_ec_c25519_m31_creduce_final_f255(uint32_t *d)
{
uint32_t t[9];
uint32_t cc;
int i;
memcpy(t, d, sizeof t);
cc = 19;
for (i = 0; i < 9; i ++) {
uint32_t w;
w = t[i] + cc;
cc = w >> 30;
t[i] = w & 0x3FFFFFFF;
}
cc = t[8] >> 15;
t[8] &= 0x7FFF;
CCOPY(cc, d, t, sizeof t);
return cc;
}
/*
* Perform a multiplication of two integers modulo 2^255-19.
* Operands are arrays of 9 words, each containing 30 bits of data, in
* little-endian order. Input value may be up to 2^256-1; on output, value
* fits on 256 bits and is lower than twice the modulus.
*/
static void
_src_ec_ec_c25519_m31_cf255_mul(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[18], cc;
int i;
/*
* Compute raw multiplication. All result words fit in 30 bits
* each; upper word (t[17]) must fit on 2 bits, since the product
* of two 256-bit integers must fit on 512 bits.
*/
_src_ec_ec_c25519_m31_cmul9(t, a, b);
/*
* Modular reduction: each high word is added where necessary.
* Since the modulus is 2^255-19 and word 9 corresponds to
* offset 9*30 = 270, word 9+k must be added to word k with
* a factor of 19*2^15 = 622592. The extra bits in word 8 are also
* added that way.
*
* Keeping the carry on 32 bits helps with 32-bit architectures,
* and does not noticeably impact performance on 64-bit systems.
*/
cc = MUL15(t[8] >> 15, 19); /* at most 19*(2^15-1) = 622573 */
t[8] &= 0x7FFF;
for (i = 0; i < 9; i ++) {
uint64_t w;
w = (uint64_t)t[i] + (uint64_t)cc + MUL31(t[i + 9], 622592);
t[i] = (uint32_t)w & 0x3FFFFFFF;
cc = (uint32_t)(w >> 30); /* at most 622592 */
}
/*
* Original product was up to (2^256-1)^2, i.e. a 512-bit integer.
* This was split into two parts (upper of 257 bits, lower of 255
* bits), and the upper was added to the lower with a factor 19,
* which means that the intermediate value is less than 77*2^255
* (19*2^257 + 2^255). Therefore, the extra bits "t[8] >> 15" are
* less than 77, and the initial carry cc is at most 76*19 = 1444.
*/
cc = MUL15(t[8] >> 15, 19);
t[8] &= 0x7FFF;
for (i = 0; i < 9; i ++) {
uint32_t z;
z = t[i] + cc;
d[i] = z & 0x3FFFFFFF;
cc = z >> 30;
}
/*
* Final result is at most 2^255 + 1443. In particular, the last
* carry is necessarily 0, since t[8] was truncated to 15 bits.
*/
}
/*
* Perform a squaring of an integer modulo 2^255-19.
* Operands are arrays of 9 words, each containing 30 bits of data, in
* little-endian order. Input value may be up to 2^256-1; on output, value
* fits on 256 bits and is lower than twice the modulus.
*/
static void
_src_ec_ec_c25519_m31_cf255_square(uint32_t *d, const uint32_t *a)
{
uint32_t t[18], cc;
int i;
/*
* Compute raw squaring. All result words fit in 30 bits
* each; upper word (t[17]) must fit on 2 bits, since the square
* of a 256-bit integers must fit on 512 bits.
*/
_src_ec_ec_c25519_m31_csquare9(t, a);
/*
* Modular reduction: each high word is added where necessary.
* See _src_ec_ec_c25519_m31_cf255_mul() for details on the reduction and carry limits.
*/
cc = MUL15(t[8] >> 15, 19);
t[8] &= 0x7FFF;
for (i = 0; i < 9; i ++) {
uint64_t w;
w = (uint64_t)t[i] + (uint64_t)cc + MUL31(t[i + 9], 622592);
t[i] = (uint32_t)w & 0x3FFFFFFF;
cc = (uint32_t)(w >> 30);
}
cc = MUL15(t[8] >> 15, 19);
t[8] &= 0x7FFF;
for (i = 0; i < 9; i ++) {
uint32_t z;
z = t[i] + cc;
d[i] = z & 0x3FFFFFFF;
cc = z >> 30;
}
}
/*
* Add two values in F255. Partial reduction is performed (down to less
* than twice the modulus).
*/
static void
_src_ec_ec_c25519_m31_cf255_add(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* Since operand words fit on 30 bits, we can use 32-bit
* variables throughout.
*/
int i;
uint32_t cc, w;
cc = 0;
for (i = 0; i < 9; i ++) {
w = a[i] + b[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = w >> 30;
}
cc = MUL15(w >> 15, 19);
d[8] &= 0x7FFF;
for (i = 0; i < 9; i ++) {
w = d[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = w >> 30;
}
}
/*
* Subtract one value from another in F255. Partial reduction is
* performed (down to less than twice the modulus).
*/
static void
_src_ec_ec_c25519_m31_cf255_sub(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* We actually compute a - b + 2*p, so that the final value is
* necessarily positive.
*/
int i;
uint32_t cc, w;
cc = (uint32_t)-38;
for (i = 0; i < 9; i ++) {
w = a[i] - b[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = ARSH(w, 30);
}
cc = MUL15((w + 0x10000) >> 15, 19);
d[8] &= 0x7FFF;
for (i = 0; i < 9; i ++) {
w = d[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = w >> 30;
}
}
/*
* Multiply an integer by the 'A24' constant (121665). Partial reduction
* is performed (down to less than twice the modulus).
*/
static void
_src_ec_ec_c25519_m31_cf255_mul_a24(uint32_t *d, const uint32_t *a)
{
int i;
uint64_t w;
uint32_t cc;
/*
* a[] is over 256 bits, thus a[8] has length at most 16 bits.
* We single out the processing of the last word: intermediate
* value w is up to 121665*2^16, yielding a carry for the next
* loop of at most 19*(121665*2^16/2^15) = 4623289.
*/
cc = 0;
for (i = 0; i < 8; i ++) {
w = MUL31(a[i], 121665) + (uint64_t)cc;
d[i] = (uint32_t)w & 0x3FFFFFFF;
cc = (uint32_t)(w >> 30);
}
w = MUL31(a[8], 121665) + (uint64_t)cc;
d[8] = (uint32_t)w & 0x7FFF;
cc = MUL15((uint32_t)(w >> 15), 19);
for (i = 0; i < 9; i ++) {
uint32_t z;
z = d[i] + cc;
d[i] = z & 0x3FFFFFFF;
cc = z >> 30;
}
}
static const unsigned char _src_ec_ec_c25519_m31_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_c25519_m31_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const unsigned char *
_src_ec_ec_c25519_m31_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m31_cGEN;
}
static const unsigned char *
_src_ec_ec_c25519_m31_capi_order(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m31_cORDER;
}
static size_t
_src_ec_ec_c25519_m31_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 0;
}
static void
_src_ec_ec_c25519_m31_ccswap(uint32_t *a, uint32_t *b, uint32_t ctl)
{
int i;
ctl = -ctl;
for (i = 0; i < 9; i ++) {
uint32_t aw, bw, tw;
aw = a[i];
bw = b[i];
tw = ctl & (aw ^ bw);
a[i] = aw ^ tw;
b[i] = bw ^ tw;
}
}
static uint32_t
_src_ec_ec_c25519_m31_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
uint32_t x1[9], x2[9], x3[9], z2[9], z3[9];
uint32_t a[9], aa[9], b[9], bb[9];
uint32_t c[9], d[9], e[9], da[9], cb[9];
unsigned char k[32];
uint32_t swap;
int i;
(void)curve;
/*
* Points are encoded over exactly 32 bytes. Multipliers must fit
* in 32 bytes as well.
* RFC 7748 mandates that the high bit of the last point byte must
* be ignored/cleared.
*/
if (Glen != 32 || kblen > 32) {
return 0;
}
G[31] &= 0x7F;
/*
* Initialise variables x1, x2, z2, x3 and z3. We set all of them
* into Montgomery representation.
*/
x1[8] = le8_to_le30(x1, G, 32);
memcpy(x3, x1, sizeof x1);
memset(z2, 0, sizeof z2);
memset(x2, 0, sizeof x2);
x2[0] = 1;
memset(z3, 0, sizeof z3);
z3[0] = 1;
memset(k, 0, (sizeof k) - kblen);
memcpy(k + (sizeof k) - kblen, kb, kblen);
k[31] &= 0xF8;
k[0] &= 0x7F;
k[0] |= 0x40;
/* obsolete
print_int("x1", x1);
*/
swap = 0;
for (i = 254; i >= 0; i --) {
uint32_t kt;
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
swap ^= kt;
_src_ec_ec_c25519_m31_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m31_ccswap(z2, z3, swap);
swap = kt;
/* obsolete
print_int("x2", x2);
print_int("z2", z2);
print_int("x3", x3);
print_int("z3", z3);
*/
_src_ec_ec_c25519_m31_cf255_add(a, x2, z2);
_src_ec_ec_c25519_m31_cf255_square(aa, a);
_src_ec_ec_c25519_m31_cf255_sub(b, x2, z2);
_src_ec_ec_c25519_m31_cf255_square(bb, b);
_src_ec_ec_c25519_m31_cf255_sub(e, aa, bb);
_src_ec_ec_c25519_m31_cf255_add(c, x3, z3);
_src_ec_ec_c25519_m31_cf255_sub(d, x3, z3);
_src_ec_ec_c25519_m31_cf255_mul(da, d, a);
_src_ec_ec_c25519_m31_cf255_mul(cb, c, b);
/* obsolete
print_int("a ", a);
print_int("aa", aa);
print_int("b ", b);
print_int("bb", bb);
print_int("e ", e);
print_int("c ", c);
print_int("d ", d);
print_int("da", da);
print_int("cb", cb);
*/
_src_ec_ec_c25519_m31_cf255_add(x3, da, cb);
_src_ec_ec_c25519_m31_cf255_square(x3, x3);
_src_ec_ec_c25519_m31_cf255_sub(z3, da, cb);
_src_ec_ec_c25519_m31_cf255_square(z3, z3);
_src_ec_ec_c25519_m31_cf255_mul(z3, z3, x1);
_src_ec_ec_c25519_m31_cf255_mul(x2, aa, bb);
_src_ec_ec_c25519_m31_cf255_mul_a24(z2, e);
_src_ec_ec_c25519_m31_cf255_add(z2, z2, aa);
_src_ec_ec_c25519_m31_cf255_mul(z2, e, z2);
/* obsolete
print_int("x2", x2);
print_int("z2", z2);
print_int("x3", x3);
print_int("z3", z3);
*/
}
_src_ec_ec_c25519_m31_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m31_ccswap(z2, z3, swap);
/*
* Inverse z2 with a modular exponentiation. This is a simple
* square-and-multiply algorithm; we mutualise most non-squarings
* since the exponent contains almost only ones.
*/
memcpy(a, z2, sizeof z2);
for (i = 0; i < 15; i ++) {
_src_ec_ec_c25519_m31_cf255_square(a, a);
_src_ec_ec_c25519_m31_cf255_mul(a, a, z2);
}
memcpy(b, a, sizeof a);
for (i = 0; i < 14; i ++) {
int j;
for (j = 0; j < 16; j ++) {
_src_ec_ec_c25519_m31_cf255_square(b, b);
}
_src_ec_ec_c25519_m31_cf255_mul(b, b, a);
}
for (i = 14; i >= 0; i --) {
_src_ec_ec_c25519_m31_cf255_square(b, b);
if ((0xFFEB >> i) & 1) {
_src_ec_ec_c25519_m31_cf255_mul(b, z2, b);
}
}
_src_ec_ec_c25519_m31_cf255_mul(x2, x2, b);
_src_ec_ec_c25519_m31_creduce_final_f255(x2);
le30_to_le8(G, 32, x2);
return 1;
}
static size_t
_src_ec_ec_c25519_m31_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_c25519_m31_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_c25519_m31_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_c25519_m31_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We don't implement this method, since it is used for ECDSA
* only, and there is no ECDSA over Curve25519 (which instead
* uses EdDSA).
*/
(void)A;
(void)B;
(void)len;
(void)x;
(void)xlen;
(void)y;
(void)ylen;
(void)curve;
return 0;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_c25519_m31 = {
(uint32_t)0x20000000,
&_src_ec_ec_c25519_m31_capi_generator,
&_src_ec_ec_c25519_m31_capi_order,
&_src_ec_ec_c25519_m31_capi_xoff,
&_src_ec_ec_c25519_m31_capi_mul,
&_src_ec_ec_c25519_m31_capi_mulgen,
&_src_ec_ec_c25519_m31_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if BR_INT128 || BR_UMUL128
#if BR_UMUL128
#include
#endif
static const unsigned char _src_ec_ec_c25519_m62_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_c25519_m62_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const unsigned char *
_src_ec_ec_c25519_m62_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m62_cGEN;
}
static const unsigned char *
_src_ec_ec_c25519_m62_capi_order(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m62_cORDER;
}
static size_t
_src_ec_ec_c25519_m62_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 0;
}
/*
* A field element is encoded as five 64-bit integers, in basis 2^51.
* Limbs may be occasionally larger than 2^51, to save on carry
* propagation costs.
*/
#define MASK51 (((uint64_t)1 << 51) - (uint64_t)1)
/*
* Swap two field elements, conditionally on a flag.
*/
static inline void
_src_ec_ec_c25519_m62_cf255__src_ec_ec_c25519_m62_ccswap(uint64_t *a, uint64_t *b, uint32_t ctl)
{
uint64_t m, w;
m = -(uint64_t)ctl;
w = m & (a[0] ^ b[0]); a[0] ^= w; b[0] ^= w;
w = m & (a[1] ^ b[1]); a[1] ^= w; b[1] ^= w;
w = m & (a[2] ^ b[2]); a[2] ^= w; b[2] ^= w;
w = m & (a[3] ^ b[3]); a[3] ^= w; b[3] ^= w;
w = m & (a[4] ^ b[4]); a[4] ^= w; b[4] ^= w;
}
/*
* Addition with no carry propagation. Limbs double in size.
*/
static inline void
_src_ec_ec_c25519_m62_cf255_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
d[0] = a[0] + b[0];
d[1] = a[1] + b[1];
d[2] = a[2] + b[2];
d[3] = a[3] + b[3];
d[4] = a[4] + b[4];
}
/*
* Subtraction.
* On input, limbs must fit on 60 bits each. On output, result is
* partially reduced, with max value 2^255+19456; moreover, all
* limbs will fit on 51 bits, except the low limb, which may have
* value up to 2^51+19455.
*/
static inline void
_src_ec_ec_c25519_m62_cf255_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
uint64_t cc, w;
/*
* We compute d = (2^255-19)*1024 + a - b. Since the limbs
* fit on 60 bits, the maximum value of operands are slightly
* more than 2^264, but much less than 2^265-19456. This
* ensures that the result is positive.
*/
/*
* Initial carry is 19456, since we add 2^265-19456. Each
* individual subtraction may yield a carry up to 513.
*/
w = a[0] - b[0] - 19456;
d[0] = w & MASK51;
cc = -(w >> 51) & 0x3FF;
w = a[1] - b[1] - cc;
d[1] = w & MASK51;
cc = -(w >> 51) & 0x3FF;
w = a[2] - b[2] - cc;
d[2] = w & MASK51;
cc = -(w >> 51) & 0x3FF;
w = a[3] - b[3] - cc;
d[3] = w & MASK51;
cc = -(w >> 51) & 0x3FF;
d[4] = ((uint64_t)1 << 61) + a[4] - b[4] - cc;
/*
* Partial reduction. The intermediate result may be up to
* slightly above 2^265, but less than 2^265+2^255. When we
* truncate to 255 bits, the upper bits will be at most 1024.
*/
d[0] += 19 * (d[4] >> 51);
d[4] &= MASK51;
}
/*
* UMUL51(hi, lo, x, y) computes:
*
* hi = floor((x * y) / (2^51))
* lo = x * y mod 2^51
*
* Note that lo < 2^51, but "hi" may be larger, if the input operands are
* larger.
*/
#if BR_INT128
#define UMUL51(hi, lo, x, y) do { \
unsigned __int128 umul_tmp; \
umul_tmp = (unsigned __int128)(x) * (unsigned __int128)(y); \
(hi) = (uint64_t)(umul_tmp >> 51); \
(lo) = (uint64_t)umul_tmp & MASK51; \
} while (0)
#elif BR_UMUL128
#define UMUL51(hi, lo, x, y) do { \
uint64_t umul_hi, umul_lo; \
umul_lo = _umul128((x), (y), &umul_hi); \
(hi) = (umul_hi << 13) | (umul_lo >> 51); \
(lo) = umul_lo & MASK51; \
} while (0)
#endif
/*
* Multiplication.
* On input, limbs must fit on 54 bits each.
* On output, limb 0 is at most 2^51 + 155647, and other limbs fit
* on 51 bits each.
*/
static inline void
_src_ec_ec_c25519_m62_cf255_mul(uint64_t *d, uint64_t *a, uint64_t *b)
{
uint64_t t[10], hi, lo, w, cc;
/*
* Perform cross products, accumulating values without carry
* propagation.
*
* Since input limbs fit on 54 bits each, each individual
* UMUL51 will produce a "hi" of less than 2^57. The maximum
* sum will be at most 5*(2^57-1) + 4*(2^51-1) (for t[5]),
* i.e. less than 324*2^51.
*/
UMUL51(t[1], t[0], a[0], b[0]);
UMUL51(t[2], lo, a[1], b[0]); t[1] += lo;
UMUL51(hi, lo, a[0], b[1]); t[1] += lo; t[2] += hi;
UMUL51(t[3], lo, a[2], b[0]); t[2] += lo;
UMUL51(hi, lo, a[1], b[1]); t[2] += lo; t[3] += hi;
UMUL51(hi, lo, a[0], b[2]); t[2] += lo; t[3] += hi;
UMUL51(t[4], lo, a[3], b[0]); t[3] += lo;
UMUL51(hi, lo, a[2], b[1]); t[3] += lo; t[4] += hi;
UMUL51(hi, lo, a[1], b[2]); t[3] += lo; t[4] += hi;
UMUL51(hi, lo, a[0], b[3]); t[3] += lo; t[4] += hi;
UMUL51(t[5], lo, a[4], b[0]); t[4] += lo;
UMUL51(hi, lo, a[3], b[1]); t[4] += lo; t[5] += hi;
UMUL51(hi, lo, a[2], b[2]); t[4] += lo; t[5] += hi;
UMUL51(hi, lo, a[1], b[3]); t[4] += lo; t[5] += hi;
UMUL51(hi, lo, a[0], b[4]); t[4] += lo; t[5] += hi;
UMUL51(t[6], lo, a[4], b[1]); t[5] += lo;
UMUL51(hi, lo, a[3], b[2]); t[5] += lo; t[6] += hi;
UMUL51(hi, lo, a[2], b[3]); t[5] += lo; t[6] += hi;
UMUL51(hi, lo, a[1], b[4]); t[5] += lo; t[6] += hi;
UMUL51(t[7], lo, a[4], b[2]); t[6] += lo;
UMUL51(hi, lo, a[3], b[3]); t[6] += lo; t[7] += hi;
UMUL51(hi, lo, a[2], b[4]); t[6] += lo; t[7] += hi;
UMUL51(t[8], lo, a[4], b[3]); t[7] += lo;
UMUL51(hi, lo, a[3], b[4]); t[7] += lo; t[8] += hi;
UMUL51(t[9], lo, a[4], b[4]); t[8] += lo;
/*
* The upper words t[5]..t[9] are folded back into the lower
* words, using the rule that 2^255 = 19 in the field.
*
* Since each t[i] is less than 324*2^51, the additions below
* will yield less than 6480*2^51 in each limb; this fits in
* 64 bits (6480*2^51 < 8192*2^51 = 2^64), hence there is
* no overflow.
*/
t[0] += 19 * t[5];
t[1] += 19 * t[6];
t[2] += 19 * t[7];
t[3] += 19 * t[8];
t[4] += 19 * t[9];
/*
* Propagate carries.
*/
w = t[0];
d[0] = w & MASK51;
cc = w >> 51;
w = t[1] + cc;
d[1] = w & MASK51;
cc = w >> 51;
w = t[2] + cc;
d[2] = w & MASK51;
cc = w >> 51;
w = t[3] + cc;
d[3] = w & MASK51;
cc = w >> 51;
w = t[4] + cc;
d[4] = w & MASK51;
cc = w >> 51;
/*
* Since the limbs were 64-bit values, the top carry is at
* most 8192 (in practice, that cannot be reached). We simply
* performed a partial reduction.
*/
d[0] += 19 * cc;
}
/*
* Multiplication by A24 = 121665.
* Input must have limbs of 60 bits at most.
*/
static inline void
_src_ec_ec_c25519_m62_cf255_mul_a24(uint64_t *d, const uint64_t *a)
{
uint64_t t[5], cc, w;
/*
* 121665 = 15 * 8111. We first multiply by 15, with carry
* propagation and partial reduction.
*/
w = a[0] * 15;
t[0] = w & MASK51;
cc = w >> 51;
w = a[1] * 15 + cc;
t[1] = w & MASK51;
cc = w >> 51;
w = a[2] * 15 + cc;
t[2] = w & MASK51;
cc = w >> 51;
w = a[3] * 15 + cc;
t[3] = w & MASK51;
cc = w >> 51;
w = a[4] * 15 + cc;
t[4] = w & MASK51;
t[0] += 19 * (w >> 51);
/*
* Then multiplication by 8111. At that point, we known that
* t[0] is less than 2^51 + 19*8192, and other limbs are less
* than 2^51; thus, there will be no overflow.
*/
w = t[0] * 8111;
d[0] = w & MASK51;
cc = w >> 51;
w = t[1] * 8111 + cc;
d[1] = w & MASK51;
cc = w >> 51;
w = t[2] * 8111 + cc;
d[2] = w & MASK51;
cc = w >> 51;
w = t[3] * 8111 + cc;
d[3] = w & MASK51;
cc = w >> 51;
w = t[4] * 8111 + cc;
d[4] = w & MASK51;
d[0] += 19 * (w >> 51);
}
/*
* Finalize reduction.
* On input, limbs must fit on 51 bits, except possibly the low limb,
* which may be slightly above 2^51.
*/
static inline void
_src_ec_ec_c25519_m62_cf255_final_reduce(uint64_t *a)
{
uint64_t t[5], cc, w;
/*
* We add 19. If the result (in t[]) is below 2^255, then a[]
* is already less than 2^255-19, thus already reduced.
* Otherwise, we subtract 2^255 from t[], in which case we
* have t = a - (2^255-19), and that's our result.
*/
w = a[0] + 19;
t[0] = w & MASK51;
cc = w >> 51;
w = a[1] + cc;
t[1] = w & MASK51;
cc = w >> 51;
w = a[2] + cc;
t[2] = w & MASK51;
cc = w >> 51;
w = a[3] + cc;
t[3] = w & MASK51;
cc = w >> 51;
w = a[4] + cc;
t[4] = w & MASK51;
cc = w >> 51;
/*
* The bit 255 of t is in cc. If that bit is 0, when a[] must
* be unchanged; otherwise, it must be replaced with t[].
*/
cc = -cc;
a[0] ^= cc & (a[0] ^ t[0]);
a[1] ^= cc & (a[1] ^ t[1]);
a[2] ^= cc & (a[2] ^ t[2]);
a[3] ^= cc & (a[3] ^ t[3]);
a[4] ^= cc & (a[4] ^ t[4]);
}
static uint32_t
_src_ec_ec_c25519_m62_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
unsigned char k[32];
uint64_t x1[5], x2[5], z2[5], x3[5], z3[5];
uint32_t swap;
int i;
(void)curve;
/*
* Points are encoded over exactly 32 bytes. Multipliers must fit
* in 32 bytes as well.
*/
if (Glen != 32 || kblen > 32) {
return 0;
}
/*
* RFC 7748 mandates that the high bit of the last point byte must
* be ignored/cleared; the "& MASK51" in the initialization for
* x1[4] clears that bit.
*/
x1[0] = br_dec64le(&G[0]) & MASK51;
x1[1] = (br_dec64le(&G[6]) >> 3) & MASK51;
x1[2] = (br_dec64le(&G[12]) >> 6) & MASK51;
x1[3] = (br_dec64le(&G[19]) >> 1) & MASK51;
x1[4] = (br_dec64le(&G[24]) >> 12) & MASK51;
/*
* We can use memset() to clear values, because exact-width types
* like uint64_t are guaranteed to have no padding bits or
* trap representations.
*/
memset(x2, 0, sizeof x2);
x2[0] = 1;
memset(z2, 0, sizeof z2);
memcpy(x3, x1, sizeof x1);
memcpy(z3, x2, sizeof x2);
/*
* The multiplier is provided in big-endian notation, and
* possibly shorter than 32 bytes.
*/
memset(k, 0, (sizeof k) - kblen);
memcpy(k + (sizeof k) - kblen, kb, kblen);
k[31] &= 0xF8;
k[0] &= 0x7F;
k[0] |= 0x40;
swap = 0;
for (i = 254; i >= 0; i --) {
uint64_t a[5], aa[5], b[5], bb[5], e[5];
uint64_t c[5], d[5], da[5], cb[5];
uint32_t kt;
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
swap ^= kt;
_src_ec_ec_c25519_m62_cf255__src_ec_ec_c25519_m62_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m62_cf255__src_ec_ec_c25519_m62_ccswap(z2, z3, swap);
swap = kt;
/*
* At that point, limbs of x_2 and z_2 are assumed to fit
* on at most 52 bits each.
*
* Each _src_ec_ec_c25519_m62_cf255_add() adds one bit to the maximum range of
* the values, but _src_ec_ec_c25519_m62_cf255_sub() and _src_ec_ec_c25519_m62_cf255_mul() bring back
* the limbs into 52 bits. All _src_ec_ec_c25519_m62_cf255_add() outputs are
* used only as inputs for _src_ec_ec_c25519_m62_cf255_mul(), which ensures
* that limbs remain in the proper range.
*/
/* A = x_2 + z_2 -- limbs fit on 53 bits each */
_src_ec_ec_c25519_m62_cf255_add(a, x2, z2);
/* AA = A^2 */
_src_ec_ec_c25519_m62_cf255_mul(aa, a, a);
/* B = x_2 - z_2 */
_src_ec_ec_c25519_m62_cf255_sub(b, x2, z2);
/* BB = B^2 */
_src_ec_ec_c25519_m62_cf255_mul(bb, b, b);
/* E = AA - BB */
_src_ec_ec_c25519_m62_cf255_sub(e, aa, bb);
/* C = x_3 + z_3 -- limbs fit on 53 bits each */
_src_ec_ec_c25519_m62_cf255_add(c, x3, z3);
/* D = x_3 - z_3 */
_src_ec_ec_c25519_m62_cf255_sub(d, x3, z3);
/* DA = D * A */
_src_ec_ec_c25519_m62_cf255_mul(da, d, a);
/* CB = C * B */
_src_ec_ec_c25519_m62_cf255_mul(cb, c, b);
/* x_3 = (DA + CB)^2 */
_src_ec_ec_c25519_m62_cf255_add(x3, da, cb);
_src_ec_ec_c25519_m62_cf255_mul(x3, x3, x3);
/* z_3 = x_1 * (DA - CB)^2 */
_src_ec_ec_c25519_m62_cf255_sub(z3, da, cb);
_src_ec_ec_c25519_m62_cf255_mul(z3, z3, z3);
_src_ec_ec_c25519_m62_cf255_mul(z3, x1, z3);
/* x_2 = AA * BB */
_src_ec_ec_c25519_m62_cf255_mul(x2, aa, bb);
/* z_2 = E * (AA + a24 * E) */
_src_ec_ec_c25519_m62_cf255_mul_a24(z2, e);
_src_ec_ec_c25519_m62_cf255_add(z2, aa, z2);
_src_ec_ec_c25519_m62_cf255_mul(z2, e, z2);
}
_src_ec_ec_c25519_m62_cf255__src_ec_ec_c25519_m62_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m62_cf255__src_ec_ec_c25519_m62_ccswap(z2, z3, swap);
/*
* Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize
* most non-squarings. We use x1 and x3, now useless, as temporaries.
*/
memcpy(x1, z2, sizeof z2);
for (i = 0; i < 15; i ++) {
_src_ec_ec_c25519_m62_cf255_mul(x1, x1, x1);
_src_ec_ec_c25519_m62_cf255_mul(x1, x1, z2);
}
memcpy(x3, x1, sizeof x1);
for (i = 0; i < 14; i ++) {
int j;
for (j = 0; j < 16; j ++) {
_src_ec_ec_c25519_m62_cf255_mul(x3, x3, x3);
}
_src_ec_ec_c25519_m62_cf255_mul(x3, x3, x1);
}
for (i = 14; i >= 0; i --) {
_src_ec_ec_c25519_m62_cf255_mul(x3, x3, x3);
if ((0xFFEB >> i) & 1) {
_src_ec_ec_c25519_m62_cf255_mul(x3, z2, x3);
}
}
/*
* Compute x2/z2. We have 1/z2 in x3.
*/
_src_ec_ec_c25519_m62_cf255_mul(x2, x2, x3);
_src_ec_ec_c25519_m62_cf255_final_reduce(x2);
/*
* Encode the final x2 value in little-endian. We first assemble
* the limbs into 64-bit values.
*/
x2[0] |= x2[1] << 51;
x2[1] = (x2[1] >> 13) | (x2[2] << 38);
x2[2] = (x2[2] >> 26) | (x2[3] << 25);
x2[3] = (x2[3] >> 39) | (x2[4] << 12);
br_enc64le(G, x2[0]);
br_enc64le(G + 8, x2[1]);
br_enc64le(G + 16, x2[2]);
br_enc64le(G + 24, x2[3]);
return 1;
}
static size_t
_src_ec_ec_c25519_m62_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_c25519_m62_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_c25519_m62_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_c25519_m62_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We don't implement this method, since it is used for ECDSA
* only, and there is no ECDSA over Curve25519 (which instead
* uses EdDSA).
*/
(void)A;
(void)B;
(void)len;
(void)x;
(void)xlen;
(void)y;
(void)ylen;
(void)curve;
return 0;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_c25519_m62 = {
(uint32_t)0x20000000,
&_src_ec_ec_c25519_m62_capi_generator,
&_src_ec_ec_c25519_m62_capi_order,
&_src_ec_ec_c25519_m62_capi_xoff,
&_src_ec_ec_c25519_m62_capi_mul,
&_src_ec_ec_c25519_m62_capi_mulgen,
&_src_ec_ec_c25519_m62_capi_muladd
};
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_c25519_m62_get(void)
{
return &br_ec_c25519_m62;
}
#else
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_c25519_m62_get(void)
{
return 0;
}
#endif
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if BR_INT128 || BR_UMUL128
#if BR_UMUL128
#include
#endif
static const unsigned char _src_ec_ec_c25519_m64_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_c25519_m64_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const unsigned char *
_src_ec_ec_c25519_m64_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m64_cGEN;
}
static const unsigned char *
_src_ec_ec_c25519_m64_capi_order(int curve, size_t *len)
{
(void)curve;
*len = 32;
return _src_ec_ec_c25519_m64_cORDER;
}
static size_t
_src_ec_ec_c25519_m64_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 0;
}
/*
* A field element is encoded as four 64-bit integers, in basis 2^63.
* Operations return partially reduced values, which may range up to
* 2^255+37.
*/
#define MASK63 (((uint64_t)1 << 63) - (uint64_t)1)
/*
* Swap two field elements, conditionally on a flag.
*/
static inline void
_src_ec_ec_c25519_m64_cf255__src_ec_ec_c25519_m64_ccswap(uint64_t *a, uint64_t *b, uint32_t ctl)
{
uint64_t m, w;
m = -(uint64_t)ctl;
w = m & (a[0] ^ b[0]); a[0] ^= w; b[0] ^= w;
w = m & (a[1] ^ b[1]); a[1] ^= w; b[1] ^= w;
w = m & (a[2] ^ b[2]); a[2] ^= w; b[2] ^= w;
w = m & (a[3] ^ b[3]); a[3] ^= w; b[3] ^= w;
}
/*
* Addition in the field.
*/
static inline void
_src_ec_ec_c25519_m64_cf255_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
#if BR_INT128
uint64_t t0, t1, t2, t3, cc;
unsigned __int128 z;
z = (unsigned __int128)a[0] + (unsigned __int128)b[0];
t0 = (uint64_t)z;
z = (unsigned __int128)a[1] + (unsigned __int128)b[1] + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)a[2] + (unsigned __int128)b[2] + (z >> 64);
t2 = (uint64_t)z;
z = (unsigned __int128)a[3] + (unsigned __int128)b[3] + (z >> 64);
t3 = (uint64_t)z & MASK63;
cc = (uint64_t)(z >> 63);
/*
* Since operands are at most 2^255+37, the sum is at most
* 2^256+74; thus, the carry cc is equal to 0, 1 or 2.
*
* We use: 2^255 = 19 mod p.
* Since we add 0, 19 or 38 to a value that fits on 255 bits,
* the result is at most 2^255+37.
*/
z = (unsigned __int128)t0 + (unsigned __int128)(19 * cc);
d[0] = (uint64_t)z;
z = (unsigned __int128)t1 + (z >> 64);
d[1] = (uint64_t)z;
z = (unsigned __int128)t2 + (z >> 64);
d[2] = (uint64_t)z;
d[3] = t3 + (uint64_t)(z >> 64);
#elif BR_UMUL128
uint64_t t0, t1, t2, t3, cc;
unsigned char k;
k = _addcarry_u64(0, a[0], b[0], &t0);
k = _addcarry_u64(k, a[1], b[1], &t1);
k = _addcarry_u64(k, a[2], b[2], &t2);
k = _addcarry_u64(k, a[3], b[3], &t3);
cc = (k << 1) + (t3 >> 63);
t3 &= MASK63;
/*
* Since operands are at most 2^255+37, the sum is at most
* 2^256+74; thus, the carry cc is equal to 0, 1 or 2.
*
* We use: 2^255 = 19 mod p.
* Since we add 0, 19 or 38 to a value that fits on 255 bits,
* the result is at most 2^255+37.
*/
k = _addcarry_u64(0, t0, 19 * cc, &d[0]);
k = _addcarry_u64(k, t1, 0, &d[1]);
k = _addcarry_u64(k, t2, 0, &d[2]);
(void)_addcarry_u64(k, t3, 0, &d[3]);
#endif
}
/*
* Subtraction.
*/
static inline void
_src_ec_ec_c25519_m64_cf255_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
#if BR_INT128
/*
* We compute t = 2^256 - 38 + a - b, which is necessarily
* positive but lower than 2^256 + 2^255, since a <= 2^255 + 37
* and b <= 2^255 + 37. We then subtract 0, p or 2*p, depending
* on the two upper bits of t (bits 255 and 256).
*/
uint64_t t0, t1, t2, t3, t4, cc;
unsigned __int128 z;
z = (unsigned __int128)a[0] - (unsigned __int128)b[0] - 38;
t0 = (uint64_t)z;
cc = -(uint64_t)(z >> 64);
z = (unsigned __int128)a[1] - (unsigned __int128)b[1]
- (unsigned __int128)cc;
t1 = (uint64_t)z;
cc = -(uint64_t)(z >> 64);
z = (unsigned __int128)a[2] - (unsigned __int128)b[2]
- (unsigned __int128)cc;
t2 = (uint64_t)z;
cc = -(uint64_t)(z >> 64);
z = (unsigned __int128)a[3] - (unsigned __int128)b[3]
- (unsigned __int128)cc;
t3 = (uint64_t)z;
t4 = 1 + (uint64_t)(z >> 64);
/*
* We have a 257-bit result. The two top bits can be 00, 01 or 10,
* but not 11 (value t <= 2^256 - 38 + 2^255 + 37 = 2^256 + 2^255 - 1).
* Therefore, we can truncate to 255 bits, and add 0, 19 or 38.
* This guarantees that the result is at most 2^255+37.
*/
cc = (38 & -t4) + (19 & -(t3 >> 63));
t3 &= MASK63;
z = (unsigned __int128)t0 + (unsigned __int128)cc;
d[0] = (uint64_t)z;
z = (unsigned __int128)t1 + (z >> 64);
d[1] = (uint64_t)z;
z = (unsigned __int128)t2 + (z >> 64);
d[2] = (uint64_t)z;
d[3] = t3 + (uint64_t)(z >> 64);
#elif BR_UMUL128
/*
* We compute t = 2^256 - 38 + a - b, which is necessarily
* positive but lower than 2^256 + 2^255, since a <= 2^255 + 37
* and b <= 2^255 + 37. We then subtract 0, p or 2*p, depending
* on the two upper bits of t (bits 255 and 256).
*/
uint64_t t0, t1, t2, t3, t4;
unsigned char k;
k = _subborrow_u64(0, a[0], b[0], &t0);
k = _subborrow_u64(k, a[1], b[1], &t1);
k = _subborrow_u64(k, a[2], b[2], &t2);
k = _subborrow_u64(k, a[3], b[3], &t3);
(void)_subborrow_u64(k, 1, 0, &t4);
k = _subborrow_u64(0, t0, 38, &t0);
k = _subborrow_u64(k, t1, 0, &t1);
k = _subborrow_u64(k, t2, 0, &t2);
k = _subborrow_u64(k, t3, 0, &t3);
(void)_subborrow_u64(k, t4, 0, &t4);
/*
* We have a 257-bit result. The two top bits can be 00, 01 or 10,
* but not 11 (value t <= 2^256 - 38 + 2^255 + 37 = 2^256 + 2^255 - 1).
* Therefore, we can truncate to 255 bits, and add 0, 19 or 38.
* This guarantees that the result is at most 2^255+37.
*/
t4 = (38 & -t4) + (19 & -(t3 >> 63));
t3 &= MASK63;
k = _addcarry_u64(0, t0, t4, &d[0]);
k = _addcarry_u64(k, t1, 0, &d[1]);
k = _addcarry_u64(k, t2, 0, &d[2]);
(void)_addcarry_u64(k, t3, 0, &d[3]);
#endif
}
/*
* Multiplication.
*/
static inline void
_src_ec_ec_c25519_m64_cf255_mul(uint64_t *d, uint64_t *a, uint64_t *b)
{
#if BR_INT128
unsigned __int128 z;
uint64_t t0, t1, t2, t3, t4, t5, t6, t7, th;
/*
* Compute the product a*b over plain integers.
*/
z = (unsigned __int128)a[0] * (unsigned __int128)b[0];
t0 = (uint64_t)z;
z = (unsigned __int128)a[0] * (unsigned __int128)b[1] + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)a[0] * (unsigned __int128)b[2] + (z >> 64);
t2 = (uint64_t)z;
z = (unsigned __int128)a[0] * (unsigned __int128)b[3] + (z >> 64);
t3 = (uint64_t)z;
t4 = (uint64_t)(z >> 64);
z = (unsigned __int128)a[1] * (unsigned __int128)b[0]
+ (unsigned __int128)t1;
t1 = (uint64_t)z;
z = (unsigned __int128)a[1] * (unsigned __int128)b[1]
+ (unsigned __int128)t2 + (z >> 64);
t2 = (uint64_t)z;
z = (unsigned __int128)a[1] * (unsigned __int128)b[2]
+ (unsigned __int128)t3 + (z >> 64);
t3 = (uint64_t)z;
z = (unsigned __int128)a[1] * (unsigned __int128)b[3]
+ (unsigned __int128)t4 + (z >> 64);
t4 = (uint64_t)z;
t5 = (uint64_t)(z >> 64);
z = (unsigned __int128)a[2] * (unsigned __int128)b[0]
+ (unsigned __int128)t2;
t2 = (uint64_t)z;
z = (unsigned __int128)a[2] * (unsigned __int128)b[1]
+ (unsigned __int128)t3 + (z >> 64);
t3 = (uint64_t)z;
z = (unsigned __int128)a[2] * (unsigned __int128)b[2]
+ (unsigned __int128)t4 + (z >> 64);
t4 = (uint64_t)z;
z = (unsigned __int128)a[2] * (unsigned __int128)b[3]
+ (unsigned __int128)t5 + (z >> 64);
t5 = (uint64_t)z;
t6 = (uint64_t)(z >> 64);
z = (unsigned __int128)a[3] * (unsigned __int128)b[0]
+ (unsigned __int128)t3;
t3 = (uint64_t)z;
z = (unsigned __int128)a[3] * (unsigned __int128)b[1]
+ (unsigned __int128)t4 + (z >> 64);
t4 = (uint64_t)z;
z = (unsigned __int128)a[3] * (unsigned __int128)b[2]
+ (unsigned __int128)t5 + (z >> 64);
t5 = (uint64_t)z;
z = (unsigned __int128)a[3] * (unsigned __int128)b[3]
+ (unsigned __int128)t6 + (z >> 64);
t6 = (uint64_t)z;
t7 = (uint64_t)(z >> 64);
/*
* Modulo p, we have:
*
* 2^255 = 19
* 2^510 = 19*19 = 361
*
* We split the intermediate t into three parts, in basis
* 2^255. The low one will be in t0..t3; the middle one in t4..t7.
* The upper one can only be a single bit (th), since the
* multiplication operands are at most 2^255+37 each.
*/
th = t7 >> 62;
t7 = ((t7 << 1) | (t6 >> 63)) & MASK63;
t6 = (t6 << 1) | (t5 >> 63);
t5 = (t5 << 1) | (t4 >> 63);
t4 = (t4 << 1) | (t3 >> 63);
t3 &= MASK63;
/*
* Multiply the middle part (t4..t7) by 19. We truncate it to
* 255 bits; the extra bits will go along with th.
*/
z = (unsigned __int128)t4 * 19;
t4 = (uint64_t)z;
z = (unsigned __int128)t5 * 19 + (z >> 64);
t5 = (uint64_t)z;
z = (unsigned __int128)t6 * 19 + (z >> 64);
t6 = (uint64_t)z;
z = (unsigned __int128)t7 * 19 + (z >> 64);
t7 = (uint64_t)z & MASK63;
th = (361 & -th) + (19 * (uint64_t)(z >> 63));
/*
* Add elements together.
* At this point:
* t0..t3 fits on 255 bits.
* t4..t7 fits on 255 bits.
* th <= 361 + 342 = 703.
*/
z = (unsigned __int128)t0 + (unsigned __int128)t4
+ (unsigned __int128)th;
t0 = (uint64_t)z;
z = (unsigned __int128)t1 + (unsigned __int128)t5 + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)t2 + (unsigned __int128)t6 + (z >> 64);
t2 = (uint64_t)z;
z = (unsigned __int128)t3 + (unsigned __int128)t7 + (z >> 64);
t3 = (uint64_t)z & MASK63;
th = (uint64_t)(z >> 63);
/*
* Since the sum is at most 2^256 + 703, the two upper bits, in th,
* can only have value 0, 1 or 2. We just add th*19, which
* guarantees a result of at most 2^255+37.
*/
z = (unsigned __int128)t0 + (19 * th);
d[0] = (uint64_t)z;
z = (unsigned __int128)t1 + (z >> 64);
d[1] = (uint64_t)z;
z = (unsigned __int128)t2 + (z >> 64);
d[2] = (uint64_t)z;
d[3] = t3 + (uint64_t)(z >> 64);
#elif BR_UMUL128
uint64_t t0, t1, t2, t3, t4, t5, t6, t7, th;
uint64_t h0, h1, h2, h3;
unsigned char k;
/*
* Compute the product a*b over plain integers.
*/
t0 = _umul128(a[0], b[0], &h0);
t1 = _umul128(a[0], b[1], &h1);
k = _addcarry_u64(0, t1, h0, &t1);
t2 = _umul128(a[0], b[2], &h2);
k = _addcarry_u64(k, t2, h1, &t2);
t3 = _umul128(a[0], b[3], &h3);
k = _addcarry_u64(k, t3, h2, &t3);
(void)_addcarry_u64(k, h3, 0, &t4);
k = _addcarry_u64(0, _umul128(a[1], b[0], &h0), t1, &t1);
k = _addcarry_u64(k, _umul128(a[1], b[1], &h1), t2, &t2);
k = _addcarry_u64(k, _umul128(a[1], b[2], &h2), t3, &t3);
k = _addcarry_u64(k, _umul128(a[1], b[3], &h3), t4, &t4);
t5 = k;
k = _addcarry_u64(0, t2, h0, &t2);
k = _addcarry_u64(k, t3, h1, &t3);
k = _addcarry_u64(k, t4, h2, &t4);
(void)_addcarry_u64(k, t5, h3, &t5);
k = _addcarry_u64(0, _umul128(a[2], b[0], &h0), t2, &t2);
k = _addcarry_u64(k, _umul128(a[2], b[1], &h1), t3, &t3);
k = _addcarry_u64(k, _umul128(a[2], b[2], &h2), t4, &t4);
k = _addcarry_u64(k, _umul128(a[2], b[3], &h3), t5, &t5);
t6 = k;
k = _addcarry_u64(0, t3, h0, &t3);
k = _addcarry_u64(k, t4, h1, &t4);
k = _addcarry_u64(k, t5, h2, &t5);
(void)_addcarry_u64(k, t6, h3, &t6);
k = _addcarry_u64(0, _umul128(a[3], b[0], &h0), t3, &t3);
k = _addcarry_u64(k, _umul128(a[3], b[1], &h1), t4, &t4);
k = _addcarry_u64(k, _umul128(a[3], b[2], &h2), t5, &t5);
k = _addcarry_u64(k, _umul128(a[3], b[3], &h3), t6, &t6);
t7 = k;
k = _addcarry_u64(0, t4, h0, &t4);
k = _addcarry_u64(k, t5, h1, &t5);
k = _addcarry_u64(k, t6, h2, &t6);
(void)_addcarry_u64(k, t7, h3, &t7);
/*
* Modulo p, we have:
*
* 2^255 = 19
* 2^510 = 19*19 = 361
*
* We split the intermediate t into three parts, in basis
* 2^255. The low one will be in t0..t3; the middle one in t4..t7.
* The upper one can only be a single bit (th), since the
* multiplication operands are at most 2^255+37 each.
*/
th = t7 >> 62;
t7 = ((t7 << 1) | (t6 >> 63)) & MASK63;
t6 = (t6 << 1) | (t5 >> 63);
t5 = (t5 << 1) | (t4 >> 63);
t4 = (t4 << 1) | (t3 >> 63);
t3 &= MASK63;
/*
* Multiply the middle part (t4..t7) by 19. We truncate it to
* 255 bits; the extra bits will go along with th.
*/
t4 = _umul128(t4, 19, &h0);
t5 = _umul128(t5, 19, &h1);
t6 = _umul128(t6, 19, &h2);
t7 = _umul128(t7, 19, &h3);
k = _addcarry_u64(0, t5, h0, &t5);
k = _addcarry_u64(k, t6, h1, &t6);
k = _addcarry_u64(k, t7, h2, &t7);
(void)_addcarry_u64(k, h3, 0, &h3);
th = (361 & -th) + (19 * ((h3 << 1) + (t7 >> 63)));
t7 &= MASK63;
/*
* Add elements together.
* At this point:
* t0..t3 fits on 255 bits.
* t4..t7 fits on 255 bits.
* th <= 361 + 342 = 703.
*/
k = _addcarry_u64(0, t0, t4, &t0);
k = _addcarry_u64(k, t1, t5, &t1);
k = _addcarry_u64(k, t2, t6, &t2);
k = _addcarry_u64(k, t3, t7, &t3);
t4 = k;
k = _addcarry_u64(0, t0, th, &t0);
k = _addcarry_u64(k, t1, 0, &t1);
k = _addcarry_u64(k, t2, 0, &t2);
k = _addcarry_u64(k, t3, 0, &t3);
(void)_addcarry_u64(k, t4, 0, &t4);
th = (t4 << 1) + (t3 >> 63);
t3 &= MASK63;
/*
* Since the sum is at most 2^256 + 703, the two upper bits, in th,
* can only have value 0, 1 or 2. We just add th*19, which
* guarantees a result of at most 2^255+37.
*/
k = _addcarry_u64(0, t0, 19 * th, &d[0]);
k = _addcarry_u64(k, t1, 0, &d[1]);
k = _addcarry_u64(k, t2, 0, &d[2]);
(void)_addcarry_u64(k, t3, 0, &d[3]);
#endif
}
/*
* Multiplication by A24 = 121665.
*/
static inline void
_src_ec_ec_c25519_m64_cf255_mul_a24(uint64_t *d, const uint64_t *a)
{
#if BR_INT128
uint64_t t0, t1, t2, t3;
unsigned __int128 z;
z = (unsigned __int128)a[0] * 121665;
t0 = (uint64_t)z;
z = (unsigned __int128)a[1] * 121665 + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)a[2] * 121665 + (z >> 64);
t2 = (uint64_t)z;
z = (unsigned __int128)a[3] * 121665 + (z >> 64);
t3 = (uint64_t)z & MASK63;
z = (unsigned __int128)t0 + (19 * (uint64_t)(z >> 63));
t0 = (uint64_t)z;
z = (unsigned __int128)t1 + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)t2 + (z >> 64);
t2 = (uint64_t)z;
t3 = t3 + (uint64_t)(z >> 64);
z = (unsigned __int128)t0 + (19 & -(t3 >> 63));
d[0] = (uint64_t)z;
z = (unsigned __int128)t1 + (z >> 64);
d[1] = (uint64_t)z;
z = (unsigned __int128)t2 + (z >> 64);
d[2] = (uint64_t)z;
d[3] = (t3 & MASK63) + (uint64_t)(z >> 64);
#elif BR_UMUL128
uint64_t t0, t1, t2, t3, t4, h0, h1, h2, h3;
unsigned char k;
t0 = _umul128(a[0], 121665, &h0);
t1 = _umul128(a[1], 121665, &h1);
k = _addcarry_u64(0, t1, h0, &t1);
t2 = _umul128(a[2], 121665, &h2);
k = _addcarry_u64(k, t2, h1, &t2);
t3 = _umul128(a[3], 121665, &h3);
k = _addcarry_u64(k, t3, h2, &t3);
(void)_addcarry_u64(k, h3, 0, &t4);
t4 = (t4 << 1) + (t3 >> 63);
t3 &= MASK63;
k = _addcarry_u64(0, t0, 19 * t4, &t0);
k = _addcarry_u64(k, t1, 0, &t1);
k = _addcarry_u64(k, t2, 0, &t2);
(void)_addcarry_u64(k, t3, 0, &t3);
t4 = 19 & -(t3 >> 63);
t3 &= MASK63;
k = _addcarry_u64(0, t0, t4, &d[0]);
k = _addcarry_u64(k, t1, 0, &d[1]);
k = _addcarry_u64(k, t2, 0, &d[2]);
(void)_addcarry_u64(k, t3, 0, &d[3]);
#endif
}
/*
* Finalize reduction.
*/
static inline void
_src_ec_ec_c25519_m64_cf255_final_reduce(uint64_t *a)
{
#if BR_INT128
uint64_t t0, t1, t2, t3, m;
unsigned __int128 z;
/*
* We add 19. If the result (in t) is below 2^255, then a[]
* is already less than 2^255-19, thus already reduced.
* Otherwise, we subtract 2^255 from t[], in which case we
* have t = a - (2^255-19), and that's our result.
*/
z = (unsigned __int128)a[0] + 19;
t0 = (uint64_t)z;
z = (unsigned __int128)a[1] + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)a[2] + (z >> 64);
t2 = (uint64_t)z;
t3 = a[3] + (uint64_t)(z >> 64);
m = -(t3 >> 63);
t3 &= MASK63;
a[0] ^= m & (a[0] ^ t0);
a[1] ^= m & (a[1] ^ t1);
a[2] ^= m & (a[2] ^ t2);
a[3] ^= m & (a[3] ^ t3);
#elif BR_UMUL128
uint64_t t0, t1, t2, t3, m;
unsigned char k;
/*
* We add 19. If the result (in t) is below 2^255, then a[]
* is already less than 2^255-19, thus already reduced.
* Otherwise, we subtract 2^255 from t[], in which case we
* have t = a - (2^255-19), and that's our result.
*/
k = _addcarry_u64(0, a[0], 19, &t0);
k = _addcarry_u64(k, a[1], 0, &t1);
k = _addcarry_u64(k, a[2], 0, &t2);
(void)_addcarry_u64(k, a[3], 0, &t3);
m = -(t3 >> 63);
t3 &= MASK63;
a[0] ^= m & (a[0] ^ t0);
a[1] ^= m & (a[1] ^ t1);
a[2] ^= m & (a[2] ^ t2);
a[3] ^= m & (a[3] ^ t3);
#endif
}
static uint32_t
_src_ec_ec_c25519_m64_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *kb, size_t kblen, int curve)
{
unsigned char k[32];
uint64_t x1[4], x2[4], z2[4], x3[4], z3[4];
uint32_t swap;
int i;
(void)curve;
/*
* Points are encoded over exactly 32 bytes. Multipliers must fit
* in 32 bytes as well.
*/
if (Glen != 32 || kblen > 32) {
return 0;
}
/*
* RFC 7748 mandates that the high bit of the last point byte must
* be ignored/cleared.
*/
x1[0] = br_dec64le(&G[ 0]);
x1[1] = br_dec64le(&G[ 8]);
x1[2] = br_dec64le(&G[16]);
x1[3] = br_dec64le(&G[24]) & MASK63;
/*
* We can use memset() to clear values, because exact-width types
* like uint64_t are guaranteed to have no padding bits or
* trap representations.
*/
memset(x2, 0, sizeof x2);
x2[0] = 1;
memset(z2, 0, sizeof z2);
memcpy(x3, x1, sizeof x1);
memcpy(z3, x2, sizeof x2);
/*
* The multiplier is provided in big-endian notation, and
* possibly shorter than 32 bytes.
*/
memset(k, 0, (sizeof k) - kblen);
memcpy(k + (sizeof k) - kblen, kb, kblen);
k[31] &= 0xF8;
k[0] &= 0x7F;
k[0] |= 0x40;
swap = 0;
for (i = 254; i >= 0; i --) {
uint64_t a[4], aa[4], b[4], bb[4], e[4];
uint64_t c[4], d[4], da[4], cb[4];
uint32_t kt;
kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;
swap ^= kt;
_src_ec_ec_c25519_m64_cf255__src_ec_ec_c25519_m64_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m64_cf255__src_ec_ec_c25519_m64_ccswap(z2, z3, swap);
swap = kt;
/* A = x_2 + z_2 */
_src_ec_ec_c25519_m64_cf255_add(a, x2, z2);
/* AA = A^2 */
_src_ec_ec_c25519_m64_cf255_mul(aa, a, a);
/* B = x_2 - z_2 */
_src_ec_ec_c25519_m64_cf255_sub(b, x2, z2);
/* BB = B^2 */
_src_ec_ec_c25519_m64_cf255_mul(bb, b, b);
/* E = AA - BB */
_src_ec_ec_c25519_m64_cf255_sub(e, aa, bb);
/* C = x_3 + z_3 */
_src_ec_ec_c25519_m64_cf255_add(c, x3, z3);
/* D = x_3 - z_3 */
_src_ec_ec_c25519_m64_cf255_sub(d, x3, z3);
/* DA = D * A */
_src_ec_ec_c25519_m64_cf255_mul(da, d, a);
/* CB = C * B */
_src_ec_ec_c25519_m64_cf255_mul(cb, c, b);
/* x_3 = (DA + CB)^2 */
_src_ec_ec_c25519_m64_cf255_add(x3, da, cb);
_src_ec_ec_c25519_m64_cf255_mul(x3, x3, x3);
/* z_3 = x_1 * (DA - CB)^2 */
_src_ec_ec_c25519_m64_cf255_sub(z3, da, cb);
_src_ec_ec_c25519_m64_cf255_mul(z3, z3, z3);
_src_ec_ec_c25519_m64_cf255_mul(z3, x1, z3);
/* x_2 = AA * BB */
_src_ec_ec_c25519_m64_cf255_mul(x2, aa, bb);
/* z_2 = E * (AA + a24 * E) */
_src_ec_ec_c25519_m64_cf255_mul_a24(z2, e);
_src_ec_ec_c25519_m64_cf255_add(z2, aa, z2);
_src_ec_ec_c25519_m64_cf255_mul(z2, e, z2);
}
_src_ec_ec_c25519_m64_cf255__src_ec_ec_c25519_m64_ccswap(x2, x3, swap);
_src_ec_ec_c25519_m64_cf255__src_ec_ec_c25519_m64_ccswap(z2, z3, swap);
/*
* Compute 1/z2 = z2^(p-2). Since p = 2^255-19, we can mutualize
* most non-squarings. We use x1 and x3, now useless, as temporaries.
*/
memcpy(x1, z2, sizeof z2);
for (i = 0; i < 15; i ++) {
_src_ec_ec_c25519_m64_cf255_mul(x1, x1, x1);
_src_ec_ec_c25519_m64_cf255_mul(x1, x1, z2);
}
memcpy(x3, x1, sizeof x1);
for (i = 0; i < 14; i ++) {
int j;
for (j = 0; j < 16; j ++) {
_src_ec_ec_c25519_m64_cf255_mul(x3, x3, x3);
}
_src_ec_ec_c25519_m64_cf255_mul(x3, x3, x1);
}
for (i = 14; i >= 0; i --) {
_src_ec_ec_c25519_m64_cf255_mul(x3, x3, x3);
if ((0xFFEB >> i) & 1) {
_src_ec_ec_c25519_m64_cf255_mul(x3, z2, x3);
}
}
/*
* Compute x2/z2. We have 1/z2 in x3.
*/
_src_ec_ec_c25519_m64_cf255_mul(x2, x2, x3);
_src_ec_ec_c25519_m64_cf255_final_reduce(x2);
/*
* Encode the final x2 value in little-endian.
*/
br_enc64le(G, x2[0]);
br_enc64le(G + 8, x2[1]);
br_enc64le(G + 16, x2[2]);
br_enc64le(G + 24, x2[3]);
return 1;
}
static size_t
_src_ec_ec_c25519_m64_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_c25519_m64_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_c25519_m64_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_c25519_m64_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We don't implement this method, since it is used for ECDSA
* only, and there is no ECDSA over Curve25519 (which instead
* uses EdDSA).
*/
(void)A;
(void)B;
(void)len;
(void)x;
(void)xlen;
(void)y;
(void)ylen;
(void)curve;
return 0;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_c25519_m64 = {
(uint32_t)0x20000000,
&_src_ec_ec_c25519_m64_capi_generator,
&_src_ec_ec_c25519_m64_capi_order,
&_src_ec_ec_c25519_m64_capi_xoff,
&_src_ec_ec_c25519_m64_capi_mul,
&_src_ec_ec_c25519_m64_capi_mulgen,
&_src_ec_ec_c25519_m64_capi_muladd
};
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_c25519_m64_get(void)
{
return &br_ec_c25519_m64;
}
#else
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_c25519_m64_get(void)
{
return 0;
}
#endif
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char _src_ec_ec_curve25519_cGEN[] = {
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const unsigned char _src_ec_ec_curve25519_cORDER[] = {
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
/* see inner.h */
const br_ec_curve_def br_curve25519 = {
BR_EC_curve25519,
_src_ec_ec_curve25519_cORDER, sizeof _src_ec_ec_curve25519_cORDER,
_src_ec_ec_curve25519_cGEN, sizeof _src_ec_ec_curve25519_cGEN
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_get_default(void)
{
#if BR_LOMUL
return &br_ec_all_m15;
#else
return &br_ec_all_m31;
#endif
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
size_t
br_ec_keygen(const br_prng_class **rng_ctx,
const br_ec_impl *impl, br_ec_private_key *sk,
void *kbuf, int curve)
{
const unsigned char *order;
unsigned char *buf;
size_t len;
unsigned mask;
if (curve < 0 || curve >= 32
|| ((impl->supported_curves >> curve) & 1) == 0)
{
return 0;
}
order = impl->order(curve, &len);
while (len > 0 && *order == 0) {
order ++;
len --;
}
if (kbuf == NULL || len == 0) {
return len;
}
mask = order[0];
mask |= (mask >> 1);
mask |= (mask >> 2);
mask |= (mask >> 4);
/*
* We generate sequences of random bits of the right size, until
* the value is strictly lower than the curve order (we also
* check for all-zero values, which are invalid).
*/
buf = (unsigned char*)kbuf;
for (;;) {
size_t u;
unsigned cc, zz;
(*rng_ctx)->generate(rng_ctx, buf, len);
buf[0] &= mask;
cc = 0;
u = len;
zz = 0;
while (u -- > 0) {
cc = ((unsigned)(buf[u] - order[u] - cc) >> 8) & 1;
zz |= buf[u];
}
if (cc != 0 && zz != 0) {
break;
}
}
if (sk != NULL) {
sk->curve = curve;
sk->x = buf;
sk->xlen = len;
}
return len;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
* that right-shifting a signed negative integer copies the sign bit
* (arithmetic right-shift). This is "implementation-defined behaviour",
* i.e. it is not undefined, but it may differ between compilers. Each
* compiler is supposed to document its behaviour in that respect. GCC
* explicitly defines that an arithmetic right shift is used. We expect
* all other compilers to do the same, because underlying CPU offer an
* arithmetic right shift opcode that could not be used otherwise.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#endif
/*
* Convert an integer from unsigned big-endian encoding to a sequence of
* 13-bit words in little-endian order. The final "partial" word is
* returned.
*/
static uint32_t
be8_to_le13(uint32_t *dst, const unsigned char *src, size_t len)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
acc |= (uint32_t)src[len] << acc_len;
acc_len += 8;
if (acc_len >= 13) {
*dst ++ = acc & 0x1FFF;
acc >>= 13;
acc_len -= 13;
}
}
return acc;
}
/*
* Convert an integer (13-bit words, little-endian) to unsigned
* big-endian encoding. The total encoding length is provided; all
* the destination bytes will be filled.
*/
static void
le13_to_be8(unsigned char *dst, size_t len, const uint32_t *src)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
if (acc_len < 8) {
acc |= (*src ++) << acc_len;
acc_len += 13;
}
dst[len] = (unsigned char)acc;
acc >>= 8;
acc_len -= 8;
}
}
/*
* Normalise an array of words to a strict 13 bits per word. Returned
* value is the resulting carry. The source (w) and destination (d)
* arrays may be identical, but shall not overlap partially.
*/
static inline uint32_t
_src_ec_ec_p256_m15_cnorm13(uint32_t *d, const uint32_t *w, size_t len)
{
size_t u;
uint32_t cc;
cc = 0;
for (u = 0; u < len; u ++) {
int32_t z;
z = w[u] + cc;
d[u] = z & 0x1FFF;
cc = ARSH(z, 13);
}
return cc;
}
/*
* _src_ec_ec_p256_m15_cmul20() multiplies two 260-bit integers together. Each word must fit
* on 13 bits; source operands use 20 words, destination operand
* receives 40 words. All overlaps allowed.
*
* _src_ec_ec_p256_m15_csquare20() computes the square of a 260-bit integer. Each word must
* fit on 13 bits; source operand uses 20 words, destination operand
* receives 40 words. All overlaps allowed.
*/
#if BR_SLOW_MUL15
static void
_src_ec_ec_p256_m15_cmul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* Two-level Karatsuba: turns a 20x20 multiplication into
* nine 5x5 multiplications. We use 13-bit words but do not
* propagate carries immediately, so words may expand:
*
* - First Karatsuba decomposition turns the 20x20 mul on
* 13-bit words into three 10x10 muls, two on 13-bit words
* and one on 14-bit words.
*
* - Second Karatsuba decomposition further splits these into:
*
* * four 5x5 muls on 13-bit words
* * four 5x5 muls on 14-bit words
* * one 5x5 mul on 15-bit words
*
* Highest word value is 8191, 16382 or 32764, for 13-bit, 14-bit
* or 15-bit words, respectively.
*/
uint32_t u[45], v[45], w[90];
uint32_t cc;
int i;
#define ZADD(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
(dw)[5 * (d_off) + 0] = (s1w)[5 * (s1_off) + 0] \
+ (s2w)[5 * (s2_off) + 0]; \
(dw)[5 * (d_off) + 1] = (s1w)[5 * (s1_off) + 1] \
+ (s2w)[5 * (s2_off) + 1]; \
(dw)[5 * (d_off) + 2] = (s1w)[5 * (s1_off) + 2] \
+ (s2w)[5 * (s2_off) + 2]; \
(dw)[5 * (d_off) + 3] = (s1w)[5 * (s1_off) + 3] \
+ (s2w)[5 * (s2_off) + 3]; \
(dw)[5 * (d_off) + 4] = (s1w)[5 * (s1_off) + 4] \
+ (s2w)[5 * (s2_off) + 4]; \
} while (0)
#define ZADDT(dw, d_off, sw, s_off) do { \
(dw)[5 * (d_off) + 0] += (sw)[5 * (s_off) + 0]; \
(dw)[5 * (d_off) + 1] += (sw)[5 * (s_off) + 1]; \
(dw)[5 * (d_off) + 2] += (sw)[5 * (s_off) + 2]; \
(dw)[5 * (d_off) + 3] += (sw)[5 * (s_off) + 3]; \
(dw)[5 * (d_off) + 4] += (sw)[5 * (s_off) + 4]; \
} while (0)
#define ZSUB2F(dw, d_off, s1w, s1_off, s2w, s2_off) do { \
(dw)[5 * (d_off) + 0] -= (s1w)[5 * (s1_off) + 0] \
+ (s2w)[5 * (s2_off) + 0]; \
(dw)[5 * (d_off) + 1] -= (s1w)[5 * (s1_off) + 1] \
+ (s2w)[5 * (s2_off) + 1]; \
(dw)[5 * (d_off) + 2] -= (s1w)[5 * (s1_off) + 2] \
+ (s2w)[5 * (s2_off) + 2]; \
(dw)[5 * (d_off) + 3] -= (s1w)[5 * (s1_off) + 3] \
+ (s2w)[5 * (s2_off) + 3]; \
(dw)[5 * (d_off) + 4] -= (s1w)[5 * (s1_off) + 4] \
+ (s2w)[5 * (s2_off) + 4]; \
} while (0)
#define CPR1(w, cprcc) do { \
uint32_t cprz = (w) + cprcc; \
(w) = cprz & 0x1FFF; \
cprcc = cprz >> 13; \
} while (0)
#define CPR(dw, d_off) do { \
uint32_t cprcc; \
cprcc = 0; \
CPR1((dw)[(d_off) + 0], cprcc); \
CPR1((dw)[(d_off) + 1], cprcc); \
CPR1((dw)[(d_off) + 2], cprcc); \
CPR1((dw)[(d_off) + 3], cprcc); \
CPR1((dw)[(d_off) + 4], cprcc); \
CPR1((dw)[(d_off) + 5], cprcc); \
CPR1((dw)[(d_off) + 6], cprcc); \
CPR1((dw)[(d_off) + 7], cprcc); \
CPR1((dw)[(d_off) + 8], cprcc); \
(dw)[(d_off) + 9] = cprcc; \
} while (0)
memcpy(u, a, 20 * sizeof *a);
ZADD(u, 4, a, 0, a, 1);
ZADD(u, 5, a, 2, a, 3);
ZADD(u, 6, a, 0, a, 2);
ZADD(u, 7, a, 1, a, 3);
ZADD(u, 8, u, 6, u, 7);
memcpy(v, b, 20 * sizeof *b);
ZADD(v, 4, b, 0, b, 1);
ZADD(v, 5, b, 2, b, 3);
ZADD(v, 6, b, 0, b, 2);
ZADD(v, 7, b, 1, b, 3);
ZADD(v, 8, v, 6, v, 7);
/*
* Do the eight first 8x8 muls. Source words are at most 16382
* each, so we can add product results together "as is" in 32-bit
* words.
*/
for (i = 0; i < 40; i += 5) {
w[(i << 1) + 0] = MUL15(u[i + 0], v[i + 0]);
w[(i << 1) + 1] = MUL15(u[i + 0], v[i + 1])
+ MUL15(u[i + 1], v[i + 0]);
w[(i << 1) + 2] = MUL15(u[i + 0], v[i + 2])
+ MUL15(u[i + 1], v[i + 1])
+ MUL15(u[i + 2], v[i + 0]);
w[(i << 1) + 3] = MUL15(u[i + 0], v[i + 3])
+ MUL15(u[i + 1], v[i + 2])
+ MUL15(u[i + 2], v[i + 1])
+ MUL15(u[i + 3], v[i + 0]);
w[(i << 1) + 4] = MUL15(u[i + 0], v[i + 4])
+ MUL15(u[i + 1], v[i + 3])
+ MUL15(u[i + 2], v[i + 2])
+ MUL15(u[i + 3], v[i + 1])
+ MUL15(u[i + 4], v[i + 0]);
w[(i << 1) + 5] = MUL15(u[i + 1], v[i + 4])
+ MUL15(u[i + 2], v[i + 3])
+ MUL15(u[i + 3], v[i + 2])
+ MUL15(u[i + 4], v[i + 1]);
w[(i << 1) + 6] = MUL15(u[i + 2], v[i + 4])
+ MUL15(u[i + 3], v[i + 3])
+ MUL15(u[i + 4], v[i + 2]);
w[(i << 1) + 7] = MUL15(u[i + 3], v[i + 4])
+ MUL15(u[i + 4], v[i + 3]);
w[(i << 1) + 8] = MUL15(u[i + 4], v[i + 4]);
w[(i << 1) + 9] = 0;
}
/*
* For the 9th multiplication, source words are up to 32764,
* so we must do some carry propagation. If we add up to
* 4 products and the carry is no more than 524224, then the
* result fits in 32 bits, and the next carry will be no more
* than 524224 (because 4*(32764^2)+524224 < 8192*524225).
*
* We thus just skip one of the products in the middle word,
* then do a carry propagation (this reduces words to 13 bits
* each, except possibly the last, which may use up to 17 bits
* or so), then add the missing product.
*/
w[80 + 0] = MUL15(u[40 + 0], v[40 + 0]);
w[80 + 1] = MUL15(u[40 + 0], v[40 + 1])
+ MUL15(u[40 + 1], v[40 + 0]);
w[80 + 2] = MUL15(u[40 + 0], v[40 + 2])
+ MUL15(u[40 + 1], v[40 + 1])
+ MUL15(u[40 + 2], v[40 + 0]);
w[80 + 3] = MUL15(u[40 + 0], v[40 + 3])
+ MUL15(u[40 + 1], v[40 + 2])
+ MUL15(u[40 + 2], v[40 + 1])
+ MUL15(u[40 + 3], v[40 + 0]);
w[80 + 4] = MUL15(u[40 + 0], v[40 + 4])
+ MUL15(u[40 + 1], v[40 + 3])
+ MUL15(u[40 + 2], v[40 + 2])
+ MUL15(u[40 + 3], v[40 + 1]);
/* + MUL15(u[40 + 4], v[40 + 0]) */
w[80 + 5] = MUL15(u[40 + 1], v[40 + 4])
+ MUL15(u[40 + 2], v[40 + 3])
+ MUL15(u[40 + 3], v[40 + 2])
+ MUL15(u[40 + 4], v[40 + 1]);
w[80 + 6] = MUL15(u[40 + 2], v[40 + 4])
+ MUL15(u[40 + 3], v[40 + 3])
+ MUL15(u[40 + 4], v[40 + 2]);
w[80 + 7] = MUL15(u[40 + 3], v[40 + 4])
+ MUL15(u[40 + 4], v[40 + 3]);
w[80 + 8] = MUL15(u[40 + 4], v[40 + 4]);
CPR(w, 80);
w[80 + 4] += MUL15(u[40 + 4], v[40 + 0]);
/*
* The products on 14-bit words in slots 6 and 7 yield values
* up to 5*(16382^2) each, and we need to subtract two such
* values from the higher word. We need the subtraction to fit
* in a _signed_ 32-bit integer, i.e. 31 bits + a sign bit.
* However, 10*(16382^2) does not fit. So we must perform a
* bit of reduction here.
*/
CPR(w, 60);
CPR(w, 70);
/*
* Recompose results.
*/
/* 0..1*0..1 into 0..3 */
ZSUB2F(w, 8, w, 0, w, 2);
ZSUB2F(w, 9, w, 1, w, 3);
ZADDT(w, 1, w, 8);
ZADDT(w, 2, w, 9);
/* 2..3*2..3 into 4..7 */
ZSUB2F(w, 10, w, 4, w, 6);
ZSUB2F(w, 11, w, 5, w, 7);
ZADDT(w, 5, w, 10);
ZADDT(w, 6, w, 11);
/* (0..1+2..3)*(0..1+2..3) into 12..15 */
ZSUB2F(w, 16, w, 12, w, 14);
ZSUB2F(w, 17, w, 13, w, 15);
ZADDT(w, 13, w, 16);
ZADDT(w, 14, w, 17);
/* first-level recomposition */
ZSUB2F(w, 12, w, 0, w, 4);
ZSUB2F(w, 13, w, 1, w, 5);
ZSUB2F(w, 14, w, 2, w, 6);
ZSUB2F(w, 15, w, 3, w, 7);
ZADDT(w, 2, w, 12);
ZADDT(w, 3, w, 13);
ZADDT(w, 4, w, 14);
ZADDT(w, 5, w, 15);
/*
* Perform carry propagation to bring all words down to 13 bits.
*/
cc = _src_ec_ec_p256_m15_cnorm13(d, w, 40);
d[39] += (cc << 13);
#undef ZADD
#undef ZADDT
#undef ZSUB2F
#undef CPR1
#undef CPR
}
static inline void
_src_ec_ec_p256_m15_csquare20(uint32_t *d, const uint32_t *a)
{
_src_ec_ec_p256_m15_cmul20(d, a, a);
}
#else
static void
_src_ec_ec_p256_m15_cmul20(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[39];
t[ 0] = MUL15(a[ 0], b[ 0]);
t[ 1] = MUL15(a[ 0], b[ 1])
+ MUL15(a[ 1], b[ 0]);
t[ 2] = MUL15(a[ 0], b[ 2])
+ MUL15(a[ 1], b[ 1])
+ MUL15(a[ 2], b[ 0]);
t[ 3] = MUL15(a[ 0], b[ 3])
+ MUL15(a[ 1], b[ 2])
+ MUL15(a[ 2], b[ 1])
+ MUL15(a[ 3], b[ 0]);
t[ 4] = MUL15(a[ 0], b[ 4])
+ MUL15(a[ 1], b[ 3])
+ MUL15(a[ 2], b[ 2])
+ MUL15(a[ 3], b[ 1])
+ MUL15(a[ 4], b[ 0]);
t[ 5] = MUL15(a[ 0], b[ 5])
+ MUL15(a[ 1], b[ 4])
+ MUL15(a[ 2], b[ 3])
+ MUL15(a[ 3], b[ 2])
+ MUL15(a[ 4], b[ 1])
+ MUL15(a[ 5], b[ 0]);
t[ 6] = MUL15(a[ 0], b[ 6])
+ MUL15(a[ 1], b[ 5])
+ MUL15(a[ 2], b[ 4])
+ MUL15(a[ 3], b[ 3])
+ MUL15(a[ 4], b[ 2])
+ MUL15(a[ 5], b[ 1])
+ MUL15(a[ 6], b[ 0]);
t[ 7] = MUL15(a[ 0], b[ 7])
+ MUL15(a[ 1], b[ 6])
+ MUL15(a[ 2], b[ 5])
+ MUL15(a[ 3], b[ 4])
+ MUL15(a[ 4], b[ 3])
+ MUL15(a[ 5], b[ 2])
+ MUL15(a[ 6], b[ 1])
+ MUL15(a[ 7], b[ 0]);
t[ 8] = MUL15(a[ 0], b[ 8])
+ MUL15(a[ 1], b[ 7])
+ MUL15(a[ 2], b[ 6])
+ MUL15(a[ 3], b[ 5])
+ MUL15(a[ 4], b[ 4])
+ MUL15(a[ 5], b[ 3])
+ MUL15(a[ 6], b[ 2])
+ MUL15(a[ 7], b[ 1])
+ MUL15(a[ 8], b[ 0]);
t[ 9] = MUL15(a[ 0], b[ 9])
+ MUL15(a[ 1], b[ 8])
+ MUL15(a[ 2], b[ 7])
+ MUL15(a[ 3], b[ 6])
+ MUL15(a[ 4], b[ 5])
+ MUL15(a[ 5], b[ 4])
+ MUL15(a[ 6], b[ 3])
+ MUL15(a[ 7], b[ 2])
+ MUL15(a[ 8], b[ 1])
+ MUL15(a[ 9], b[ 0]);
t[10] = MUL15(a[ 0], b[10])
+ MUL15(a[ 1], b[ 9])
+ MUL15(a[ 2], b[ 8])
+ MUL15(a[ 3], b[ 7])
+ MUL15(a[ 4], b[ 6])
+ MUL15(a[ 5], b[ 5])
+ MUL15(a[ 6], b[ 4])
+ MUL15(a[ 7], b[ 3])
+ MUL15(a[ 8], b[ 2])
+ MUL15(a[ 9], b[ 1])
+ MUL15(a[10], b[ 0]);
t[11] = MUL15(a[ 0], b[11])
+ MUL15(a[ 1], b[10])
+ MUL15(a[ 2], b[ 9])
+ MUL15(a[ 3], b[ 8])
+ MUL15(a[ 4], b[ 7])
+ MUL15(a[ 5], b[ 6])
+ MUL15(a[ 6], b[ 5])
+ MUL15(a[ 7], b[ 4])
+ MUL15(a[ 8], b[ 3])
+ MUL15(a[ 9], b[ 2])
+ MUL15(a[10], b[ 1])
+ MUL15(a[11], b[ 0]);
t[12] = MUL15(a[ 0], b[12])
+ MUL15(a[ 1], b[11])
+ MUL15(a[ 2], b[10])
+ MUL15(a[ 3], b[ 9])
+ MUL15(a[ 4], b[ 8])
+ MUL15(a[ 5], b[ 7])
+ MUL15(a[ 6], b[ 6])
+ MUL15(a[ 7], b[ 5])
+ MUL15(a[ 8], b[ 4])
+ MUL15(a[ 9], b[ 3])
+ MUL15(a[10], b[ 2])
+ MUL15(a[11], b[ 1])
+ MUL15(a[12], b[ 0]);
t[13] = MUL15(a[ 0], b[13])
+ MUL15(a[ 1], b[12])
+ MUL15(a[ 2], b[11])
+ MUL15(a[ 3], b[10])
+ MUL15(a[ 4], b[ 9])
+ MUL15(a[ 5], b[ 8])
+ MUL15(a[ 6], b[ 7])
+ MUL15(a[ 7], b[ 6])
+ MUL15(a[ 8], b[ 5])
+ MUL15(a[ 9], b[ 4])
+ MUL15(a[10], b[ 3])
+ MUL15(a[11], b[ 2])
+ MUL15(a[12], b[ 1])
+ MUL15(a[13], b[ 0]);
t[14] = MUL15(a[ 0], b[14])
+ MUL15(a[ 1], b[13])
+ MUL15(a[ 2], b[12])
+ MUL15(a[ 3], b[11])
+ MUL15(a[ 4], b[10])
+ MUL15(a[ 5], b[ 9])
+ MUL15(a[ 6], b[ 8])
+ MUL15(a[ 7], b[ 7])
+ MUL15(a[ 8], b[ 6])
+ MUL15(a[ 9], b[ 5])
+ MUL15(a[10], b[ 4])
+ MUL15(a[11], b[ 3])
+ MUL15(a[12], b[ 2])
+ MUL15(a[13], b[ 1])
+ MUL15(a[14], b[ 0]);
t[15] = MUL15(a[ 0], b[15])
+ MUL15(a[ 1], b[14])
+ MUL15(a[ 2], b[13])
+ MUL15(a[ 3], b[12])
+ MUL15(a[ 4], b[11])
+ MUL15(a[ 5], b[10])
+ MUL15(a[ 6], b[ 9])
+ MUL15(a[ 7], b[ 8])
+ MUL15(a[ 8], b[ 7])
+ MUL15(a[ 9], b[ 6])
+ MUL15(a[10], b[ 5])
+ MUL15(a[11], b[ 4])
+ MUL15(a[12], b[ 3])
+ MUL15(a[13], b[ 2])
+ MUL15(a[14], b[ 1])
+ MUL15(a[15], b[ 0]);
t[16] = MUL15(a[ 0], b[16])
+ MUL15(a[ 1], b[15])
+ MUL15(a[ 2], b[14])
+ MUL15(a[ 3], b[13])
+ MUL15(a[ 4], b[12])
+ MUL15(a[ 5], b[11])
+ MUL15(a[ 6], b[10])
+ MUL15(a[ 7], b[ 9])
+ MUL15(a[ 8], b[ 8])
+ MUL15(a[ 9], b[ 7])
+ MUL15(a[10], b[ 6])
+ MUL15(a[11], b[ 5])
+ MUL15(a[12], b[ 4])
+ MUL15(a[13], b[ 3])
+ MUL15(a[14], b[ 2])
+ MUL15(a[15], b[ 1])
+ MUL15(a[16], b[ 0]);
t[17] = MUL15(a[ 0], b[17])
+ MUL15(a[ 1], b[16])
+ MUL15(a[ 2], b[15])
+ MUL15(a[ 3], b[14])
+ MUL15(a[ 4], b[13])
+ MUL15(a[ 5], b[12])
+ MUL15(a[ 6], b[11])
+ MUL15(a[ 7], b[10])
+ MUL15(a[ 8], b[ 9])
+ MUL15(a[ 9], b[ 8])
+ MUL15(a[10], b[ 7])
+ MUL15(a[11], b[ 6])
+ MUL15(a[12], b[ 5])
+ MUL15(a[13], b[ 4])
+ MUL15(a[14], b[ 3])
+ MUL15(a[15], b[ 2])
+ MUL15(a[16], b[ 1])
+ MUL15(a[17], b[ 0]);
t[18] = MUL15(a[ 0], b[18])
+ MUL15(a[ 1], b[17])
+ MUL15(a[ 2], b[16])
+ MUL15(a[ 3], b[15])
+ MUL15(a[ 4], b[14])
+ MUL15(a[ 5], b[13])
+ MUL15(a[ 6], b[12])
+ MUL15(a[ 7], b[11])
+ MUL15(a[ 8], b[10])
+ MUL15(a[ 9], b[ 9])
+ MUL15(a[10], b[ 8])
+ MUL15(a[11], b[ 7])
+ MUL15(a[12], b[ 6])
+ MUL15(a[13], b[ 5])
+ MUL15(a[14], b[ 4])
+ MUL15(a[15], b[ 3])
+ MUL15(a[16], b[ 2])
+ MUL15(a[17], b[ 1])
+ MUL15(a[18], b[ 0]);
t[19] = MUL15(a[ 0], b[19])
+ MUL15(a[ 1], b[18])
+ MUL15(a[ 2], b[17])
+ MUL15(a[ 3], b[16])
+ MUL15(a[ 4], b[15])
+ MUL15(a[ 5], b[14])
+ MUL15(a[ 6], b[13])
+ MUL15(a[ 7], b[12])
+ MUL15(a[ 8], b[11])
+ MUL15(a[ 9], b[10])
+ MUL15(a[10], b[ 9])
+ MUL15(a[11], b[ 8])
+ MUL15(a[12], b[ 7])
+ MUL15(a[13], b[ 6])
+ MUL15(a[14], b[ 5])
+ MUL15(a[15], b[ 4])
+ MUL15(a[16], b[ 3])
+ MUL15(a[17], b[ 2])
+ MUL15(a[18], b[ 1])
+ MUL15(a[19], b[ 0]);
t[20] = MUL15(a[ 1], b[19])
+ MUL15(a[ 2], b[18])
+ MUL15(a[ 3], b[17])
+ MUL15(a[ 4], b[16])
+ MUL15(a[ 5], b[15])
+ MUL15(a[ 6], b[14])
+ MUL15(a[ 7], b[13])
+ MUL15(a[ 8], b[12])
+ MUL15(a[ 9], b[11])
+ MUL15(a[10], b[10])
+ MUL15(a[11], b[ 9])
+ MUL15(a[12], b[ 8])
+ MUL15(a[13], b[ 7])
+ MUL15(a[14], b[ 6])
+ MUL15(a[15], b[ 5])
+ MUL15(a[16], b[ 4])
+ MUL15(a[17], b[ 3])
+ MUL15(a[18], b[ 2])
+ MUL15(a[19], b[ 1]);
t[21] = MUL15(a[ 2], b[19])
+ MUL15(a[ 3], b[18])
+ MUL15(a[ 4], b[17])
+ MUL15(a[ 5], b[16])
+ MUL15(a[ 6], b[15])
+ MUL15(a[ 7], b[14])
+ MUL15(a[ 8], b[13])
+ MUL15(a[ 9], b[12])
+ MUL15(a[10], b[11])
+ MUL15(a[11], b[10])
+ MUL15(a[12], b[ 9])
+ MUL15(a[13], b[ 8])
+ MUL15(a[14], b[ 7])
+ MUL15(a[15], b[ 6])
+ MUL15(a[16], b[ 5])
+ MUL15(a[17], b[ 4])
+ MUL15(a[18], b[ 3])
+ MUL15(a[19], b[ 2]);
t[22] = MUL15(a[ 3], b[19])
+ MUL15(a[ 4], b[18])
+ MUL15(a[ 5], b[17])
+ MUL15(a[ 6], b[16])
+ MUL15(a[ 7], b[15])
+ MUL15(a[ 8], b[14])
+ MUL15(a[ 9], b[13])
+ MUL15(a[10], b[12])
+ MUL15(a[11], b[11])
+ MUL15(a[12], b[10])
+ MUL15(a[13], b[ 9])
+ MUL15(a[14], b[ 8])
+ MUL15(a[15], b[ 7])
+ MUL15(a[16], b[ 6])
+ MUL15(a[17], b[ 5])
+ MUL15(a[18], b[ 4])
+ MUL15(a[19], b[ 3]);
t[23] = MUL15(a[ 4], b[19])
+ MUL15(a[ 5], b[18])
+ MUL15(a[ 6], b[17])
+ MUL15(a[ 7], b[16])
+ MUL15(a[ 8], b[15])
+ MUL15(a[ 9], b[14])
+ MUL15(a[10], b[13])
+ MUL15(a[11], b[12])
+ MUL15(a[12], b[11])
+ MUL15(a[13], b[10])
+ MUL15(a[14], b[ 9])
+ MUL15(a[15], b[ 8])
+ MUL15(a[16], b[ 7])
+ MUL15(a[17], b[ 6])
+ MUL15(a[18], b[ 5])
+ MUL15(a[19], b[ 4]);
t[24] = MUL15(a[ 5], b[19])
+ MUL15(a[ 6], b[18])
+ MUL15(a[ 7], b[17])
+ MUL15(a[ 8], b[16])
+ MUL15(a[ 9], b[15])
+ MUL15(a[10], b[14])
+ MUL15(a[11], b[13])
+ MUL15(a[12], b[12])
+ MUL15(a[13], b[11])
+ MUL15(a[14], b[10])
+ MUL15(a[15], b[ 9])
+ MUL15(a[16], b[ 8])
+ MUL15(a[17], b[ 7])
+ MUL15(a[18], b[ 6])
+ MUL15(a[19], b[ 5]);
t[25] = MUL15(a[ 6], b[19])
+ MUL15(a[ 7], b[18])
+ MUL15(a[ 8], b[17])
+ MUL15(a[ 9], b[16])
+ MUL15(a[10], b[15])
+ MUL15(a[11], b[14])
+ MUL15(a[12], b[13])
+ MUL15(a[13], b[12])
+ MUL15(a[14], b[11])
+ MUL15(a[15], b[10])
+ MUL15(a[16], b[ 9])
+ MUL15(a[17], b[ 8])
+ MUL15(a[18], b[ 7])
+ MUL15(a[19], b[ 6]);
t[26] = MUL15(a[ 7], b[19])
+ MUL15(a[ 8], b[18])
+ MUL15(a[ 9], b[17])
+ MUL15(a[10], b[16])
+ MUL15(a[11], b[15])
+ MUL15(a[12], b[14])
+ MUL15(a[13], b[13])
+ MUL15(a[14], b[12])
+ MUL15(a[15], b[11])
+ MUL15(a[16], b[10])
+ MUL15(a[17], b[ 9])
+ MUL15(a[18], b[ 8])
+ MUL15(a[19], b[ 7]);
t[27] = MUL15(a[ 8], b[19])
+ MUL15(a[ 9], b[18])
+ MUL15(a[10], b[17])
+ MUL15(a[11], b[16])
+ MUL15(a[12], b[15])
+ MUL15(a[13], b[14])
+ MUL15(a[14], b[13])
+ MUL15(a[15], b[12])
+ MUL15(a[16], b[11])
+ MUL15(a[17], b[10])
+ MUL15(a[18], b[ 9])
+ MUL15(a[19], b[ 8]);
t[28] = MUL15(a[ 9], b[19])
+ MUL15(a[10], b[18])
+ MUL15(a[11], b[17])
+ MUL15(a[12], b[16])
+ MUL15(a[13], b[15])
+ MUL15(a[14], b[14])
+ MUL15(a[15], b[13])
+ MUL15(a[16], b[12])
+ MUL15(a[17], b[11])
+ MUL15(a[18], b[10])
+ MUL15(a[19], b[ 9]);
t[29] = MUL15(a[10], b[19])
+ MUL15(a[11], b[18])
+ MUL15(a[12], b[17])
+ MUL15(a[13], b[16])
+ MUL15(a[14], b[15])
+ MUL15(a[15], b[14])
+ MUL15(a[16], b[13])
+ MUL15(a[17], b[12])
+ MUL15(a[18], b[11])
+ MUL15(a[19], b[10]);
t[30] = MUL15(a[11], b[19])
+ MUL15(a[12], b[18])
+ MUL15(a[13], b[17])
+ MUL15(a[14], b[16])
+ MUL15(a[15], b[15])
+ MUL15(a[16], b[14])
+ MUL15(a[17], b[13])
+ MUL15(a[18], b[12])
+ MUL15(a[19], b[11]);
t[31] = MUL15(a[12], b[19])
+ MUL15(a[13], b[18])
+ MUL15(a[14], b[17])
+ MUL15(a[15], b[16])
+ MUL15(a[16], b[15])
+ MUL15(a[17], b[14])
+ MUL15(a[18], b[13])
+ MUL15(a[19], b[12]);
t[32] = MUL15(a[13], b[19])
+ MUL15(a[14], b[18])
+ MUL15(a[15], b[17])
+ MUL15(a[16], b[16])
+ MUL15(a[17], b[15])
+ MUL15(a[18], b[14])
+ MUL15(a[19], b[13]);
t[33] = MUL15(a[14], b[19])
+ MUL15(a[15], b[18])
+ MUL15(a[16], b[17])
+ MUL15(a[17], b[16])
+ MUL15(a[18], b[15])
+ MUL15(a[19], b[14]);
t[34] = MUL15(a[15], b[19])
+ MUL15(a[16], b[18])
+ MUL15(a[17], b[17])
+ MUL15(a[18], b[16])
+ MUL15(a[19], b[15]);
t[35] = MUL15(a[16], b[19])
+ MUL15(a[17], b[18])
+ MUL15(a[18], b[17])
+ MUL15(a[19], b[16]);
t[36] = MUL15(a[17], b[19])
+ MUL15(a[18], b[18])
+ MUL15(a[19], b[17]);
t[37] = MUL15(a[18], b[19])
+ MUL15(a[19], b[18]);
t[38] = MUL15(a[19], b[19]);
d[39] = _src_ec_ec_p256_m15_cnorm13(d, t, 39);
}
static void
_src_ec_ec_p256_m15_csquare20(uint32_t *d, const uint32_t *a)
{
uint32_t t[39];
t[ 0] = MUL15(a[ 0], a[ 0]);
t[ 1] = ((MUL15(a[ 0], a[ 1])) << 1);
t[ 2] = MUL15(a[ 1], a[ 1])
+ ((MUL15(a[ 0], a[ 2])) << 1);
t[ 3] = ((MUL15(a[ 0], a[ 3])
+ MUL15(a[ 1], a[ 2])) << 1);
t[ 4] = MUL15(a[ 2], a[ 2])
+ ((MUL15(a[ 0], a[ 4])
+ MUL15(a[ 1], a[ 3])) << 1);
t[ 5] = ((MUL15(a[ 0], a[ 5])
+ MUL15(a[ 1], a[ 4])
+ MUL15(a[ 2], a[ 3])) << 1);
t[ 6] = MUL15(a[ 3], a[ 3])
+ ((MUL15(a[ 0], a[ 6])
+ MUL15(a[ 1], a[ 5])
+ MUL15(a[ 2], a[ 4])) << 1);
t[ 7] = ((MUL15(a[ 0], a[ 7])
+ MUL15(a[ 1], a[ 6])
+ MUL15(a[ 2], a[ 5])
+ MUL15(a[ 3], a[ 4])) << 1);
t[ 8] = MUL15(a[ 4], a[ 4])
+ ((MUL15(a[ 0], a[ 8])
+ MUL15(a[ 1], a[ 7])
+ MUL15(a[ 2], a[ 6])
+ MUL15(a[ 3], a[ 5])) << 1);
t[ 9] = ((MUL15(a[ 0], a[ 9])
+ MUL15(a[ 1], a[ 8])
+ MUL15(a[ 2], a[ 7])
+ MUL15(a[ 3], a[ 6])
+ MUL15(a[ 4], a[ 5])) << 1);
t[10] = MUL15(a[ 5], a[ 5])
+ ((MUL15(a[ 0], a[10])
+ MUL15(a[ 1], a[ 9])
+ MUL15(a[ 2], a[ 8])
+ MUL15(a[ 3], a[ 7])
+ MUL15(a[ 4], a[ 6])) << 1);
t[11] = ((MUL15(a[ 0], a[11])
+ MUL15(a[ 1], a[10])
+ MUL15(a[ 2], a[ 9])
+ MUL15(a[ 3], a[ 8])
+ MUL15(a[ 4], a[ 7])
+ MUL15(a[ 5], a[ 6])) << 1);
t[12] = MUL15(a[ 6], a[ 6])
+ ((MUL15(a[ 0], a[12])
+ MUL15(a[ 1], a[11])
+ MUL15(a[ 2], a[10])
+ MUL15(a[ 3], a[ 9])
+ MUL15(a[ 4], a[ 8])
+ MUL15(a[ 5], a[ 7])) << 1);
t[13] = ((MUL15(a[ 0], a[13])
+ MUL15(a[ 1], a[12])
+ MUL15(a[ 2], a[11])
+ MUL15(a[ 3], a[10])
+ MUL15(a[ 4], a[ 9])
+ MUL15(a[ 5], a[ 8])
+ MUL15(a[ 6], a[ 7])) << 1);
t[14] = MUL15(a[ 7], a[ 7])
+ ((MUL15(a[ 0], a[14])
+ MUL15(a[ 1], a[13])
+ MUL15(a[ 2], a[12])
+ MUL15(a[ 3], a[11])
+ MUL15(a[ 4], a[10])
+ MUL15(a[ 5], a[ 9])
+ MUL15(a[ 6], a[ 8])) << 1);
t[15] = ((MUL15(a[ 0], a[15])
+ MUL15(a[ 1], a[14])
+ MUL15(a[ 2], a[13])
+ MUL15(a[ 3], a[12])
+ MUL15(a[ 4], a[11])
+ MUL15(a[ 5], a[10])
+ MUL15(a[ 6], a[ 9])
+ MUL15(a[ 7], a[ 8])) << 1);
t[16] = MUL15(a[ 8], a[ 8])
+ ((MUL15(a[ 0], a[16])
+ MUL15(a[ 1], a[15])
+ MUL15(a[ 2], a[14])
+ MUL15(a[ 3], a[13])
+ MUL15(a[ 4], a[12])
+ MUL15(a[ 5], a[11])
+ MUL15(a[ 6], a[10])
+ MUL15(a[ 7], a[ 9])) << 1);
t[17] = ((MUL15(a[ 0], a[17])
+ MUL15(a[ 1], a[16])
+ MUL15(a[ 2], a[15])
+ MUL15(a[ 3], a[14])
+ MUL15(a[ 4], a[13])
+ MUL15(a[ 5], a[12])
+ MUL15(a[ 6], a[11])
+ MUL15(a[ 7], a[10])
+ MUL15(a[ 8], a[ 9])) << 1);
t[18] = MUL15(a[ 9], a[ 9])
+ ((MUL15(a[ 0], a[18])
+ MUL15(a[ 1], a[17])
+ MUL15(a[ 2], a[16])
+ MUL15(a[ 3], a[15])
+ MUL15(a[ 4], a[14])
+ MUL15(a[ 5], a[13])
+ MUL15(a[ 6], a[12])
+ MUL15(a[ 7], a[11])
+ MUL15(a[ 8], a[10])) << 1);
t[19] = ((MUL15(a[ 0], a[19])
+ MUL15(a[ 1], a[18])
+ MUL15(a[ 2], a[17])
+ MUL15(a[ 3], a[16])
+ MUL15(a[ 4], a[15])
+ MUL15(a[ 5], a[14])
+ MUL15(a[ 6], a[13])
+ MUL15(a[ 7], a[12])
+ MUL15(a[ 8], a[11])
+ MUL15(a[ 9], a[10])) << 1);
t[20] = MUL15(a[10], a[10])
+ ((MUL15(a[ 1], a[19])
+ MUL15(a[ 2], a[18])
+ MUL15(a[ 3], a[17])
+ MUL15(a[ 4], a[16])
+ MUL15(a[ 5], a[15])
+ MUL15(a[ 6], a[14])
+ MUL15(a[ 7], a[13])
+ MUL15(a[ 8], a[12])
+ MUL15(a[ 9], a[11])) << 1);
t[21] = ((MUL15(a[ 2], a[19])
+ MUL15(a[ 3], a[18])
+ MUL15(a[ 4], a[17])
+ MUL15(a[ 5], a[16])
+ MUL15(a[ 6], a[15])
+ MUL15(a[ 7], a[14])
+ MUL15(a[ 8], a[13])
+ MUL15(a[ 9], a[12])
+ MUL15(a[10], a[11])) << 1);
t[22] = MUL15(a[11], a[11])
+ ((MUL15(a[ 3], a[19])
+ MUL15(a[ 4], a[18])
+ MUL15(a[ 5], a[17])
+ MUL15(a[ 6], a[16])
+ MUL15(a[ 7], a[15])
+ MUL15(a[ 8], a[14])
+ MUL15(a[ 9], a[13])
+ MUL15(a[10], a[12])) << 1);
t[23] = ((MUL15(a[ 4], a[19])
+ MUL15(a[ 5], a[18])
+ MUL15(a[ 6], a[17])
+ MUL15(a[ 7], a[16])
+ MUL15(a[ 8], a[15])
+ MUL15(a[ 9], a[14])
+ MUL15(a[10], a[13])
+ MUL15(a[11], a[12])) << 1);
t[24] = MUL15(a[12], a[12])
+ ((MUL15(a[ 5], a[19])
+ MUL15(a[ 6], a[18])
+ MUL15(a[ 7], a[17])
+ MUL15(a[ 8], a[16])
+ MUL15(a[ 9], a[15])
+ MUL15(a[10], a[14])
+ MUL15(a[11], a[13])) << 1);
t[25] = ((MUL15(a[ 6], a[19])
+ MUL15(a[ 7], a[18])
+ MUL15(a[ 8], a[17])
+ MUL15(a[ 9], a[16])
+ MUL15(a[10], a[15])
+ MUL15(a[11], a[14])
+ MUL15(a[12], a[13])) << 1);
t[26] = MUL15(a[13], a[13])
+ ((MUL15(a[ 7], a[19])
+ MUL15(a[ 8], a[18])
+ MUL15(a[ 9], a[17])
+ MUL15(a[10], a[16])
+ MUL15(a[11], a[15])
+ MUL15(a[12], a[14])) << 1);
t[27] = ((MUL15(a[ 8], a[19])
+ MUL15(a[ 9], a[18])
+ MUL15(a[10], a[17])
+ MUL15(a[11], a[16])
+ MUL15(a[12], a[15])
+ MUL15(a[13], a[14])) << 1);
t[28] = MUL15(a[14], a[14])
+ ((MUL15(a[ 9], a[19])
+ MUL15(a[10], a[18])
+ MUL15(a[11], a[17])
+ MUL15(a[12], a[16])
+ MUL15(a[13], a[15])) << 1);
t[29] = ((MUL15(a[10], a[19])
+ MUL15(a[11], a[18])
+ MUL15(a[12], a[17])
+ MUL15(a[13], a[16])
+ MUL15(a[14], a[15])) << 1);
t[30] = MUL15(a[15], a[15])
+ ((MUL15(a[11], a[19])
+ MUL15(a[12], a[18])
+ MUL15(a[13], a[17])
+ MUL15(a[14], a[16])) << 1);
t[31] = ((MUL15(a[12], a[19])
+ MUL15(a[13], a[18])
+ MUL15(a[14], a[17])
+ MUL15(a[15], a[16])) << 1);
t[32] = MUL15(a[16], a[16])
+ ((MUL15(a[13], a[19])
+ MUL15(a[14], a[18])
+ MUL15(a[15], a[17])) << 1);
t[33] = ((MUL15(a[14], a[19])
+ MUL15(a[15], a[18])
+ MUL15(a[16], a[17])) << 1);
t[34] = MUL15(a[17], a[17])
+ ((MUL15(a[15], a[19])
+ MUL15(a[16], a[18])) << 1);
t[35] = ((MUL15(a[16], a[19])
+ MUL15(a[17], a[18])) << 1);
t[36] = MUL15(a[18], a[18])
+ ((MUL15(a[17], a[19])) << 1);
t[37] = ((MUL15(a[18], a[19])) << 1);
t[38] = MUL15(a[19], a[19]);
d[39] = _src_ec_ec_p256_m15_cnorm13(d, t, 39);
}
#endif
/*
* Modulus for field _src_ec_ec_p256_m15_cF256 (field for point coordinates in curve P-256).
*/
static const uint32_t _src_ec_ec_p256_m15_cF256[] = {
0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x1FFF, 0x001F,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0400, 0x0000,
0x0000, 0x1FF8, 0x1FFF, 0x01FF
};
/*
* The 'b' curve equation coefficient for P-256.
*/
static const uint32_t _src_ec_ec_p256_m15_cP256_B[] = {
0x004B, 0x1E93, 0x0F89, 0x1C78, 0x03BC, 0x187B, 0x114E, 0x1619,
0x1D06, 0x0328, 0x01AF, 0x0D31, 0x1557, 0x15DE, 0x1ECF, 0x127C,
0x0A3A, 0x0EC5, 0x118D, 0x00B5
};
/*
* Perform a "short reduction" in field _src_ec_ec_p256_m15_cF256 (field for curve P-256).
* The source value should be less than 262 bits; on output, it will
* be at most 257 bits, and less than twice the modulus.
*/
static void
reduce_f256(uint32_t *d)
{
uint32_t x;
x = d[19] >> 9;
d[19] &= 0x01FF;
d[17] += x << 3;
d[14] -= x << 10;
d[7] -= x << 5;
d[0] += x;
_src_ec_ec_p256_m15_cnorm13(d, d, 20);
}
/*
* Perform a "final reduction" in field _src_ec_ec_p256_m15_cF256 (field for curve P-256).
* The source value must be less than twice the modulus. If the value
* is not lower than the modulus, then the modulus is subtracted and
* this function returns 1; otherwise, it leaves it untouched and it
* returns 0.
*/
static uint32_t
_src_ec_ec_p256_m15_creduce_final_f256(uint32_t *d)
{
uint32_t t[20];
uint32_t cc;
int i;
memcpy(t, d, sizeof t);
cc = 0;
for (i = 0; i < 20; i ++) {
uint32_t w;
w = t[i] - _src_ec_ec_p256_m15_cF256[i] - cc;
cc = w >> 31;
t[i] = w & 0x1FFF;
}
cc ^= 1;
CCOPY(cc, d, t, sizeof t);
return cc;
}
/*
* Perform a multiplication of two integers modulo
* 2^256-2^224+2^192+2^96-1 (for NIST curve P-256). Operands are arrays
* of 20 words, each containing 13 bits of data, in little-endian order.
* On input, upper word may be up to 13 bits (hence value up to 2^260-1);
* on output, value fits on 257 bits and is lower than twice the modulus.
*/
static void
_src_ec_ec_p256_m15_cmul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[40], cc;
int i;
/*
* Compute raw multiplication. All result words fit in 13 bits
* each.
*/
_src_ec_ec_p256_m15_cmul20(t, a, b);
/*
* Modular reduction: each high word in added/subtracted where
* necessary.
*
* The modulus is:
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1
* Therefore:
* 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
*
* For a word x at bit offset n (n >= 256), we have:
* x*2^n = x*2^(n-32) - x*2^(n-64)
* - x*2^(n - 160) + x*2^(n-256) mod p
*
* Thus, we can nullify the high word if we reinject it at some
* proper emplacements.
*/
for (i = 39; i >= 20; i --) {
uint32_t x;
x = t[i];
t[i - 2] += ARSH(x, 6);
t[i - 3] += (x << 7) & 0x1FFF;
t[i - 4] -= ARSH(x, 12);
t[i - 5] -= (x << 1) & 0x1FFF;
t[i - 12] -= ARSH(x, 4);
t[i - 13] -= (x << 9) & 0x1FFF;
t[i - 19] += ARSH(x, 9);
t[i - 20] += (x << 4) & 0x1FFF;
}
/*
* Propagate carries. This is a signed propagation, and the
* result may be negative. The loop above may enlarge values,
* but not two much: worst case is the chain involving t[i - 3],
* in which a value may be added to itself up to 7 times. Since
* starting values are 13-bit each, all words fit on 20 bits
* (21 to account for the sign bit).
*/
cc = _src_ec_ec_p256_m15_cnorm13(t, t, 20);
/*
* Perform modular reduction again for the bits beyond 256 (the carry
* and the bits 256..259). Since the largest shift below is by 10
* bits, and the values fit on 21 bits, values fit in 32-bit words,
* thereby allowing injecting full word values.
*/
cc = (cc << 4) | (t[19] >> 9);
t[19] &= 0x01FF;
t[17] += cc << 3;
t[14] -= cc << 10;
t[7] -= cc << 5;
t[0] += cc;
/*
* If the carry is negative, then after carry propagation, we may
* end up with a value which is negative, and we don't want that.
* Thus, in that case, we add the modulus. Note that the subtraction
* result, when the carry is negative, is always smaller than the
* modulus, so the extra addition will not make the value exceed
* twice the modulus.
*/
cc >>= 31;
t[0] -= cc;
t[7] += cc << 5;
t[14] += cc << 10;
t[17] -= cc << 3;
t[19] += cc << 9;
_src_ec_ec_p256_m15_cnorm13(d, t, 20);
}
/*
* Square an integer modulo 2^256-2^224+2^192+2^96-1 (for NIST curve
* P-256). Operand is an array of 20 words, each containing 13 bits of
* data, in little-endian order. On input, upper word may be up to 13
* bits (hence value up to 2^260-1); on output, value fits on 257 bits
* and is lower than twice the modulus.
*/
static void
_src_ec_ec_p256_m15_csquare_f256(uint32_t *d, const uint32_t *a)
{
uint32_t t[40], cc;
int i;
/*
* Compute raw square. All result words fit in 13 bits each.
*/
_src_ec_ec_p256_m15_csquare20(t, a);
/*
* Modular reduction: each high word in added/subtracted where
* necessary.
*
* The modulus is:
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1
* Therefore:
* 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
*
* For a word x at bit offset n (n >= 256), we have:
* x*2^n = x*2^(n-32) - x*2^(n-64)
* - x*2^(n - 160) + x*2^(n-256) mod p
*
* Thus, we can nullify the high word if we reinject it at some
* proper emplacements.
*/
for (i = 39; i >= 20; i --) {
uint32_t x;
x = t[i];
t[i - 2] += ARSH(x, 6);
t[i - 3] += (x << 7) & 0x1FFF;
t[i - 4] -= ARSH(x, 12);
t[i - 5] -= (x << 1) & 0x1FFF;
t[i - 12] -= ARSH(x, 4);
t[i - 13] -= (x << 9) & 0x1FFF;
t[i - 19] += ARSH(x, 9);
t[i - 20] += (x << 4) & 0x1FFF;
}
/*
* Propagate carries. This is a signed propagation, and the
* result may be negative. The loop above may enlarge values,
* but not two much: worst case is the chain involving t[i - 3],
* in which a value may be added to itself up to 7 times. Since
* starting values are 13-bit each, all words fit on 20 bits
* (21 to account for the sign bit).
*/
cc = _src_ec_ec_p256_m15_cnorm13(t, t, 20);
/*
* Perform modular reduction again for the bits beyond 256 (the carry
* and the bits 256..259). Since the largest shift below is by 10
* bits, and the values fit on 21 bits, values fit in 32-bit words,
* thereby allowing injecting full word values.
*/
cc = (cc << 4) | (t[19] >> 9);
t[19] &= 0x01FF;
t[17] += cc << 3;
t[14] -= cc << 10;
t[7] -= cc << 5;
t[0] += cc;
/*
* If the carry is negative, then after carry propagation, we may
* end up with a value which is negative, and we don't want that.
* Thus, in that case, we add the modulus. Note that the subtraction
* result, when the carry is negative, is always smaller than the
* modulus, so the extra addition will not make the value exceed
* twice the modulus.
*/
cc >>= 31;
t[0] -= cc;
t[7] += cc << 5;
t[14] += cc << 10;
t[17] -= cc << 3;
t[19] += cc << 9;
_src_ec_ec_p256_m15_cnorm13(d, t, 20);
}
/*
* Jacobian coordinates for a point in P-256: affine coordinates (X,Y)
* are such that:
* X = x / z^2
* Y = y / z^3
* For the point at infinity, z = 0.
* Each point thus admits many possible representations.
*
* Coordinates are represented in arrays of 32-bit integers, each holding
* 13 bits of data. Values may also be slightly greater than the modulus,
* but they will always be lower than twice the modulus.
*/
typedef struct {
uint32_t x[20];
uint32_t y[20];
uint32_t z[20];
} p256__src_ec_ec_p256_m15_cjacobian;
/*
* Convert a point to affine coordinates:
* - If the point is the point at infinity, then all three coordinates
* are set to 0.
* - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y'
* coordinates are the 'X' and 'Y' affine coordinates.
* The coordinates are guaranteed to be lower than the modulus.
*/
static void
_src_ec_ec_p256_m15_cp256_to_affine(p256__src_ec_ec_p256_m15_cjacobian *P)
{
uint32_t t1[20], t2[20];
int i;
/*
* Invert z with a modular exponentiation: the modulus is
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is
* p-2. Exponent bit pattern (from high to low) is:
* - 32 bits of value 1
* - 31 bits of value 0
* - 1 bit of value 1
* - 96 bits of value 0
* - 94 bits of value 1
* - 1 bit of value 0
* - 1 bit of value 1
* Thus, we precompute z^(2^31-1) to speed things up.
*
* If z = 0 (point at infinity) then the modular exponentiation
* will yield 0, which leads to the expected result (all three
* coordinates set to 0).
*/
/*
* A simple square-and-multiply for z^(2^31-1). We could save about
* two dozen multiplications here with an addition chain, but
* this would require a bit more code, and extra stack buffers.
*/
memcpy(t1, P->z, sizeof P->z);
for (i = 0; i < 30; i ++) {
_src_ec_ec_p256_m15_csquare_f256(t1, t1);
_src_ec_ec_p256_m15_cmul_f256(t1, t1, P->z);
}
/*
* Square-and-multiply. Apart from the squarings, we have a few
* multiplications to set bits to 1; we multiply by the original z
* for setting 1 bit, and by t1 for setting 31 bits.
*/
memcpy(t2, P->z, sizeof P->z);
for (i = 1; i < 256; i ++) {
_src_ec_ec_p256_m15_csquare_f256(t2, t2);
switch (i) {
case 31:
case 190:
case 221:
case 252:
_src_ec_ec_p256_m15_cmul_f256(t2, t2, t1);
break;
case 63:
case 253:
case 255:
_src_ec_ec_p256_m15_cmul_f256(t2, t2, P->z);
break;
}
}
/*
* Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3.
*/
_src_ec_ec_p256_m15_cmul_f256(t1, t2, t2);
_src_ec_ec_p256_m15_cmul_f256(P->x, t1, P->x);
_src_ec_ec_p256_m15_cmul_f256(t1, t1, t2);
_src_ec_ec_p256_m15_cmul_f256(P->y, t1, P->y);
_src_ec_ec_p256_m15_creduce_final_f256(P->x);
_src_ec_ec_p256_m15_creduce_final_f256(P->y);
/*
* Multiply z by 1/z. If z = 0, then this will yield 0, otherwise
* this will set z to 1.
*/
_src_ec_ec_p256_m15_cmul_f256(P->z, P->z, t2);
_src_ec_ec_p256_m15_creduce_final_f256(P->z);
}
/*
* Double a point in P-256. This function works for all valid points,
* including the point at infinity.
*/
static void
_src_ec_ec_p256_m15_cp256_double(p256__src_ec_ec_p256_m15_cjacobian *Q)
{
/*
* Doubling formulas are:
*
* s = 4*x*y^2
* m = 3*(x + z^2)*(x - z^2)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y^4
* z' = 2*y*z
*
* These formulas work for all points, including points of order 2
* and points at infinity:
* - If y = 0 then z' = 0. But there is no such point in P-256
* anyway.
* - If z = 0 then z' = 0.
*/
uint32_t t1[20], t2[20], t3[20], t4[20];
int i;
/*
* Compute z^2 in t1.
*/
_src_ec_ec_p256_m15_csquare_f256(t1, Q->z);
/*
* Compute x-z^2 in t2 and x+z^2 in t1.
*/
for (i = 0; i < 20; i ++) {
t2[i] = (_src_ec_ec_p256_m15_cF256[i] << 1) + Q->x[i] - t1[i];
t1[i] += Q->x[i];
}
_src_ec_ec_p256_m15_cnorm13(t1, t1, 20);
_src_ec_ec_p256_m15_cnorm13(t2, t2, 20);
/*
* Compute 3*(x+z^2)*(x-z^2) in t1.
*/
_src_ec_ec_p256_m15_cmul_f256(t3, t1, t2);
for (i = 0; i < 20; i ++) {
t1[i] = MUL15(3, t3[i]);
}
_src_ec_ec_p256_m15_cnorm13(t1, t1, 20);
/*
* Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
*/
_src_ec_ec_p256_m15_csquare_f256(t3, Q->y);
for (i = 0; i < 20; i ++) {
t3[i] <<= 1;
}
_src_ec_ec_p256_m15_cnorm13(t3, t3, 20);
_src_ec_ec_p256_m15_cmul_f256(t2, Q->x, t3);
for (i = 0; i < 20; i ++) {
t2[i] <<= 1;
}
_src_ec_ec_p256_m15_cnorm13(t2, t2, 20);
reduce_f256(t2);
/*
* Compute x' = m^2 - 2*s.
*/
_src_ec_ec_p256_m15_csquare_f256(Q->x, t1);
for (i = 0; i < 20; i ++) {
Q->x[i] += (_src_ec_ec_p256_m15_cF256[i] << 2) - (t2[i] << 1);
}
_src_ec_ec_p256_m15_cnorm13(Q->x, Q->x, 20);
reduce_f256(Q->x);
/*
* Compute z' = 2*y*z.
*/
_src_ec_ec_p256_m15_cmul_f256(t4, Q->y, Q->z);
for (i = 0; i < 20; i ++) {
Q->z[i] = t4[i] << 1;
}
_src_ec_ec_p256_m15_cnorm13(Q->z, Q->z, 20);
reduce_f256(Q->z);
/*
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
* 2*y^2 in t3.
*/
for (i = 0; i < 20; i ++) {
t2[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - Q->x[i];
}
_src_ec_ec_p256_m15_cnorm13(t2, t2, 20);
_src_ec_ec_p256_m15_cmul_f256(Q->y, t1, t2);
_src_ec_ec_p256_m15_csquare_f256(t4, t3);
for (i = 0; i < 20; i ++) {
Q->y[i] += (_src_ec_ec_p256_m15_cF256[i] << 2) - (t4[i] << 1);
}
_src_ec_ec_p256_m15_cnorm13(Q->y, Q->y, 20);
reduce_f256(Q->y);
}
/*
* Add point P2 to point P1.
*
* This function computes the wrong result in the following cases:
*
* - If P1 == 0 but P2 != 0
* - If P1 != 0 but P2 == 0
* - If P1 == P2
*
* In all three cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y coordinate
* - P1 == 0 and P2 == 0
* - The Y coordinate of one of the points is 0 and the other point is
* the point at infinity.
*
* The third case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*/
static uint32_t
_src_ec_ec_p256_m15_cp256_add(p256__src_ec_ec_p256_m15_cjacobian *P1, const p256__src_ec_ec_p256_m15_cjacobian *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1 * z2^2
* u2 = x2 * z1^2
* s1 = y1 * z2^3
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1 * z2
*/
uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20];
uint32_t ret;
int i;
/*
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
*/
_src_ec_ec_p256_m15_csquare_f256(t3, P2->z);
_src_ec_ec_p256_m15_cmul_f256(t1, P1->x, t3);
_src_ec_ec_p256_m15_cmul_f256(t4, P2->z, t3);
_src_ec_ec_p256_m15_cmul_f256(t3, P1->y, t4);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m15_csquare_f256(t4, P1->z);
_src_ec_ec_p256_m15_cmul_f256(t2, P2->x, t4);
_src_ec_ec_p256_m15_cmul_f256(t5, P1->z, t4);
_src_ec_ec_p256_m15_cmul_f256(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
for (i = 0; i < 20; i ++) {
t2[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - t1[i];
t4[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - t3[i];
}
_src_ec_ec_p256_m15_cnorm13(t2, t2, 20);
_src_ec_ec_p256_m15_cnorm13(t4, t4, 20);
reduce_f256(t4);
_src_ec_ec_p256_m15_creduce_final_f256(t4);
ret = 0;
for (i = 0; i < 20; i ++) {
ret |= t4[i];
}
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m15_csquare_f256(t7, t2);
_src_ec_ec_p256_m15_cmul_f256(t6, t1, t7);
_src_ec_ec_p256_m15_cmul_f256(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m15_csquare_f256(P1->x, t4);
for (i = 0; i < 20; i ++) {
P1->x[i] += (_src_ec_ec_p256_m15_cF256[i] << 3) - t5[i] - (t6[i] << 1);
}
_src_ec_ec_p256_m15_cnorm13(P1->x, P1->x, 20);
reduce_f256(P1->x);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
for (i = 0; i < 20; i ++) {
t6[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - P1->x[i];
}
_src_ec_ec_p256_m15_cnorm13(t6, t6, 20);
_src_ec_ec_p256_m15_cmul_f256(P1->y, t4, t6);
_src_ec_ec_p256_m15_cmul_f256(t1, t5, t3);
for (i = 0; i < 20; i ++) {
P1->y[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - t1[i];
}
_src_ec_ec_p256_m15_cnorm13(P1->y, P1->y, 20);
reduce_f256(P1->y);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m15_cmul_f256(t1, P1->z, P2->z);
_src_ec_ec_p256_m15_cmul_f256(P1->z, t1, t2);
return ret;
}
/*
* Add point P2 to point P1. This is a specialised function for the
* case when P2 is a non-zero point in affine coordinate.
*
* This function computes the wrong result in the following cases:
*
* - If P1 == 0
* - If P1 == P2
*
* In both cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y coordinate
* - The Y coordinate of P2 is 0 and P1 is the point at infinity.
*
* The second case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*/
static uint32_t
_src_ec_ec_p256_m15_c_src_ec_ec_p256_m15_cp256_add_mixed(p256__src_ec_ec_p256_m15_cjacobian *P1, const p256__src_ec_ec_p256_m15_cjacobian *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1
* u2 = x2 * z1^2
* s1 = y1
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1
*/
uint32_t t1[20], t2[20], t3[20], t4[20], t5[20], t6[20], t7[20];
uint32_t ret;
int i;
/*
* Compute u1 = x1 (in t1) and s1 = y1 (in t3).
*/
memcpy(t1, P1->x, sizeof t1);
memcpy(t3, P1->y, sizeof t3);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m15_csquare_f256(t4, P1->z);
_src_ec_ec_p256_m15_cmul_f256(t2, P2->x, t4);
_src_ec_ec_p256_m15_cmul_f256(t5, P1->z, t4);
_src_ec_ec_p256_m15_cmul_f256(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
for (i = 0; i < 20; i ++) {
t2[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - t1[i];
t4[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - t3[i];
}
_src_ec_ec_p256_m15_cnorm13(t2, t2, 20);
_src_ec_ec_p256_m15_cnorm13(t4, t4, 20);
reduce_f256(t4);
_src_ec_ec_p256_m15_creduce_final_f256(t4);
ret = 0;
for (i = 0; i < 20; i ++) {
ret |= t4[i];
}
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m15_csquare_f256(t7, t2);
_src_ec_ec_p256_m15_cmul_f256(t6, t1, t7);
_src_ec_ec_p256_m15_cmul_f256(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m15_csquare_f256(P1->x, t4);
for (i = 0; i < 20; i ++) {
P1->x[i] += (_src_ec_ec_p256_m15_cF256[i] << 3) - t5[i] - (t6[i] << 1);
}
_src_ec_ec_p256_m15_cnorm13(P1->x, P1->x, 20);
reduce_f256(P1->x);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
for (i = 0; i < 20; i ++) {
t6[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - P1->x[i];
}
_src_ec_ec_p256_m15_cnorm13(t6, t6, 20);
_src_ec_ec_p256_m15_cmul_f256(P1->y, t4, t6);
_src_ec_ec_p256_m15_cmul_f256(t1, t5, t3);
for (i = 0; i < 20; i ++) {
P1->y[i] += (_src_ec_ec_p256_m15_cF256[i] << 1) - t1[i];
}
_src_ec_ec_p256_m15_cnorm13(P1->y, P1->y, 20);
reduce_f256(P1->y);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m15_cmul_f256(P1->z, P1->z, t2);
return ret;
}
/*
* Decode a P-256 point. This function does not support the point at
* infinity. Returned value is 0 if the point is invalid, 1 otherwise.
*/
static uint32_t
_src_ec_ec_p256_m15_cp256_decode(p256__src_ec_ec_p256_m15_cjacobian *P, const void *src, size_t len)
{
const unsigned char *buf;
uint32_t tx[20], ty[20], t1[20], t2[20];
uint32_t bad;
int i;
if (len != 65) {
return 0;
}
buf = (const unsigned char*)src;
/*
* First byte must be 0x04 (uncompressed format). We could support
* "hybrid format" (first byte is 0x06 or 0x07, and encodes the
* least significant bit of the Y coordinate), but it is explicitly
* forbidden by RFC 5480 (section 2.2).
*/
bad = NEQ(buf[0], 0x04);
/*
* Decode the coordinates, and check that they are both lower
* than the modulus.
*/
tx[19] = be8_to_le13(tx, buf + 1, 32);
ty[19] = be8_to_le13(ty, buf + 33, 32);
bad |= _src_ec_ec_p256_m15_creduce_final_f256(tx);
bad |= _src_ec_ec_p256_m15_creduce_final_f256(ty);
/*
* Check curve equation.
*/
_src_ec_ec_p256_m15_csquare_f256(t1, tx);
_src_ec_ec_p256_m15_cmul_f256(t1, tx, t1);
_src_ec_ec_p256_m15_csquare_f256(t2, ty);
for (i = 0; i < 20; i ++) {
t1[i] += (_src_ec_ec_p256_m15_cF256[i] << 3) - MUL15(3, tx[i]) + _src_ec_ec_p256_m15_cP256_B[i] - t2[i];
}
_src_ec_ec_p256_m15_cnorm13(t1, t1, 20);
reduce_f256(t1);
_src_ec_ec_p256_m15_creduce_final_f256(t1);
for (i = 0; i < 20; i ++) {
bad |= t1[i];
}
/*
* Copy coordinates to the point structure.
*/
memcpy(P->x, tx, sizeof tx);
memcpy(P->y, ty, sizeof ty);
memset(P->z, 0, sizeof P->z);
P->z[0] = 1;
return EQ(bad, 0);
}
/*
* Encode a point into a buffer. This function assumes that the point is
* valid, in affine coordinates, and not the point at infinity.
*/
static void
_src_ec_ec_p256_m15_cp256_encode(void *dst, const p256__src_ec_ec_p256_m15_cjacobian *P)
{
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = 0x04;
le13_to_be8(buf + 1, 32, P->x);
le13_to_be8(buf + 33, 32, P->y);
}
/*
* Multiply a curve point by an integer. The integer is assumed to be
* lower than the curve order, and the base point must not be the point
* at infinity.
*/
static void
_src_ec_ec_p256_m15_cp256_mul(p256__src_ec_ec_p256_m15_cjacobian *P, const unsigned char *x, size_t xlen)
{
/*
* qz is a flag that is initially 1, and remains equal to 1
* as long as the point is the point at infinity.
*
* We use a 2-bit window to handle multiplier bits by pairs.
* The precomputed window really is the points P2 and P3.
*/
uint32_t qz;
p256__src_ec_ec_p256_m15_cjacobian P2, P3, Q, T, U;
/*
* Compute window values.
*/
P2 = *P;
_src_ec_ec_p256_m15_cp256_double(&P2);
P3 = *P;
_src_ec_ec_p256_m15_cp256_add(&P3, &P2);
/*
* We start with Q = 0. We process multiplier bits 2 by 2.
*/
memset(&Q, 0, sizeof Q);
qz = 1;
while (xlen -- > 0) {
int k;
for (k = 6; k >= 0; k -= 2) {
uint32_t bits;
uint32_t bnz;
_src_ec_ec_p256_m15_cp256_double(&Q);
_src_ec_ec_p256_m15_cp256_double(&Q);
T = *P;
U = Q;
bits = (*x >> k) & (uint32_t)3;
bnz = NEQ(bits, 0);
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
_src_ec_ec_p256_m15_cp256_add(&U, &T);
CCOPY(bnz & qz, &Q, &T, sizeof Q);
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
}
x ++;
}
*P = Q;
}
/*
* Precomputed window: k*G points, where G is the curve generator, and k
* is an integer from 1 to 15 (inclusive). The X and Y coordinates of
* the point are encoded as 20 words of 13 bits each (little-endian
* order); 13-bit words are then grouped 2-by-2 into 32-bit words
* (little-endian order within each word).
*/
static const uint32_t _src_ec_ec_p256_m15_cGwin[15][20] = {
{ 0x04C60296, 0x02721176, 0x19D00F4A, 0x102517AC,
0x13B8037D, 0x0748103C, 0x1E730E56, 0x08481FE2,
0x0F97012C, 0x00D605F4, 0x1DFA11F5, 0x0C801A0D,
0x0F670CBB, 0x0AED0CC5, 0x115E0E33, 0x181F0785,
0x13F514A7, 0x0FF30E3B, 0x17171E1A, 0x009F18D0 },
{ 0x1B341978, 0x16911F11, 0x0D9A1A60, 0x1C4E1FC8,
0x1E040969, 0x096A06B0, 0x091C0030, 0x09EF1A29,
0x18C40D03, 0x00F91C9E, 0x13C313D1, 0x096F0748,
0x011419E0, 0x1CC713A6, 0x1DD31DAD, 0x1EE80C36,
0x1ECD0C69, 0x1A0800A4, 0x08861B8E, 0x000E1DD5 },
{ 0x173F1D6C, 0x02CC06F1, 0x14C21FB4, 0x043D1EB6,
0x0F3606B7, 0x1A971C59, 0x1BF71951, 0x01481323,
0x068D0633, 0x00BD12F9, 0x13EA1032, 0x136209E8,
0x1C1E19A7, 0x06C7013E, 0x06C10AB0, 0x14C908BB,
0x05830CE1, 0x1FEF18DD, 0x00620998, 0x010E0D19 },
{ 0x18180852, 0x0604111A, 0x0B771509, 0x1B6F0156,
0x00181FE2, 0x1DCC0AF4, 0x16EF0659, 0x11F70E80,
0x11A912D0, 0x01C414D2, 0x027618C6, 0x05840FC6,
0x100215C4, 0x187E0C3B, 0x12771C96, 0x150C0B5D,
0x0FF705FD, 0x07981C67, 0x1AD20C63, 0x01C11C55 },
{ 0x1E8113ED, 0x0A940370, 0x12920215, 0x1FA31D6F,
0x1F7C0C82, 0x10CD03F7, 0x02640560, 0x081A0B5E,
0x1BD21151, 0x00A21642, 0x0D0B0DA4, 0x0176113F,
0x04440D1D, 0x001A1360, 0x1068012F, 0x1F141E49,
0x10DF136B, 0x0E4F162B, 0x0D44104A, 0x01C1105F },
{ 0x011411A9, 0x01551A4F, 0x0ADA0C6B, 0x01BD0EC8,
0x18120C74, 0x112F1778, 0x099202CB, 0x0C05124B,
0x195316A4, 0x01600685, 0x1E3B1FE2, 0x189014E3,
0x0B5E1FD7, 0x0E0311F8, 0x08E000F7, 0x174E00DE,
0x160702DF, 0x1B5A15BF, 0x03A11237, 0x01D01704 },
{ 0x0C3D12A3, 0x0C501C0C, 0x17AD1300, 0x1715003F,
0x03F719F8, 0x18031ED8, 0x1D980667, 0x0F681896,
0x1B7D00BF, 0x011C14CE, 0x0FA000B4, 0x1C3501B0,
0x0D901C55, 0x06790C10, 0x029E0736, 0x0DEB0400,
0x034F183A, 0x030619B4, 0x0DEF0033, 0x00E71AC7 },
{ 0x1B7D1393, 0x1B3B1076, 0x0BED1B4D, 0x13011F3A,
0x0E0E1238, 0x156A132B, 0x013A02D3, 0x160A0D01,
0x1CED1EE9, 0x00C5165D, 0x184C157E, 0x08141A83,
0x153C0DA5, 0x1ED70F9D, 0x05170D51, 0x02CF13B8,
0x18AE1771, 0x1B04113F, 0x05EC11E9, 0x015A16B3 },
{ 0x04A41EE0, 0x1D1412E4, 0x1C591D79, 0x118511B7,
0x14F00ACB, 0x1AE31E1C, 0x049C0D51, 0x016E061E,
0x1DB71EDF, 0x01D41A35, 0x0E8208FA, 0x14441293,
0x011F1E85, 0x1D54137A, 0x026B114F, 0x151D0832,
0x00A50964, 0x1F9C1E1C, 0x064B12C9, 0x005409D1 },
{ 0x062B123F, 0x0C0D0501, 0x183704C3, 0x08E31120,
0x0A2E0A6C, 0x14440FED, 0x090A0D1E, 0x13271964,
0x0B590A3A, 0x019D1D9B, 0x05780773, 0x09770A91,
0x0F770CA3, 0x053F19D4, 0x02C80DED, 0x1A761304,
0x091E0DD9, 0x15D201B8, 0x151109AA, 0x010F0198 },
{ 0x05E101D1, 0x072314DD, 0x045F1433, 0x1A041541,
0x10B3142E, 0x01840736, 0x1C1B19DB, 0x098B0418,
0x1DBC083B, 0x007D1444, 0x01511740, 0x11DD1F3A,
0x04ED0E2F, 0x1B4B1A62, 0x10480D04, 0x09E911A2,
0x04211AFA, 0x19140893, 0x04D60CC4, 0x01210648 },
{ 0x112703C4, 0x018B1BA1, 0x164C1D50, 0x05160BE0,
0x0BCC1830, 0x01CB1554, 0x13291732, 0x1B2B1918,
0x0DED0817, 0x00E80775, 0x0A2401D3, 0x0BFE08B3,
0x0E531199, 0x058616E9, 0x04770B91, 0x110F0C55,
0x19C11554, 0x0BFB1159, 0x03541C38, 0x000E1C2D },
{ 0x10390C01, 0x02BB0751, 0x0AC5098E, 0x096C17AB,
0x03C90E28, 0x10BD18BF, 0x002E1F2D, 0x092B0986,
0x1BD700AC, 0x002E1F20, 0x1E3D1FD8, 0x077718BB,
0x06F919C4, 0x187407ED, 0x11370E14, 0x081E139C,
0x00481ADB, 0x14AB0289, 0x066A0EBE, 0x00C70ED6 },
{ 0x0694120B, 0x124E1CC9, 0x0E2F0570, 0x17CF081A,
0x078906AC, 0x066D17CF, 0x1B3207F4, 0x0C5705E9,
0x10001C38, 0x00A919DE, 0x06851375, 0x0F900BD8,
0x080401BA, 0x0EEE0D42, 0x1B8B11EA, 0x0B4519F0,
0x090F18C0, 0x062E1508, 0x0DD909F4, 0x01EB067C },
{ 0x0CDC1D5F, 0x0D1818F9, 0x07781636, 0x125B18E8,
0x0D7003AF, 0x13110099, 0x1D9B1899, 0x175C1EB7,
0x0E34171A, 0x01E01153, 0x081A0F36, 0x0B391783,
0x1D1F147E, 0x19CE16D7, 0x11511B21, 0x1F2C10F9,
0x12CA0E51, 0x05A31D39, 0x171A192E, 0x016B0E4F }
};
/*
* Lookup one of the _src_ec_ec_p256_m15_cGwin[] values, by index. This is constant-time.
*/
static void
_src_ec_ec_p256_m15_clookup__src_ec_ec_p256_m15_cGwin(p256__src_ec_ec_p256_m15_cjacobian *T, uint32_t idx)
{
uint32_t xy[20];
uint32_t k;
size_t u;
memset(xy, 0, sizeof xy);
for (k = 0; k < 15; k ++) {
uint32_t m;
m = -EQ(idx, k + 1);
for (u = 0; u < 20; u ++) {
xy[u] |= m & _src_ec_ec_p256_m15_cGwin[k][u];
}
}
for (u = 0; u < 10; u ++) {
T->x[(u << 1) + 0] = xy[u] & 0xFFFF;
T->x[(u << 1) + 1] = xy[u] >> 16;
T->y[(u << 1) + 0] = xy[u + 10] & 0xFFFF;
T->y[(u << 1) + 1] = xy[u + 10] >> 16;
}
memset(T->z, 0, sizeof T->z);
T->z[0] = 1;
}
/*
* Multiply the generator by an integer. The integer is assumed non-zero
* and lower than the curve order.
*/
static void
_src_ec_ec_p256_m15_c_src_ec_ec_p256_m15_cp256_mulgen(p256__src_ec_ec_p256_m15_cjacobian *P, const unsigned char *x, size_t xlen)
{
/*
* qz is a flag that is initially 1, and remains equal to 1
* as long as the point is the point at infinity.
*
* We use a 4-bit window to handle multiplier bits by groups
* of 4. The precomputed window is constant static data, with
* points in affine coordinates; we use a constant-time lookup.
*/
p256__src_ec_ec_p256_m15_cjacobian Q;
uint32_t qz;
memset(&Q, 0, sizeof Q);
qz = 1;
while (xlen -- > 0) {
int k;
unsigned bx;
bx = *x ++;
for (k = 0; k < 2; k ++) {
uint32_t bits;
uint32_t bnz;
p256__src_ec_ec_p256_m15_cjacobian T, U;
_src_ec_ec_p256_m15_cp256_double(&Q);
_src_ec_ec_p256_m15_cp256_double(&Q);
_src_ec_ec_p256_m15_cp256_double(&Q);
_src_ec_ec_p256_m15_cp256_double(&Q);
bits = (bx >> 4) & 0x0F;
bnz = NEQ(bits, 0);
_src_ec_ec_p256_m15_clookup__src_ec_ec_p256_m15_cGwin(&T, bits);
U = Q;
_src_ec_ec_p256_m15_c_src_ec_ec_p256_m15_cp256_add_mixed(&U, &T);
CCOPY(bnz & qz, &Q, &T, sizeof Q);
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
bx <<= 4;
}
}
*P = Q;
}
static const unsigned char _src_ec_ec_p256_m15_cP256_G[] = {
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
0x68, 0x37, 0xBF, 0x51, 0xF5
};
static const unsigned char _src_ec_ec_p256_m15_cP256_N[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
0x25, 0x51
};
static const unsigned char *
_src_ec_ec_p256_m15_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m15_cP256_G;
return _src_ec_ec_p256_m15_cP256_G;
}
static const unsigned char *
_src_ec_ec_p256_m15_capi_order(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m15_cP256_N;
return _src_ec_ec_p256_m15_cP256_N;
}
static size_t
_src_ec_ec_p256_m15_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 1;
}
static uint32_t
_src_ec_ec_p256_m15_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *x, size_t xlen, int curve)
{
uint32_t r;
p256__src_ec_ec_p256_m15_cjacobian P;
(void)curve;
if (Glen != 65) {
return 0;
}
r = _src_ec_ec_p256_m15_cp256_decode(&P, G, Glen);
_src_ec_ec_p256_m15_cp256_mul(&P, x, xlen);
_src_ec_ec_p256_m15_cp256_to_affine(&P);
_src_ec_ec_p256_m15_cp256_encode(G, &P);
return r;
}
static size_t
_src_ec_ec_p256_m15_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
p256__src_ec_ec_p256_m15_cjacobian P;
(void)curve;
_src_ec_ec_p256_m15_c_src_ec_ec_p256_m15_cp256_mulgen(&P, x, xlen);
_src_ec_ec_p256_m15_cp256_to_affine(&P);
_src_ec_ec_p256_m15_cp256_encode(R, &P);
return 65;
}
static uint32_t
_src_ec_ec_p256_m15_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
p256__src_ec_ec_p256_m15_cjacobian P, Q;
uint32_t r, t, z;
int i;
(void)curve;
if (len != 65) {
return 0;
}
r = _src_ec_ec_p256_m15_cp256_decode(&P, A, len);
_src_ec_ec_p256_m15_cp256_mul(&P, x, xlen);
if (B == NULL) {
_src_ec_ec_p256_m15_c_src_ec_ec_p256_m15_cp256_mulgen(&Q, y, ylen);
} else {
r &= _src_ec_ec_p256_m15_cp256_decode(&Q, B, len);
_src_ec_ec_p256_m15_cp256_mul(&Q, y, ylen);
}
/*
* The final addition may fail in case both points are equal.
*/
t = _src_ec_ec_p256_m15_cp256_add(&P, &Q);
_src_ec_ec_p256_m15_creduce_final_f256(P.z);
z = 0;
for (i = 0; i < 20; i ++) {
z |= P.z[i];
}
z = EQ(z, 0);
_src_ec_ec_p256_m15_cp256_double(&Q);
/*
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
* have the following:
*
* z = 0, t = 0 return P (normal addition)
* z = 0, t = 1 return P (normal addition)
* z = 1, t = 0 return Q (a 'double' case)
* z = 1, t = 1 report an error (P+Q = 0)
*/
CCOPY(z & ~t, &P, &Q, sizeof Q);
_src_ec_ec_p256_m15_cp256_to_affine(&P);
_src_ec_ec_p256_m15_cp256_encode(A, &P);
r &= ~(z & t);
return r;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_p256_m15 = {
(uint32_t)0x00800000,
&_src_ec_ec_p256_m15_capi_generator,
&_src_ec_ec_p256_m15_capi_order,
&_src_ec_ec_p256_m15_capi_xoff,
&_src_ec_ec_p256_m15_capi_mul,
&_src_ec_ec_p256_m15_capi_mulgen,
&_src_ec_ec_p256_m15_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* If BR_NO_ARITH_SHIFT is undefined, or defined to 0, then we _assume_
* that right-shifting a signed negative integer copies the sign bit
* (arithmetic right-shift). This is "implementation-defined behaviour",
* i.e. it is not undefined, but it may differ between compilers. Each
* compiler is supposed to document its behaviour in that respect. GCC
* explicitly defines that an arithmetic right shift is used. We expect
* all other compilers to do the same, because underlying CPU offer an
* arithmetic right shift opcode that could not be used otherwise.
*/
#if BR_NO_ARITH_SHIFT
#define ARSH(x, n) (((uint32_t)(x) >> (n)) \
| ((-((uint32_t)(x) >> 31)) << (32 - (n))))
#define ARSHW(x, n) (((uint64_t)(x) >> (n)) \
| ((-((uint64_t)(x) >> 63)) << (64 - (n))))
#else
#define ARSH(x, n) ((*(int32_t *)&(x)) >> (n))
#define ARSHW(x, n) ((*(int64_t *)&(x)) >> (n))
#endif
/*
* Convert an integer from unsigned big-endian encoding to a sequence of
* 30-bit words in little-endian order. The final "partial" word is
* returned.
*/
static uint32_t
be8_to_le30(uint32_t *dst, const unsigned char *src, size_t len)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
uint32_t b;
b = src[len];
if (acc_len < 22) {
acc |= b << acc_len;
acc_len += 8;
} else {
*dst ++ = (acc | (b << acc_len)) & 0x3FFFFFFF;
acc = b >> (30 - acc_len);
acc_len -= 22;
}
}
return acc;
}
/*
* Convert an integer (30-bit words, little-endian) to unsigned
* big-endian encoding. The total encoding length is provided; all
* the destination bytes will be filled.
*/
static void
le30_to_be8(unsigned char *dst, size_t len, const uint32_t *src)
{
uint32_t acc;
int acc_len;
acc = 0;
acc_len = 0;
while (len -- > 0) {
if (acc_len < 8) {
uint32_t w;
w = *src ++;
dst[len] = (unsigned char)(acc | (w << acc_len));
acc = w >> (8 - acc_len);
acc_len += 22;
} else {
dst[len] = (unsigned char)acc;
acc >>= 8;
acc_len -= 8;
}
}
}
/*
* Multiply two integers. Source integers are represented as arrays of
* nine 30-bit words, for values up to 2^270-1. Result is encoded over
* 18 words of 30 bits each.
*/
static void
_src_ec_ec_p256_m31_cmul9(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
/*
* Maximum intermediate result is no more than
* 10376293531797946367, which fits in 64 bits. Reason:
*
* 10376293531797946367 = 9 * (2^30-1)^2 + 9663676406
* 10376293531797946367 < 9663676407 * 2^30
*
* Thus, adding together 9 products of 30-bit integers, with
* a carry of at most 9663676406, yields an integer that fits
* on 64 bits and generates a carry of at most 9663676406.
*/
uint64_t t[17];
uint64_t cc;
int i;
t[ 0] = MUL31(a[0], b[0]);
t[ 1] = MUL31(a[0], b[1])
+ MUL31(a[1], b[0]);
t[ 2] = MUL31(a[0], b[2])
+ MUL31(a[1], b[1])
+ MUL31(a[2], b[0]);
t[ 3] = MUL31(a[0], b[3])
+ MUL31(a[1], b[2])
+ MUL31(a[2], b[1])
+ MUL31(a[3], b[0]);
t[ 4] = MUL31(a[0], b[4])
+ MUL31(a[1], b[3])
+ MUL31(a[2], b[2])
+ MUL31(a[3], b[1])
+ MUL31(a[4], b[0]);
t[ 5] = MUL31(a[0], b[5])
+ MUL31(a[1], b[4])
+ MUL31(a[2], b[3])
+ MUL31(a[3], b[2])
+ MUL31(a[4], b[1])
+ MUL31(a[5], b[0]);
t[ 6] = MUL31(a[0], b[6])
+ MUL31(a[1], b[5])
+ MUL31(a[2], b[4])
+ MUL31(a[3], b[3])
+ MUL31(a[4], b[2])
+ MUL31(a[5], b[1])
+ MUL31(a[6], b[0]);
t[ 7] = MUL31(a[0], b[7])
+ MUL31(a[1], b[6])
+ MUL31(a[2], b[5])
+ MUL31(a[3], b[4])
+ MUL31(a[4], b[3])
+ MUL31(a[5], b[2])
+ MUL31(a[6], b[1])
+ MUL31(a[7], b[0]);
t[ 8] = MUL31(a[0], b[8])
+ MUL31(a[1], b[7])
+ MUL31(a[2], b[6])
+ MUL31(a[3], b[5])
+ MUL31(a[4], b[4])
+ MUL31(a[5], b[3])
+ MUL31(a[6], b[2])
+ MUL31(a[7], b[1])
+ MUL31(a[8], b[0]);
t[ 9] = MUL31(a[1], b[8])
+ MUL31(a[2], b[7])
+ MUL31(a[3], b[6])
+ MUL31(a[4], b[5])
+ MUL31(a[5], b[4])
+ MUL31(a[6], b[3])
+ MUL31(a[7], b[2])
+ MUL31(a[8], b[1]);
t[10] = MUL31(a[2], b[8])
+ MUL31(a[3], b[7])
+ MUL31(a[4], b[6])
+ MUL31(a[5], b[5])
+ MUL31(a[6], b[4])
+ MUL31(a[7], b[3])
+ MUL31(a[8], b[2]);
t[11] = MUL31(a[3], b[8])
+ MUL31(a[4], b[7])
+ MUL31(a[5], b[6])
+ MUL31(a[6], b[5])
+ MUL31(a[7], b[4])
+ MUL31(a[8], b[3]);
t[12] = MUL31(a[4], b[8])
+ MUL31(a[5], b[7])
+ MUL31(a[6], b[6])
+ MUL31(a[7], b[5])
+ MUL31(a[8], b[4]);
t[13] = MUL31(a[5], b[8])
+ MUL31(a[6], b[7])
+ MUL31(a[7], b[6])
+ MUL31(a[8], b[5]);
t[14] = MUL31(a[6], b[8])
+ MUL31(a[7], b[7])
+ MUL31(a[8], b[6]);
t[15] = MUL31(a[7], b[8])
+ MUL31(a[8], b[7]);
t[16] = MUL31(a[8], b[8]);
/*
* Propagate carries.
*/
cc = 0;
for (i = 0; i < 17; i ++) {
uint64_t w;
w = t[i] + cc;
d[i] = (uint32_t)w & 0x3FFFFFFF;
cc = w >> 30;
}
d[17] = (uint32_t)cc;
}
/*
* Square a 270-bit integer, represented as an array of nine 30-bit words.
* Result uses 18 words of 30 bits each.
*/
static void
_src_ec_ec_p256_m31_csquare9(uint32_t *d, const uint32_t *a)
{
uint64_t t[17];
uint64_t cc;
int i;
t[ 0] = MUL31(a[0], a[0]);
t[ 1] = ((MUL31(a[0], a[1])) << 1);
t[ 2] = MUL31(a[1], a[1])
+ ((MUL31(a[0], a[2])) << 1);
t[ 3] = ((MUL31(a[0], a[3])
+ MUL31(a[1], a[2])) << 1);
t[ 4] = MUL31(a[2], a[2])
+ ((MUL31(a[0], a[4])
+ MUL31(a[1], a[3])) << 1);
t[ 5] = ((MUL31(a[0], a[5])
+ MUL31(a[1], a[4])
+ MUL31(a[2], a[3])) << 1);
t[ 6] = MUL31(a[3], a[3])
+ ((MUL31(a[0], a[6])
+ MUL31(a[1], a[5])
+ MUL31(a[2], a[4])) << 1);
t[ 7] = ((MUL31(a[0], a[7])
+ MUL31(a[1], a[6])
+ MUL31(a[2], a[5])
+ MUL31(a[3], a[4])) << 1);
t[ 8] = MUL31(a[4], a[4])
+ ((MUL31(a[0], a[8])
+ MUL31(a[1], a[7])
+ MUL31(a[2], a[6])
+ MUL31(a[3], a[5])) << 1);
t[ 9] = ((MUL31(a[1], a[8])
+ MUL31(a[2], a[7])
+ MUL31(a[3], a[6])
+ MUL31(a[4], a[5])) << 1);
t[10] = MUL31(a[5], a[5])
+ ((MUL31(a[2], a[8])
+ MUL31(a[3], a[7])
+ MUL31(a[4], a[6])) << 1);
t[11] = ((MUL31(a[3], a[8])
+ MUL31(a[4], a[7])
+ MUL31(a[5], a[6])) << 1);
t[12] = MUL31(a[6], a[6])
+ ((MUL31(a[4], a[8])
+ MUL31(a[5], a[7])) << 1);
t[13] = ((MUL31(a[5], a[8])
+ MUL31(a[6], a[7])) << 1);
t[14] = MUL31(a[7], a[7])
+ ((MUL31(a[6], a[8])) << 1);
t[15] = ((MUL31(a[7], a[8])) << 1);
t[16] = MUL31(a[8], a[8]);
/*
* Propagate carries.
*/
cc = 0;
for (i = 0; i < 17; i ++) {
uint64_t w;
w = t[i] + cc;
d[i] = (uint32_t)w & 0x3FFFFFFF;
cc = w >> 30;
}
d[17] = (uint32_t)cc;
}
/*
* Base field modulus for P-256.
*/
static const uint32_t _src_ec_ec_p256_m31_cF256[] = {
0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x0000003F, 0x00000000,
0x00000000, 0x00001000, 0x3FFFC000, 0x0000FFFF
};
/*
* The 'b' curve equation coefficient for P-256.
*/
static const uint32_t _src_ec_ec_p256_m31_cP256_B[] = {
0x27D2604B, 0x2F38F0F8, 0x053B0F63, 0x0741AC33, 0x1886BC65,
0x2EF555DA, 0x293E7B3E, 0x0D762A8E, 0x00005AC6
};
/*
* Addition in the field. Source operands shall fit on 257 bits; output
* will be lower than twice the modulus.
*/
static void
add_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t w, cc;
int i;
cc = 0;
for (i = 0; i < 9; i ++) {
w = a[i] + b[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = w >> 30;
}
w >>= 16;
d[8] &= 0xFFFF;
d[3] -= w << 6;
d[6] -= w << 12;
d[7] += w << 14;
cc = w;
for (i = 0; i < 9; i ++) {
w = d[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = ARSH(w, 30);
}
}
/*
* Subtraction in the field. Source operands shall be smaller than twice
* the modulus; the result will fulfil the same property.
*/
static void
sub_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t w, cc;
int i;
/*
* We really compute a - b + 2*p to make sure that the result is
* positive.
*/
w = a[0] - b[0] - 0x00002;
d[0] = w & 0x3FFFFFFF;
w = a[1] - b[1] + ARSH(w, 30);
d[1] = w & 0x3FFFFFFF;
w = a[2] - b[2] + ARSH(w, 30);
d[2] = w & 0x3FFFFFFF;
w = a[3] - b[3] + ARSH(w, 30) + 0x00080;
d[3] = w & 0x3FFFFFFF;
w = a[4] - b[4] + ARSH(w, 30);
d[4] = w & 0x3FFFFFFF;
w = a[5] - b[5] + ARSH(w, 30);
d[5] = w & 0x3FFFFFFF;
w = a[6] - b[6] + ARSH(w, 30) + 0x02000;
d[6] = w & 0x3FFFFFFF;
w = a[7] - b[7] + ARSH(w, 30) - 0x08000;
d[7] = w & 0x3FFFFFFF;
w = a[8] - b[8] + ARSH(w, 30) + 0x20000;
d[8] = w & 0xFFFF;
w >>= 16;
d[8] &= 0xFFFF;
d[3] -= w << 6;
d[6] -= w << 12;
d[7] += w << 14;
cc = w;
for (i = 0; i < 9; i ++) {
w = d[i] + cc;
d[i] = w & 0x3FFFFFFF;
cc = ARSH(w, 30);
}
}
/*
* Compute a multiplication in _src_ec_ec_p256_m31_cF256. Source operands shall be less than
* twice the modulus.
*/
static void
_src_ec_ec_p256_m31_cmul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
{
uint32_t t[18];
uint64_t s[18];
uint64_t cc, x;
uint32_t z, c;
int i;
_src_ec_ec_p256_m31_cmul9(t, a, b);
/*
* Modular reduction: each high word in added/subtracted where
* necessary.
*
* The modulus is:
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1
* Therefore:
* 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
*
* For a word x at bit offset n (n >= 256), we have:
* x*2^n = x*2^(n-32) - x*2^(n-64)
* - x*2^(n - 160) + x*2^(n-256) mod p
*
* Thus, we can nullify the high word if we reinject it at some
* proper emplacements.
*
* We use 64-bit intermediate words to allow for carries to
* accumulate easily, before performing the final propagation.
*/
for (i = 0; i < 18; i ++) {
s[i] = t[i];
}
for (i = 17; i >= 9; i --) {
uint64_t y;
y = s[i];
s[i - 1] += ARSHW(y, 2);
s[i - 2] += (y << 28) & 0x3FFFFFFF;
s[i - 2] -= ARSHW(y, 4);
s[i - 3] -= (y << 26) & 0x3FFFFFFF;
s[i - 5] -= ARSHW(y, 10);
s[i - 6] -= (y << 20) & 0x3FFFFFFF;
s[i - 8] += ARSHW(y, 16);
s[i - 9] += (y << 14) & 0x3FFFFFFF;
}
/*
* Carry propagation must be signed. Moreover, we may have overdone
* it a bit, and obtain a negative result.
*
* The loop above ran 9 times; each time, each word was augmented
* by at most one extra word (in absolute value). Thus, the top
* word must in fine fit in 39 bits, so the carry below will fit
* on 9 bits.
*/
cc = 0;
for (i = 0; i < 9; i ++) {
x = s[i] + cc;
d[i] = (uint32_t)x & 0x3FFFFFFF;
cc = ARSHW(x, 30);
}
/*
* All nine words fit on 30 bits, but there may be an extra
* carry for a few bits (at most 9), and that carry may be
* negative. Moreover, we want the result to fit on 257 bits.
* The two lines below ensure that the word in d[] has length
* 256 bits, and the (signed) carry (beyond 2^256) is in cc. The
* significant length of cc is less than 24 bits, so we will be
* able to switch to 32-bit operations.
*/
cc = ARSHW(x, 16);
d[8] &= 0xFFFF;
/*
* One extra round of reduction, for cc*2^256, which means
* adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative)
* value. If cc is negative, then it may happen (rarely, but
* not neglectibly so) that the result would be negative. In
* order to avoid that, if cc is negative, then we add the
* modulus once. Note that if cc is negative, then propagating
* that carry must yield a value lower than the modulus, so
* adding the modulus once will keep the final result under
* twice the modulus.
*/
z = (uint32_t)cc;
d[3] -= z << 6;
d[6] -= (z << 12) & 0x3FFFFFFF;
d[7] -= ARSH(z, 18);
d[7] += (z << 14) & 0x3FFFFFFF;
d[8] += ARSH(z, 16);
c = z >> 31;
d[0] -= c;
d[3] += c << 6;
d[6] += c << 12;
d[7] -= c << 14;
d[8] += c << 16;
for (i = 0; i < 9; i ++) {
uint32_t w;
w = d[i] + z;
d[i] = w & 0x3FFFFFFF;
z = ARSH(w, 30);
}
}
/*
* Compute a square in _src_ec_ec_p256_m31_cF256. Source operand shall be less than
* twice the modulus.
*/
static void
_src_ec_ec_p256_m31_csquare_f256(uint32_t *d, const uint32_t *a)
{
uint32_t t[18];
uint64_t s[18];
uint64_t cc, x;
uint32_t z, c;
int i;
_src_ec_ec_p256_m31_csquare9(t, a);
/*
* Modular reduction: each high word in added/subtracted where
* necessary.
*
* The modulus is:
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1
* Therefore:
* 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
*
* For a word x at bit offset n (n >= 256), we have:
* x*2^n = x*2^(n-32) - x*2^(n-64)
* - x*2^(n - 160) + x*2^(n-256) mod p
*
* Thus, we can nullify the high word if we reinject it at some
* proper emplacements.
*
* We use 64-bit intermediate words to allow for carries to
* accumulate easily, before performing the final propagation.
*/
for (i = 0; i < 18; i ++) {
s[i] = t[i];
}
for (i = 17; i >= 9; i --) {
uint64_t y;
y = s[i];
s[i - 1] += ARSHW(y, 2);
s[i - 2] += (y << 28) & 0x3FFFFFFF;
s[i - 2] -= ARSHW(y, 4);
s[i - 3] -= (y << 26) & 0x3FFFFFFF;
s[i - 5] -= ARSHW(y, 10);
s[i - 6] -= (y << 20) & 0x3FFFFFFF;
s[i - 8] += ARSHW(y, 16);
s[i - 9] += (y << 14) & 0x3FFFFFFF;
}
/*
* Carry propagation must be signed. Moreover, we may have overdone
* it a bit, and obtain a negative result.
*
* The loop above ran 9 times; each time, each word was augmented
* by at most one extra word (in absolute value). Thus, the top
* word must in fine fit in 39 bits, so the carry below will fit
* on 9 bits.
*/
cc = 0;
for (i = 0; i < 9; i ++) {
x = s[i] + cc;
d[i] = (uint32_t)x & 0x3FFFFFFF;
cc = ARSHW(x, 30);
}
/*
* All nine words fit on 30 bits, but there may be an extra
* carry for a few bits (at most 9), and that carry may be
* negative. Moreover, we want the result to fit on 257 bits.
* The two lines below ensure that the word in d[] has length
* 256 bits, and the (signed) carry (beyond 2^256) is in cc. The
* significant length of cc is less than 24 bits, so we will be
* able to switch to 32-bit operations.
*/
cc = ARSHW(x, 16);
d[8] &= 0xFFFF;
/*
* One extra round of reduction, for cc*2^256, which means
* adding cc*(2^224-2^192-2^96+1) to a 256-bit (nonnegative)
* value. If cc is negative, then it may happen (rarely, but
* not neglectibly so) that the result would be negative. In
* order to avoid that, if cc is negative, then we add the
* modulus once. Note that if cc is negative, then propagating
* that carry must yield a value lower than the modulus, so
* adding the modulus once will keep the final result under
* twice the modulus.
*/
z = (uint32_t)cc;
d[3] -= z << 6;
d[6] -= (z << 12) & 0x3FFFFFFF;
d[7] -= ARSH(z, 18);
d[7] += (z << 14) & 0x3FFFFFFF;
d[8] += ARSH(z, 16);
c = z >> 31;
d[0] -= c;
d[3] += c << 6;
d[6] += c << 12;
d[7] -= c << 14;
d[8] += c << 16;
for (i = 0; i < 9; i ++) {
uint32_t w;
w = d[i] + z;
d[i] = w & 0x3FFFFFFF;
z = ARSH(w, 30);
}
}
/*
* Perform a "final reduction" in field _src_ec_ec_p256_m31_cF256 (field for curve P-256).
* The source value must be less than twice the modulus. If the value
* is not lower than the modulus, then the modulus is subtracted and
* this function returns 1; otherwise, it leaves it untouched and it
* returns 0.
*/
static uint32_t
_src_ec_ec_p256_m31_creduce_final_f256(uint32_t *d)
{
uint32_t t[9];
uint32_t cc;
int i;
cc = 0;
for (i = 0; i < 9; i ++) {
uint32_t w;
w = d[i] - _src_ec_ec_p256_m31_cF256[i] - cc;
cc = w >> 31;
t[i] = w & 0x3FFFFFFF;
}
cc ^= 1;
CCOPY(cc, d, t, sizeof t);
return cc;
}
/*
* Jacobian coordinates for a point in P-256: affine coordinates (X,Y)
* are such that:
* X = x / z^2
* Y = y / z^3
* For the point at infinity, z = 0.
* Each point thus admits many possible representations.
*
* Coordinates are represented in arrays of 32-bit integers, each holding
* 30 bits of data. Values may also be slightly greater than the modulus,
* but they will always be lower than twice the modulus.
*/
typedef struct {
uint32_t x[9];
uint32_t y[9];
uint32_t z[9];
} p256__src_ec_ec_p256_m31_cjacobian;
/*
* Convert a point to affine coordinates:
* - If the point is the point at infinity, then all three coordinates
* are set to 0.
* - Otherwise, the 'z' coordinate is set to 1, and the 'x' and 'y'
* coordinates are the 'X' and 'Y' affine coordinates.
* The coordinates are guaranteed to be lower than the modulus.
*/
static void
_src_ec_ec_p256_m31_cp256_to_affine(p256__src_ec_ec_p256_m31_cjacobian *P)
{
uint32_t t1[9], t2[9];
int i;
/*
* Invert z with a modular exponentiation: the modulus is
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1, and the exponent is
* p-2. Exponent bit pattern (from high to low) is:
* - 32 bits of value 1
* - 31 bits of value 0
* - 1 bit of value 1
* - 96 bits of value 0
* - 94 bits of value 1
* - 1 bit of value 0
* - 1 bit of value 1
* Thus, we precompute z^(2^31-1) to speed things up.
*
* If z = 0 (point at infinity) then the modular exponentiation
* will yield 0, which leads to the expected result (all three
* coordinates set to 0).
*/
/*
* A simple square-and-multiply for z^(2^31-1). We could save about
* two dozen multiplications here with an addition chain, but
* this would require a bit more code, and extra stack buffers.
*/
memcpy(t1, P->z, sizeof P->z);
for (i = 0; i < 30; i ++) {
_src_ec_ec_p256_m31_csquare_f256(t1, t1);
_src_ec_ec_p256_m31_cmul_f256(t1, t1, P->z);
}
/*
* Square-and-multiply. Apart from the squarings, we have a few
* multiplications to set bits to 1; we multiply by the original z
* for setting 1 bit, and by t1 for setting 31 bits.
*/
memcpy(t2, P->z, sizeof P->z);
for (i = 1; i < 256; i ++) {
_src_ec_ec_p256_m31_csquare_f256(t2, t2);
switch (i) {
case 31:
case 190:
case 221:
case 252:
_src_ec_ec_p256_m31_cmul_f256(t2, t2, t1);
break;
case 63:
case 253:
case 255:
_src_ec_ec_p256_m31_cmul_f256(t2, t2, P->z);
break;
}
}
/*
* Now that we have 1/z, multiply x by 1/z^2 and y by 1/z^3.
*/
_src_ec_ec_p256_m31_cmul_f256(t1, t2, t2);
_src_ec_ec_p256_m31_cmul_f256(P->x, t1, P->x);
_src_ec_ec_p256_m31_cmul_f256(t1, t1, t2);
_src_ec_ec_p256_m31_cmul_f256(P->y, t1, P->y);
_src_ec_ec_p256_m31_creduce_final_f256(P->x);
_src_ec_ec_p256_m31_creduce_final_f256(P->y);
/*
* Multiply z by 1/z. If z = 0, then this will yield 0, otherwise
* this will set z to 1.
*/
_src_ec_ec_p256_m31_cmul_f256(P->z, P->z, t2);
_src_ec_ec_p256_m31_creduce_final_f256(P->z);
}
/*
* Double a point in P-256. This function works for all valid points,
* including the point at infinity.
*/
static void
_src_ec_ec_p256_m31_cp256_double(p256__src_ec_ec_p256_m31_cjacobian *Q)
{
/*
* Doubling formulas are:
*
* s = 4*x*y^2
* m = 3*(x + z^2)*(x - z^2)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y^4
* z' = 2*y*z
*
* These formulas work for all points, including points of order 2
* and points at infinity:
* - If y = 0 then z' = 0. But there is no such point in P-256
* anyway.
* - If z = 0 then z' = 0.
*/
uint32_t t1[9], t2[9], t3[9], t4[9];
/*
* Compute z^2 in t1.
*/
_src_ec_ec_p256_m31_csquare_f256(t1, Q->z);
/*
* Compute x-z^2 in t2 and x+z^2 in t1.
*/
add_f256(t2, Q->x, t1);
sub_f256(t1, Q->x, t1);
/*
* Compute 3*(x+z^2)*(x-z^2) in t1.
*/
_src_ec_ec_p256_m31_cmul_f256(t3, t1, t2);
add_f256(t1, t3, t3);
add_f256(t1, t3, t1);
/*
* Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
*/
_src_ec_ec_p256_m31_csquare_f256(t3, Q->y);
add_f256(t3, t3, t3);
_src_ec_ec_p256_m31_cmul_f256(t2, Q->x, t3);
add_f256(t2, t2, t2);
/*
* Compute x' = m^2 - 2*s.
*/
_src_ec_ec_p256_m31_csquare_f256(Q->x, t1);
sub_f256(Q->x, Q->x, t2);
sub_f256(Q->x, Q->x, t2);
/*
* Compute z' = 2*y*z.
*/
_src_ec_ec_p256_m31_cmul_f256(t4, Q->y, Q->z);
add_f256(Q->z, t4, t4);
/*
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
* 2*y^2 in t3.
*/
sub_f256(t2, t2, Q->x);
_src_ec_ec_p256_m31_cmul_f256(Q->y, t1, t2);
_src_ec_ec_p256_m31_csquare_f256(t4, t3);
add_f256(t4, t4, t4);
sub_f256(Q->y, Q->y, t4);
}
/*
* Add point P2 to point P1.
*
* This function computes the wrong result in the following cases:
*
* - If P1 == 0 but P2 != 0
* - If P1 != 0 but P2 == 0
* - If P1 == P2
*
* In all three cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y coordinate
* - P1 == 0 and P2 == 0
* - The Y coordinate of one of the points is 0 and the other point is
* the point at infinity.
*
* The third case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*/
static uint32_t
_src_ec_ec_p256_m31_cp256_add(p256__src_ec_ec_p256_m31_cjacobian *P1, const p256__src_ec_ec_p256_m31_cjacobian *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1 * z2^2
* u2 = x2 * z1^2
* s1 = y1 * z2^3
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1 * z2
*/
uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9];
uint32_t ret;
int i;
/*
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
*/
_src_ec_ec_p256_m31_csquare_f256(t3, P2->z);
_src_ec_ec_p256_m31_cmul_f256(t1, P1->x, t3);
_src_ec_ec_p256_m31_cmul_f256(t4, P2->z, t3);
_src_ec_ec_p256_m31_cmul_f256(t3, P1->y, t4);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m31_csquare_f256(t4, P1->z);
_src_ec_ec_p256_m31_cmul_f256(t2, P2->x, t4);
_src_ec_ec_p256_m31_cmul_f256(t5, P1->z, t4);
_src_ec_ec_p256_m31_cmul_f256(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
sub_f256(t2, t2, t1);
sub_f256(t4, t4, t3);
_src_ec_ec_p256_m31_creduce_final_f256(t4);
ret = 0;
for (i = 0; i < 9; i ++) {
ret |= t4[i];
}
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m31_csquare_f256(t7, t2);
_src_ec_ec_p256_m31_cmul_f256(t6, t1, t7);
_src_ec_ec_p256_m31_cmul_f256(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m31_csquare_f256(P1->x, t4);
sub_f256(P1->x, P1->x, t5);
sub_f256(P1->x, P1->x, t6);
sub_f256(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
sub_f256(t6, t6, P1->x);
_src_ec_ec_p256_m31_cmul_f256(P1->y, t4, t6);
_src_ec_ec_p256_m31_cmul_f256(t1, t5, t3);
sub_f256(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m31_cmul_f256(t1, P1->z, P2->z);
_src_ec_ec_p256_m31_cmul_f256(P1->z, t1, t2);
return ret;
}
/*
* Add point P2 to point P1. This is a specialised function for the
* case when P2 is a non-zero point in affine coordinate.
*
* This function computes the wrong result in the following cases:
*
* - If P1 == 0
* - If P1 == P2
*
* In both cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y coordinate
* - The Y coordinate of P2 is 0 and P1 is the point at infinity.
*
* The second case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*/
static uint32_t
_src_ec_ec_p256_m31_c_src_ec_ec_p256_m31_cp256_add_mixed(p256__src_ec_ec_p256_m31_cjacobian *P1, const p256__src_ec_ec_p256_m31_cjacobian *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1
* u2 = x2 * z1^2
* s1 = y1
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1
*/
uint32_t t1[9], t2[9], t3[9], t4[9], t5[9], t6[9], t7[9];
uint32_t ret;
int i;
/*
* Compute u1 = x1 (in t1) and s1 = y1 (in t3).
*/
memcpy(t1, P1->x, sizeof t1);
memcpy(t3, P1->y, sizeof t3);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m31_csquare_f256(t4, P1->z);
_src_ec_ec_p256_m31_cmul_f256(t2, P2->x, t4);
_src_ec_ec_p256_m31_cmul_f256(t5, P1->z, t4);
_src_ec_ec_p256_m31_cmul_f256(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
sub_f256(t2, t2, t1);
sub_f256(t4, t4, t3);
_src_ec_ec_p256_m31_creduce_final_f256(t4);
ret = 0;
for (i = 0; i < 9; i ++) {
ret |= t4[i];
}
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m31_csquare_f256(t7, t2);
_src_ec_ec_p256_m31_cmul_f256(t6, t1, t7);
_src_ec_ec_p256_m31_cmul_f256(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m31_csquare_f256(P1->x, t4);
sub_f256(P1->x, P1->x, t5);
sub_f256(P1->x, P1->x, t6);
sub_f256(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
sub_f256(t6, t6, P1->x);
_src_ec_ec_p256_m31_cmul_f256(P1->y, t4, t6);
_src_ec_ec_p256_m31_cmul_f256(t1, t5, t3);
sub_f256(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m31_cmul_f256(P1->z, P1->z, t2);
return ret;
}
/*
* Decode a P-256 point. This function does not support the point at
* infinity. Returned value is 0 if the point is invalid, 1 otherwise.
*/
static uint32_t
_src_ec_ec_p256_m31_cp256_decode(p256__src_ec_ec_p256_m31_cjacobian *P, const void *src, size_t len)
{
const unsigned char *buf;
uint32_t tx[9], ty[9], t1[9], t2[9];
uint32_t bad;
int i;
if (len != 65) {
return 0;
}
buf = (const unsigned char*)src;
/*
* First byte must be 0x04 (uncompressed format). We could support
* "hybrid format" (first byte is 0x06 or 0x07, and encodes the
* least significant bit of the Y coordinate), but it is explicitly
* forbidden by RFC 5480 (section 2.2).
*/
bad = NEQ(buf[0], 0x04);
/*
* Decode the coordinates, and check that they are both lower
* than the modulus.
*/
tx[8] = be8_to_le30(tx, buf + 1, 32);
ty[8] = be8_to_le30(ty, buf + 33, 32);
bad |= _src_ec_ec_p256_m31_creduce_final_f256(tx);
bad |= _src_ec_ec_p256_m31_creduce_final_f256(ty);
/*
* Check curve equation.
*/
_src_ec_ec_p256_m31_csquare_f256(t1, tx);
_src_ec_ec_p256_m31_cmul_f256(t1, tx, t1);
_src_ec_ec_p256_m31_csquare_f256(t2, ty);
sub_f256(t1, t1, tx);
sub_f256(t1, t1, tx);
sub_f256(t1, t1, tx);
add_f256(t1, t1, _src_ec_ec_p256_m31_cP256_B);
sub_f256(t1, t1, t2);
_src_ec_ec_p256_m31_creduce_final_f256(t1);
for (i = 0; i < 9; i ++) {
bad |= t1[i];
}
/*
* Copy coordinates to the point structure.
*/
memcpy(P->x, tx, sizeof tx);
memcpy(P->y, ty, sizeof ty);
memset(P->z, 0, sizeof P->z);
P->z[0] = 1;
return EQ(bad, 0);
}
/*
* Encode a point into a buffer. This function assumes that the point is
* valid, in affine coordinates, and not the point at infinity.
*/
static void
_src_ec_ec_p256_m31_cp256_encode(void *dst, const p256__src_ec_ec_p256_m31_cjacobian *P)
{
unsigned char *buf;
buf = (unsigned char*)dst;
buf[0] = 0x04;
le30_to_be8(buf + 1, 32, P->x);
le30_to_be8(buf + 33, 32, P->y);
}
/*
* Multiply a curve point by an integer. The integer is assumed to be
* lower than the curve order, and the base point must not be the point
* at infinity.
*/
static void
_src_ec_ec_p256_m31_cp256_mul(p256__src_ec_ec_p256_m31_cjacobian *P, const unsigned char *x, size_t xlen)
{
/*
* qz is a flag that is initially 1, and remains equal to 1
* as long as the point is the point at infinity.
*
* We use a 2-bit window to handle multiplier bits by pairs.
* The precomputed window really is the points P2 and P3.
*/
uint32_t qz;
p256__src_ec_ec_p256_m31_cjacobian P2, P3, Q, T, U;
/*
* Compute window values.
*/
P2 = *P;
_src_ec_ec_p256_m31_cp256_double(&P2);
P3 = *P;
_src_ec_ec_p256_m31_cp256_add(&P3, &P2);
/*
* We start with Q = 0. We process multiplier bits 2 by 2.
*/
memset(&Q, 0, sizeof Q);
qz = 1;
while (xlen -- > 0) {
int k;
for (k = 6; k >= 0; k -= 2) {
uint32_t bits;
uint32_t bnz;
_src_ec_ec_p256_m31_cp256_double(&Q);
_src_ec_ec_p256_m31_cp256_double(&Q);
T = *P;
U = Q;
bits = (*x >> k) & (uint32_t)3;
bnz = NEQ(bits, 0);
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
_src_ec_ec_p256_m31_cp256_add(&U, &T);
CCOPY(bnz & qz, &Q, &T, sizeof Q);
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
}
x ++;
}
*P = Q;
}
/*
* Precomputed window: k*G points, where G is the curve generator, and k
* is an integer from 1 to 15 (inclusive). The X and Y coordinates of
* the point are encoded as 9 words of 30 bits each (little-endian
* order).
*/
static const uint32_t _src_ec_ec_p256_m31_cGwin[15][18] = {
{ 0x1898C296, 0x1284E517, 0x1EB33A0F, 0x00DF604B,
0x2440F277, 0x339B958E, 0x04247F8B, 0x347CB84B,
0x00006B17, 0x37BF51F5, 0x2ED901A0, 0x3315ECEC,
0x338CD5DA, 0x0F9E162B, 0x1FAD29F0, 0x27F9B8EE,
0x10B8BF86, 0x00004FE3 },
{ 0x07669978, 0x182D23F1, 0x3F21B35A, 0x225A789D,
0x351AC3C0, 0x08E00C12, 0x34F7E8A5, 0x1EC62340,
0x00007CF2, 0x227873D1, 0x3812DE74, 0x0E982299,
0x1F6B798F, 0x3430DBBA, 0x366B1A7D, 0x2D040293,
0x154436E3, 0x00000777 },
{ 0x06E7FD6C, 0x2D05986F, 0x3ADA985F, 0x31ADC87B,
0x0BF165E6, 0x1FBE5475, 0x30A44C8F, 0x3934698C,
0x00005ECB, 0x227D5032, 0x29E6C49E, 0x04FB83D9,
0x0AAC0D8E, 0x24A2ECD8, 0x2C1B3869, 0x0FF7E374,
0x19031266, 0x00008734 },
{ 0x2B030852, 0x024C0911, 0x05596EF5, 0x07F8B6DE,
0x262BD003, 0x3779967B, 0x08FBBA02, 0x128D4CB4,
0x0000E253, 0x184ED8C6, 0x310B08FC, 0x30EE0055,
0x3F25B0FC, 0x062D764E, 0x3FB97F6A, 0x33CC719D,
0x15D69318, 0x0000E0F1 },
{ 0x03D033ED, 0x05552837, 0x35BE5242, 0x2320BF47,
0x268FDFEF, 0x13215821, 0x140D2D78, 0x02DE9454,
0x00005159, 0x3DA16DA4, 0x0742ED13, 0x0D80888D,
0x004BC035, 0x0A79260D, 0x06FCDAFE, 0x2727D8AE,
0x1F6A2412, 0x0000E0C1 },
{ 0x3C2291A9, 0x1AC2ABA4, 0x3B215B4C, 0x131D037A,
0x17DDE302, 0x0C90B2E2, 0x0602C92D, 0x05CA9DA9,
0x0000B01A, 0x0FC77FE2, 0x35F1214E, 0x07E16BDF,
0x003DDC07, 0x2703791C, 0x3038B7EE, 0x3DAD56FE,
0x041D0C8D, 0x0000E85C },
{ 0x3187B2A3, 0x0018A1C0, 0x00FEF5B3, 0x3E7E2E2A,
0x01FB607E, 0x2CC199F0, 0x37B4625B, 0x0EDBE82F,
0x00008E53, 0x01F400B4, 0x15786A1B, 0x3041B21C,
0x31CD8CF2, 0x35900053, 0x1A7E0E9B, 0x318366D0,
0x076F780C, 0x000073EB },
{ 0x1B6FB393, 0x13767707, 0x3CE97DBB, 0x348E2603,
0x354CADC1, 0x09D0B4EA, 0x1B053404, 0x1DE76FBA,
0x000062D9, 0x0F09957E, 0x295029A8, 0x3E76A78D,
0x3B547DAE, 0x27CEE0A2, 0x0575DC45, 0x1D8244FF,
0x332F647A, 0x0000AD5A },
{ 0x10949EE0, 0x1E7A292E, 0x06DF8B3D, 0x02B2E30B,
0x31F8729E, 0x24E35475, 0x30B71878, 0x35EDBFB7,
0x0000EA68, 0x0DD048FA, 0x21688929, 0x0DE823FE,
0x1C53FAA9, 0x0EA0C84D, 0x052A592A, 0x1FCE7870,
0x11325CB2, 0x00002A27 },
{ 0x04C5723F, 0x30D81A50, 0x048306E4, 0x329B11C7,
0x223FB545, 0x085347A8, 0x2993E591, 0x1B5ACA8E,
0x0000CEF6, 0x04AF0773, 0x28D2EEA9, 0x2751EEEC,
0x037B4A7F, 0x3B4C1059, 0x08F37674, 0x2AE906E1,
0x18A88A6A, 0x00008786 },
{ 0x34BC21D1, 0x0CCE474D, 0x15048BF4, 0x1D0BB409,
0x021CDA16, 0x20DE76C3, 0x34C59063, 0x04EDE20E,
0x00003ED1, 0x282A3740, 0x0BE3BBF3, 0x29889DAE,
0x03413697, 0x34C68A09, 0x210EBE93, 0x0C8A224C,
0x0826B331, 0x00009099 },
{ 0x0624E3C4, 0x140317BA, 0x2F82C99D, 0x260C0A2C,
0x25D55179, 0x194DCC83, 0x3D95E462, 0x356F6A05,
0x0000741D, 0x0D4481D3, 0x2657FC8B, 0x1BA5CA71,
0x3AE44B0D, 0x07B1548E, 0x0E0D5522, 0x05FDC567,
0x2D1AA70E, 0x00000770 },
{ 0x06072C01, 0x23857675, 0x1EAD58A9, 0x0B8A12D9,
0x1EE2FC79, 0x0177CB61, 0x0495A618, 0x20DEB82B,
0x0000177C, 0x2FC7BFD8, 0x310EEF8B, 0x1FB4DF39,
0x3B8530E8, 0x0F4E7226, 0x0246B6D0, 0x2A558A24,
0x163353AF, 0x000063BB },
{ 0x24D2920B, 0x1C249DCC, 0x2069C5E5, 0x09AB2F9E,
0x36DF3CF1, 0x1991FD0C, 0x062B97A7, 0x1E80070E,
0x000054E7, 0x20D0B375, 0x2E9F20BD, 0x35090081,
0x1C7A9DDC, 0x22E7C371, 0x087E3016, 0x03175421,
0x3C6ECA7D, 0x0000F599 },
{ 0x259B9D5F, 0x0D9A318F, 0x23A0EF16, 0x00EBE4B7,
0x088265AE, 0x2CDE2666, 0x2BAE7ADF, 0x1371A5C6,
0x0000F045, 0x0D034F36, 0x1F967378, 0x1B5FA3F4,
0x0EC8739D, 0x1643E62A, 0x1653947E, 0x22D1F4E6,
0x0FB8D64B, 0x0000B5B9 }
};
/*
* Lookup one of the _src_ec_ec_p256_m31_cGwin[] values, by index. This is constant-time.
*/
static void
_src_ec_ec_p256_m31_clookup__src_ec_ec_p256_m31_cGwin(p256__src_ec_ec_p256_m31_cjacobian *T, uint32_t idx)
{
uint32_t xy[18];
uint32_t k;
size_t u;
memset(xy, 0, sizeof xy);
for (k = 0; k < 15; k ++) {
uint32_t m;
m = -EQ(idx, k + 1);
for (u = 0; u < 18; u ++) {
xy[u] |= m & _src_ec_ec_p256_m31_cGwin[k][u];
}
}
memcpy(T->x, &xy[0], sizeof T->x);
memcpy(T->y, &xy[9], sizeof T->y);
memset(T->z, 0, sizeof T->z);
T->z[0] = 1;
}
/*
* Multiply the generator by an integer. The integer is assumed non-zero
* and lower than the curve order.
*/
static void
_src_ec_ec_p256_m31_c_src_ec_ec_p256_m31_cp256_mulgen(p256__src_ec_ec_p256_m31_cjacobian *P, const unsigned char *x, size_t xlen)
{
/*
* qz is a flag that is initially 1, and remains equal to 1
* as long as the point is the point at infinity.
*
* We use a 4-bit window to handle multiplier bits by groups
* of 4. The precomputed window is constant static data, with
* points in affine coordinates; we use a constant-time lookup.
*/
p256__src_ec_ec_p256_m31_cjacobian Q;
uint32_t qz;
memset(&Q, 0, sizeof Q);
qz = 1;
while (xlen -- > 0) {
int k;
unsigned bx;
bx = *x ++;
for (k = 0; k < 2; k ++) {
uint32_t bits;
uint32_t bnz;
p256__src_ec_ec_p256_m31_cjacobian T, U;
_src_ec_ec_p256_m31_cp256_double(&Q);
_src_ec_ec_p256_m31_cp256_double(&Q);
_src_ec_ec_p256_m31_cp256_double(&Q);
_src_ec_ec_p256_m31_cp256_double(&Q);
bits = (bx >> 4) & 0x0F;
bnz = NEQ(bits, 0);
_src_ec_ec_p256_m31_clookup__src_ec_ec_p256_m31_cGwin(&T, bits);
U = Q;
_src_ec_ec_p256_m31_c_src_ec_ec_p256_m31_cp256_add_mixed(&U, &T);
CCOPY(bnz & qz, &Q, &T, sizeof Q);
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
bx <<= 4;
}
}
*P = Q;
}
static const unsigned char _src_ec_ec_p256_m31_cP256_G[] = {
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
0x68, 0x37, 0xBF, 0x51, 0xF5
};
static const unsigned char _src_ec_ec_p256_m31_cP256_N[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
0x25, 0x51
};
static const unsigned char *
_src_ec_ec_p256_m31_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m31_cP256_G;
return _src_ec_ec_p256_m31_cP256_G;
}
static const unsigned char *
_src_ec_ec_p256_m31_capi_order(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m31_cP256_N;
return _src_ec_ec_p256_m31_cP256_N;
}
static size_t
_src_ec_ec_p256_m31_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 1;
}
static uint32_t
_src_ec_ec_p256_m31_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *x, size_t xlen, int curve)
{
uint32_t r;
p256__src_ec_ec_p256_m31_cjacobian P;
(void)curve;
if (Glen != 65) {
return 0;
}
r = _src_ec_ec_p256_m31_cp256_decode(&P, G, Glen);
_src_ec_ec_p256_m31_cp256_mul(&P, x, xlen);
_src_ec_ec_p256_m31_cp256_to_affine(&P);
_src_ec_ec_p256_m31_cp256_encode(G, &P);
return r;
}
static size_t
_src_ec_ec_p256_m31_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
p256__src_ec_ec_p256_m31_cjacobian P;
(void)curve;
_src_ec_ec_p256_m31_c_src_ec_ec_p256_m31_cp256_mulgen(&P, x, xlen);
_src_ec_ec_p256_m31_cp256_to_affine(&P);
_src_ec_ec_p256_m31_cp256_encode(R, &P);
return 65;
}
static uint32_t
_src_ec_ec_p256_m31_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
p256__src_ec_ec_p256_m31_cjacobian P, Q;
uint32_t r, t, z;
int i;
(void)curve;
if (len != 65) {
return 0;
}
r = _src_ec_ec_p256_m31_cp256_decode(&P, A, len);
_src_ec_ec_p256_m31_cp256_mul(&P, x, xlen);
if (B == NULL) {
_src_ec_ec_p256_m31_c_src_ec_ec_p256_m31_cp256_mulgen(&Q, y, ylen);
} else {
r &= _src_ec_ec_p256_m31_cp256_decode(&Q, B, len);
_src_ec_ec_p256_m31_cp256_mul(&Q, y, ylen);
}
/*
* The final addition may fail in case both points are equal.
*/
t = _src_ec_ec_p256_m31_cp256_add(&P, &Q);
_src_ec_ec_p256_m31_creduce_final_f256(P.z);
z = 0;
for (i = 0; i < 9; i ++) {
z |= P.z[i];
}
z = EQ(z, 0);
_src_ec_ec_p256_m31_cp256_double(&Q);
/*
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
* have the following:
*
* z = 0, t = 0 return P (normal addition)
* z = 0, t = 1 return P (normal addition)
* z = 1, t = 0 return Q (a 'double' case)
* z = 1, t = 1 report an error (P+Q = 0)
*/
CCOPY(z & ~t, &P, &Q, sizeof Q);
_src_ec_ec_p256_m31_cp256_to_affine(&P);
_src_ec_ec_p256_m31_cp256_encode(A, &P);
r &= ~(z & t);
return r;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_p256_m31 = {
(uint32_t)0x00800000,
&_src_ec_ec_p256_m31_capi_generator,
&_src_ec_ec_p256_m31_capi_order,
&_src_ec_ec_p256_m31_capi_xoff,
&_src_ec_ec_p256_m31_capi_mul,
&_src_ec_ec_p256_m31_capi_mulgen,
&_src_ec_ec_p256_m31_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if BR_INT128 || BR_UMUL128
#if BR_UMUL128
#include
#endif
static const unsigned char _src_ec_ec_p256_m62_cP256_G[] = {
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
0x68, 0x37, 0xBF, 0x51, 0xF5
};
static const unsigned char _src_ec_ec_p256_m62_cP256_N[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
0x25, 0x51
};
static const unsigned char *
_src_ec_ec_p256_m62_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m62_cP256_G;
return _src_ec_ec_p256_m62_cP256_G;
}
static const unsigned char *
_src_ec_ec_p256_m62_capi_order(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m62_cP256_N;
return _src_ec_ec_p256_m62_cP256_N;
}
static size_t
_src_ec_ec_p256_m62_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 1;
}
/*
* A field element is encoded as five 64-bit integers, in basis 2^52.
* Limbs may occasionally exceed 2^52.
*
* A _partially reduced_ value is such that the following hold:
* - top limb is less than 2^48 + 2^30
* - the other limbs fit on 53 bits each
* In particular, such a value is less than twice the modulus p.
*/
#define BIT(n) ((uint64_t)1 << (n))
#define MASK48 (BIT(48) - BIT(0))
#define MASK52 (BIT(52) - BIT(0))
/* R = 2^260 mod p */
static const uint64_t _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R[] = {
0x0000000000010, 0xF000000000000, 0xFFFFFFFFFFFFF,
0xFFEFFFFFFFFFF, 0x00000000FFFFF
};
/* Curve equation is y^2 = x^3 - 3*x + B. This constant is B*R mod p
(Montgomery representation of B). */
static const uint64_t _src_ec_ec_p256_m62_cP256_B_MONTY[] = {
0xDF6229C4BDDFD, 0xCA8843090D89C, 0x212ED6ACF005C,
0x83415A220ABF7, 0x0C30061DD4874
};
/*
* Addition in the field. Carry propagation is not performed.
* On input, limbs may be up to 63 bits each; on output, they will
* be up to one bit more than on input.
*/
static inline void
_src_ec_ec_p256_m62_cf256_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
d[0] = a[0] + b[0];
d[1] = a[1] + b[1];
d[2] = a[2] + b[2];
d[3] = a[3] + b[3];
d[4] = a[4] + b[4];
}
/*
* Partially reduce the provided value.
* Input: limbs can go up to 61 bits each.
* Output: partially reduced.
*/
static inline void
f256_partial_reduce(uint64_t *a)
{
uint64_t w, cc, s;
/*
* Propagate carries.
*/
w = a[0];
a[0] = w & MASK52;
cc = w >> 52;
w = a[1] + cc;
a[1] = w & MASK52;
cc = w >> 52;
w = a[2] + cc;
a[2] = w & MASK52;
cc = w >> 52;
w = a[3] + cc;
a[3] = w & MASK52;
cc = w >> 52;
a[4] += cc;
s = a[4] >> 48; /* s < 2^14 */
a[0] += s; /* a[0] < 2^52 + 2^14 */
w = a[1] - (s << 44);
a[1] = w & MASK52; /* a[1] < 2^52 */
cc = -(w >> 52) & 0xFFF; /* cc < 16 */
w = a[2] - cc;
a[2] = w & MASK52; /* a[2] < 2^52 */
cc = w >> 63; /* cc = 0 or 1 */
w = a[3] - cc - (s << 36);
a[3] = w & MASK52; /* a[3] < 2^52 */
cc = w >> 63; /* cc = 0 or 1 */
w = a[4] & MASK48;
a[4] = w + (s << 16) - cc; /* a[4] < 2^48 + 2^30 */
}
/*
* Subtraction in the field.
* Input: limbs must fit on 60 bits each; in particular, the complete
* integer will be less than 2^268 + 2^217.
* Output: partially reduced.
*/
static inline void
_src_ec_ec_p256_m62_cf256_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
uint64_t t[5], w, s, cc;
/*
* We compute d = 2^13*p + a - b; this ensures a positive
* intermediate value.
*
* Each individual addition/subtraction may yield a positive or
* negative result; thus, we need to handle a signed carry, thus
* with sign extension. We prefer not to use signed types (int64_t)
* because conversion from unsigned to signed is cumbersome (a
* direct cast with the top bit set is undefined behavior; instead,
* we have to use pointer aliasing, using the guaranteed properties
* of exact-width types, but this requires the compiler to optimize
* away the writes and reads from RAM), and right-shifting a
* signed negative value is implementation-defined. Therefore,
* we use a custom sign extension.
*/
w = a[0] - b[0] - BIT(13);
t[0] = w & MASK52;
cc = w >> 52;
cc |= -(cc & BIT(11));
w = a[1] - b[1] + cc;
t[1] = w & MASK52;
cc = w >> 52;
cc |= -(cc & BIT(11));
w = a[2] - b[2] + cc;
t[2] = (w & MASK52) + BIT(5);
cc = w >> 52;
cc |= -(cc & BIT(11));
w = a[3] - b[3] + cc;
t[3] = (w & MASK52) + BIT(49);
cc = w >> 52;
cc |= -(cc & BIT(11));
t[4] = (BIT(61) - BIT(29)) + a[4] - b[4] + cc;
/*
* Perform partial reduction. Rule is:
* 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p
*
* At that point:
* 0 <= t[0] <= 2^52 - 1
* 0 <= t[1] <= 2^52 - 1
* 2^5 <= t[2] <= 2^52 + 2^5 - 1
* 2^49 <= t[3] <= 2^52 + 2^49 - 1
* 2^59 < t[4] <= 2^61 + 2^60 - 2^29
*
* Thus, the value 's' (t[4] / 2^48) will be necessarily
* greater than 2048, and less than 12288.
*/
s = t[4] >> 48;
d[0] = t[0] + s; /* d[0] <= 2^52 + 12287 */
w = t[1] - (s << 44);
d[1] = w & MASK52; /* d[1] <= 2^52 - 1 */
cc = -(w >> 52) & 0xFFF; /* cc <= 48 */
w = t[2] - cc;
cc = w >> 63; /* cc = 0 or 1 */
d[2] = w + (cc << 52); /* d[2] <= 2^52 + 31 */
w = t[3] - cc - (s << 36);
cc = w >> 63; /* cc = 0 or 1 */
d[3] = w + (cc << 52); /* t[3] <= 2^52 + 2^49 - 1 */
d[4] = (t[4] & MASK48) + (s << 16) - cc; /* d[4] < 2^48 + 2^30 */
/*
* If s = 0, then none of the limbs is modified, and there cannot
* be an overflow; if s != 0, then (s << 16) > cc, and there is
* no overflow either.
*/
}
/*
* Montgomery multiplication in the field.
* Input: limbs must fit on 56 bits each.
* Output: partially reduced.
*/
static void
_src_ec_ec_p256_m62_cf256_montymul(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
#if BR_INT128
int i;
uint64_t t[5];
t[0] = 0;
t[1] = 0;
t[2] = 0;
t[3] = 0;
t[4] = 0;
for (i = 0; i < 5; i ++) {
uint64_t x, f, cc, w, s;
unsigned __int128 z;
/*
* Since limbs of a[] and b[] fit on 56 bits each,
* each individual product fits on 112 bits. Also,
* the factor f fits on 52 bits, so f<<48 fits on
* 112 bits too. This guarantees that carries (cc)
* will fit on 62 bits, thus no overflow.
*
* The operations below compute:
* t <- (t + x*b + f*p) / 2^64
*/
x = a[i];
z = (unsigned __int128)b[0] * (unsigned __int128)x
+ (unsigned __int128)t[0];
f = (uint64_t)z & MASK52;
cc = (uint64_t)(z >> 52);
z = (unsigned __int128)b[1] * (unsigned __int128)x
+ (unsigned __int128)t[1] + cc
+ ((unsigned __int128)f << 44);
t[0] = (uint64_t)z & MASK52;
cc = (uint64_t)(z >> 52);
z = (unsigned __int128)b[2] * (unsigned __int128)x
+ (unsigned __int128)t[2] + cc;
t[1] = (uint64_t)z & MASK52;
cc = (uint64_t)(z >> 52);
z = (unsigned __int128)b[3] * (unsigned __int128)x
+ (unsigned __int128)t[3] + cc
+ ((unsigned __int128)f << 36);
t[2] = (uint64_t)z & MASK52;
cc = (uint64_t)(z >> 52);
z = (unsigned __int128)b[4] * (unsigned __int128)x
+ (unsigned __int128)t[4] + cc
+ ((unsigned __int128)f << 48)
- ((unsigned __int128)f << 16);
t[3] = (uint64_t)z & MASK52;
t[4] = (uint64_t)(z >> 52);
/*
* t[4] may be up to 62 bits here; we need to do a
* partial reduction. Note that limbs t[0] to t[3]
* fit on 52 bits each.
*/
s = t[4] >> 48; /* s < 2^14 */
t[0] += s; /* t[0] < 2^52 + 2^14 */
w = t[1] - (s << 44);
t[1] = w & MASK52; /* t[1] < 2^52 */
cc = -(w >> 52) & 0xFFF; /* cc < 16 */
w = t[2] - cc;
t[2] = w & MASK52; /* t[2] < 2^52 */
cc = w >> 63; /* cc = 0 or 1 */
w = t[3] - cc - (s << 36);
t[3] = w & MASK52; /* t[3] < 2^52 */
cc = w >> 63; /* cc = 0 or 1 */
w = t[4] & MASK48;
t[4] = w + (s << 16) - cc; /* t[4] < 2^48 + 2^30 */
/*
* The final t[4] cannot overflow because cc is 0 or 1,
* and cc can be 1 only if s != 0.
*/
}
d[0] = t[0];
d[1] = t[1];
d[2] = t[2];
d[3] = t[3];
d[4] = t[4];
#elif BR_UMUL128
int i;
uint64_t t[5];
t[0] = 0;
t[1] = 0;
t[2] = 0;
t[3] = 0;
t[4] = 0;
for (i = 0; i < 5; i ++) {
uint64_t x, f, cc, w, s, zh, zl;
unsigned char k;
/*
* Since limbs of a[] and b[] fit on 56 bits each,
* each individual product fits on 112 bits. Also,
* the factor f fits on 52 bits, so f<<48 fits on
* 112 bits too. This guarantees that carries (cc)
* will fit on 62 bits, thus no overflow.
*
* The operations below compute:
* t <- (t + x*b + f*p) / 2^64
*/
x = a[i];
zl = _umul128(b[0], x, &zh);
k = _addcarry_u64(0, t[0], zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
f = zl & MASK52;
cc = (zl >> 52) | (zh << 12);
zl = _umul128(b[1], x, &zh);
k = _addcarry_u64(0, t[1], zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, cc, zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, f << 44, zl, &zl);
(void)_addcarry_u64(k, f >> 20, zh, &zh);
t[0] = zl & MASK52;
cc = (zl >> 52) | (zh << 12);
zl = _umul128(b[2], x, &zh);
k = _addcarry_u64(0, t[2], zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, cc, zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
t[1] = zl & MASK52;
cc = (zl >> 52) | (zh << 12);
zl = _umul128(b[3], x, &zh);
k = _addcarry_u64(0, t[3], zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, cc, zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, f << 36, zl, &zl);
(void)_addcarry_u64(k, f >> 28, zh, &zh);
t[2] = zl & MASK52;
cc = (zl >> 52) | (zh << 12);
zl = _umul128(b[4], x, &zh);
k = _addcarry_u64(0, t[4], zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, cc, zl, &zl);
(void)_addcarry_u64(k, 0, zh, &zh);
k = _addcarry_u64(0, f << 48, zl, &zl);
(void)_addcarry_u64(k, f >> 16, zh, &zh);
k = _subborrow_u64(0, zl, f << 16, &zl);
(void)_subborrow_u64(k, zh, f >> 48, &zh);
t[3] = zl & MASK52;
t[4] = (zl >> 52) | (zh << 12);
/*
* t[4] may be up to 62 bits here; we need to do a
* partial reduction. Note that limbs t[0] to t[3]
* fit on 52 bits each.
*/
s = t[4] >> 48; /* s < 2^14 */
t[0] += s; /* t[0] < 2^52 + 2^14 */
w = t[1] - (s << 44);
t[1] = w & MASK52; /* t[1] < 2^52 */
cc = -(w >> 52) & 0xFFF; /* cc < 16 */
w = t[2] - cc;
t[2] = w & MASK52; /* t[2] < 2^52 */
cc = w >> 63; /* cc = 0 or 1 */
w = t[3] - cc - (s << 36);
t[3] = w & MASK52; /* t[3] < 2^52 */
cc = w >> 63; /* cc = 0 or 1 */
w = t[4] & MASK48;
t[4] = w + (s << 16) - cc; /* t[4] < 2^48 + 2^30 */
/*
* The final t[4] cannot overflow because cc is 0 or 1,
* and cc can be 1 only if s != 0.
*/
}
d[0] = t[0];
d[1] = t[1];
d[2] = t[2];
d[3] = t[3];
d[4] = t[4];
#endif
}
/*
* Montgomery squaring in the field; currently a basic wrapper around
* multiplication (inline, should be optimized away).
* TODO: see if some extra speed can be gained here.
*/
static inline void
_src_ec_ec_p256_m62_cf256_montysquare(uint64_t *d, const uint64_t *a)
{
_src_ec_ec_p256_m62_cf256_montymul(d, a, a);
}
/*
* Convert to Montgomery representation.
*/
static void
_src_ec_ec_p256_m62_cf256_tomonty(uint64_t *d, const uint64_t *a)
{
/*
* R2 = 2^520 mod p.
* If R = 2^260 mod p, then R2 = R^2 mod p; and the Montgomery
* multiplication of a by R2 is: a*R2/R = a*R mod p, i.e. the
* conversion to Montgomery representation.
*/
static const uint64_t R2[] = {
0x0000000000300, 0xFFFFFFFF00000, 0xFFFFEFFFFFFFB,
0xFDFFFFFFFFFFF, 0x0000004FFFFFF
};
_src_ec_ec_p256_m62_cf256_montymul(d, a, R2);
}
/*
* Convert from Montgomery representation.
*/
static void
_src_ec_ec_p256_m62_cf256_frommonty(uint64_t *d, const uint64_t *a)
{
/*
* Montgomery multiplication by 1 is division by 2^260 modulo p.
*/
static const uint64_t one[] = { 1, 0, 0, 0, 0 };
_src_ec_ec_p256_m62_cf256_montymul(d, a, one);
}
/*
* Inversion in the field. If the source value is 0 modulo p, then this
* returns 0 or p. This function uses Montgomery representation.
*/
static void
_src_ec_ec_p256_m62_cf256_invert(uint64_t *d, const uint64_t *a)
{
/*
* We compute a^(p-2) mod p. The exponent pattern (from high to
* low) is:
* - 32 bits of value 1
* - 31 bits of value 0
* - 1 bit of value 1
* - 96 bits of value 0
* - 94 bits of value 1
* - 1 bit of value 0
* - 1 bit of value 1
* To speed up the square-and-multiply algorithm, we precompute
* a^(2^31-1).
*/
uint64_t r[5], t[5];
int i;
memcpy(t, a, sizeof t);
for (i = 0; i < 30; i ++) {
_src_ec_ec_p256_m62_cf256_montysquare(t, t);
_src_ec_ec_p256_m62_cf256_montymul(t, t, a);
}
memcpy(r, t, sizeof t);
for (i = 224; i >= 0; i --) {
_src_ec_ec_p256_m62_cf256_montysquare(r, r);
switch (i) {
case 0:
case 2:
case 192:
case 224:
_src_ec_ec_p256_m62_cf256_montymul(r, r, a);
break;
case 3:
case 34:
case 65:
_src_ec_ec_p256_m62_cf256_montymul(r, r, t);
break;
}
}
memcpy(d, r, sizeof r);
}
/*
* Finalize reduction.
* Input value should be partially reduced.
* On output, limbs a[0] to a[3] fit on 52 bits each, limb a[4] fits
* on 48 bits, and the integer is less than p.
*/
static inline void
_src_ec_ec_p256_m62_cf256_final_reduce(uint64_t *a)
{
uint64_t r[5], t[5], w, cc;
int i;
/*
* Propagate carries to ensure that limbs 0 to 3 fit on 52 bits.
*/
cc = 0;
for (i = 0; i < 5; i ++) {
w = a[i] + cc;
r[i] = w & MASK52;
cc = w >> 52;
}
/*
* We compute t = r + (2^256 - p) = r + 2^224 - 2^192 - 2^96 + 1.
* If t < 2^256, then r < p, and we return r. Otherwise, we
* want to return r - p = t - 2^256.
*/
/*
* Add 2^224 + 1, and propagate carries to ensure that limbs
* t[0] to t[3] fit in 52 bits each.
*/
w = r[0] + 1;
t[0] = w & MASK52;
cc = w >> 52;
w = r[1] + cc;
t[1] = w & MASK52;
cc = w >> 52;
w = r[2] + cc;
t[2] = w & MASK52;
cc = w >> 52;
w = r[3] + cc;
t[3] = w & MASK52;
cc = w >> 52;
t[4] = r[4] + cc + BIT(16);
/*
* Subtract 2^192 + 2^96. Since we just added 2^224 + 1, the
* result cannot be negative.
*/
w = t[1] - BIT(44);
t[1] = w & MASK52;
cc = w >> 63;
w = t[2] - cc;
t[2] = w & MASK52;
cc = w >> 63;
w = t[3] - BIT(36) - cc;
t[3] = w & MASK52;
cc = w >> 63;
t[4] -= cc;
/*
* If the top limb t[4] fits on 48 bits, then r[] is already
* in the proper range. Otherwise, t[] is the value to return
* (truncated to 256 bits).
*/
cc = -(t[4] >> 48);
t[4] &= MASK48;
for (i = 0; i < 5; i ++) {
a[i] = r[i] ^ (cc & (r[i] ^ t[i]));
}
}
/*
* Points in affine and Jacobian coordinates.
*
* - In affine coordinates, the point-at-infinity cannot be encoded.
* - Jacobian coordinates (X,Y,Z) correspond to affine (X/Z^2,Y/Z^3);
* if Z = 0 then this is the point-at-infinity.
*/
typedef struct {
uint64_t x[5];
uint64_t y[5];
} _src_ec_ec_p256_m62_cp256_affine;
typedef struct {
uint64_t x[5];
uint64_t y[5];
uint64_t z[5];
} p256__src_ec_ec_p256_m62_cjacobian;
/*
* Decode a field element (unsigned big endian notation).
*/
static void
f256_decode(uint64_t *a, const unsigned char *buf)
{
uint64_t w0, w1, w2, w3;
w3 = br_dec64be(buf + 0);
w2 = br_dec64be(buf + 8);
w1 = br_dec64be(buf + 16);
w0 = br_dec64be(buf + 24);
a[0] = w0 & MASK52;
a[1] = ((w0 >> 52) | (w1 << 12)) & MASK52;
a[2] = ((w1 >> 40) | (w2 << 24)) & MASK52;
a[3] = ((w2 >> 28) | (w3 << 36)) & MASK52;
a[4] = w3 >> 16;
}
/*
* Encode a field element (unsigned big endian notation). The field
* element MUST be fully reduced.
*/
static void
f256_encode(unsigned char *buf, const uint64_t *a)
{
uint64_t w0, w1, w2, w3;
w0 = a[0] | (a[1] << 52);
w1 = (a[1] >> 12) | (a[2] << 40);
w2 = (a[2] >> 24) | (a[3] << 28);
w3 = (a[3] >> 36) | (a[4] << 16);
br_enc64be(buf + 0, w3);
br_enc64be(buf + 8, w2);
br_enc64be(buf + 16, w1);
br_enc64be(buf + 24, w0);
}
/*
* Decode a point. The returned point is in Jacobian coordinates, but
* with z = 1. If the encoding is invalid, or encodes a point which is
* not on the curve, or encodes the point at infinity, then this function
* returns 0. Otherwise, 1 is returned.
*
* The buffer is assumed to have length exactly 65 bytes.
*/
static uint32_t
_src_ec_ec_p256_m62_cpoint_decode(p256__src_ec_ec_p256_m62_cjacobian *P, const unsigned char *buf)
{
uint64_t x[5], y[5], t[5], x3[5], tt;
uint32_t r;
/*
* Header byte shall be 0x04.
*/
r = EQ(buf[0], 0x04);
/*
* Decode X and Y coordinates, and convert them into
* Montgomery representation.
*/
f256_decode(x, buf + 1);
f256_decode(y, buf + 33);
_src_ec_ec_p256_m62_cf256_tomonty(x, x);
_src_ec_ec_p256_m62_cf256_tomonty(y, y);
/*
* Verify y^2 = x^3 + A*x + B. In curve P-256, A = -3.
* Note that the Montgomery representation of 0 is 0. We must
* take care to apply the final reduction to make sure we have
* 0 and not p.
*/
_src_ec_ec_p256_m62_cf256_montysquare(t, y);
_src_ec_ec_p256_m62_cf256_montysquare(x3, x);
_src_ec_ec_p256_m62_cf256_montymul(x3, x3, x);
_src_ec_ec_p256_m62_cf256_sub(t, t, x3);
_src_ec_ec_p256_m62_cf256_add(t, t, x);
_src_ec_ec_p256_m62_cf256_add(t, t, x);
_src_ec_ec_p256_m62_cf256_add(t, t, x);
_src_ec_ec_p256_m62_cf256_sub(t, t, _src_ec_ec_p256_m62_cP256_B_MONTY);
_src_ec_ec_p256_m62_cf256_final_reduce(t);
tt = t[0] | t[1] | t[2] | t[3] | t[4];
r &= EQ((uint32_t)(tt | (tt >> 32)), 0);
/*
* Return the point in Jacobian coordinates (and Montgomery
* representation).
*/
memcpy(P->x, x, sizeof x);
memcpy(P->y, y, sizeof y);
memcpy(P->z, _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R, sizeof _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R);
return r;
}
/*
* Final conversion for a point:
* - The point is converted back to affine coordinates.
* - Final reduction is performed.
* - The point is encoded into the provided buffer.
*
* If the point is the point-at-infinity, all operations are performed,
* but the buffer contents are indeterminate, and 0 is returned. Otherwise,
* the encoded point is written in the buffer, and 1 is returned.
*/
static uint32_t
_src_ec_ec_p256_m62_cpoint_encode(unsigned char *buf, const p256__src_ec_ec_p256_m62_cjacobian *P)
{
uint64_t t1[5], t2[5], z;
/* Set t1 = 1/z^2 and t2 = 1/z^3. */
_src_ec_ec_p256_m62_cf256_invert(t2, P->z);
_src_ec_ec_p256_m62_cf256_montysquare(t1, t2);
_src_ec_ec_p256_m62_cf256_montymul(t2, t2, t1);
/* Compute affine coordinates x (in t1) and y (in t2). */
_src_ec_ec_p256_m62_cf256_montymul(t1, P->x, t1);
_src_ec_ec_p256_m62_cf256_montymul(t2, P->y, t2);
/* Convert back from Montgomery representation, and finalize
reductions. */
_src_ec_ec_p256_m62_cf256_frommonty(t1, t1);
_src_ec_ec_p256_m62_cf256_frommonty(t2, t2);
_src_ec_ec_p256_m62_cf256_final_reduce(t1);
_src_ec_ec_p256_m62_cf256_final_reduce(t2);
/* Encode. */
buf[0] = 0x04;
f256_encode(buf + 1, t1);
f256_encode(buf + 33, t2);
/* Return success if and only if P->z != 0. */
z = P->z[0] | P->z[1] | P->z[2] | P->z[3] | P->z[4];
return NEQ((uint32_t)(z | z >> 32), 0);
}
/*
* Point doubling in Jacobian coordinates: point P is doubled.
* Note: if the source point is the point-at-infinity, then the result is
* still the point-at-infinity, which is correct. Moreover, if the three
* coordinates were zero, then they still are zero in the returned value.
*/
static void
_src_ec_ec_p256_m62_cp256_double(p256__src_ec_ec_p256_m62_cjacobian *P)
{
/*
* Doubling formulas are:
*
* s = 4*x*y^2
* m = 3*(x + z^2)*(x - z^2)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y^4
* z' = 2*y*z
*
* These formulas work for all points, including points of order 2
* and points at infinity:
* - If y = 0 then z' = 0. But there is no such point in P-256
* anyway.
* - If z = 0 then z' = 0.
*/
uint64_t t1[5], t2[5], t3[5], t4[5];
/*
* Compute z^2 in t1.
*/
_src_ec_ec_p256_m62_cf256_montysquare(t1, P->z);
/*
* Compute x-z^2 in t2 and x+z^2 in t1.
*/
_src_ec_ec_p256_m62_cf256_add(t2, P->x, t1);
_src_ec_ec_p256_m62_cf256_sub(t1, P->x, t1);
/*
* Compute 3*(x+z^2)*(x-z^2) in t1.
*/
_src_ec_ec_p256_m62_cf256_montymul(t3, t1, t2);
_src_ec_ec_p256_m62_cf256_add(t1, t3, t3);
_src_ec_ec_p256_m62_cf256_add(t1, t3, t1);
/*
* Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t3, P->y);
_src_ec_ec_p256_m62_cf256_add(t3, t3, t3);
_src_ec_ec_p256_m62_cf256_montymul(t2, P->x, t3);
_src_ec_ec_p256_m62_cf256_add(t2, t2, t2);
/*
* Compute x' = m^2 - 2*s.
*/
_src_ec_ec_p256_m62_cf256_montysquare(P->x, t1);
_src_ec_ec_p256_m62_cf256_sub(P->x, P->x, t2);
_src_ec_ec_p256_m62_cf256_sub(P->x, P->x, t2);
/*
* Compute z' = 2*y*z.
*/
_src_ec_ec_p256_m62_cf256_montymul(t4, P->y, P->z);
_src_ec_ec_p256_m62_cf256_add(P->z, t4, t4);
f256_partial_reduce(P->z);
/*
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
* 2*y^2 in t3.
*/
_src_ec_ec_p256_m62_cf256_sub(t2, t2, P->x);
_src_ec_ec_p256_m62_cf256_montymul(P->y, t1, t2);
_src_ec_ec_p256_m62_cf256_montysquare(t4, t3);
_src_ec_ec_p256_m62_cf256_add(t4, t4, t4);
_src_ec_ec_p256_m62_cf256_sub(P->y, P->y, t4);
}
/*
* Point addition (Jacobian coordinates): P1 is replaced with P1+P2.
* This function computes the wrong result in the following cases:
*
* - If P1 == 0 but P2 != 0
* - If P1 != 0 but P2 == 0
* - If P1 == P2
*
* In all three cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y coordinate.
* - P1 == 0 and P2 == 0.
* - The Y coordinate of one of the points is 0 and the other point is
* the point at infinity.
*
* The third case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*
* Note that you can get a returned value of 0 with a correct result,
* e.g. if P1 and P2 have the same Y coordinate, but distinct X coordinates.
*/
static uint32_t
_src_ec_ec_p256_m62_cp256_add(p256__src_ec_ec_p256_m62_cjacobian *P1, const p256__src_ec_ec_p256_m62_cjacobian *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1 * z2^2
* u2 = x2 * z1^2
* s1 = y1 * z2^3
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1 * z2
*/
uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt;
uint32_t ret;
/*
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t3, P2->z);
_src_ec_ec_p256_m62_cf256_montymul(t1, P1->x, t3);
_src_ec_ec_p256_m62_cf256_montymul(t4, P2->z, t3);
_src_ec_ec_p256_m62_cf256_montymul(t3, P1->y, t4);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t4, P1->z);
_src_ec_ec_p256_m62_cf256_montymul(t2, P2->x, t4);
_src_ec_ec_p256_m62_cf256_montymul(t5, P1->z, t4);
_src_ec_ec_p256_m62_cf256_montymul(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
_src_ec_ec_p256_m62_cf256_sub(t2, t2, t1);
_src_ec_ec_p256_m62_cf256_sub(t4, t4, t3);
_src_ec_ec_p256_m62_cf256_final_reduce(t4);
tt = t4[0] | t4[1] | t4[2] | t4[3] | t4[4];
ret = (uint32_t)(tt | (tt >> 32));
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m62_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m62_cf256_montymul(t6, t1, t7);
_src_ec_ec_p256_m62_cf256_montymul(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m62_cf256_montysquare(P1->x, t4);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t5);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t6);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
_src_ec_ec_p256_m62_cf256_sub(t6, t6, P1->x);
_src_ec_ec_p256_m62_cf256_montymul(P1->y, t4, t6);
_src_ec_ec_p256_m62_cf256_montymul(t1, t5, t3);
_src_ec_ec_p256_m62_cf256_sub(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m62_cf256_montymul(t1, P1->z, P2->z);
_src_ec_ec_p256_m62_cf256_montymul(P1->z, t1, t2);
return ret;
}
/*
* Point addition (mixed coordinates): P1 is replaced with P1+P2.
* This is a specialised function for the case when P2 is a non-zero point
* in affine coordinates.
*
* This function computes the wrong result in the following cases:
*
* - If P1 == 0
* - If P1 == P2
*
* In both cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y (affine) coordinate.
* - The Y coordinate of P2 is 0 and P1 is the point at infinity.
*
* The second case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*
* Again, a value of 0 may be returned in some cases where the addition
* result is correct.
*/
static uint32_t
_src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cp256_add_mixed(p256__src_ec_ec_p256_m62_cjacobian *P1, const _src_ec_ec_p256_m62_cp256_affine *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1
* u2 = x2 * z1^2
* s1 = y1
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1
*/
uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt;
uint32_t ret;
/*
* Compute u1 = x1 (in t1) and s1 = y1 (in t3).
*/
memcpy(t1, P1->x, sizeof t1);
memcpy(t3, P1->y, sizeof t3);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t4, P1->z);
_src_ec_ec_p256_m62_cf256_montymul(t2, P2->x, t4);
_src_ec_ec_p256_m62_cf256_montymul(t5, P1->z, t4);
_src_ec_ec_p256_m62_cf256_montymul(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
_src_ec_ec_p256_m62_cf256_sub(t2, t2, t1);
_src_ec_ec_p256_m62_cf256_sub(t4, t4, t3);
_src_ec_ec_p256_m62_cf256_final_reduce(t4);
tt = t4[0] | t4[1] | t4[2] | t4[3] | t4[4];
ret = (uint32_t)(tt | (tt >> 32));
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m62_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m62_cf256_montymul(t6, t1, t7);
_src_ec_ec_p256_m62_cf256_montymul(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m62_cf256_montysquare(P1->x, t4);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t5);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t6);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
_src_ec_ec_p256_m62_cf256_sub(t6, t6, P1->x);
_src_ec_ec_p256_m62_cf256_montymul(P1->y, t4, t6);
_src_ec_ec_p256_m62_cf256_montymul(t1, t5, t3);
_src_ec_ec_p256_m62_cf256_sub(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m62_cf256_montymul(P1->z, P1->z, t2);
return ret;
}
#if 0
/* unused */
/*
* Point addition (mixed coordinates, complete): P1 is replaced with P1+P2.
* This is a specialised function for the case when P2 is a non-zero point
* in affine coordinates.
*
* This function returns the correct result in all cases.
*/
static uint32_t
_src_ec_ec_p256_m62_cp256_add_complete_mixed(p256__src_ec_ec_p256_m62_cjacobian *P1, const _src_ec_ec_p256_m62_cp256_affine *P2)
{
/*
* Addtions formulas, in the general case, are:
*
* u1 = x1
* u2 = x2 * z1^2
* s1 = y1
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1
*
* These formulas mishandle the two following cases:
*
* - If P1 is the point-at-infinity (z1 = 0), then z3 is
* incorrectly set to 0.
*
* - If P1 = P2, then u1 = u2 and s1 = s2, and x3, y3 and z3
* are all set to 0.
*
* However, if P1 + P2 = 0, then u1 = u2 but s1 != s2, and then
* we correctly get z3 = 0 (the point-at-infinity).
*
* To fix the case P1 = 0, we perform at the end a copy of P2
* over P1, conditional to z1 = 0.
*
* For P1 = P2: in that case, both h and r are set to 0, and
* we get x3, y3 and z3 equal to 0. We can test for that
* occurrence to make a mask which will be all-one if P1 = P2,
* or all-zero otherwise; then we can compute the double of P2
* and add it, combined with the mask, to (x3,y3,z3).
*
* Using the doubling formulas in _src_ec_ec_p256_m62_cp256_double() on (x2,y2),
* simplifying since P2 is affine (i.e. z2 = 1, implicitly),
* we get:
* s = 4*x2*y2^2
* m = 3*(x2 + 1)*(x2 - 1)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y2^4
* z' = 2*y2
* which requires only 6 multiplications. Added to the 11
* multiplications of the normal mixed addition in Jacobian
* coordinates, we get a cost of 17 multiplications in total.
*/
uint64_t t1[5], t2[5], t3[5], t4[5], t5[5], t6[5], t7[5], tt, zz;
int i;
/*
* Set zz to -1 if P1 is the point at infinity, 0 otherwise.
*/
zz = P1->z[0] | P1->z[1] | P1->z[2] | P1->z[3] | P1->z[4];
zz = ((zz | -zz) >> 63) - (uint64_t)1;
/*
* Compute u1 = x1 (in t1) and s1 = y1 (in t3).
*/
memcpy(t1, P1->x, sizeof t1);
memcpy(t3, P1->y, sizeof t3);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t4, P1->z);
_src_ec_ec_p256_m62_cf256_montymul(t2, P2->x, t4);
_src_ec_ec_p256_m62_cf256_montymul(t5, P1->z, t4);
_src_ec_ec_p256_m62_cf256_montymul(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* reduce.
*/
_src_ec_ec_p256_m62_cf256_sub(t2, t2, t1);
_src_ec_ec_p256_m62_cf256_sub(t4, t4, t3);
/*
* If both h = 0 and r = 0, then P1 = P2, and we want to set
* the mask tt to -1; otherwise, the mask will be 0.
*/
_src_ec_ec_p256_m62_cf256_final_reduce(t2);
_src_ec_ec_p256_m62_cf256_final_reduce(t4);
tt = t2[0] | t2[1] | t2[2] | t2[3] | t2[4]
| t4[0] | t4[1] | t4[2] | t4[3] | t4[4];
tt = ((tt | -tt) >> 63) - (uint64_t)1;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m62_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m62_cf256_montymul(t6, t1, t7);
_src_ec_ec_p256_m62_cf256_montymul(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m62_cf256_montysquare(P1->x, t4);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t5);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t6);
_src_ec_ec_p256_m62_cf256_sub(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
_src_ec_ec_p256_m62_cf256_sub(t6, t6, P1->x);
_src_ec_ec_p256_m62_cf256_montymul(P1->y, t4, t6);
_src_ec_ec_p256_m62_cf256_montymul(t1, t5, t3);
_src_ec_ec_p256_m62_cf256_sub(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1.
*/
_src_ec_ec_p256_m62_cf256_montymul(P1->z, P1->z, t2);
/*
* The "double" result, in case P1 = P2.
*/
/*
* Compute z' = 2*y2 (in t1).
*/
_src_ec_ec_p256_m62_cf256_add(t1, P2->y, P2->y);
f256_partial_reduce(t1);
/*
* Compute 2*(y2^2) (in t2) and s = 4*x2*(y2^2) (in t3).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t2, P2->y);
_src_ec_ec_p256_m62_cf256_add(t2, t2, t2);
_src_ec_ec_p256_m62_cf256_add(t3, t2, t2);
_src_ec_ec_p256_m62_cf256_montymul(t3, P2->x, t3);
/*
* Compute m = 3*(x2^2 - 1) (in t4).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t4, P2->x);
_src_ec_ec_p256_m62_cf256_sub(t4, t4, _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R);
_src_ec_ec_p256_m62_cf256_add(t5, t4, t4);
_src_ec_ec_p256_m62_cf256_add(t4, t4, t5);
/*
* Compute x' = m^2 - 2*s (in t5).
*/
_src_ec_ec_p256_m62_cf256_montysquare(t5, t4);
_src_ec_ec_p256_m62_cf256_sub(t5, t3);
_src_ec_ec_p256_m62_cf256_sub(t5, t3);
/*
* Compute y' = m*(s - x') - 8*y2^4 (in t6).
*/
_src_ec_ec_p256_m62_cf256_sub(t6, t3, t5);
_src_ec_ec_p256_m62_cf256_montymul(t6, t6, t4);
_src_ec_ec_p256_m62_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m62_cf256_sub(t6, t6, t7);
_src_ec_ec_p256_m62_cf256_sub(t6, t6, t7);
/*
* We now have the alternate (doubling) coordinates in (t5,t6,t1).
* We combine them with (x3,y3,z3).
*/
for (i = 0; i < 5; i ++) {
P1->x[i] |= tt & t5[i];
P1->y[i] |= tt & t6[i];
P1->z[i] |= tt & t1[i];
}
/*
* If P1 = 0, then we get z3 = 0 (which is invalid); if z1 is 0,
* then we want to replace the result with a copy of P2. The
* test on z1 was done at the start, in the zz mask.
*/
for (i = 0; i < 5; i ++) {
P1->x[i] ^= zz & (P1->x[i] ^ P2->x[i]);
P1->y[i] ^= zz & (P1->y[i] ^ P2->y[i]);
P1->z[i] ^= zz & (P1->z[i] ^ _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R[i]);
}
}
#endif
/*
* Inner function for computing a point multiplication. A window is
* provided, with points 1*P to 15*P in affine coordinates.
*
* Assumptions:
* - All provided points are valid points on the curve.
* - Multiplier is non-zero, and smaller than the curve order.
* - Everything is in Montgomery representation.
*/
static void
_src_ec_ec_p256_m62_cpoint_mul_inner(p256__src_ec_ec_p256_m62_cjacobian *R, const _src_ec_ec_p256_m62_cp256_affine *W,
const unsigned char *k, size_t klen)
{
p256__src_ec_ec_p256_m62_cjacobian Q;
uint32_t qz;
memset(&Q, 0, sizeof Q);
qz = 1;
while (klen -- > 0) {
int i;
unsigned bk;
bk = *k ++;
for (i = 0; i < 2; i ++) {
uint32_t bits;
uint32_t bnz;
_src_ec_ec_p256_m62_cp256_affine T;
p256__src_ec_ec_p256_m62_cjacobian U;
uint32_t n;
int j;
uint64_t m;
_src_ec_ec_p256_m62_cp256_double(&Q);
_src_ec_ec_p256_m62_cp256_double(&Q);
_src_ec_ec_p256_m62_cp256_double(&Q);
_src_ec_ec_p256_m62_cp256_double(&Q);
bits = (bk >> 4) & 0x0F;
bnz = NEQ(bits, 0);
/*
* Lookup point in window. If the bits are 0,
* we get something invalid, which is not a
* problem because we will use it only if the
* bits are non-zero.
*/
memset(&T, 0, sizeof T);
for (n = 0; n < 15; n ++) {
m = -(uint64_t)EQ(bits, n + 1);
T.x[0] |= m & W[n].x[0];
T.x[1] |= m & W[n].x[1];
T.x[2] |= m & W[n].x[2];
T.x[3] |= m & W[n].x[3];
T.x[4] |= m & W[n].x[4];
T.y[0] |= m & W[n].y[0];
T.y[1] |= m & W[n].y[1];
T.y[2] |= m & W[n].y[2];
T.y[3] |= m & W[n].y[3];
T.y[4] |= m & W[n].y[4];
}
U = Q;
_src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cp256_add_mixed(&U, &T);
/*
* If qz is still 1, then Q was all-zeros, and this
* is conserved through _src_ec_ec_p256_m62_cp256_double().
*/
m = -(uint64_t)(bnz & qz);
for (j = 0; j < 5; j ++) {
Q.x[j] ^= m & (Q.x[j] ^ T.x[j]);
Q.y[j] ^= m & (Q.y[j] ^ T.y[j]);
Q.z[j] ^= m & (Q.z[j] ^ _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R[j]);
}
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
bk <<= 4;
}
}
*R = Q;
}
/*
* Convert a window from Jacobian to affine coordinates. A single
* field inversion is used. This function works for windows up to
* 32 elements.
*
* The destination array (aff[]) and the source array (jac[]) may
* overlap, provided that the start of aff[] is not after the start of
* jac[]. Even if the arrays do _not_ overlap, the source array is
* modified.
*/
static void
_src_ec_ec_p256_m62_cwindow_to_affine(_src_ec_ec_p256_m62_cp256_affine *aff, p256__src_ec_ec_p256_m62_cjacobian *jac, int num)
{
/*
* Convert the window points to affine coordinates. We use the
* following trick to mutualize the inversion computation: if
* we have z1, z2, z3, and z4, and want to invert all of them,
* we compute u = 1/(z1*z2*z3*z4), and then we have:
* 1/z1 = u*z2*z3*z4
* 1/z2 = u*z1*z3*z4
* 1/z3 = u*z1*z2*z4
* 1/z4 = u*z1*z2*z3
*
* The partial products are computed recursively:
*
* - on input (z_1,z_2), return (z_2,z_1) and z_1*z_2
* - on input (z_1,z_2,... z_n):
* recurse on (z_1,z_2,... z_(n/2)) -> r1 and m1
* recurse on (z_(n/2+1),z_(n/2+2)... z_n) -> r2 and m2
* multiply elements of r1 by m2 -> s1
* multiply elements of r2 by m1 -> s2
* return r1||r2 and m1*m2
*
* In the example below, we suppose that we have 14 elements.
* Let z1, z2,... zE be the 14 values to invert (index noted in
* hexadecimal, starting at 1).
*
* - Depth 1:
* swap(z1, z2); z12 = z1*z2
* swap(z3, z4); z34 = z3*z4
* swap(z5, z6); z56 = z5*z6
* swap(z7, z8); z78 = z7*z8
* swap(z9, zA); z9A = z9*zA
* swap(zB, zC); zBC = zB*zC
* swap(zD, zE); zDE = zD*zE
*
* - Depth 2:
* z1 <- z1*z34, z2 <- z2*z34, z3 <- z3*z12, z4 <- z4*z12
* z1234 = z12*z34
* z5 <- z5*z78, z6 <- z6*z78, z7 <- z7*z56, z8 <- z8*z56
* z5678 = z56*z78
* z9 <- z9*zBC, zA <- zA*zBC, zB <- zB*z9A, zC <- zC*z9A
* z9ABC = z9A*zBC
*
* - Depth 3:
* z1 <- z1*z5678, z2 <- z2*z5678, z3 <- z3*z5678, z4 <- z4*z5678
* z5 <- z5*z1234, z6 <- z6*z1234, z7 <- z7*z1234, z8 <- z8*z1234
* z12345678 = z1234*z5678
* z9 <- z9*zDE, zA <- zA*zDE, zB <- zB*zDE, zC <- zC*zDE
* zD <- zD*z9ABC, zE*z9ABC
* z9ABCDE = z9ABC*zDE
*
* - Depth 4:
* multiply z1..z8 by z9ABCDE
* multiply z9..zE by z12345678
* final z = z12345678*z9ABCDE
*/
uint64_t z[16][5];
int i, k, s;
#define zt (z[15])
#define zu (z[14])
#define zv (z[13])
/*
* First recursion step (pairwise swapping and multiplication).
* If there is an odd number of elements, then we "invent" an
* extra one with coordinate Z = 1 (in Montgomery representation).
*/
for (i = 0; (i + 1) < num; i += 2) {
memcpy(zt, jac[i].z, sizeof zt);
memcpy(jac[i].z, jac[i + 1].z, sizeof zt);
memcpy(jac[i + 1].z, zt, sizeof zt);
_src_ec_ec_p256_m62_cf256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z);
}
if ((num & 1) != 0) {
memcpy(z[num >> 1], jac[num - 1].z, sizeof zt);
memcpy(jac[num - 1].z, _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R, sizeof _src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cF256_R);
}
/*
* Perform further recursion steps. At the entry of each step,
* the process has been done for groups of 's' points. The
* integer k is the log2 of s.
*/
for (k = 1, s = 2; s < num; k ++, s <<= 1) {
int n;
for (i = 0; i < num; i ++) {
_src_ec_ec_p256_m62_cf256_montymul(jac[i].z, jac[i].z, z[(i >> k) ^ 1]);
}
n = (num + s - 1) >> k;
for (i = 0; i < (n >> 1); i ++) {
_src_ec_ec_p256_m62_cf256_montymul(z[i], z[i << 1], z[(i << 1) + 1]);
}
if ((n & 1) != 0) {
memmove(z[n >> 1], z[n], sizeof zt);
}
}
/*
* Invert the final result, and convert all points.
*/
_src_ec_ec_p256_m62_cf256_invert(zt, z[0]);
for (i = 0; i < num; i ++) {
_src_ec_ec_p256_m62_cf256_montymul(zv, jac[i].z, zt);
_src_ec_ec_p256_m62_cf256_montysquare(zu, zv);
_src_ec_ec_p256_m62_cf256_montymul(zv, zv, zu);
_src_ec_ec_p256_m62_cf256_montymul(aff[i].x, jac[i].x, zu);
_src_ec_ec_p256_m62_cf256_montymul(aff[i].y, jac[i].y, zv);
}
}
/*
* Multiply the provided point by an integer.
* Assumptions:
* - Source point is a valid curve point.
* - Source point is not the point-at-infinity.
* - Integer is not 0, and is lower than the curve order.
* If these conditions are not met, then the result is indeterminate
* (but the process is still constant-time).
*/
static void
_src_ec_ec_p256_m62_cp256_mul(p256__src_ec_ec_p256_m62_cjacobian *P, const unsigned char *k, size_t klen)
{
union {
_src_ec_ec_p256_m62_cp256_affine aff[15];
p256__src_ec_ec_p256_m62_cjacobian jac[15];
} window;
int i;
/*
* Compute window, in Jacobian coordinates.
*/
window.jac[0] = *P;
for (i = 2; i < 16; i ++) {
window.jac[i - 1] = window.jac[(i >> 1) - 1];
if ((i & 1) == 0) {
_src_ec_ec_p256_m62_cp256_double(&window.jac[i - 1]);
} else {
_src_ec_ec_p256_m62_cp256_add(&window.jac[i - 1], &window.jac[i >> 1]);
}
}
/*
* Convert the window points to affine coordinates. Point
* window[0] is the source point, already in affine coordinates.
*/
_src_ec_ec_p256_m62_cwindow_to_affine(window.aff, window.jac, 15);
/*
* Perform point multiplication.
*/
_src_ec_ec_p256_m62_cpoint_mul_inner(P, window.aff, k, klen);
}
/*
* Precomputed window for the conventional generator: _src_ec_ec_p256_m62_cP256__src_ec_ec_p256_m62_cGwin[n]
* contains (n+1)*G (affine coordinates, in Montgomery representation).
*/
static const _src_ec_ec_p256_m62_cp256_affine _src_ec_ec_p256_m62_cP256__src_ec_ec_p256_m62_cGwin[] = {
{
{ 0x30D418A9143C1, 0xC4FEDB60179E7, 0x62251075BA95F,
0x5C669FB732B77, 0x08905F76B5375 },
{ 0x5357CE95560A8, 0x43A19E45CDDF2, 0x21F3258B4AB8E,
0xD8552E88688DD, 0x0571FF18A5885 }
},
{
{ 0x46D410DDD64DF, 0x0B433827D8500, 0x1490D9AA6AE3C,
0xA3A832205038D, 0x06BB32E52DCF3 },
{ 0x48D361BEE1A57, 0xB7B236FF82F36, 0x042DBE152CD7C,
0xA3AA9A8FB0E92, 0x08C577517A5B8 }
},
{
{ 0x3F904EEBC1272, 0x9E87D81FBFFAC, 0xCBBC98B027F84,
0x47E46AD77DD87, 0x06936A3FD6FF7 },
{ 0x5C1FC983A7EBD, 0xC3861FE1AB04C, 0x2EE98E583E47A,
0xC06A88208311A, 0x05F06A2AB587C }
},
{
{ 0xB50D46918DCC5, 0xD7623C17374B0, 0x100AF24650A6E,
0x76ABCDAACACE8, 0x077362F591B01 },
{ 0xF24CE4CBABA68, 0x17AD6F4472D96, 0xDDD22E1762847,
0x862EB6C36DEE5, 0x04B14C39CC5AB }
},
{
{ 0x8AAEC45C61F5C, 0x9D4B9537DBE1B, 0x76C20C90EC649,
0x3C7D41CB5AAD0, 0x0907960649052 },
{ 0x9B4AE7BA4F107, 0xF75EB882BEB30, 0x7A1F6873C568E,
0x915C540A9877E, 0x03A076BB9DD1E }
},
{
{ 0x47373E77664A1, 0xF246CEE3E4039, 0x17A3AD55AE744,
0x673C50A961A5B, 0x03074B5964213 },
{ 0x6220D377E44BA, 0x30DFF14B593D3, 0x639F11299C2B5,
0x75F5424D44CEF, 0x04C9916DEA07F }
},
{
{ 0x354EA0173B4F1, 0x3C23C00F70746, 0x23BB082BD2021,
0xE03E43EAAB50C, 0x03BA5119D3123 },
{ 0xD0303F5B9D4DE, 0x17DA67BDD2847, 0xC941956742F2F,
0x8670F933BDC77, 0x0AEDD9164E240 }
},
{
{ 0x4CD19499A78FB, 0x4BF9B345527F1, 0x2CFC6B462AB5C,
0x30CDF90F02AF0, 0x0763891F62652 },
{ 0xA3A9532D49775, 0xD7F9EBA15F59D, 0x60BBF021E3327,
0xF75C23C7B84BE, 0x06EC12F2C706D }
},
{
{ 0x6E8F264E20E8E, 0xC79A7A84175C9, 0xC8EB00ABE6BFE,
0x16A4CC09C0444, 0x005B3081D0C4E },
{ 0x777AA45F33140, 0xDCE5D45E31EB7, 0xB12F1A56AF7BE,
0xF9B2B6E019A88, 0x086659CDFD835 }
},
{
{ 0xDBD19DC21EC8C, 0x94FCF81392C18, 0x250B4998F9868,
0x28EB37D2CD648, 0x0C61C947E4B34 },
{ 0x407880DD9E767, 0x0C83FBE080C2B, 0x9BE5D2C43A899,
0xAB4EF7D2D6577, 0x08719A555B3B4 }
},
{
{ 0x260A6245E4043, 0x53E7FDFE0EA7D, 0xAC1AB59DE4079,
0x072EFF3A4158D, 0x0E7090F1949C9 },
{ 0x85612B944E886, 0xE857F61C81A76, 0xAD643D250F939,
0x88DAC0DAA891E, 0x089300244125B }
},
{
{ 0x1AA7D26977684, 0x58A345A3304B7, 0x37385EABDEDEF,
0x155E409D29DEE, 0x0EE1DF780B83E },
{ 0x12D91CBB5B437, 0x65A8956370CAC, 0xDE6D66170ED2F,
0xAC9B8228CFA8A, 0x0FF57C95C3238 }
},
{
{ 0x25634B2ED7097, 0x9156FD30DCCC4, 0x9E98110E35676,
0x7594CBCD43F55, 0x038477ACC395B },
{ 0x2B90C00EE17FF, 0xF842ED2E33575, 0x1F5BC16874838,
0x7968CD06422BD, 0x0BC0876AB9E7B }
},
{
{ 0xA35BB0CF664AF, 0x68F9707E3A242, 0x832660126E48F,
0x72D2717BF54C6, 0x0AAE7333ED12C },
{ 0x2DB7995D586B1, 0xE732237C227B5, 0x65E7DBBE29569,
0xBBBD8E4193E2A, 0x052706DC3EAA1 }
},
{
{ 0xD8B7BC60055BE, 0xD76E27E4B72BC, 0x81937003CC23E,
0xA090E337424E4, 0x02AA0E43EAD3D },
{ 0x524F6383C45D2, 0x422A41B2540B8, 0x8A4797D766355,
0xDF444EFA6DE77, 0x0042170A9079A }
},
};
/*
* Multiply the conventional generator of the curve by the provided
* integer. Return is written in *P.
*
* Assumptions:
* - Integer is not 0, and is lower than the curve order.
* If this conditions is not met, then the result is indeterminate
* (but the process is still constant-time).
*/
static void
_src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cp256_mulgen(p256__src_ec_ec_p256_m62_cjacobian *P, const unsigned char *k, size_t klen)
{
_src_ec_ec_p256_m62_cpoint_mul_inner(P, _src_ec_ec_p256_m62_cP256__src_ec_ec_p256_m62_cGwin, k, klen);
}
/*
* Return 1 if all of the following hold:
* - klen <= 32
* - k != 0
* - k is lower than the curve order
* Otherwise, return 0.
*
* Constant-time behaviour: only klen may be observable.
*/
static uint32_t
_src_ec_ec_p256_m62_ccheck_scalar(const unsigned char *k, size_t klen)
{
uint32_t z;
int32_t c;
size_t u;
if (klen > 32) {
return 0;
}
z = 0;
for (u = 0; u < klen; u ++) {
z |= k[u];
}
if (klen == 32) {
c = 0;
for (u = 0; u < klen; u ++) {
c |= -(int32_t)EQ0(c) & CMP(k[u], _src_ec_ec_p256_m62_cP256_N[u]);
}
} else {
c = -1;
}
return NEQ(z, 0) & LT0(c);
}
static uint32_t
_src_ec_ec_p256_m62_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *k, size_t klen, int curve)
{
uint32_t r;
p256__src_ec_ec_p256_m62_cjacobian P;
(void)curve;
if (Glen != 65) {
return 0;
}
r = _src_ec_ec_p256_m62_ccheck_scalar(k, klen);
r &= _src_ec_ec_p256_m62_cpoint_decode(&P, G);
_src_ec_ec_p256_m62_cp256_mul(&P, k, klen);
r &= _src_ec_ec_p256_m62_cpoint_encode(G, &P);
return r;
}
static size_t
_src_ec_ec_p256_m62_capi_mulgen(unsigned char *R,
const unsigned char *k, size_t klen, int curve)
{
p256__src_ec_ec_p256_m62_cjacobian P;
(void)curve;
_src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cp256_mulgen(&P, k, klen);
_src_ec_ec_p256_m62_cpoint_encode(R, &P);
return 65;
}
static uint32_t
_src_ec_ec_p256_m62_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We might want to use Shamir's trick here: make a composite
* window of u*P+v*Q points, to merge the two doubling-ladders
* into one. This, however, has some complications:
*
* - During the computation, we may hit the point-at-infinity.
* Thus, we would need _src_ec_ec_p256_m62_cp256_add_complete_mixed() (complete
* formulas for point addition), with a higher cost (17 muls
* instead of 11).
*
* - A 4-bit window would be too large, since it would involve
* 16*16-1 = 255 points. For the same window size as in the
* _src_ec_ec_p256_m62_cp256_mul() case, we would need to reduce the window size
* to 2 bits, and thus perform twice as many non-doubling
* point additions.
*
* - The window may itself contain the point-at-infinity, and
* thus cannot be in all generality be made of affine points.
* Instead, we would need to make it a window of points in
* Jacobian coordinates. Even _src_ec_ec_p256_m62_cp256_add_complete_mixed() would
* be inappropriate.
*
* For these reasons, the code below performs two separate
* point multiplications, then computes the final point addition
* (which is both a "normal" addition, and a doubling, to handle
* all cases).
*/
p256__src_ec_ec_p256_m62_cjacobian P, Q;
uint32_t r, t, s;
uint64_t z;
(void)curve;
if (len != 65) {
return 0;
}
r = _src_ec_ec_p256_m62_cpoint_decode(&P, A);
_src_ec_ec_p256_m62_cp256_mul(&P, x, xlen);
if (B == NULL) {
_src_ec_ec_p256_m62_c_src_ec_ec_p256_m62_cp256_mulgen(&Q, y, ylen);
} else {
r &= _src_ec_ec_p256_m62_cpoint_decode(&Q, B);
_src_ec_ec_p256_m62_cp256_mul(&Q, y, ylen);
}
/*
* The final addition may fail in case both points are equal.
*/
t = _src_ec_ec_p256_m62_cp256_add(&P, &Q);
_src_ec_ec_p256_m62_cf256_final_reduce(P.z);
z = P.z[0] | P.z[1] | P.z[2] | P.z[3] | P.z[4];
s = EQ((uint32_t)(z | (z >> 32)), 0);
_src_ec_ec_p256_m62_cp256_double(&Q);
/*
* If s is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
* have the following:
*
* s = 0, t = 0 return P (normal addition)
* s = 0, t = 1 return P (normal addition)
* s = 1, t = 0 return Q (a 'double' case)
* s = 1, t = 1 report an error (P+Q = 0)
*/
CCOPY(s & ~t, &P, &Q, sizeof Q);
_src_ec_ec_p256_m62_cpoint_encode(A, &P);
r &= ~(s & t);
return r;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_p256_m62 = {
(uint32_t)0x00800000,
&_src_ec_ec_p256_m62_capi_generator,
&_src_ec_ec_p256_m62_capi_order,
&_src_ec_ec_p256_m62_capi_xoff,
&_src_ec_ec_p256_m62_capi_mul,
&_src_ec_ec_p256_m62_capi_mulgen,
&_src_ec_ec_p256_m62_capi_muladd
};
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_p256_m62_get(void)
{
return &br_ec_p256_m62;
}
#else
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_p256_m62_get(void)
{
return 0;
}
#endif
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#if BR_INT128 || BR_UMUL128
#if BR_UMUL128
#include
#endif
static const unsigned char _src_ec_ec_p256_m64_cP256_G[] = {
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8,
0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D,
0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8,
0x98, 0xC2, 0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, 0x2B,
0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40,
0x68, 0x37, 0xBF, 0x51, 0xF5
};
static const unsigned char _src_ec_ec_p256_m64_cP256_N[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD,
0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63,
0x25, 0x51
};
static const unsigned char *
_src_ec_ec_p256_m64_capi_generator(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m64_cP256_G;
return _src_ec_ec_p256_m64_cP256_G;
}
static const unsigned char *
_src_ec_ec_p256_m64_capi_order(int curve, size_t *len)
{
(void)curve;
*len = sizeof _src_ec_ec_p256_m64_cP256_N;
return _src_ec_ec_p256_m64_cP256_N;
}
static size_t
_src_ec_ec_p256_m64_capi_xoff(int curve, size_t *len)
{
(void)curve;
*len = 32;
return 1;
}
/*
* A field element is encoded as four 64-bit integers, in basis 2^64.
* Values may reach up to 2^256-1. Montgomery multiplication is used.
*/
/* R = 2^256 mod p */
static const uint64_t _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R[] = {
0x0000000000000001, 0xFFFFFFFF00000000,
0xFFFFFFFFFFFFFFFF, 0x00000000FFFFFFFE
};
/* Curve equation is y^2 = x^3 - 3*x + B. This constant is B*R mod p
(Montgomery representation of B). */
static const uint64_t _src_ec_ec_p256_m64_cP256_B_MONTY[] = {
0xD89CDF6229C4BDDF, 0xACF005CD78843090,
0xE5A220ABF7212ED6, 0xDC30061D04874834
};
/*
* Addition in the field.
*/
static inline void
_src_ec_ec_p256_m64_cf256_add(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
#if BR_INT128
unsigned __int128 w;
uint64_t t;
/*
* Do the addition, with an extra carry in t.
*/
w = (unsigned __int128)a[0] + b[0];
d[0] = (uint64_t)w;
w = (unsigned __int128)a[1] + b[1] + (w >> 64);
d[1] = (uint64_t)w;
w = (unsigned __int128)a[2] + b[2] + (w >> 64);
d[2] = (uint64_t)w;
w = (unsigned __int128)a[3] + b[3] + (w >> 64);
d[3] = (uint64_t)w;
t = (uint64_t)(w >> 64);
/*
* Fold carry t, using: 2^256 = 2^224 - 2^192 - 2^96 + 1 mod p.
*/
w = (unsigned __int128)d[0] + t;
d[0] = (uint64_t)w;
w = (unsigned __int128)d[1] + (w >> 64) - (t << 32);
d[1] = (uint64_t)w;
/* Here, carry "w >> 64" can only be 0 or -1 */
w = (unsigned __int128)d[2] - ((w >> 64) & 1);
d[2] = (uint64_t)w;
/* Again, carry is 0 or -1. But there can be carry only if t = 1,
in which case the addition of (t << 32) - t is positive. */
w = (unsigned __int128)d[3] - ((w >> 64) & 1) + (t << 32) - t;
d[3] = (uint64_t)w;
t = (uint64_t)(w >> 64);
/*
* There can be an extra carry here, which we must fold again.
*/
w = (unsigned __int128)d[0] + t;
d[0] = (uint64_t)w;
w = (unsigned __int128)d[1] + (w >> 64) - (t << 32);
d[1] = (uint64_t)w;
w = (unsigned __int128)d[2] - ((w >> 64) & 1);
d[2] = (uint64_t)w;
d[3] += (t << 32) - t - (uint64_t)((w >> 64) & 1);
#elif BR_UMUL128
unsigned char cc;
uint64_t t;
cc = _addcarry_u64(0, a[0], b[0], &d[0]);
cc = _addcarry_u64(cc, a[1], b[1], &d[1]);
cc = _addcarry_u64(cc, a[2], b[2], &d[2]);
cc = _addcarry_u64(cc, a[3], b[3], &d[3]);
/*
* If there is a carry, then we want to subtract p, which we
* do by adding 2^256 - p.
*/
t = cc;
cc = _addcarry_u64(cc, d[0], 0, &d[0]);
cc = _addcarry_u64(cc, d[1], -(t << 32), &d[1]);
cc = _addcarry_u64(cc, d[2], -t, &d[2]);
cc = _addcarry_u64(cc, d[3], (t << 32) - (t << 1), &d[3]);
/*
* We have to do it again if there still is a carry.
*/
t = cc;
cc = _addcarry_u64(cc, d[0], 0, &d[0]);
cc = _addcarry_u64(cc, d[1], -(t << 32), &d[1]);
cc = _addcarry_u64(cc, d[2], -t, &d[2]);
(void)_addcarry_u64(cc, d[3], (t << 32) - (t << 1), &d[3]);
#endif
}
/*
* Subtraction in the field.
*/
static inline void
_src_ec_ec_p256_m64_cf256_sub(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
#if BR_INT128
unsigned __int128 w;
uint64_t t;
w = (unsigned __int128)a[0] - b[0];
d[0] = (uint64_t)w;
w = (unsigned __int128)a[1] - b[1] - ((w >> 64) & 1);
d[1] = (uint64_t)w;
w = (unsigned __int128)a[2] - b[2] - ((w >> 64) & 1);
d[2] = (uint64_t)w;
w = (unsigned __int128)a[3] - b[3] - ((w >> 64) & 1);
d[3] = (uint64_t)w;
t = (uint64_t)(w >> 64) & 1;
/*
* If there is a borrow (t = 1), then we must add the modulus
* p = 2^256 - 2^224 + 2^192 + 2^96 - 1.
*/
w = (unsigned __int128)d[0] - t;
d[0] = (uint64_t)w;
w = (unsigned __int128)d[1] + (t << 32) - ((w >> 64) & 1);
d[1] = (uint64_t)w;
/* Here, carry "w >> 64" can only be 0 or +1 */
w = (unsigned __int128)d[2] + (w >> 64);
d[2] = (uint64_t)w;
/* Again, carry is 0 or +1 */
w = (unsigned __int128)d[3] + (w >> 64) - (t << 32) + t;
d[3] = (uint64_t)w;
t = (uint64_t)(w >> 64) & 1;
/*
* There may be again a borrow, in which case we must add the
* modulus again.
*/
w = (unsigned __int128)d[0] - t;
d[0] = (uint64_t)w;
w = (unsigned __int128)d[1] + (t << 32) - ((w >> 64) & 1);
d[1] = (uint64_t)w;
w = (unsigned __int128)d[2] + (w >> 64);
d[2] = (uint64_t)w;
d[3] += (uint64_t)(w >> 64) - (t << 32) + t;
#elif BR_UMUL128
unsigned char cc;
uint64_t t;
cc = _subborrow_u64(0, a[0], b[0], &d[0]);
cc = _subborrow_u64(cc, a[1], b[1], &d[1]);
cc = _subborrow_u64(cc, a[2], b[2], &d[2]);
cc = _subborrow_u64(cc, a[3], b[3], &d[3]);
/*
* If there is a borrow, then we need to add p. We (virtually)
* add 2^256, then subtract 2^256 - p.
*/
t = cc;
cc = _subborrow_u64(0, d[0], t, &d[0]);
cc = _subborrow_u64(cc, d[1], -(t << 32), &d[1]);
cc = _subborrow_u64(cc, d[2], -t, &d[2]);
cc = _subborrow_u64(cc, d[3], (t << 32) - (t << 1), &d[3]);
/*
* If there still is a borrow, then we need to add p again.
*/
t = cc;
cc = _subborrow_u64(0, d[0], t, &d[0]);
cc = _subborrow_u64(cc, d[1], -(t << 32), &d[1]);
cc = _subborrow_u64(cc, d[2], -t, &d[2]);
(void)_subborrow_u64(cc, d[3], (t << 32) - (t << 1), &d[3]);
#endif
}
/*
* Montgomery multiplication in the field.
*/
static void
_src_ec_ec_p256_m64_cf256_montymul(uint64_t *d, const uint64_t *a, const uint64_t *b)
{
#if BR_INT128
uint64_t x, f, t0, t1, t2, t3, t4;
unsigned __int128 z, ff;
int i;
/*
* When computing d <- d + a[u]*b, we also add f*p such
* that d + a[u]*b + f*p is a multiple of 2^64. Since
* p = -1 mod 2^64, we can compute f = d[0] + a[u]*b[0] mod 2^64.
*/
/*
* Step 1: t <- (a[0]*b + f*p) / 2^64
* We have f = a[0]*b[0] mod 2^64. Since p = -1 mod 2^64, this
* ensures that (a[0]*b + f*p) is a multiple of 2^64.
*
* We also have: f*p = f*2^256 - f*2^224 + f*2^192 + f*2^96 - f.
*/
x = a[0];
z = (unsigned __int128)b[0] * x;
f = (uint64_t)z;
z = (unsigned __int128)b[1] * x + (z >> 64) + (uint64_t)(f << 32);
t0 = (uint64_t)z;
z = (unsigned __int128)b[2] * x + (z >> 64) + (uint64_t)(f >> 32);
t1 = (uint64_t)z;
z = (unsigned __int128)b[3] * x + (z >> 64) + f;
t2 = (uint64_t)z;
t3 = (uint64_t)(z >> 64);
ff = ((unsigned __int128)f << 64) - ((unsigned __int128)f << 32);
z = (unsigned __int128)t2 + (uint64_t)ff;
t2 = (uint64_t)z;
z = (unsigned __int128)t3 + (z >> 64) + (ff >> 64);
t3 = (uint64_t)z;
t4 = (uint64_t)(z >> 64);
/*
* Steps 2 to 4: t <- (t + a[i]*b + f*p) / 2^64
*/
for (i = 1; i < 4; i ++) {
x = a[i];
/* t <- (t + x*b - f) / 2^64 */
z = (unsigned __int128)b[0] * x + t0;
f = (uint64_t)z;
z = (unsigned __int128)b[1] * x + t1 + (z >> 64);
t0 = (uint64_t)z;
z = (unsigned __int128)b[2] * x + t2 + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)b[3] * x + t3 + (z >> 64);
t2 = (uint64_t)z;
z = t4 + (z >> 64);
t3 = (uint64_t)z;
t4 = (uint64_t)(z >> 64);
/* t <- t + f*2^32, carry in the upper half of z */
z = (unsigned __int128)t0 + (uint64_t)(f << 32);
t0 = (uint64_t)z;
z = (z >> 64) + (unsigned __int128)t1 + (uint64_t)(f >> 32);
t1 = (uint64_t)z;
/* t <- t + f*2^192 - f*2^160 + f*2^128 */
ff = ((unsigned __int128)f << 64)
- ((unsigned __int128)f << 32) + f;
z = (z >> 64) + (unsigned __int128)t2 + (uint64_t)ff;
t2 = (uint64_t)z;
z = (unsigned __int128)t3 + (z >> 64) + (ff >> 64);
t3 = (uint64_t)z;
t4 += (uint64_t)(z >> 64);
}
/*
* At that point, we have computed t = (a*b + F*p) / 2^256, where
* F is a 256-bit integer whose limbs are the "f" coefficients
* in the steps above. We have:
* a <= 2^256-1
* b <= 2^256-1
* F <= 2^256-1
* Hence:
* a*b + F*p <= (2^256-1)*(2^256-1) + p*(2^256-1)
* a*b + F*p <= 2^256*(2^256 - 2 + p) + 1 - p
* Therefore:
* t < 2^256 + p - 2
* Since p < 2^256, it follows that:
* t4 can be only 0 or 1
* t - p < 2^256
* We can therefore subtract p from t, conditionally on t4, to
* get a nonnegative result that fits on 256 bits.
*/
z = (unsigned __int128)t0 + t4;
t0 = (uint64_t)z;
z = (unsigned __int128)t1 - (t4 << 32) + (z >> 64);
t1 = (uint64_t)z;
z = (unsigned __int128)t2 - (z >> 127);
t2 = (uint64_t)z;
t3 = t3 - (uint64_t)(z >> 127) - t4 + (t4 << 32);
d[0] = t0;
d[1] = t1;
d[2] = t2;
d[3] = t3;
#elif BR_UMUL128
uint64_t x, f, t0, t1, t2, t3, t4;
uint64_t zl, zh, ffl, ffh;
unsigned char k, m;
int i;
/*
* When computing d <- d + a[u]*b, we also add f*p such
* that d + a[u]*b + f*p is a multiple of 2^64. Since
* p = -1 mod 2^64, we can compute f = d[0] + a[u]*b[0] mod 2^64.
*/
/*
* Step 1: t <- (a[0]*b + f*p) / 2^64
* We have f = a[0]*b[0] mod 2^64. Since p = -1 mod 2^64, this
* ensures that (a[0]*b + f*p) is a multiple of 2^64.
*
* We also have: f*p = f*2^256 - f*2^224 + f*2^192 + f*2^96 - f.
*/
x = a[0];
zl = _umul128(b[0], x, &zh);
f = zl;
t0 = zh;
zl = _umul128(b[1], x, &zh);
k = _addcarry_u64(0, zl, t0, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
k = _addcarry_u64(0, zl, f << 32, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
t0 = zl;
t1 = zh;
zl = _umul128(b[2], x, &zh);
k = _addcarry_u64(0, zl, t1, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
k = _addcarry_u64(0, zl, f >> 32, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
t1 = zl;
t2 = zh;
zl = _umul128(b[3], x, &zh);
k = _addcarry_u64(0, zl, t2, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
k = _addcarry_u64(0, zl, f, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
t2 = zl;
t3 = zh;
t4 = _addcarry_u64(0, t3, f, &t3);
k = _subborrow_u64(0, t2, f << 32, &t2);
k = _subborrow_u64(k, t3, f >> 32, &t3);
(void)_subborrow_u64(k, t4, 0, &t4);
/*
* Steps 2 to 4: t <- (t + a[i]*b + f*p) / 2^64
*/
for (i = 1; i < 4; i ++) {
x = a[i];
/* f = t0 + x * b[0]; -- computed below */
/* t <- (t + x*b - f) / 2^64 */
zl = _umul128(b[0], x, &zh);
k = _addcarry_u64(0, zl, t0, &f);
(void)_addcarry_u64(k, zh, 0, &t0);
zl = _umul128(b[1], x, &zh);
k = _addcarry_u64(0, zl, t0, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
k = _addcarry_u64(0, zl, t1, &t0);
(void)_addcarry_u64(k, zh, 0, &t1);
zl = _umul128(b[2], x, &zh);
k = _addcarry_u64(0, zl, t1, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
k = _addcarry_u64(0, zl, t2, &t1);
(void)_addcarry_u64(k, zh, 0, &t2);
zl = _umul128(b[3], x, &zh);
k = _addcarry_u64(0, zl, t2, &zl);
(void)_addcarry_u64(k, zh, 0, &zh);
k = _addcarry_u64(0, zl, t3, &t2);
(void)_addcarry_u64(k, zh, 0, &t3);
t4 = _addcarry_u64(0, t3, t4, &t3);
/* t <- t + f*2^32, carry in k */
k = _addcarry_u64(0, t0, f << 32, &t0);
k = _addcarry_u64(k, t1, f >> 32, &t1);
/* t <- t + f*2^192 - f*2^160 + f*2^128 */
m = _subborrow_u64(0, f, f << 32, &ffl);
(void)_subborrow_u64(m, f, f >> 32, &ffh);
k = _addcarry_u64(k, t2, ffl, &t2);
k = _addcarry_u64(k, t3, ffh, &t3);
(void)_addcarry_u64(k, t4, 0, &t4);
}
/*
* At that point, we have computed t = (a*b + F*p) / 2^256, where
* F is a 256-bit integer whose limbs are the "f" coefficients
* in the steps above. We have:
* a <= 2^256-1
* b <= 2^256-1
* F <= 2^256-1
* Hence:
* a*b + F*p <= (2^256-1)*(2^256-1) + p*(2^256-1)
* a*b + F*p <= 2^256*(2^256 - 2 + p) + 1 - p
* Therefore:
* t < 2^256 + p - 2
* Since p < 2^256, it follows that:
* t4 can be only 0 or 1
* t - p < 2^256
* We can therefore subtract p from t, conditionally on t4, to
* get a nonnegative result that fits on 256 bits.
*/
k = _addcarry_u64(0, t0, t4, &t0);
k = _addcarry_u64(k, t1, -(t4 << 32), &t1);
k = _addcarry_u64(k, t2, -t4, &t2);
(void)_addcarry_u64(k, t3, (t4 << 32) - (t4 << 1), &t3);
d[0] = t0;
d[1] = t1;
d[2] = t2;
d[3] = t3;
#endif
}
/*
* Montgomery squaring in the field; currently a basic wrapper around
* multiplication (inline, should be optimized away).
* TODO: see if some extra speed can be gained here.
*/
static inline void
_src_ec_ec_p256_m64_cf256_montysquare(uint64_t *d, const uint64_t *a)
{
_src_ec_ec_p256_m64_cf256_montymul(d, a, a);
}
/*
* Convert to Montgomery representation.
*/
static void
_src_ec_ec_p256_m64_cf256_tomonty(uint64_t *d, const uint64_t *a)
{
/*
* R2 = 2^512 mod p.
* If R = 2^256 mod p, then R2 = R^2 mod p; and the Montgomery
* multiplication of a by R2 is: a*R2/R = a*R mod p, i.e. the
* conversion to Montgomery representation.
*/
static const uint64_t R2[] = {
0x0000000000000003,
0xFFFFFFFBFFFFFFFF,
0xFFFFFFFFFFFFFFFE,
0x00000004FFFFFFFD
};
_src_ec_ec_p256_m64_cf256_montymul(d, a, R2);
}
/*
* Convert from Montgomery representation.
*/
static void
_src_ec_ec_p256_m64_cf256_frommonty(uint64_t *d, const uint64_t *a)
{
/*
* Montgomery multiplication by 1 is division by 2^256 modulo p.
*/
static const uint64_t one[] = { 1, 0, 0, 0 };
_src_ec_ec_p256_m64_cf256_montymul(d, a, one);
}
/*
* Inversion in the field. If the source value is 0 modulo p, then this
* returns 0 or p. This function uses Montgomery representation.
*/
static void
_src_ec_ec_p256_m64_cf256_invert(uint64_t *d, const uint64_t *a)
{
/*
* We compute a^(p-2) mod p. The exponent pattern (from high to
* low) is:
* - 32 bits of value 1
* - 31 bits of value 0
* - 1 bit of value 1
* - 96 bits of value 0
* - 94 bits of value 1
* - 1 bit of value 0
* - 1 bit of value 1
* To speed up the square-and-multiply algorithm, we precompute
* a^(2^31-1).
*/
uint64_t r[4], t[4];
int i;
memcpy(t, a, sizeof t);
for (i = 0; i < 30; i ++) {
_src_ec_ec_p256_m64_cf256_montysquare(t, t);
_src_ec_ec_p256_m64_cf256_montymul(t, t, a);
}
memcpy(r, t, sizeof t);
for (i = 224; i >= 0; i --) {
_src_ec_ec_p256_m64_cf256_montysquare(r, r);
switch (i) {
case 0:
case 2:
case 192:
case 224:
_src_ec_ec_p256_m64_cf256_montymul(r, r, a);
break;
case 3:
case 34:
case 65:
_src_ec_ec_p256_m64_cf256_montymul(r, r, t);
break;
}
}
memcpy(d, r, sizeof r);
}
/*
* Finalize reduction.
* Input value fits on 256 bits. This function subtracts p if and only
* if the input is greater than or equal to p.
*/
static inline void
_src_ec_ec_p256_m64_cf256_final_reduce(uint64_t *a)
{
#if BR_INT128
uint64_t t0, t1, t2, t3, cc;
unsigned __int128 z;
/*
* We add 2^224 - 2^192 - 2^96 + 1 to a. If there is no carry,
* then a < p; otherwise, the addition result we computed is
* the value we must return.
*/
z = (unsigned __int128)a[0] + 1;
t0 = (uint64_t)z;
z = (unsigned __int128)a[1] + (z >> 64) - ((uint64_t)1 << 32);
t1 = (uint64_t)z;
z = (unsigned __int128)a[2] - (z >> 127);
t2 = (uint64_t)z;
z = (unsigned __int128)a[3] - (z >> 127) + 0xFFFFFFFF;
t3 = (uint64_t)z;
cc = -(uint64_t)(z >> 64);
a[0] ^= cc & (a[0] ^ t0);
a[1] ^= cc & (a[1] ^ t1);
a[2] ^= cc & (a[2] ^ t2);
a[3] ^= cc & (a[3] ^ t3);
#elif BR_UMUL128
uint64_t t0, t1, t2, t3, m;
unsigned char k;
k = _addcarry_u64(0, a[0], (uint64_t)1, &t0);
k = _addcarry_u64(k, a[1], -((uint64_t)1 << 32), &t1);
k = _addcarry_u64(k, a[2], -(uint64_t)1, &t2);
k = _addcarry_u64(k, a[3], ((uint64_t)1 << 32) - 2, &t3);
m = -(uint64_t)k;
a[0] ^= m & (a[0] ^ t0);
a[1] ^= m & (a[1] ^ t1);
a[2] ^= m & (a[2] ^ t2);
a[3] ^= m & (a[3] ^ t3);
#endif
}
/*
* Points in affine and Jacobian coordinates.
*
* - In affine coordinates, the point-at-infinity cannot be encoded.
* - Jacobian coordinates (X,Y,Z) correspond to affine (X/Z^2,Y/Z^3);
* if Z = 0 then this is the point-at-infinity.
*/
typedef struct {
uint64_t x[4];
uint64_t y[4];
} _src_ec_ec_p256_m64_cp256_affine;
typedef struct {
uint64_t x[4];
uint64_t y[4];
uint64_t z[4];
} p256__src_ec_ec_p256_m64_cjacobian;
/*
* Decode a point. The returned point is in Jacobian coordinates, but
* with z = 1. If the encoding is invalid, or encodes a point which is
* not on the curve, or encodes the point at infinity, then this function
* returns 0. Otherwise, 1 is returned.
*
* The buffer is assumed to have length exactly 65 bytes.
*/
static uint32_t
_src_ec_ec_p256_m64_cpoint_decode(p256__src_ec_ec_p256_m64_cjacobian *P, const unsigned char *buf)
{
uint64_t x[4], y[4], t[4], x3[4], tt;
uint32_t r;
/*
* Header byte shall be 0x04.
*/
r = EQ(buf[0], 0x04);
/*
* Decode X and Y coordinates, and convert them into
* Montgomery representation.
*/
x[3] = br_dec64be(buf + 1);
x[2] = br_dec64be(buf + 9);
x[1] = br_dec64be(buf + 17);
x[0] = br_dec64be(buf + 25);
y[3] = br_dec64be(buf + 33);
y[2] = br_dec64be(buf + 41);
y[1] = br_dec64be(buf + 49);
y[0] = br_dec64be(buf + 57);
_src_ec_ec_p256_m64_cf256_tomonty(x, x);
_src_ec_ec_p256_m64_cf256_tomonty(y, y);
/*
* Verify y^2 = x^3 + A*x + B. In curve P-256, A = -3.
* Note that the Montgomery representation of 0 is 0. We must
* take care to apply the final reduction to make sure we have
* 0 and not p.
*/
_src_ec_ec_p256_m64_cf256_montysquare(t, y);
_src_ec_ec_p256_m64_cf256_montysquare(x3, x);
_src_ec_ec_p256_m64_cf256_montymul(x3, x3, x);
_src_ec_ec_p256_m64_cf256_sub(t, t, x3);
_src_ec_ec_p256_m64_cf256_add(t, t, x);
_src_ec_ec_p256_m64_cf256_add(t, t, x);
_src_ec_ec_p256_m64_cf256_add(t, t, x);
_src_ec_ec_p256_m64_cf256_sub(t, t, _src_ec_ec_p256_m64_cP256_B_MONTY);
_src_ec_ec_p256_m64_cf256_final_reduce(t);
tt = t[0] | t[1] | t[2] | t[3];
r &= EQ((uint32_t)(tt | (tt >> 32)), 0);
/*
* Return the point in Jacobian coordinates (and Montgomery
* representation).
*/
memcpy(P->x, x, sizeof x);
memcpy(P->y, y, sizeof y);
memcpy(P->z, _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R, sizeof _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R);
return r;
}
/*
* Final conversion for a point:
* - The point is converted back to affine coordinates.
* - Final reduction is performed.
* - The point is encoded into the provided buffer.
*
* If the point is the point-at-infinity, all operations are performed,
* but the buffer contents are indeterminate, and 0 is returned. Otherwise,
* the encoded point is written in the buffer, and 1 is returned.
*/
static uint32_t
_src_ec_ec_p256_m64_cpoint_encode(unsigned char *buf, const p256__src_ec_ec_p256_m64_cjacobian *P)
{
uint64_t t1[4], t2[4], z;
/* Set t1 = 1/z^2 and t2 = 1/z^3. */
_src_ec_ec_p256_m64_cf256_invert(t2, P->z);
_src_ec_ec_p256_m64_cf256_montysquare(t1, t2);
_src_ec_ec_p256_m64_cf256_montymul(t2, t2, t1);
/* Compute affine coordinates x (in t1) and y (in t2). */
_src_ec_ec_p256_m64_cf256_montymul(t1, P->x, t1);
_src_ec_ec_p256_m64_cf256_montymul(t2, P->y, t2);
/* Convert back from Montgomery representation, and finalize
reductions. */
_src_ec_ec_p256_m64_cf256_frommonty(t1, t1);
_src_ec_ec_p256_m64_cf256_frommonty(t2, t2);
_src_ec_ec_p256_m64_cf256_final_reduce(t1);
_src_ec_ec_p256_m64_cf256_final_reduce(t2);
/* Encode. */
buf[0] = 0x04;
br_enc64be(buf + 1, t1[3]);
br_enc64be(buf + 9, t1[2]);
br_enc64be(buf + 17, t1[1]);
br_enc64be(buf + 25, t1[0]);
br_enc64be(buf + 33, t2[3]);
br_enc64be(buf + 41, t2[2]);
br_enc64be(buf + 49, t2[1]);
br_enc64be(buf + 57, t2[0]);
/* Return success if and only if P->z != 0. */
z = P->z[0] | P->z[1] | P->z[2] | P->z[3];
return NEQ((uint32_t)(z | z >> 32), 0);
}
/*
* Point doubling in Jacobian coordinates: point P is doubled.
* Note: if the source point is the point-at-infinity, then the result is
* still the point-at-infinity, which is correct. Moreover, if the three
* coordinates were zero, then they still are zero in the returned value.
*
* (Note: this is true even without the final reduction: if the three
* coordinates are encoded as four words of value zero each, then the
* result will also have all-zero coordinate encodings, not the alternate
* encoding as the integer p.)
*/
static void
_src_ec_ec_p256_m64_cp256_double(p256__src_ec_ec_p256_m64_cjacobian *P)
{
/*
* Doubling formulas are:
*
* s = 4*x*y^2
* m = 3*(x + z^2)*(x - z^2)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y^4
* z' = 2*y*z
*
* These formulas work for all points, including points of order 2
* and points at infinity:
* - If y = 0 then z' = 0. But there is no such point in P-256
* anyway.
* - If z = 0 then z' = 0.
*/
uint64_t t1[4], t2[4], t3[4], t4[4];
/*
* Compute z^2 in t1.
*/
_src_ec_ec_p256_m64_cf256_montysquare(t1, P->z);
/*
* Compute x-z^2 in t2 and x+z^2 in t1.
*/
_src_ec_ec_p256_m64_cf256_add(t2, P->x, t1);
_src_ec_ec_p256_m64_cf256_sub(t1, P->x, t1);
/*
* Compute 3*(x+z^2)*(x-z^2) in t1.
*/
_src_ec_ec_p256_m64_cf256_montymul(t3, t1, t2);
_src_ec_ec_p256_m64_cf256_add(t1, t3, t3);
_src_ec_ec_p256_m64_cf256_add(t1, t3, t1);
/*
* Compute 4*x*y^2 (in t2) and 2*y^2 (in t3).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t3, P->y);
_src_ec_ec_p256_m64_cf256_add(t3, t3, t3);
_src_ec_ec_p256_m64_cf256_montymul(t2, P->x, t3);
_src_ec_ec_p256_m64_cf256_add(t2, t2, t2);
/*
* Compute x' = m^2 - 2*s.
*/
_src_ec_ec_p256_m64_cf256_montysquare(P->x, t1);
_src_ec_ec_p256_m64_cf256_sub(P->x, P->x, t2);
_src_ec_ec_p256_m64_cf256_sub(P->x, P->x, t2);
/*
* Compute z' = 2*y*z.
*/
_src_ec_ec_p256_m64_cf256_montymul(t4, P->y, P->z);
_src_ec_ec_p256_m64_cf256_add(P->z, t4, t4);
/*
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
* 2*y^2 in t3.
*/
_src_ec_ec_p256_m64_cf256_sub(t2, t2, P->x);
_src_ec_ec_p256_m64_cf256_montymul(P->y, t1, t2);
_src_ec_ec_p256_m64_cf256_montysquare(t4, t3);
_src_ec_ec_p256_m64_cf256_add(t4, t4, t4);
_src_ec_ec_p256_m64_cf256_sub(P->y, P->y, t4);
}
/*
* Point addition (Jacobian coordinates): P1 is replaced with P1+P2.
* This function computes the wrong result in the following cases:
*
* - If P1 == 0 but P2 != 0
* - If P1 != 0 but P2 == 0
* - If P1 == P2
*
* In all three cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y coordinate.
* - P1 == 0 and P2 == 0.
* - The Y coordinate of one of the points is 0 and the other point is
* the point at infinity.
*
* The third case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 and P2 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*
* Note that you can get a returned value of 0 with a correct result,
* e.g. if P1 and P2 have the same Y coordinate, but distinct X coordinates.
*/
static uint32_t
_src_ec_ec_p256_m64_cp256_add(p256__src_ec_ec_p256_m64_cjacobian *P1, const p256__src_ec_ec_p256_m64_cjacobian *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1 * z2^2
* u2 = x2 * z1^2
* s1 = y1 * z2^3
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1 * z2
*/
uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt;
uint32_t ret;
/*
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t3, P2->z);
_src_ec_ec_p256_m64_cf256_montymul(t1, P1->x, t3);
_src_ec_ec_p256_m64_cf256_montymul(t4, P2->z, t3);
_src_ec_ec_p256_m64_cf256_montymul(t3, P1->y, t4);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t4, P1->z);
_src_ec_ec_p256_m64_cf256_montymul(t2, P2->x, t4);
_src_ec_ec_p256_m64_cf256_montymul(t5, P1->z, t4);
_src_ec_ec_p256_m64_cf256_montymul(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
_src_ec_ec_p256_m64_cf256_sub(t2, t2, t1);
_src_ec_ec_p256_m64_cf256_sub(t4, t4, t3);
_src_ec_ec_p256_m64_cf256_final_reduce(t4);
tt = t4[0] | t4[1] | t4[2] | t4[3];
ret = (uint32_t)(tt | (tt >> 32));
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m64_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m64_cf256_montymul(t6, t1, t7);
_src_ec_ec_p256_m64_cf256_montymul(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m64_cf256_montysquare(P1->x, t4);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t5);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t6);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
_src_ec_ec_p256_m64_cf256_sub(t6, t6, P1->x);
_src_ec_ec_p256_m64_cf256_montymul(P1->y, t4, t6);
_src_ec_ec_p256_m64_cf256_montymul(t1, t5, t3);
_src_ec_ec_p256_m64_cf256_sub(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m64_cf256_montymul(t1, P1->z, P2->z);
_src_ec_ec_p256_m64_cf256_montymul(P1->z, t1, t2);
return ret;
}
/*
* Point addition (mixed coordinates): P1 is replaced with P1+P2.
* This is a specialised function for the case when P2 is a non-zero point
* in affine coordinates.
*
* This function computes the wrong result in the following cases:
*
* - If P1 == 0
* - If P1 == P2
*
* In both cases, P1 is set to the point at infinity.
*
* Returned value is 0 if one of the following occurs:
*
* - P1 and P2 have the same Y (affine) coordinate.
* - The Y coordinate of P2 is 0 and P1 is the point at infinity.
*
* The second case cannot actually happen with valid points, since a point
* with Y == 0 is a point of order 2, and there is no point of order 2 on
* curve P-256.
*
* Therefore, assuming that P1 != 0 on input, then the caller
* can apply the following:
*
* - If the result is not the point at infinity, then it is correct.
* - Otherwise, if the returned value is 1, then this is a case of
* P1+P2 == 0, so the result is indeed the point at infinity.
* - Otherwise, P1 == P2, so a "double" operation should have been
* performed.
*
* Again, a value of 0 may be returned in some cases where the addition
* result is correct.
*/
static uint32_t
_src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cp256_add_mixed(p256__src_ec_ec_p256_m64_cjacobian *P1, const _src_ec_ec_p256_m64_cp256_affine *P2)
{
/*
* Addtions formulas are:
*
* u1 = x1
* u2 = x2 * z1^2
* s1 = y1
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1
*/
uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt;
uint32_t ret;
/*
* Compute u1 = x1 (in t1) and s1 = y1 (in t3).
*/
memcpy(t1, P1->x, sizeof t1);
memcpy(t3, P1->y, sizeof t3);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t4, P1->z);
_src_ec_ec_p256_m64_cf256_montymul(t2, P2->x, t4);
_src_ec_ec_p256_m64_cf256_montymul(t5, P1->z, t4);
_src_ec_ec_p256_m64_cf256_montymul(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* We need to test whether r is zero, so we will do some extra
* reduce.
*/
_src_ec_ec_p256_m64_cf256_sub(t2, t2, t1);
_src_ec_ec_p256_m64_cf256_sub(t4, t4, t3);
_src_ec_ec_p256_m64_cf256_final_reduce(t4);
tt = t4[0] | t4[1] | t4[2] | t4[3];
ret = (uint32_t)(tt | (tt >> 32));
ret = (ret | -ret) >> 31;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m64_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m64_cf256_montymul(t6, t1, t7);
_src_ec_ec_p256_m64_cf256_montymul(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m64_cf256_montysquare(P1->x, t4);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t5);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t6);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
_src_ec_ec_p256_m64_cf256_sub(t6, t6, P1->x);
_src_ec_ec_p256_m64_cf256_montymul(P1->y, t4, t6);
_src_ec_ec_p256_m64_cf256_montymul(t1, t5, t3);
_src_ec_ec_p256_m64_cf256_sub(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_p256_m64_cf256_montymul(P1->z, P1->z, t2);
return ret;
}
#if 0
/* unused */
/*
* Point addition (mixed coordinates, complete): P1 is replaced with P1+P2.
* This is a specialised function for the case when P2 is a non-zero point
* in affine coordinates.
*
* This function returns the correct result in all cases.
*/
static uint32_t
_src_ec_ec_p256_m64_cp256_add_complete_mixed(p256__src_ec_ec_p256_m64_cjacobian *P1, const _src_ec_ec_p256_m64_cp256_affine *P2)
{
/*
* Addtions formulas, in the general case, are:
*
* u1 = x1
* u2 = x2 * z1^2
* s1 = y1
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1
*
* These formulas mishandle the two following cases:
*
* - If P1 is the point-at-infinity (z1 = 0), then z3 is
* incorrectly set to 0.
*
* - If P1 = P2, then u1 = u2 and s1 = s2, and x3, y3 and z3
* are all set to 0.
*
* However, if P1 + P2 = 0, then u1 = u2 but s1 != s2, and then
* we correctly get z3 = 0 (the point-at-infinity).
*
* To fix the case P1 = 0, we perform at the end a copy of P2
* over P1, conditional to z1 = 0.
*
* For P1 = P2: in that case, both h and r are set to 0, and
* we get x3, y3 and z3 equal to 0. We can test for that
* occurrence to make a mask which will be all-one if P1 = P2,
* or all-zero otherwise; then we can compute the double of P2
* and add it, combined with the mask, to (x3,y3,z3).
*
* Using the doubling formulas in _src_ec_ec_p256_m64_cp256_double() on (x2,y2),
* simplifying since P2 is affine (i.e. z2 = 1, implicitly),
* we get:
* s = 4*x2*y2^2
* m = 3*(x2 + 1)*(x2 - 1)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y2^4
* z' = 2*y2
* which requires only 6 multiplications. Added to the 11
* multiplications of the normal mixed addition in Jacobian
* coordinates, we get a cost of 17 multiplications in total.
*/
uint64_t t1[4], t2[4], t3[4], t4[4], t5[4], t6[4], t7[4], tt, zz;
int i;
/*
* Set zz to -1 if P1 is the point at infinity, 0 otherwise.
*/
zz = P1->z[0] | P1->z[1] | P1->z[2] | P1->z[3];
zz = ((zz | -zz) >> 63) - (uint64_t)1;
/*
* Compute u1 = x1 (in t1) and s1 = y1 (in t3).
*/
memcpy(t1, P1->x, sizeof t1);
memcpy(t3, P1->y, sizeof t3);
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t4, P1->z);
_src_ec_ec_p256_m64_cf256_montymul(t2, P2->x, t4);
_src_ec_ec_p256_m64_cf256_montymul(t5, P1->z, t4);
_src_ec_ec_p256_m64_cf256_montymul(t4, P2->y, t5);
/*
* Compute h = h2 - u1 (in t2) and r = s2 - s1 (in t4).
* reduce.
*/
_src_ec_ec_p256_m64_cf256_sub(t2, t2, t1);
_src_ec_ec_p256_m64_cf256_sub(t4, t4, t3);
/*
* If both h = 0 and r = 0, then P1 = P2, and we want to set
* the mask tt to -1; otherwise, the mask will be 0.
*/
_src_ec_ec_p256_m64_cf256_final_reduce(t2);
_src_ec_ec_p256_m64_cf256_final_reduce(t4);
tt = t2[0] | t2[1] | t2[2] | t2[3] | t4[0] | t4[1] | t4[2] | t4[3];
tt = ((tt | -tt) >> 63) - (uint64_t)1;
/*
* Compute u1*h^2 (in t6) and h^3 (in t5);
*/
_src_ec_ec_p256_m64_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m64_cf256_montymul(t6, t1, t7);
_src_ec_ec_p256_m64_cf256_montymul(t5, t7, t2);
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
*/
_src_ec_ec_p256_m64_cf256_montysquare(P1->x, t4);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t5);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t6);
_src_ec_ec_p256_m64_cf256_sub(P1->x, P1->x, t6);
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
_src_ec_ec_p256_m64_cf256_sub(t6, t6, P1->x);
_src_ec_ec_p256_m64_cf256_montymul(P1->y, t4, t6);
_src_ec_ec_p256_m64_cf256_montymul(t1, t5, t3);
_src_ec_ec_p256_m64_cf256_sub(P1->y, P1->y, t1);
/*
* Compute z3 = h*z1.
*/
_src_ec_ec_p256_m64_cf256_montymul(P1->z, P1->z, t2);
/*
* The "double" result, in case P1 = P2.
*/
/*
* Compute z' = 2*y2 (in t1).
*/
_src_ec_ec_p256_m64_cf256_add(t1, P2->y, P2->y);
/*
* Compute 2*(y2^2) (in t2) and s = 4*x2*(y2^2) (in t3).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t2, P2->y);
_src_ec_ec_p256_m64_cf256_add(t2, t2, t2);
_src_ec_ec_p256_m64_cf256_add(t3, t2, t2);
_src_ec_ec_p256_m64_cf256_montymul(t3, P2->x, t3);
/*
* Compute m = 3*(x2^2 - 1) (in t4).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t4, P2->x);
_src_ec_ec_p256_m64_cf256_sub(t4, t4, _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R);
_src_ec_ec_p256_m64_cf256_add(t5, t4, t4);
_src_ec_ec_p256_m64_cf256_add(t4, t4, t5);
/*
* Compute x' = m^2 - 2*s (in t5).
*/
_src_ec_ec_p256_m64_cf256_montysquare(t5, t4);
_src_ec_ec_p256_m64_cf256_sub(t5, t3);
_src_ec_ec_p256_m64_cf256_sub(t5, t3);
/*
* Compute y' = m*(s - x') - 8*y2^4 (in t6).
*/
_src_ec_ec_p256_m64_cf256_sub(t6, t3, t5);
_src_ec_ec_p256_m64_cf256_montymul(t6, t6, t4);
_src_ec_ec_p256_m64_cf256_montysquare(t7, t2);
_src_ec_ec_p256_m64_cf256_sub(t6, t6, t7);
_src_ec_ec_p256_m64_cf256_sub(t6, t6, t7);
/*
* We now have the alternate (doubling) coordinates in (t5,t6,t1).
* We combine them with (x3,y3,z3).
*/
for (i = 0; i < 4; i ++) {
P1->x[i] |= tt & t5[i];
P1->y[i] |= tt & t6[i];
P1->z[i] |= tt & t1[i];
}
/*
* If P1 = 0, then we get z3 = 0 (which is invalid); if z1 is 0,
* then we want to replace the result with a copy of P2. The
* test on z1 was done at the start, in the zz mask.
*/
for (i = 0; i < 4; i ++) {
P1->x[i] ^= zz & (P1->x[i] ^ P2->x[i]);
P1->y[i] ^= zz & (P1->y[i] ^ P2->y[i]);
P1->z[i] ^= zz & (P1->z[i] ^ _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R[i]);
}
}
#endif
/*
* Inner function for computing a point multiplication. A window is
* provided, with points 1*P to 15*P in affine coordinates.
*
* Assumptions:
* - All provided points are valid points on the curve.
* - Multiplier is non-zero, and smaller than the curve order.
* - Everything is in Montgomery representation.
*/
static void
_src_ec_ec_p256_m64_cpoint_mul_inner(p256__src_ec_ec_p256_m64_cjacobian *R, const _src_ec_ec_p256_m64_cp256_affine *W,
const unsigned char *k, size_t klen)
{
p256__src_ec_ec_p256_m64_cjacobian Q;
uint32_t qz;
memset(&Q, 0, sizeof Q);
qz = 1;
while (klen -- > 0) {
int i;
unsigned bk;
bk = *k ++;
for (i = 0; i < 2; i ++) {
uint32_t bits;
uint32_t bnz;
_src_ec_ec_p256_m64_cp256_affine T;
p256__src_ec_ec_p256_m64_cjacobian U;
uint32_t n;
int j;
uint64_t m;
_src_ec_ec_p256_m64_cp256_double(&Q);
_src_ec_ec_p256_m64_cp256_double(&Q);
_src_ec_ec_p256_m64_cp256_double(&Q);
_src_ec_ec_p256_m64_cp256_double(&Q);
bits = (bk >> 4) & 0x0F;
bnz = NEQ(bits, 0);
/*
* Lookup point in window. If the bits are 0,
* we get something invalid, which is not a
* problem because we will use it only if the
* bits are non-zero.
*/
memset(&T, 0, sizeof T);
for (n = 0; n < 15; n ++) {
m = -(uint64_t)EQ(bits, n + 1);
T.x[0] |= m & W[n].x[0];
T.x[1] |= m & W[n].x[1];
T.x[2] |= m & W[n].x[2];
T.x[3] |= m & W[n].x[3];
T.y[0] |= m & W[n].y[0];
T.y[1] |= m & W[n].y[1];
T.y[2] |= m & W[n].y[2];
T.y[3] |= m & W[n].y[3];
}
U = Q;
_src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cp256_add_mixed(&U, &T);
/*
* If qz is still 1, then Q was all-zeros, and this
* is conserved through _src_ec_ec_p256_m64_cp256_double().
*/
m = -(uint64_t)(bnz & qz);
for (j = 0; j < 4; j ++) {
Q.x[j] |= m & T.x[j];
Q.y[j] |= m & T.y[j];
Q.z[j] |= m & _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R[j];
}
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
bk <<= 4;
}
}
*R = Q;
}
/*
* Convert a window from Jacobian to affine coordinates. A single
* field inversion is used. This function works for windows up to
* 32 elements.
*
* The destination array (aff[]) and the source array (jac[]) may
* overlap, provided that the start of aff[] is not after the start of
* jac[]. Even if the arrays do _not_ overlap, the source array is
* modified.
*/
static void
_src_ec_ec_p256_m64_cwindow_to_affine(_src_ec_ec_p256_m64_cp256_affine *aff, p256__src_ec_ec_p256_m64_cjacobian *jac, int num)
{
/*
* Convert the window points to affine coordinates. We use the
* following trick to mutualize the inversion computation: if
* we have z1, z2, z3, and z4, and want to inverse all of them,
* we compute u = 1/(z1*z2*z3*z4), and then we have:
* 1/z1 = u*z2*z3*z4
* 1/z2 = u*z1*z3*z4
* 1/z3 = u*z1*z2*z4
* 1/z4 = u*z1*z2*z3
*
* The partial products are computed recursively:
*
* - on input (z_1,z_2), return (z_2,z_1) and z_1*z_2
* - on input (z_1,z_2,... z_n):
* recurse on (z_1,z_2,... z_(n/2)) -> r1 and m1
* recurse on (z_(n/2+1),z_(n/2+2)... z_n) -> r2 and m2
* multiply elements of r1 by m2 -> s1
* multiply elements of r2 by m1 -> s2
* return r1||r2 and m1*m2
*
* In the example below, we suppose that we have 14 elements.
* Let z1, z2,... zE be the 14 values to invert (index noted in
* hexadecimal, starting at 1).
*
* - Depth 1:
* swap(z1, z2); z12 = z1*z2
* swap(z3, z4); z34 = z3*z4
* swap(z5, z6); z56 = z5*z6
* swap(z7, z8); z78 = z7*z8
* swap(z9, zA); z9A = z9*zA
* swap(zB, zC); zBC = zB*zC
* swap(zD, zE); zDE = zD*zE
*
* - Depth 2:
* z1 <- z1*z34, z2 <- z2*z34, z3 <- z3*z12, z4 <- z4*z12
* z1234 = z12*z34
* z5 <- z5*z78, z6 <- z6*z78, z7 <- z7*z56, z8 <- z8*z56
* z5678 = z56*z78
* z9 <- z9*zBC, zA <- zA*zBC, zB <- zB*z9A, zC <- zC*z9A
* z9ABC = z9A*zBC
*
* - Depth 3:
* z1 <- z1*z5678, z2 <- z2*z5678, z3 <- z3*z5678, z4 <- z4*z5678
* z5 <- z5*z1234, z6 <- z6*z1234, z7 <- z7*z1234, z8 <- z8*z1234
* z12345678 = z1234*z5678
* z9 <- z9*zDE, zA <- zA*zDE, zB <- zB*zDE, zC <- zC*zDE
* zD <- zD*z9ABC, zE*z9ABC
* z9ABCDE = z9ABC*zDE
*
* - Depth 4:
* multiply z1..z8 by z9ABCDE
* multiply z9..zE by z12345678
* final z = z12345678*z9ABCDE
*/
uint64_t z[16][4];
int i, k, s;
#define zt (z[15])
#define zu (z[14])
#define zv (z[13])
/*
* First recursion step (pairwise swapping and multiplication).
* If there is an odd number of elements, then we "invent" an
* extra one with coordinate Z = 1 (in Montgomery representation).
*/
for (i = 0; (i + 1) < num; i += 2) {
memcpy(zt, jac[i].z, sizeof zt);
memcpy(jac[i].z, jac[i + 1].z, sizeof zt);
memcpy(jac[i + 1].z, zt, sizeof zt);
_src_ec_ec_p256_m64_cf256_montymul(z[i >> 1], jac[i].z, jac[i + 1].z);
}
if ((num & 1) != 0) {
memcpy(z[num >> 1], jac[num - 1].z, sizeof zt);
memcpy(jac[num - 1].z, _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R, sizeof _src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cF256_R);
}
/*
* Perform further recursion steps. At the entry of each step,
* the process has been done for groups of 's' points. The
* integer k is the log2 of s.
*/
for (k = 1, s = 2; s < num; k ++, s <<= 1) {
int n;
for (i = 0; i < num; i ++) {
_src_ec_ec_p256_m64_cf256_montymul(jac[i].z, jac[i].z, z[(i >> k) ^ 1]);
}
n = (num + s - 1) >> k;
for (i = 0; i < (n >> 1); i ++) {
_src_ec_ec_p256_m64_cf256_montymul(z[i], z[i << 1], z[(i << 1) + 1]);
}
if ((n & 1) != 0) {
memmove(z[n >> 1], z[n], sizeof zt);
}
}
/*
* Invert the final result, and convert all points.
*/
_src_ec_ec_p256_m64_cf256_invert(zt, z[0]);
for (i = 0; i < num; i ++) {
_src_ec_ec_p256_m64_cf256_montymul(zv, jac[i].z, zt);
_src_ec_ec_p256_m64_cf256_montysquare(zu, zv);
_src_ec_ec_p256_m64_cf256_montymul(zv, zv, zu);
_src_ec_ec_p256_m64_cf256_montymul(aff[i].x, jac[i].x, zu);
_src_ec_ec_p256_m64_cf256_montymul(aff[i].y, jac[i].y, zv);
}
}
/*
* Multiply the provided point by an integer.
* Assumptions:
* - Source point is a valid curve point.
* - Source point is not the point-at-infinity.
* - Integer is not 0, and is lower than the curve order.
* If these conditions are not met, then the result is indeterminate
* (but the process is still constant-time).
*/
static void
_src_ec_ec_p256_m64_cp256_mul(p256__src_ec_ec_p256_m64_cjacobian *P, const unsigned char *k, size_t klen)
{
union {
_src_ec_ec_p256_m64_cp256_affine aff[15];
p256__src_ec_ec_p256_m64_cjacobian jac[15];
} window;
int i;
/*
* Compute window, in Jacobian coordinates.
*/
window.jac[0] = *P;
for (i = 2; i < 16; i ++) {
window.jac[i - 1] = window.jac[(i >> 1) - 1];
if ((i & 1) == 0) {
_src_ec_ec_p256_m64_cp256_double(&window.jac[i - 1]);
} else {
_src_ec_ec_p256_m64_cp256_add(&window.jac[i - 1], &window.jac[i >> 1]);
}
}
/*
* Convert the window points to affine coordinates. Point
* window[0] is the source point, already in affine coordinates.
*/
_src_ec_ec_p256_m64_cwindow_to_affine(window.aff, window.jac, 15);
/*
* Perform point multiplication.
*/
_src_ec_ec_p256_m64_cpoint_mul_inner(P, window.aff, k, klen);
}
/*
* Precomputed window for the conventional generator: _src_ec_ec_p256_m64_cP256__src_ec_ec_p256_m64_cGwin[n]
* contains (n+1)*G (affine coordinates, in Montgomery representation).
*/
static const _src_ec_ec_p256_m64_cp256_affine _src_ec_ec_p256_m64_cP256__src_ec_ec_p256_m64_cGwin[] = {
{
{ 0x79E730D418A9143C, 0x75BA95FC5FEDB601,
0x79FB732B77622510, 0x18905F76A53755C6 },
{ 0xDDF25357CE95560A, 0x8B4AB8E4BA19E45C,
0xD2E88688DD21F325, 0x8571FF1825885D85 }
},
{
{ 0x850046D410DDD64D, 0xAA6AE3C1A433827D,
0x732205038D1490D9, 0xF6BB32E43DCF3A3B },
{ 0x2F3648D361BEE1A5, 0x152CD7CBEB236FF8,
0x19A8FB0E92042DBE, 0x78C577510A5B8A3B }
},
{
{ 0xFFAC3F904EEBC127, 0xB027F84A087D81FB,
0x66AD77DD87CBBC98, 0x26936A3FB6FF747E },
{ 0xB04C5C1FC983A7EB, 0x583E47AD0861FE1A,
0x788208311A2EE98E, 0xD5F06A29E587CC07 }
},
{
{ 0x74B0B50D46918DCC, 0x4650A6EDC623C173,
0x0CDAACACE8100AF2, 0x577362F541B0176B },
{ 0x2D96F24CE4CBABA6, 0x17628471FAD6F447,
0x6B6C36DEE5DDD22E, 0x84B14C394C5AB863 }
},
{
{ 0xBE1B8AAEC45C61F5, 0x90EC649A94B9537D,
0x941CB5AAD076C20C, 0xC9079605890523C8 },
{ 0xEB309B4AE7BA4F10, 0x73C568EFE5EB882B,
0x3540A9877E7A1F68, 0x73A076BB2DD1E916 }
},
{
{ 0x403947373E77664A, 0x55AE744F346CEE3E,
0xD50A961A5B17A3AD, 0x13074B5954213673 },
{ 0x93D36220D377E44B, 0x299C2B53ADFF14B5,
0xF424D44CEF639F11, 0xA4C9916D4A07F75F }
},
{
{ 0x0746354EA0173B4F, 0x2BD20213D23C00F7,
0xF43EAAB50C23BB08, 0x13BA5119C3123E03 },
{ 0x2847D0303F5B9D4D, 0x6742F2F25DA67BDD,
0xEF933BDC77C94195, 0xEAEDD9156E240867 }
},
{
{ 0x27F14CD19499A78F, 0x462AB5C56F9B3455,
0x8F90F02AF02CFC6B, 0xB763891EB265230D },
{ 0xF59DA3A9532D4977, 0x21E3327DCF9EBA15,
0x123C7B84BE60BBF0, 0x56EC12F27706DF76 }
},
{
{ 0x75C96E8F264E20E8, 0xABE6BFED59A7A841,
0x2CC09C0444C8EB00, 0xE05B3080F0C4E16B },
{ 0x1EB7777AA45F3314, 0x56AF7BEDCE5D45E3,
0x2B6E019A88B12F1A, 0x086659CDFD835F9B }
},
{
{ 0x2C18DBD19DC21EC8, 0x98F9868A0FCF8139,
0x737D2CD648250B49, 0xCC61C94724B3428F },
{ 0x0C2B407880DD9E76, 0xC43A8991383FBE08,
0x5F7D2D65779BE5D2, 0x78719A54EB3B4AB5 }
},
{
{ 0xEA7D260A6245E404, 0x9DE407956E7FDFE0,
0x1FF3A4158DAC1AB5, 0x3E7090F1649C9073 },
{ 0x1A7685612B944E88, 0x250F939EE57F61C8,
0x0C0DAA891EAD643D, 0x68930023E125B88E }
},
{
{ 0x04B71AA7D2697768, 0xABDEDEF5CA345A33,
0x2409D29DEE37385E, 0x4EE1DF77CB83E156 },
{ 0x0CAC12D91CBB5B43, 0x170ED2F6CA895637,
0x28228CFA8ADE6D66, 0x7FF57C9553238ACA }
},
{
{ 0xCCC425634B2ED709, 0x0E356769856FD30D,
0xBCBCD43F559E9811, 0x738477AC5395B759 },
{ 0x35752B90C00EE17F, 0x68748390742ED2E3,
0x7CD06422BD1F5BC1, 0xFBC08769C9E7B797 }
},
{
{ 0xA242A35BB0CF664A, 0x126E48F77F9707E3,
0x1717BF54C6832660, 0xFAAE7332FD12C72E },
{ 0x27B52DB7995D586B, 0xBE29569E832237C2,
0xE8E4193E2A65E7DB, 0x152706DC2EAA1BBB }
},
{
{ 0x72BCD8B7BC60055B, 0x03CC23EE56E27E4B,
0xEE337424E4819370, 0xE2AA0E430AD3DA09 },
{ 0x40B8524F6383C45D, 0xD766355442A41B25,
0x64EFA6DE778A4797, 0x2042170A7079ADF4 }
}
};
/*
* Multiply the conventional generator of the curve by the provided
* integer. Return is written in *P.
*
* Assumptions:
* - Integer is not 0, and is lower than the curve order.
* If this conditions is not met, then the result is indeterminate
* (but the process is still constant-time).
*/
static void
_src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cp256_mulgen(p256__src_ec_ec_p256_m64_cjacobian *P, const unsigned char *k, size_t klen)
{
_src_ec_ec_p256_m64_cpoint_mul_inner(P, _src_ec_ec_p256_m64_cP256__src_ec_ec_p256_m64_cGwin, k, klen);
}
/*
* Return 1 if all of the following hold:
* - klen <= 32
* - k != 0
* - k is lower than the curve order
* Otherwise, return 0.
*
* Constant-time behaviour: only klen may be observable.
*/
static uint32_t
_src_ec_ec_p256_m64_ccheck_scalar(const unsigned char *k, size_t klen)
{
uint32_t z;
int32_t c;
size_t u;
if (klen > 32) {
return 0;
}
z = 0;
for (u = 0; u < klen; u ++) {
z |= k[u];
}
if (klen == 32) {
c = 0;
for (u = 0; u < klen; u ++) {
c |= -(int32_t)EQ0(c) & CMP(k[u], _src_ec_ec_p256_m64_cP256_N[u]);
}
} else {
c = -1;
}
return NEQ(z, 0) & LT0(c);
}
static uint32_t
_src_ec_ec_p256_m64_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *k, size_t klen, int curve)
{
uint32_t r;
p256__src_ec_ec_p256_m64_cjacobian P;
(void)curve;
if (Glen != 65) {
return 0;
}
r = _src_ec_ec_p256_m64_ccheck_scalar(k, klen);
r &= _src_ec_ec_p256_m64_cpoint_decode(&P, G);
_src_ec_ec_p256_m64_cp256_mul(&P, k, klen);
r &= _src_ec_ec_p256_m64_cpoint_encode(G, &P);
return r;
}
static size_t
_src_ec_ec_p256_m64_capi_mulgen(unsigned char *R,
const unsigned char *k, size_t klen, int curve)
{
p256__src_ec_ec_p256_m64_cjacobian P;
(void)curve;
_src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cp256_mulgen(&P, k, klen);
_src_ec_ec_p256_m64_cpoint_encode(R, &P);
return 65;
}
static uint32_t
_src_ec_ec_p256_m64_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
/*
* We might want to use Shamir's trick here: make a composite
* window of u*P+v*Q points, to merge the two doubling-ladders
* into one. This, however, has some complications:
*
* - During the computation, we may hit the point-at-infinity.
* Thus, we would need _src_ec_ec_p256_m64_cp256_add_complete_mixed() (complete
* formulas for point addition), with a higher cost (17 muls
* instead of 11).
*
* - A 4-bit window would be too large, since it would involve
* 16*16-1 = 255 points. For the same window size as in the
* _src_ec_ec_p256_m64_cp256_mul() case, we would need to reduce the window size
* to 2 bits, and thus perform twice as many non-doubling
* point additions.
*
* - The window may itself contain the point-at-infinity, and
* thus cannot be in all generality be made of affine points.
* Instead, we would need to make it a window of points in
* Jacobian coordinates. Even _src_ec_ec_p256_m64_cp256_add_complete_mixed() would
* be inappropriate.
*
* For these reasons, the code below performs two separate
* point multiplications, then computes the final point addition
* (which is both a "normal" addition, and a doubling, to handle
* all cases).
*/
p256__src_ec_ec_p256_m64_cjacobian P, Q;
uint32_t r, t, s;
uint64_t z;
(void)curve;
if (len != 65) {
return 0;
}
r = _src_ec_ec_p256_m64_cpoint_decode(&P, A);
_src_ec_ec_p256_m64_cp256_mul(&P, x, xlen);
if (B == NULL) {
_src_ec_ec_p256_m64_c_src_ec_ec_p256_m64_cp256_mulgen(&Q, y, ylen);
} else {
r &= _src_ec_ec_p256_m64_cpoint_decode(&Q, B);
_src_ec_ec_p256_m64_cp256_mul(&Q, y, ylen);
}
/*
* The final addition may fail in case both points are equal.
*/
t = _src_ec_ec_p256_m64_cp256_add(&P, &Q);
_src_ec_ec_p256_m64_cf256_final_reduce(P.z);
z = P.z[0] | P.z[1] | P.z[2] | P.z[3];
s = EQ((uint32_t)(z | (z >> 32)), 0);
_src_ec_ec_p256_m64_cp256_double(&Q);
/*
* If s is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
* have the following:
*
* s = 0, t = 0 return P (normal addition)
* s = 0, t = 1 return P (normal addition)
* s = 1, t = 0 return Q (a 'double' case)
* s = 1, t = 1 report an error (P+Q = 0)
*/
CCOPY(s & ~t, &P, &Q, sizeof Q);
_src_ec_ec_p256_m64_cpoint_encode(A, &P);
r &= ~(s & t);
return r;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_p256_m64 = {
(uint32_t)0x00800000,
&_src_ec_ec_p256_m64_capi_generator,
&_src_ec_ec_p256_m64_capi_order,
&_src_ec_ec_p256_m64_capi_xoff,
&_src_ec_ec_p256_m64_capi_mul,
&_src_ec_ec_p256_m64_capi_mulgen,
&_src_ec_ec_p256_m64_capi_muladd
};
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_p256_m64_get(void)
{
return &br_ec_p256_m64;
}
#else
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_p256_m64_get(void)
{
return 0;
}
#endif
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Parameters for supported curves:
* - field modulus p
* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)
* - b*R mod p (b is the second curve equation parameter)
*/
static const uint16_t _src_ec_ec_prime_i15_cP256_P[] = {
0x0111,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x003F, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x4000, 0x7FFF,
0x7FFF, 0x0001
};
static const uint16_t _src_ec_ec_prime_i15_cP256_R2[] = {
0x0111,
0x0000, 0x6000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FFC, 0x7FFF,
0x7FBF, 0x7FFF, 0x7FBF, 0x7FFF, 0x7FFF, 0x7FFF, 0x77FF, 0x7FFF,
0x4FFF, 0x0000
};
static const uint16_t _src_ec_ec_prime_i15_cP256_B[] = {
0x0111,
0x770C, 0x5EEF, 0x29C4, 0x3EC4, 0x6273, 0x0486, 0x4543, 0x3993,
0x3C01, 0x6B56, 0x212E, 0x57EE, 0x4882, 0x204B, 0x7483, 0x3C16,
0x0187, 0x0000
};
static const uint16_t _src_ec_ec_prime_i15_cP384_P[] = {
0x0199,
0x7FFF, 0x7FFF, 0x0003, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FFF,
0x7EFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x01FF
};
static const uint16_t _src_ec_ec_prime_i15_cP384_R2[] = {
0x0199,
0x1000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x0001, 0x0000, 0x0010,
0x0000, 0x0000, 0x0000, 0x7F00, 0x7FFF, 0x01FF, 0x0000, 0x1000,
0x0000, 0x2000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
static const uint16_t _src_ec_ec_prime_i15_cP384_B[] = {
0x0199,
0x7333, 0x2096, 0x70D1, 0x2310, 0x3020, 0x6197, 0x1464, 0x35BB,
0x70CA, 0x0117, 0x1920, 0x4136, 0x5FC8, 0x5713, 0x4938, 0x7DD2,
0x4DD2, 0x4A71, 0x0220, 0x683E, 0x2C87, 0x4DB1, 0x7BFF, 0x6C09,
0x0452, 0x0084
};
static const uint16_t _src_ec_ec_prime_i15_cP521_P[] = {
0x022B,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
0x7FFF, 0x7FFF, 0x07FF
};
static const uint16_t _src_ec_ec_prime_i15_cP521_R2[] = {
0x022B,
0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000
};
static const uint16_t _src_ec_ec_prime_i15_cP521_B[] = {
0x022B,
0x7002, 0x6A07, 0x751A, 0x228F, 0x71EF, 0x5869, 0x20F4, 0x1EFC,
0x7357, 0x37E0, 0x4EEC, 0x605E, 0x1652, 0x26F6, 0x31FA, 0x4A8F,
0x6193, 0x3C2A, 0x3C42, 0x48C7, 0x3489, 0x6771, 0x4C57, 0x5CCD,
0x2725, 0x545B, 0x503B, 0x5B42, 0x21A0, 0x2534, 0x687E, 0x70E4,
0x1618, 0x27D7, 0x0465
};
typedef struct {
const uint16_t *p;
const uint16_t *b;
const uint16_t *R2;
uint16_t p0i;
size_t point_len;
} _src_ec_ec_prime_i15_ccurve_params;
static inline const _src_ec_ec_prime_i15_ccurve_params *
_src_ec_ec_prime_i15_cid_to_curve(int curve)
{
static const _src_ec_ec_prime_i15_ccurve_params pp[] = {
{ _src_ec_ec_prime_i15_cP256_P, _src_ec_ec_prime_i15_cP256_B, _src_ec_ec_prime_i15_cP256_R2, 0x0001, 65 },
{ _src_ec_ec_prime_i15_cP384_P, _src_ec_ec_prime_i15_cP384_B, _src_ec_ec_prime_i15_cP384_R2, 0x0001, 97 },
{ _src_ec_ec_prime_i15_cP521_P, _src_ec_ec_prime_i15_cP521_B, _src_ec_ec_prime_i15_cP521_R2, 0x0001, 133 }
};
return &pp[curve - BR_EC_secp256r1];
}
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
/*
* Type for a point in Jacobian coordinates:
* -- three values, x, y and z, in Montgomery representation
* -- affine coordinates are X = x / z^2 and Y = y / z^3
* -- for the point at infinity, z = 0
*/
typedef struct {
uint16_t c[3][I15_LEN];
} _src_ec_ec_prime_i15_cjacobian;
/*
* We use a custom interpreter that uses a dozen registers, and
* only six operations:
* MSET(d, a) copy a into d
* MADD(d, a) d = d+a (modular)
* MSUB(d, a) d = d-a (modular)
* _src_ec_ec_prime_i15_cMMUL(d, a, b) d = a*b (Montgomery multiplication)
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
* MTZ(d) clear return value if d = 0
* Destination of _src_ec_ec_prime_i15_cMMUL (d) must be distinct from operands (a and b).
* There is no such constraint for MSUB and MADD.
*
* Registers include the operand coordinates, and temporaries.
*/
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
#define _src_ec_ec_prime_i15_cMMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
#define MTZ(d) (0x5000 + ((d) << 8))
#define ENDCODE 0
/*
* Registers for the input operands.
*/
#define _src_ec_ec_prime_i15_cP1x 0
#define _src_ec_ec_prime_i15_cP1y 1
#define _src_ec_ec_prime_i15_cP1z 2
#define _src_ec_ec_prime_i15_cP2x 3
#define _src_ec_ec_prime_i15_cP2y 4
#define _src_ec_ec_prime_i15_cP2z 5
/*
* Alternate names for the first input operand.
*/
#define _src_ec_ec_prime_i15_cPx 0
#define _src_ec_ec_prime_i15_cPy 1
#define _src_ec_ec_prime_i15_cPz 2
/*
* Temporaries.
*/
#define _src_ec_ec_prime_i15_ct1 6
#define _src_ec_ec_prime_i15_ct2 7
#define _src_ec_ec_prime_i15_ct3 8
#define _src_ec_ec_prime_i15_ct4 9
#define _src_ec_ec_prime_i15_ct5 10
#define _src_ec_ec_prime_i15_ct6 11
#define _src_ec_ec_prime_i15_ct7 12
/*
* Extra scratch registers available when there is no second operand (e.g.
* for "double" and "affine").
*/
#define _src_ec_ec_prime_i15_ct8 3
#define _src_ec_ec_prime_i15_ct9 4
#define _src_ec_ec_prime_i15_ct10 5
/*
* Doubling formulas are:
*
* s = 4*x*y^2
* m = 3*(x + z^2)*(x - z^2)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y^4
* z' = 2*y*z
*
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
* should. This case should not happen anyway, because our curves have
* prime order, and thus do not contain any point of order 2.
*
* If P is infinity (z = 0), then again the formulas yield infinity,
* which is correct. Thus, this code works for all points.
*
* Cost: 8 multiplications
*/
static const uint16_t _src_ec_ec_prime_i15_ccode_double[] = {
/*
* Compute z^2 (in t1).
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cPz, _src_ec_ec_prime_i15_cPz),
/*
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
*/
MSET(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cPx),
MSUB(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct1),
MADD(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cPx),
/*
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct2),
MSET(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct3),
MADD(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct3),
MADD(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct3),
/*
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_cPy, _src_ec_ec_prime_i15_cPy),
MADD(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_ct3),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cPx, _src_ec_ec_prime_i15_ct3),
MADD(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct2),
/*
* Compute x' = m^2 - 2*s.
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cPx, _src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct1),
MSUB(_src_ec_ec_prime_i15_cPx, _src_ec_ec_prime_i15_ct2),
MSUB(_src_ec_ec_prime_i15_cPx, _src_ec_ec_prime_i15_ct2),
/*
* Compute z' = 2*y*z.
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_cPy, _src_ec_ec_prime_i15_cPz),
MSET(_src_ec_ec_prime_i15_cPz, _src_ec_ec_prime_i15_ct4),
MADD(_src_ec_ec_prime_i15_cPz, _src_ec_ec_prime_i15_ct4),
/*
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
* 2*y^2 in t3.
*/
MSUB(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cPx),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cPy, _src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct2),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_ct3),
MSUB(_src_ec_ec_prime_i15_cPy, _src_ec_ec_prime_i15_ct4),
MSUB(_src_ec_ec_prime_i15_cPy, _src_ec_ec_prime_i15_ct4),
ENDCODE
};
/*
* Addtions formulas are:
*
* u1 = x1 * z2^2
* u2 = x2 * z1^2
* s1 = y1 * z2^3
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1 * z2
*
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
* z3 == 0, so the result is correct.
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
* not correct.
* h == 0 only if u1 == u2; this happens in two cases:
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
*
* Thus, the following situations are not handled correctly:
* -- P1 = 0 and P2 != 0
* -- P1 != 0 and P2 = 0
* -- P1 = P2
* All other cases are properly computed. However, even in "incorrect"
* situations, the three coordinates still are properly formed field
* elements.
*
* The returned flag is cleared if r == 0. This happens in the following
* cases:
* -- Both points are on the same horizontal line (same Y coordinate).
* -- Both points are infinity.
* -- One point is infinity and the other is on line Y = 0.
* The third case cannot happen with our curves (there is no valid point
* on line Y = 0 since that would be a point of order 2). If the two
* source points are non-infinity, then remains only the case where the
* two points are on the same horizontal line.
*
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
* P2 != 0:
* -- If the returned value is not the point at infinity, then it was properly
* computed.
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
* is indeed the point at infinity.
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
* use the 'double' code.
*
* Cost: 16 multiplications
*/
static const uint16_t _src_ec_ec_prime_i15_ccode_add[] = {
/*
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_cP2z, _src_ec_ec_prime_i15_cP2z),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct3),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_cP2z, _src_ec_ec_prime_i15_ct3),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_ct4),
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_cP1z),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cP2x, _src_ec_ec_prime_i15_ct4),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct5, _src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_ct4),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_cP2y, _src_ec_ec_prime_i15_ct5),
/*
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
*/
MSUB( _src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct1),
MSUB( _src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_ct3),
/*
* Report cases where r = 0 through the returned flag.
*/
MTZ( _src_ec_ec_prime_i15_ct4),
/*
* Compute u1*h^2 (in t6) and h^3 (in t5).
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct7, _src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct2),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct6, _src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct7),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct5, _src_ec_ec_prime_i15_ct7, _src_ec_ec_prime_i15_ct2),
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
* t1 and t7 can be used as scratch registers.
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_ct4),
MSUB( _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct5),
MSUB( _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct6),
MSUB( _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct6),
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
MSUB(_src_ec_ec_prime_i15_ct6, _src_ec_ec_prime_i15_cP1x),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_ct4, _src_ec_ec_prime_i15_ct6),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct5, _src_ec_ec_prime_i15_ct3),
MSUB(_src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_ct1),
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_cP2z),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct2),
ENDCODE
};
/*
* Check that the point is on the curve. This code snippet assumes the
* following conventions:
* -- Coordinates x and y have been freshly decoded in P1 (but not
* converted to Montgomery coordinates yet).
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
*/
static const uint16_t _src_ec_ec_prime_i15_ccode_check[] = {
/* Convert x and y to Montgomery representation. */
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_cP2x),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_cP2x),
MSET(_src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct1),
MSET(_src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_ct2),
/* Compute x^3 in t1. */
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_cP1x),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct2),
/* Subtract 3*x from t1. */
MSUB(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1x),
MSUB(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1x),
MSUB(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1x),
/* Add b. */
MADD(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP2y),
/* Compute y^2 in t2. */
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_cP1y),
/* Compare y^2 with x^3 - 3*x + b; they must match. */
MSUB(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_ct2),
MTZ(_src_ec_ec_prime_i15_ct1),
/* Set z to 1 (in Montgomery representation). */
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_cP2x, _src_ec_ec_prime_i15_cP2z),
ENDCODE
};
/*
* Conversion back to affine coordinates. This code snippet assumes that
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
*/
static const uint16_t _src_ec_ec_prime_i15_ccode_affine[] = {
/* Save z*R in t1. */
MSET(_src_ec_ec_prime_i15_ct1, _src_ec_ec_prime_i15_cP1z),
/* Compute z^3 in t2. */
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_cP1z),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_cP1z, _src_ec_ec_prime_i15_ct2),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_cP2z),
/* Invert to (1/z^3) in t2. */
MINV(_src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_ct4),
/* Compute y. */
MSET(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_cP1y),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cP1y, _src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct3),
/* Compute (1/z^2) in t3. */
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_ct3, _src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct1),
/* Compute x. */
MSET( _src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_cP1x),
_src_ec_ec_prime_i15_cMMUL(_src_ec_ec_prime_i15_cP1x, _src_ec_ec_prime_i15_ct2, _src_ec_ec_prime_i15_ct3),
ENDCODE
};
static uint32_t
_src_ec_ec_prime_i15_crun_code(_src_ec_ec_prime_i15_cjacobian *P1, const _src_ec_ec_prime_i15_cjacobian *P2,
const _src_ec_ec_prime_i15_ccurve_params *cc, const uint16_t *code)
{
uint32_t r;
uint16_t t[13][I15_LEN];
size_t u;
r = 1;
/*
* Copy the two operands in the dedicated registers.
*/
memcpy(t[_src_ec_ec_prime_i15_cP1x], P1->c, 3 * I15_LEN * sizeof(uint16_t));
memcpy(t[_src_ec_ec_prime_i15_cP2x], P2->c, 3 * I15_LEN * sizeof(uint16_t));
/*
* Run formulas.
*/
for (u = 0;; u ++) {
unsigned op, d, a, b;
op = code[u];
if (op == 0) {
break;
}
d = (op >> 8) & 0x0F;
a = (op >> 4) & 0x0F;
b = op & 0x0F;
op >>= 12;
switch (op) {
uint32_t ctl;
size_t plen;
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
case 0:
memcpy(t[d], t[a], I15_LEN * sizeof(uint16_t));
break;
case 1:
ctl = br_i15_add(t[d], t[a], 1);
ctl |= NOT(br_i15_sub(t[d], cc->p, 0));
br_i15_sub(t[d], cc->p, ctl);
break;
case 2:
br_i15_add(t[d], cc->p, br_i15_sub(t[d], t[a], 1));
break;
case 3:
br_i15_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
break;
case 4:
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
br_i15_encode(tp, plen, cc->p);
tp[plen - 1] -= 2;
br_i15_modpow(t[d], tp, plen,
cc->p, cc->p0i, t[a], t[b]);
break;
default:
r &= ~br_i15_iszero(t[d]);
break;
}
}
/*
* Copy back result.
*/
memcpy(P1->c, t[_src_ec_ec_prime_i15_cP1x], 3 * I15_LEN * sizeof(uint16_t));
return r;
}
static void
_src_ec_ec_prime_i15_cset_one(uint16_t *x, const uint16_t *p)
{
size_t plen;
plen = (p[0] + 31) >> 4;
memset(x, 0, plen * sizeof *x);
x[0] = p[0];
x[1] = 0x0001;
}
static void
_src_ec_ec_prime_i15_cpoint_zero(_src_ec_ec_prime_i15_cjacobian *P, const _src_ec_ec_prime_i15_ccurve_params *cc)
{
memset(P, 0, sizeof *P);
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
}
static inline void
_src_ec_ec_prime_i15_cpoint_double(_src_ec_ec_prime_i15_cjacobian *P, const _src_ec_ec_prime_i15_ccurve_params *cc)
{
_src_ec_ec_prime_i15_crun_code(P, P, cc, _src_ec_ec_prime_i15_ccode_double);
}
static inline uint32_t
_src_ec_ec_prime_i15_cpoint_add(_src_ec_ec_prime_i15_cjacobian *P1, const _src_ec_ec_prime_i15_cjacobian *P2, const _src_ec_ec_prime_i15_ccurve_params *cc)
{
return _src_ec_ec_prime_i15_crun_code(P1, P2, cc, _src_ec_ec_prime_i15_ccode_add);
}
static void
_src_ec_ec_prime_i15_cpoint_mul(_src_ec_ec_prime_i15_cjacobian *P, const unsigned char *x, size_t xlen,
const _src_ec_ec_prime_i15_ccurve_params *cc)
{
/*
* We do a simple double-and-add ladder with a 2-bit window
* to make only one add every two doublings. We thus first
* precompute 2P and 3P in some local buffers.
*
* We always perform two doublings and one addition; the
* addition is with P, 2P and 3P and is done in a temporary
* array.
*
* The addition code cannot handle cases where one of the
* operands is infinity, which is the case at the start of the
* ladder. We therefore need to maintain a flag that controls
* this situation.
*/
uint32_t qz;
_src_ec_ec_prime_i15_cjacobian P2, P3, Q, T, U;
memcpy(&P2, P, sizeof P2);
_src_ec_ec_prime_i15_cpoint_double(&P2, cc);
memcpy(&P3, P, sizeof P3);
_src_ec_ec_prime_i15_cpoint_add(&P3, &P2, cc);
_src_ec_ec_prime_i15_cpoint_zero(&Q, cc);
qz = 1;
while (xlen -- > 0) {
int k;
for (k = 6; k >= 0; k -= 2) {
uint32_t bits;
uint32_t bnz;
_src_ec_ec_prime_i15_cpoint_double(&Q, cc);
_src_ec_ec_prime_i15_cpoint_double(&Q, cc);
memcpy(&T, P, sizeof T);
memcpy(&U, &Q, sizeof U);
bits = (*x >> k) & (uint32_t)3;
bnz = NEQ(bits, 0);
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
_src_ec_ec_prime_i15_cpoint_add(&U, &T, cc);
CCOPY(bnz & qz, &Q, &T, sizeof Q);
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
}
x ++;
}
memcpy(P, &Q, sizeof Q);
}
/*
* Decode point into Jacobian coordinates. This function does not support
* the point at infinity. If the point is invalid then this returns 0, but
* the coordinates are still set to properly formed field elements.
*/
static uint32_t
_src_ec_ec_prime_i15_cpoint_decode(_src_ec_ec_prime_i15_cjacobian *P, const void *src, size_t len, const _src_ec_ec_prime_i15_ccurve_params *cc)
{
/*
* Points must use uncompressed format:
* -- first byte is 0x04;
* -- coordinates X and Y use unsigned big-endian, with the same
* length as the field modulus.
*
* We don't support hybrid format (uncompressed, but first byte
* has value 0x06 or 0x07, depending on the least significant bit
* of Y) because it is rather useless, and explicitly forbidden
* by PKIX (RFC 5480, section 2.2).
*
* We don't support compressed format either, because it is not
* much used in practice (there are or were patent-related
* concerns about point compression, which explains the lack of
* generalised support). Also, point compression support would
* need a bit more code.
*/
const unsigned char *buf;
size_t plen, zlen;
uint32_t r;
_src_ec_ec_prime_i15_cjacobian Q;
buf = (const unsigned char*)src;
_src_ec_ec_prime_i15_cpoint_zero(P, cc);
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
if (len != 1 + (plen << 1)) {
return 0;
}
r = br_i15_decode_mod(P->c[0], buf + 1, plen, cc->p);
r &= br_i15_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
/*
* Check first byte.
*/
r &= EQ(buf[0], 0x04);
/* obsolete
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
*/
/*
* Convert coordinates and check that the point is valid.
*/
zlen = ((cc->p[0] + 31) >> 4) * sizeof(uint16_t);
memcpy(Q.c[0], cc->R2, zlen);
memcpy(Q.c[1], cc->b, zlen);
_src_ec_ec_prime_i15_cset_one(Q.c[2], cc->p);
r &= ~_src_ec_ec_prime_i15_crun_code(P, &Q, cc, _src_ec_ec_prime_i15_ccode_check);
return r;
}
/*
* Encode a point. This method assumes that the point is correct and is
* not the point at infinity. Encoded size is always 1+2*plen, where
* plen is the field modulus length, in bytes.
*/
static void
_src_ec_ec_prime_i15_cpoint_encode(void *dst, const _src_ec_ec_prime_i15_cjacobian *P, const _src_ec_ec_prime_i15_ccurve_params *cc)
{
unsigned char *buf;
size_t plen;
_src_ec_ec_prime_i15_cjacobian Q, T;
buf = (unsigned char*)dst;
plen = (cc->p[0] - (cc->p[0] >> 4) + 7) >> 3;
buf[0] = 0x04;
memcpy(&Q, P, sizeof *P);
_src_ec_ec_prime_i15_cset_one(T.c[2], cc->p);
_src_ec_ec_prime_i15_crun_code(&Q, &T, cc, _src_ec_ec_prime_i15_ccode_affine);
br_i15_encode(buf + 1, plen, Q.c[0]);
br_i15_encode(buf + 1 + plen, plen, Q.c[1]);
}
static const br_ec_curve_def *
_src_ec_ec_prime_i15_cid_to_curve_def(int curve)
{
switch (curve) {
case BR_EC_secp256r1:
return &br_secp256r1;
case BR_EC_secp384r1:
return &br_secp384r1;
case BR_EC_secp521r1:
return &br_secp521r1;
}
return NULL;
}
static const unsigned char *
_src_ec_ec_prime_i15_capi_generator(int curve, size_t *len)
{
const br_ec_curve_def *cd;
cd = _src_ec_ec_prime_i15_cid_to_curve_def(curve);
*len = cd->generator_len;
return cd->generator;
}
static const unsigned char *
_src_ec_ec_prime_i15_capi_order(int curve, size_t *len)
{
const br_ec_curve_def *cd;
cd = _src_ec_ec_prime_i15_cid_to_curve_def(curve);
*len = cd->order_len;
return cd->order;
}
static size_t
_src_ec_ec_prime_i15_capi_xoff(int curve, size_t *len)
{
_src_ec_ec_prime_i15_capi_generator(curve, len);
*len >>= 1;
return 1;
}
static uint32_t
_src_ec_ec_prime_i15_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *x, size_t xlen, int curve)
{
uint32_t r;
const _src_ec_ec_prime_i15_ccurve_params *cc;
_src_ec_ec_prime_i15_cjacobian P;
cc = _src_ec_ec_prime_i15_cid_to_curve(curve);
if (Glen != cc->point_len) {
return 0;
}
r = _src_ec_ec_prime_i15_cpoint_decode(&P, G, Glen, cc);
_src_ec_ec_prime_i15_cpoint_mul(&P, x, xlen, cc);
_src_ec_ec_prime_i15_cpoint_encode(G, &P, cc);
return r;
}
static size_t
_src_ec_ec_prime_i15_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_prime_i15_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_prime_i15_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_prime_i15_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
uint32_t r, t, z;
const _src_ec_ec_prime_i15_ccurve_params *cc;
_src_ec_ec_prime_i15_cjacobian P, Q;
/*
* TODO: see about merging the two ladders. Right now, we do
* two independent point multiplications, which is a bit
* wasteful of CPU resources (but yields short code).
*/
cc = _src_ec_ec_prime_i15_cid_to_curve(curve);
if (len != cc->point_len) {
return 0;
}
r = _src_ec_ec_prime_i15_cpoint_decode(&P, A, len, cc);
if (B == NULL) {
size_t Glen;
B = _src_ec_ec_prime_i15_capi_generator(curve, &Glen);
}
r &= _src_ec_ec_prime_i15_cpoint_decode(&Q, B, len, cc);
_src_ec_ec_prime_i15_cpoint_mul(&P, x, xlen, cc);
_src_ec_ec_prime_i15_cpoint_mul(&Q, y, ylen, cc);
/*
* We want to compute P+Q. Since the base points A and B are distinct
* from infinity, and the multipliers are non-zero and lower than the
* curve order, then we know that P and Q are non-infinity. This
* leaves two special situations to test for:
* -- If P = Q then we must use _src_ec_ec_prime_i15_cpoint_double().
* -- If P+Q = 0 then we must report an error.
*/
t = _src_ec_ec_prime_i15_cpoint_add(&P, &Q, cc);
_src_ec_ec_prime_i15_cpoint_double(&Q, cc);
z = br_i15_iszero(P.c[2]);
/*
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
* have the following:
*
* z = 0, t = 0 return P (normal addition)
* z = 0, t = 1 return P (normal addition)
* z = 1, t = 0 return Q (a 'double' case)
* z = 1, t = 1 report an error (P+Q = 0)
*/
CCOPY(z & ~t, &P, &Q, sizeof Q);
_src_ec_ec_prime_i15_cpoint_encode(A, &P, cc);
r &= ~(z & t);
return r;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_prime_i15 = {
(uint32_t)0x03800000,
&_src_ec_ec_prime_i15_capi_generator,
&_src_ec_ec_prime_i15_capi_order,
&_src_ec_ec_prime_i15_capi_xoff,
&_src_ec_ec_prime_i15_capi_mul,
&_src_ec_ec_prime_i15_capi_mulgen,
&_src_ec_ec_prime_i15_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Parameters for supported curves (field modulus, and 'b' equation
* parameter; both values use the 'i31' format, and 'b' is in Montgomery
* representation).
*/
static const uint32_t _src_ec_ec_prime_i31_cP256_P[] = {
0x00000108,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
0x000000FF
};
static const uint32_t _src_ec_ec_prime_i31_cP256_R2[] = {
0x00000108,
0x00014000, 0x00018000, 0x00000000, 0x7FF40000,
0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF,
0x00000000
};
static const uint32_t _src_ec_ec_prime_i31_cP256_B[] = {
0x00000108,
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
0x0000000E
};
static const uint32_t _src_ec_ec_prime_i31_cP384_P[] = {
0x0000018C,
0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x00000FFF
};
static const uint32_t _src_ec_ec_prime_i31_cP384_R2[] = {
0x0000018C,
0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF,
0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF,
0x00008000, 0x00008000, 0x00000000, 0x00000000,
0x00000000
};
static const uint32_t _src_ec_ec_prime_i31_cP384_B[] = {
0x0000018C,
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
0x000008A5
};
static const uint32_t _src_ec_ec_prime_i31_cP521_P[] = {
0x00000219,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
0x01FFFFFF
};
static const uint32_t _src_ec_ec_prime_i31_cP521_R2[] = {
0x00000219,
0x00001000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000
};
static const uint32_t _src_ec_ec_prime_i31_cP521_B[] = {
0x00000219,
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
0x00654FAE
};
typedef struct {
const uint32_t *p;
const uint32_t *b;
const uint32_t *R2;
uint32_t p0i;
size_t point_len;
} _src_ec_ec_prime_i31_ccurve_params;
static inline const _src_ec_ec_prime_i31_ccurve_params *
_src_ec_ec_prime_i31_cid_to_curve(int curve)
{
static const _src_ec_ec_prime_i31_ccurve_params pp[] = {
{ _src_ec_ec_prime_i31_cP256_P, _src_ec_ec_prime_i31_cP256_B, _src_ec_ec_prime_i31_cP256_R2, 0x00000001, 65 },
{ _src_ec_ec_prime_i31_cP384_P, _src_ec_ec_prime_i31_cP384_B, _src_ec_ec_prime_i31_cP384_R2, 0x00000001, 97 },
{ _src_ec_ec_prime_i31_cP521_P, _src_ec_ec_prime_i31_cP521_B, _src_ec_ec_prime_i31_cP521_R2, 0x00000001, 133 }
};
return &pp[curve - BR_EC_secp256r1];
}
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
/*
* Type for a point in Jacobian coordinates:
* -- three values, x, y and z, in Montgomery representation
* -- affine coordinates are X = x / z^2 and Y = y / z^3
* -- for the point at infinity, z = 0
*/
typedef struct {
uint32_t c[3][I31_LEN];
} _src_ec_ec_prime_i31_cjacobian;
/*
* We use a custom interpreter that uses a dozen registers, and
* only six operations:
* MSET(d, a) copy a into d
* MADD(d, a) d = d+a (modular)
* MSUB(d, a) d = d-a (modular)
* _src_ec_ec_prime_i31_cMMUL(d, a, b) d = a*b (Montgomery multiplication)
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
* MTZ(d) clear return value if d = 0
* Destination of _src_ec_ec_prime_i31_cMMUL (d) must be distinct from operands (a and b).
* There is no such constraint for MSUB and MADD.
*
* Registers include the operand coordinates, and temporaries.
*/
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
#define _src_ec_ec_prime_i31_cMMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
#define MTZ(d) (0x5000 + ((d) << 8))
#define ENDCODE 0
/*
* Registers for the input operands.
*/
#define _src_ec_ec_prime_i31_cP1x 0
#define _src_ec_ec_prime_i31_cP1y 1
#define _src_ec_ec_prime_i31_cP1z 2
#define _src_ec_ec_prime_i31_cP2x 3
#define _src_ec_ec_prime_i31_cP2y 4
#define _src_ec_ec_prime_i31_cP2z 5
/*
* Alternate names for the first input operand.
*/
#define _src_ec_ec_prime_i31_cPx 0
#define _src_ec_ec_prime_i31_cPy 1
#define _src_ec_ec_prime_i31_cPz 2
/*
* Temporaries.
*/
#define _src_ec_ec_prime_i31_ct1 6
#define _src_ec_ec_prime_i31_ct2 7
#define _src_ec_ec_prime_i31_ct3 8
#define _src_ec_ec_prime_i31_ct4 9
#define _src_ec_ec_prime_i31_ct5 10
#define _src_ec_ec_prime_i31_ct6 11
#define _src_ec_ec_prime_i31_ct7 12
/*
* Extra scratch registers available when there is no second operand (e.g.
* for "double" and "affine").
*/
#define _src_ec_ec_prime_i31_ct8 3
#define _src_ec_ec_prime_i31_ct9 4
#define _src_ec_ec_prime_i31_ct10 5
/*
* Doubling formulas are:
*
* s = 4*x*y^2
* m = 3*(x + z^2)*(x - z^2)
* x' = m^2 - 2*s
* y' = m*(s - x') - 8*y^4
* z' = 2*y*z
*
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
* should. This case should not happen anyway, because our curves have
* prime order, and thus do not contain any point of order 2.
*
* If P is infinity (z = 0), then again the formulas yield infinity,
* which is correct. Thus, this code works for all points.
*
* Cost: 8 multiplications
*/
static const uint16_t _src_ec_ec_prime_i31_ccode_double[] = {
/*
* Compute z^2 (in t1).
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cPz, _src_ec_ec_prime_i31_cPz),
/*
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
*/
MSET(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cPx),
MSUB(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct1),
MADD(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cPx),
/*
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct2),
MSET(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct3),
MADD(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct3),
MADD(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct3),
/*
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
*/
_src_ec_ec_prime_i31_cMMUL( _src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_cPy, _src_ec_ec_prime_i31_cPy),
MADD( _src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_ct3),
_src_ec_ec_prime_i31_cMMUL( _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cPx, _src_ec_ec_prime_i31_ct3),
MADD( _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct2),
/*
* Compute x' = m^2 - 2*s.
*/
_src_ec_ec_prime_i31_cMMUL( _src_ec_ec_prime_i31_cPx, _src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct1),
MSUB( _src_ec_ec_prime_i31_cPx, _src_ec_ec_prime_i31_ct2),
MSUB( _src_ec_ec_prime_i31_cPx, _src_ec_ec_prime_i31_ct2),
/*
* Compute z' = 2*y*z.
*/
_src_ec_ec_prime_i31_cMMUL( _src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_cPy, _src_ec_ec_prime_i31_cPz),
MSET( _src_ec_ec_prime_i31_cPz, _src_ec_ec_prime_i31_ct4),
MADD( _src_ec_ec_prime_i31_cPz, _src_ec_ec_prime_i31_ct4),
/*
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
* 2*y^2 in t3.
*/
MSUB( _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cPx),
_src_ec_ec_prime_i31_cMMUL( _src_ec_ec_prime_i31_cPy, _src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct2),
_src_ec_ec_prime_i31_cMMUL( _src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_ct3),
MSUB( _src_ec_ec_prime_i31_cPy, _src_ec_ec_prime_i31_ct4),
MSUB( _src_ec_ec_prime_i31_cPy, _src_ec_ec_prime_i31_ct4),
ENDCODE
};
/*
* Addtions formulas are:
*
* u1 = x1 * z2^2
* u2 = x2 * z1^2
* s1 = y1 * z2^3
* s2 = y2 * z1^3
* h = u2 - u1
* r = s2 - s1
* x3 = r^2 - h^3 - 2 * u1 * h^2
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
* z3 = h * z1 * z2
*
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
* z3 == 0, so the result is correct.
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
* not correct.
* h == 0 only if u1 == u2; this happens in two cases:
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
*
* Thus, the following situations are not handled correctly:
* -- P1 = 0 and P2 != 0
* -- P1 != 0 and P2 = 0
* -- P1 = P2
* All other cases are properly computed. However, even in "incorrect"
* situations, the three coordinates still are properly formed field
* elements.
*
* The returned flag is cleared if r == 0. This happens in the following
* cases:
* -- Both points are on the same horizontal line (same Y coordinate).
* -- Both points are infinity.
* -- One point is infinity and the other is on line Y = 0.
* The third case cannot happen with our curves (there is no valid point
* on line Y = 0 since that would be a point of order 2). If the two
* source points are non-infinity, then remains only the case where the
* two points are on the same horizontal line.
*
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
* P2 != 0:
* -- If the returned value is not the point at infinity, then it was properly
* computed.
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
* is indeed the point at infinity.
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
* use the 'double' code.
*
* Cost: 16 multiplications
*/
static const uint16_t _src_ec_ec_prime_i31_ccode_add[] = {
/*
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_cP2z, _src_ec_ec_prime_i31_cP2z),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct3),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_cP2z, _src_ec_ec_prime_i31_ct3),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_ct4),
/*
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_cP1z),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cP2x, _src_ec_ec_prime_i31_ct4),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct5, _src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_ct4),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_cP2y, _src_ec_ec_prime_i31_ct5),
/*
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
*/
MSUB(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct1),
MSUB(_src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_ct3),
/*
* Report cases where r = 0 through the returned flag.
*/
MTZ(_src_ec_ec_prime_i31_ct4),
/*
* Compute u1*h^2 (in t6) and h^3 (in t5).
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct7, _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct2),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct6, _src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct7),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct5, _src_ec_ec_prime_i31_ct7, _src_ec_ec_prime_i31_ct2),
/*
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
* t1 and t7 can be used as scratch registers.
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_ct4),
MSUB(_src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct5),
MSUB(_src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct6),
MSUB(_src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct6),
/*
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
*/
MSUB(_src_ec_ec_prime_i31_ct6, _src_ec_ec_prime_i31_cP1x),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_ct4, _src_ec_ec_prime_i31_ct6),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct5, _src_ec_ec_prime_i31_ct3),
MSUB(_src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_ct1),
/*
* Compute z3 = h*z1*z2.
*/
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_cP2z),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct2),
ENDCODE
};
/*
* Check that the point is on the curve. This code snippet assumes the
* following conventions:
* -- Coordinates x and y have been freshly decoded in P1 (but not
* converted to Montgomery coordinates yet).
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
*/
static const uint16_t _src_ec_ec_prime_i31_ccode_check[] = {
/* Convert x and y to Montgomery representation. */
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_cP2x),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_cP2x),
MSET(_src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct1),
MSET(_src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_ct2),
/* Compute x^3 in t1. */
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_cP1x),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct2),
/* Subtract 3*x from t1. */
MSUB(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1x),
MSUB(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1x),
MSUB(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1x),
/* Add b. */
MADD(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP2y),
/* Compute y^2 in t2. */
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_cP1y),
/* Compare y^2 with x^3 - 3*x + b; they must match. */
MSUB(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_ct2),
MTZ(_src_ec_ec_prime_i31_ct1),
/* Set z to 1 (in Montgomery representation). */
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_cP2x, _src_ec_ec_prime_i31_cP2z),
ENDCODE
};
/*
* Conversion back to affine coordinates. This code snippet assumes that
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
*/
static const uint16_t _src_ec_ec_prime_i31_ccode_affine[] = {
/* Save z*R in t1. */
MSET(_src_ec_ec_prime_i31_ct1, _src_ec_ec_prime_i31_cP1z),
/* Compute z^3 in t2. */
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_cP1z),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_cP1z, _src_ec_ec_prime_i31_ct2),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_cP2z),
/* Invert to (1/z^3) in t2. */
MINV(_src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_ct4),
/* Compute y. */
MSET(_src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_cP1y),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_cP1y, _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct3),
/* Compute (1/z^2) in t3. */
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_ct3, _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct1),
/* Compute x. */
MSET( _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_cP1x),
_src_ec_ec_prime_i31_cMMUL(_src_ec_ec_prime_i31_cP1x, _src_ec_ec_prime_i31_ct2, _src_ec_ec_prime_i31_ct3),
ENDCODE
};
static uint32_t
_src_ec_ec_prime_i31_crun_code(_src_ec_ec_prime_i31_cjacobian *P1, const _src_ec_ec_prime_i31_cjacobian *P2,
const _src_ec_ec_prime_i31_ccurve_params *cc, const uint16_t *code)
{
uint32_t r;
uint32_t t[13][I31_LEN];
size_t u;
r = 1;
/*
* Copy the two operands in the dedicated registers.
*/
memcpy(t[_src_ec_ec_prime_i31_cP1x], P1->c, 3 * I31_LEN * sizeof(uint32_t));
memcpy(t[_src_ec_ec_prime_i31_cP2x], P2->c, 3 * I31_LEN * sizeof(uint32_t));
/*
* Run formulas.
*/
for (u = 0;; u ++) {
unsigned op, d, a, b;
op = code[u];
if (op == 0) {
break;
}
d = (op >> 8) & 0x0F;
a = (op >> 4) & 0x0F;
b = op & 0x0F;
op >>= 12;
switch (op) {
uint32_t ctl;
size_t plen;
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
case 0:
memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t));
break;
case 1:
ctl = br_i31_add(t[d], t[a], 1);
ctl |= NOT(br_i31_sub(t[d], cc->p, 0));
br_i31_sub(t[d], cc->p, ctl);
break;
case 2:
br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1));
break;
case 3:
br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
break;
case 4:
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
br_i31_encode(tp, plen, cc->p);
tp[plen - 1] -= 2;
br_i31_modpow(t[d], tp, plen,
cc->p, cc->p0i, t[a], t[b]);
break;
default:
r &= ~br_i31_iszero(t[d]);
break;
}
}
/*
* Copy back result.
*/
memcpy(P1->c, t[_src_ec_ec_prime_i31_cP1x], 3 * I31_LEN * sizeof(uint32_t));
return r;
}
static void
_src_ec_ec_prime_i31_cset_one(uint32_t *x, const uint32_t *p)
{
size_t plen;
plen = (p[0] + 63) >> 5;
memset(x, 0, plen * sizeof *x);
x[0] = p[0];
x[1] = 0x00000001;
}
static void
_src_ec_ec_prime_i31_cpoint_zero(_src_ec_ec_prime_i31_cjacobian *P, const _src_ec_ec_prime_i31_ccurve_params *cc)
{
memset(P, 0, sizeof *P);
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
}
static inline void
_src_ec_ec_prime_i31_cpoint_double(_src_ec_ec_prime_i31_cjacobian *P, const _src_ec_ec_prime_i31_ccurve_params *cc)
{
_src_ec_ec_prime_i31_crun_code(P, P, cc, _src_ec_ec_prime_i31_ccode_double);
}
static inline uint32_t
_src_ec_ec_prime_i31_cpoint_add(_src_ec_ec_prime_i31_cjacobian *P1, const _src_ec_ec_prime_i31_cjacobian *P2, const _src_ec_ec_prime_i31_ccurve_params *cc)
{
return _src_ec_ec_prime_i31_crun_code(P1, P2, cc, _src_ec_ec_prime_i31_ccode_add);
}
static void
_src_ec_ec_prime_i31_cpoint_mul(_src_ec_ec_prime_i31_cjacobian *P, const unsigned char *x, size_t xlen,
const _src_ec_ec_prime_i31_ccurve_params *cc)
{
/*
* We do a simple double-and-add ladder with a 2-bit window
* to make only one add every two doublings. We thus first
* precompute 2P and 3P in some local buffers.
*
* We always perform two doublings and one addition; the
* addition is with P, 2P and 3P and is done in a temporary
* array.
*
* The addition code cannot handle cases where one of the
* operands is infinity, which is the case at the start of the
* ladder. We therefore need to maintain a flag that controls
* this situation.
*/
uint32_t qz;
_src_ec_ec_prime_i31_cjacobian P2, P3, Q, T, U;
memcpy(&P2, P, sizeof P2);
_src_ec_ec_prime_i31_cpoint_double(&P2, cc);
memcpy(&P3, P, sizeof P3);
_src_ec_ec_prime_i31_cpoint_add(&P3, &P2, cc);
_src_ec_ec_prime_i31_cpoint_zero(&Q, cc);
qz = 1;
while (xlen -- > 0) {
int k;
for (k = 6; k >= 0; k -= 2) {
uint32_t bits;
uint32_t bnz;
_src_ec_ec_prime_i31_cpoint_double(&Q, cc);
_src_ec_ec_prime_i31_cpoint_double(&Q, cc);
memcpy(&T, P, sizeof T);
memcpy(&U, &Q, sizeof U);
bits = (*x >> k) & (uint32_t)3;
bnz = NEQ(bits, 0);
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
_src_ec_ec_prime_i31_cpoint_add(&U, &T, cc);
CCOPY(bnz & qz, &Q, &T, sizeof Q);
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
qz &= ~bnz;
}
x ++;
}
memcpy(P, &Q, sizeof Q);
}
/*
* Decode point into Jacobian coordinates. This function does not support
* the point at infinity. If the point is invalid then this returns 0, but
* the coordinates are still set to properly formed field elements.
*/
static uint32_t
_src_ec_ec_prime_i31_cpoint_decode(_src_ec_ec_prime_i31_cjacobian *P, const void *src, size_t len, const _src_ec_ec_prime_i31_ccurve_params *cc)
{
/*
* Points must use uncompressed format:
* -- first byte is 0x04;
* -- coordinates X and Y use unsigned big-endian, with the same
* length as the field modulus.
*
* We don't support hybrid format (uncompressed, but first byte
* has value 0x06 or 0x07, depending on the least significant bit
* of Y) because it is rather useless, and explicitly forbidden
* by PKIX (RFC 5480, section 2.2).
*
* We don't support compressed format either, because it is not
* much used in practice (there are or were patent-related
* concerns about point compression, which explains the lack of
* generalised support). Also, point compression support would
* need a bit more code.
*/
const unsigned char *buf;
size_t plen, zlen;
uint32_t r;
_src_ec_ec_prime_i31_cjacobian Q;
buf = (const unsigned char*)src;
_src_ec_ec_prime_i31_cpoint_zero(P, cc);
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
if (len != 1 + (plen << 1)) {
return 0;
}
r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p);
r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
/*
* Check first byte.
*/
r &= EQ(buf[0], 0x04);
/* obsolete
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
*/
/*
* Convert coordinates and check that the point is valid.
*/
zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t);
memcpy(Q.c[0], cc->R2, zlen);
memcpy(Q.c[1], cc->b, zlen);
_src_ec_ec_prime_i31_cset_one(Q.c[2], cc->p);
r &= ~_src_ec_ec_prime_i31_crun_code(P, &Q, cc, _src_ec_ec_prime_i31_ccode_check);
return r;
}
/*
* Encode a point. This method assumes that the point is correct and is
* not the point at infinity. Encoded size is always 1+2*plen, where
* plen is the field modulus length, in bytes.
*/
static void
_src_ec_ec_prime_i31_cpoint_encode(void *dst, const _src_ec_ec_prime_i31_cjacobian *P, const _src_ec_ec_prime_i31_ccurve_params *cc)
{
unsigned char *buf;
uint32_t xbl;
size_t plen;
_src_ec_ec_prime_i31_cjacobian Q, T;
buf = (unsigned char*)dst;
xbl = cc->p[0];
xbl -= (xbl >> 5);
plen = (xbl + 7) >> 3;
buf[0] = 0x04;
memcpy(&Q, P, sizeof *P);
_src_ec_ec_prime_i31_cset_one(T.c[2], cc->p);
_src_ec_ec_prime_i31_crun_code(&Q, &T, cc, _src_ec_ec_prime_i31_ccode_affine);
br_i31_encode(buf + 1, plen, Q.c[0]);
br_i31_encode(buf + 1 + plen, plen, Q.c[1]);
}
static const br_ec_curve_def *
_src_ec_ec_prime_i31_cid_to_curve_def(int curve)
{
switch (curve) {
case BR_EC_secp256r1:
return &br_secp256r1;
case BR_EC_secp384r1:
return &br_secp384r1;
case BR_EC_secp521r1:
return &br_secp521r1;
}
return NULL;
}
static const unsigned char *
_src_ec_ec_prime_i31_capi_generator(int curve, size_t *len)
{
const br_ec_curve_def *cd;
cd = _src_ec_ec_prime_i31_cid_to_curve_def(curve);
*len = cd->generator_len;
return cd->generator;
}
static const unsigned char *
_src_ec_ec_prime_i31_capi_order(int curve, size_t *len)
{
const br_ec_curve_def *cd;
cd = _src_ec_ec_prime_i31_cid_to_curve_def(curve);
*len = cd->order_len;
return cd->order;
}
static size_t
_src_ec_ec_prime_i31_capi_xoff(int curve, size_t *len)
{
_src_ec_ec_prime_i31_capi_generator(curve, len);
*len >>= 1;
return 1;
}
static uint32_t
_src_ec_ec_prime_i31_capi_mul(unsigned char *G, size_t Glen,
const unsigned char *x, size_t xlen, int curve)
{
uint32_t r;
const _src_ec_ec_prime_i31_ccurve_params *cc;
_src_ec_ec_prime_i31_cjacobian P;
cc = _src_ec_ec_prime_i31_cid_to_curve(curve);
if (Glen != cc->point_len) {
return 0;
}
r = _src_ec_ec_prime_i31_cpoint_decode(&P, G, Glen, cc);
_src_ec_ec_prime_i31_cpoint_mul(&P, x, xlen, cc);
_src_ec_ec_prime_i31_cpoint_encode(G, &P, cc);
return r;
}
static size_t
_src_ec_ec_prime_i31_capi_mulgen(unsigned char *R,
const unsigned char *x, size_t xlen, int curve)
{
const unsigned char *G;
size_t Glen;
G = _src_ec_ec_prime_i31_capi_generator(curve, &Glen);
memcpy(R, G, Glen);
_src_ec_ec_prime_i31_capi_mul(R, Glen, x, xlen, curve);
return Glen;
}
static uint32_t
_src_ec_ec_prime_i31_capi_muladd(unsigned char *A, const unsigned char *B, size_t len,
const unsigned char *x, size_t xlen,
const unsigned char *y, size_t ylen, int curve)
{
uint32_t r, t, z;
const _src_ec_ec_prime_i31_ccurve_params *cc;
_src_ec_ec_prime_i31_cjacobian P, Q;
/*
* TODO: see about merging the two ladders. Right now, we do
* two independent point multiplications, which is a bit
* wasteful of CPU resources (but yields short code).
*/
cc = _src_ec_ec_prime_i31_cid_to_curve(curve);
if (len != cc->point_len) {
return 0;
}
r = _src_ec_ec_prime_i31_cpoint_decode(&P, A, len, cc);
if (B == NULL) {
size_t Glen;
B = _src_ec_ec_prime_i31_capi_generator(curve, &Glen);
}
r &= _src_ec_ec_prime_i31_cpoint_decode(&Q, B, len, cc);
_src_ec_ec_prime_i31_cpoint_mul(&P, x, xlen, cc);
_src_ec_ec_prime_i31_cpoint_mul(&Q, y, ylen, cc);
/*
* We want to compute P+Q. Since the base points A and B are distinct
* from infinity, and the multipliers are non-zero and lower than the
* curve order, then we know that P and Q are non-infinity. This
* leaves two special situations to test for:
* -- If P = Q then we must use _src_ec_ec_prime_i31_cpoint_double().
* -- If P+Q = 0 then we must report an error.
*/
t = _src_ec_ec_prime_i31_cpoint_add(&P, &Q, cc);
_src_ec_ec_prime_i31_cpoint_double(&Q, cc);
z = br_i31_iszero(P.c[2]);
/*
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
* have the following:
*
* z = 0, t = 0 return P (normal addition)
* z = 0, t = 1 return P (normal addition)
* z = 1, t = 0 return Q (a 'double' case)
* z = 1, t = 1 report an error (P+Q = 0)
*/
CCOPY(z & ~t, &P, &Q, sizeof Q);
_src_ec_ec_prime_i31_cpoint_encode(A, &P, cc);
r &= ~(z & t);
return r;
}
/* see bearssl_ec.h */
const br_ec_impl br_ec_prime_i31 = {
(uint32_t)0x03800000,
&_src_ec_ec_prime_i31_capi_generator,
&_src_ec_ec_prime_i31_capi_order,
&_src_ec_ec_prime_i31_capi_xoff,
&_src_ec_ec_prime_i31_capi_mul,
&_src_ec_ec_prime_i31_capi_mulgen,
&_src_ec_ec_prime_i31_capi_muladd
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2018 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char POINT_LEN[] = {
0, /* 0: not a valid curve ID */
43, /* sect163k1 */
43, /* sect163r1 */
43, /* sect163r2 */
51, /* sect193r1 */
51, /* sect193r2 */
61, /* sect233k1 */
61, /* sect233r1 */
61, /* sect239k1 */
73, /* sect283k1 */
73, /* sect283r1 */
105, /* sect409k1 */
105, /* sect409r1 */
145, /* sect571k1 */
145, /* sect571r1 */
41, /* secp160k1 */
41, /* secp160r1 */
41, /* secp160r2 */
49, /* secp192k1 */
49, /* secp192r1 */
57, /* secp224k1 */
57, /* secp224r1 */
65, /* secp256k1 */
65, /* secp256r1 */
97, /* secp384r1 */
133, /* secp521r1 */
65, /* brainpoolP256r1 */
97, /* brainpoolP384r1 */
129, /* brainpoolP512r1 */
32, /* curve25519 */
56, /* curve448 */
};
/* see bearssl_ec.h */
size_t
br_ec_compute_pub(const br_ec_impl *impl, br_ec_public_key *pk,
void *kbuf, const br_ec_private_key *sk)
{
int curve;
size_t len;
curve = sk->curve;
if (curve < 0 || curve >= 32 || curve >= (int)(sizeof POINT_LEN)
|| ((impl->supported_curves >> curve) & 1) == 0)
{
return 0;
}
if (kbuf == NULL) {
return POINT_LEN[curve];
}
len = impl->mulgen((unsigned char*)kbuf, sk->x, sk->xlen, curve);
if (pk != NULL) {
pk->curve = curve;
pk->q = (unsigned char*)kbuf;
pk->qlen = len;
}
return len;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char _src_ec_ec_secp256r1_cP256_N[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
};
static const unsigned char _src_ec_ec_secp256r1_cP256_G[] = {
0x04, 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42,
0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40,
0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33,
0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2,
0x96, 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F,
0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E,
0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E,
0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51,
0xF5
};
/* see inner.h */
const br_ec_curve_def br_secp256r1 = {
BR_EC_secp256r1,
_src_ec_ec_secp256r1_cP256_N, sizeof _src_ec_ec_secp256r1_cP256_N,
_src_ec_ec_secp256r1_cP256_G, sizeof _src_ec_ec_secp256r1_cP256_G
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char P384_N[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF,
0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A,
0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
};
static const unsigned char P384_G[] = {
0x04, 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05,
0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD,
0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B,
0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A,
0x38, 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29,
0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A,
0xB7, 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C,
0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC,
0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14,
0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8,
0xC0, 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81,
0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E,
0x5F
};
/* see inner.h */
const br_ec_curve_def br_secp384r1 = {
BR_EC_secp384r1,
P384_N, sizeof P384_N,
P384_G, sizeof P384_G
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const unsigned char P521_N[] = {
0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F,
0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C,
0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38,
0x64, 0x09
};
static const unsigned char P521_G[] = {
0x04, 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04,
0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23,
0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05,
0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B,
0x4D, 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF,
0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2,
0xFF, 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85,
0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2,
0xE5, 0xBD, 0x66, 0x01, 0x18, 0x39, 0x29, 0x6A,
0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F,
0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44,
0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD,
0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE, 0x72,
0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9,
0x01, 0x3F, 0xAD, 0x07, 0x61, 0x35, 0x3C, 0x70,
0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94,
0x76, 0x9F, 0xD1, 0x66, 0x50
};
/* see inner.h */
const br_ec_curve_def br_secp521r1 = {
BR_EC_secp521r1,
P521_N, sizeof P521_N,
P521_G, sizeof P521_G
};
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
size_t
br_ecdsa_asn1_to_raw(void *sig, size_t sig_len)
{
/*
* Note: this code is a bit lenient in that it accepts a few
* deviations to DER with regards to minimality of encoding of
* lengths and integer values. These deviations are still
* unambiguous.
*
* Signature format is a SEQUENCE of two INTEGER values. We
* support only integers of less than 127 bytes each (signed
* encoding) so the resulting raw signature will have length
* at most 254 bytes.
*/
unsigned char *buf, *r, *s;
size_t zlen, rlen, slen, off;
unsigned char tmp[254];
buf = (unsigned char*)sig;
if (sig_len < 8) {
return 0;
}
/*
* First byte is SEQUENCE tag.
*/
if (buf[0] != 0x30) {
return 0;
}
/*
* The SEQUENCE length will be encoded over one or two bytes. We
* limit the total SEQUENCE contents to 255 bytes, because it
* makes things simpler; this is enough for subgroup orders up
* to 999 bits.
*/
zlen = buf[1];
if (zlen > 0x80) {
if (zlen != 0x81) {
return 0;
}
zlen = buf[2];
if (zlen != sig_len - 3) {
return 0;
}
off = 3;
} else {
if (zlen != sig_len - 2) {
return 0;
}
off = 2;
}
/*
* First INTEGER (r).
*/
if (buf[off ++] != 0x02) {
return 0;
}
rlen = buf[off ++];
if (rlen >= 0x80) {
return 0;
}
r = buf + off;
off += rlen;
/*
* Second INTEGER (s).
*/
if (off + 2 > sig_len) {
return 0;
}
if (buf[off ++] != 0x02) {
return 0;
}
slen = buf[off ++];
if (slen >= 0x80 || slen != sig_len - off) {
return 0;
}
s = buf + off;
/*
* Removing leading zeros from r and s.
*/
while (rlen > 0 && *r == 0) {
rlen --;
r ++;
}
while (slen > 0 && *s == 0) {
slen --;
s ++;
}
/*
* Compute common length for the two integers, then copy integers
* into the temporary buffer, and finally copy it back over the
* signature buffer.
*/
zlen = rlen > slen ? rlen : slen;
sig_len = zlen << 1;
memset(tmp, 0, sig_len);
memcpy(tmp + zlen - rlen, r, rlen);
memcpy(tmp + sig_len - slen, s, slen);
memcpy(sig, tmp, sig_len);
return sig_len;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
br_ecdsa_sign
br_ecdsa_sign_asn1_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_sign_asn1;
#else
return &br_ecdsa_i31_sign_asn1;
#endif
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
br_ecdsa_sign
br_ecdsa_sign_raw_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_sign_raw;
#else
return &br_ecdsa_i31_sign_raw;
#endif
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
br_ecdsa_vrfy
br_ecdsa_vrfy_asn1_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_vrfy_asn1;
#else
return &br_ecdsa_i31_vrfy_asn1;
#endif
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see bearssl_ec.h */
br_ecdsa_vrfy
br_ecdsa_vrfy_raw_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_vrfy_raw;
#else
return &br_ecdsa_i31_vrfy_raw;
#endif
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_ecdsa_i15_bits2int(uint16_t *x,
const void *src, size_t len, uint32_t ebitlen)
{
uint32_t bitlen, hbitlen;
int sc;
bitlen = ebitlen - (ebitlen >> 4);
hbitlen = (uint32_t)len << 3;
if (hbitlen > bitlen) {
len = (bitlen + 7) >> 3;
sc = (int)((hbitlen - bitlen) & 7);
} else {
sc = 0;
}
br_i15_zero(x, ebitlen);
br_i15_decode(x, src, len);
br_i15_rshift(x, sc);
x[0] = ebitlen;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define _src_ec_ecdsa_i15_sign_asn1_cORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
/* see bearssl_ec.h */
size_t
br_ecdsa_i15_sign_asn1(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig)
{
unsigned char rsig[(_src_ec_ecdsa_i15_sign_asn1_cORDER_LEN << 1) + 12];
size_t sig_len;
sig_len = br_ecdsa_i15_sign_raw(impl, hf, hash_value, sk, rsig);
if (sig_len == 0) {
return 0;
}
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
memcpy(sig, rsig, sig_len);
return sig_len;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
#define _src_ec_ecdsa_i15_sign_raw_cORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
/* see bearssl_ec.h */
size_t
br_ecdsa_i15_sign_raw(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig)
{
/*
* IMPORTANT: this code is fit only for curves with a prime
* order. This is needed so that modular reduction of the X
* coordinate of a point can be done with a simple subtraction.
* We also rely on the last byte of the curve order to be distinct
* from 0 and 1.
*/
const br_ec_curve_def *cd;
uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], x[I15_LEN];
uint16_t m[I15_LEN], k[I15_LEN], t1[I15_LEN], t2[I15_LEN];
unsigned char tt[_src_ec_ecdsa_i15_sign_raw_cORDER_LEN << 1];
unsigned char eU[POINT_LEN];
size_t hash_len, nlen, ulen;
uint16_t n0i;
uint32_t ctl;
br_hmac_drbg_context drbg;
/*
* If the curve is not supported, then exit with an error.
*/
if (((impl->supported_curves >> sk->curve) & 1) == 0) {
return 0;
}
/*
* Get the curve parameters (generator and order).
*/
switch (sk->curve) {
case BR_EC_secp256r1:
cd = &br_secp256r1;
break;
case BR_EC_secp384r1:
cd = &br_secp384r1;
break;
case BR_EC_secp521r1:
cd = &br_secp521r1;
break;
default:
return 0;
}
/*
* Get modulus.
*/
nlen = cd->order_len;
br_i15_decode(n, cd->order, nlen);
n0i = br_i15_ninv15(n[1]);
/*
* Get private key as an i15 integer. This also checks that the
* private key is well-defined (not zero, and less than the
* curve order).
*/
if (!br_i15_decode_mod(x, sk->x, sk->xlen, n)) {
return 0;
}
if (br_i15_iszero(x)) {
return 0;
}
/*
* Get hash length.
*/
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
/*
* Truncate and reduce the hash value modulo the curve order.
*/
br_ecdsa_i15_bits2int(m, hash_value, hash_len, n[0]);
br_i15_sub(m, n, br_i15_sub(m, n, 0) ^ 1);
/*
* RFC 6979 generation of the "k" value.
*
* The process uses HMAC_DRBG (with the hash function used to
* process the message that is to be signed). The seed is the
* concatenation of the encodings of the private key and
* the hash value (after truncation and modular reduction).
*/
br_i15_encode(tt, nlen, x);
br_i15_encode(tt + nlen, nlen, m);
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
for (;;) {
br_hmac_drbg_generate(&drbg, tt, nlen);
br_ecdsa_i15_bits2int(k, tt, nlen, n[0]);
if (br_i15_iszero(k)) {
continue;
}
if (br_i15_sub(k, n, 0)) {
break;
}
}
/*
* Compute k*G and extract the X coordinate, then reduce it
* modulo the curve order. Since we support only curves with
* prime order, that reduction is only a matter of computing
* a subtraction.
*/
br_i15_encode(tt, nlen, k);
ulen = impl->mulgen(eU, tt, nlen, sk->curve);
br_i15_zero(r, n[0]);
br_i15_decode(r, &eU[1], ulen >> 1);
r[0] = n[0];
br_i15_sub(r, n, br_i15_sub(r, n, 0) ^ 1);
/*
* Compute 1/k in double-Montgomery representation. We do so by
* first converting _from_ Montgomery representation (twice),
* then using a modular exponentiation.
*/
br_i15_from_monty(k, n, n0i);
br_i15_from_monty(k, n, n0i);
memcpy(tt, cd->order, nlen);
tt[nlen - 1] -= 2;
br_i15_modpow(k, tt, nlen, n, n0i, t1, t2);
/*
* Compute s = (m+xr)/k (mod n).
* The k[] array contains R^2/k (double-Montgomery representation);
* we thus can use direct Montgomery multiplications and conversions
* from Montgomery, avoiding any call to br_i15_to_monty() (which
* is slower).
*/
br_i15_from_monty(m, n, n0i);
br_i15_montymul(t1, x, r, n, n0i);
ctl = br_i15_add(t1, m, 1);
ctl |= br_i15_sub(t1, n, 0) ^ 1;
br_i15_sub(t1, n, ctl);
br_i15_montymul(s, t1, k, n, n0i);
/*
* Encode r and s in the signature.
*/
br_i15_encode(sig, nlen, r);
br_i15_encode((unsigned char *)sig + nlen, nlen, s);
return nlen << 1;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
/* see bearssl_ec.h */
uint32_t
br_ecdsa_i15_vrfy_asn1(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk,
const void *sig, size_t sig_len)
{
/*
* We use a double-sized buffer because a malformed ASN.1 signature
* may trigger a size expansion when converting to "raw" format.
*/
unsigned char rsig[(FIELD_LEN << 2) + 24];
if (sig_len > ((sizeof rsig) >> 1)) {
return 0;
}
memcpy(rsig, sig, sig_len);
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
return br_ecdsa_i15_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define I15_LEN ((BR_MAX_EC_SIZE + 29) / 15)
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
/* see bearssl_ec.h */
uint32_t
br_ecdsa_i15_vrfy_raw(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk,
const void *sig, size_t sig_len)
{
/*
* IMPORTANT: this code is fit only for curves with a prime
* order. This is needed so that modular reduction of the X
* coordinate of a point can be done with a simple subtraction.
*/
const br_ec_curve_def *cd;
uint16_t n[I15_LEN], r[I15_LEN], s[I15_LEN], t1[I15_LEN], t2[I15_LEN];
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
unsigned char eU[POINT_LEN];
size_t nlen, rlen, ulen;
uint16_t n0i;
uint32_t res;
/*
* If the curve is not supported, then report an error.
*/
if (((impl->supported_curves >> pk->curve) & 1) == 0) {
return 0;
}
/*
* Get the curve parameters (generator and order).
*/
switch (pk->curve) {
case BR_EC_secp256r1:
cd = &br_secp256r1;
break;
case BR_EC_secp384r1:
cd = &br_secp384r1;
break;
case BR_EC_secp521r1:
cd = &br_secp521r1;
break;
default:
return 0;
}
/*
* Signature length must be even.
*/
if (sig_len & 1) {
return 0;
}
rlen = sig_len >> 1;
/*
* Public key point must have the proper size for this curve.
*/
if (pk->qlen != cd->generator_len) {
return 0;
}
/*
* Get modulus; then decode the r and s values. They must be
* lower than the modulus, and s must not be null.
*/
nlen = cd->order_len;
br_i15_decode(n, cd->order, nlen);
n0i = br_i15_ninv15(n[1]);
if (!br_i15_decode_mod(r, sig, rlen, n)) {
return 0;
}
if (!br_i15_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
return 0;
}
if (br_i15_iszero(s)) {
return 0;
}
/*
* Invert s. We do that with a modular exponentiation; we use
* the fact that for all the curves we support, the least
* significant byte is not 0 or 1, so we can subtract 2 without
* any carry to process.
* We also want 1/s in Montgomery representation, which can be
* done by converting _from_ Montgomery representation before
* the inversion (because (1/s)*R = 1/(s/R)).
*/
br_i15_from_monty(s, n, n0i);
memcpy(tx, cd->order, nlen);
tx[nlen - 1] -= 2;
br_i15_modpow(s, tx, nlen, n, n0i, t1, t2);
/*
* Truncate the hash to the modulus length (in bits) and reduce
* it modulo the curve order. The modular reduction can be done
* with a subtraction since the truncation already reduced the
* value to the modulus bit length.
*/
br_ecdsa_i15_bits2int(t1, hash, hash_len, n[0]);
br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
/*
* Multiply the (truncated, reduced) hash value with 1/s, result in
* t2, encoded in ty.
*/
br_i15_montymul(t2, t1, s, n, n0i);
br_i15_encode(ty, nlen, t2);
/*
* Multiply r with 1/s, result in t1, encoded in tx.
*/
br_i15_montymul(t1, r, s, n, n0i);
br_i15_encode(tx, nlen, t1);
/*
* Compute the point x*Q + y*G.
*/
ulen = cd->generator_len;
memcpy(eU, pk->q, ulen);
res = impl->muladd(eU, NULL, ulen,
tx, nlen, ty, nlen, cd->curve);
/*
* Get the X coordinate, reduce modulo the curve order, and
* compare with the 'r' value.
*
* The modular reduction can be done with subtractions because
* we work with curves of prime order, so the curve order is
* close to the field order (Hasse's theorem).
*/
br_i15_zero(t1, n[0]);
br_i15_decode(t1, &eU[1], ulen >> 1);
t1[0] = n[0];
br_i15_sub(t1, n, br_i15_sub(t1, n, 0) ^ 1);
res &= ~br_i15_sub(t1, r, 1);
res &= br_i15_iszero(t1);
return res;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
void
br_ecdsa_i31_bits2int(uint32_t *x,
const void *src, size_t len, uint32_t ebitlen)
{
uint32_t bitlen, hbitlen;
int sc;
bitlen = ebitlen - (ebitlen >> 5);
hbitlen = (uint32_t)len << 3;
if (hbitlen > bitlen) {
len = (bitlen + 7) >> 3;
sc = (int)((hbitlen - bitlen) & 7);
} else {
sc = 0;
}
br_i31_zero(x, ebitlen);
br_i31_decode(x, src, len);
br_i31_rshift(x, sc);
x[0] = ebitlen;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define _src_ec_ecdsa_i31_sign_asn1_cORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
/* see bearssl_ec.h */
size_t
br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig)
{
unsigned char rsig[(_src_ec_ecdsa_i31_sign_asn1_cORDER_LEN << 1) + 12];
size_t sig_len;
sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig);
if (sig_len == 0) {
return 0;
}
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
memcpy(sig, rsig, sig_len);
return sig_len;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
#define _src_ec_ecdsa_i31_sign_raw_cORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
/* see bearssl_ec.h */
size_t
br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
const br_hash_class *hf, const void *hash_value,
const br_ec_private_key *sk, void *sig)
{
/*
* IMPORTANT: this code is fit only for curves with a prime
* order. This is needed so that modular reduction of the X
* coordinate of a point can be done with a simple subtraction.
* We also rely on the last byte of the curve order to be distinct
* from 0 and 1.
*/
const br_ec_curve_def *cd;
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN];
uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN];
unsigned char tt[_src_ec_ecdsa_i31_sign_raw_cORDER_LEN << 1];
unsigned char eU[POINT_LEN];
size_t hash_len, nlen, ulen;
uint32_t n0i, ctl;
br_hmac_drbg_context drbg;
/*
* If the curve is not supported, then exit with an error.
*/
if (((impl->supported_curves >> sk->curve) & 1) == 0) {
return 0;
}
/*
* Get the curve parameters (generator and order).
*/
switch (sk->curve) {
case BR_EC_secp256r1:
cd = &br_secp256r1;
break;
case BR_EC_secp384r1:
cd = &br_secp384r1;
break;
case BR_EC_secp521r1:
cd = &br_secp521r1;
break;
default:
return 0;
}
/*
* Get modulus.
*/
nlen = cd->order_len;
br_i31_decode(n, cd->order, nlen);
n0i = br_i31_ninv31(n[1]);
/*
* Get private key as an i31 integer. This also checks that the
* private key is well-defined (not zero, and less than the
* curve order).
*/
if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) {
return 0;
}
if (br_i31_iszero(x)) {
return 0;
}
/*
* Get hash length.
*/
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
/*
* Truncate and reduce the hash value modulo the curve order.
*/
br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]);
br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1);
/*
* RFC 6979 generation of the "k" value.
*
* The process uses HMAC_DRBG (with the hash function used to
* process the message that is to be signed). The seed is the
* concatenation of the encodings of the private key and
* the hash value (after truncation and modular reduction).
*/
br_i31_encode(tt, nlen, x);
br_i31_encode(tt + nlen, nlen, m);
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
for (;;) {
br_hmac_drbg_generate(&drbg, tt, nlen);
br_ecdsa_i31_bits2int(k, tt, nlen, n[0]);
if (br_i31_iszero(k)) {
continue;
}
if (br_i31_sub(k, n, 0)) {
break;
}
}
/*
* Compute k*G and extract the X coordinate, then reduce it
* modulo the curve order. Since we support only curves with
* prime order, that reduction is only a matter of computing
* a subtraction.
*/
br_i31_encode(tt, nlen, k);
ulen = impl->mulgen(eU, tt, nlen, sk->curve);
br_i31_zero(r, n[0]);
br_i31_decode(r, &eU[1], ulen >> 1);
r[0] = n[0];
br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1);
/*
* Compute 1/k in double-Montgomery representation. We do so by
* first converting _from_ Montgomery representation (twice),
* then using a modular exponentiation.
*/
br_i31_from_monty(k, n, n0i);
br_i31_from_monty(k, n, n0i);
memcpy(tt, cd->order, nlen);
tt[nlen - 1] -= 2;
br_i31_modpow(k, tt, nlen, n, n0i, t1, t2);
/*
* Compute s = (m+xr)/k (mod n).
* The k[] array contains R^2/k (double-Montgomery representation);
* we thus can use direct Montgomery multiplications and conversions
* from Montgomery, avoiding any call to br_i31_to_monty() (which
* is slower).
*/
br_i31_from_monty(m, n, n0i);
br_i31_montymul(t1, x, r, n, n0i);
ctl = br_i31_add(t1, m, 1);
ctl |= br_i31_sub(t1, n, 0) ^ 1;
br_i31_sub(t1, n, ctl);
br_i31_montymul(s, t1, k, n, n0i);
/*
* Encode r and s in the signature.
*/
br_i31_encode(sig, nlen, r);
br_i31_encode((unsigned char *)sig + nlen, nlen, s);
return nlen << 1;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
/* see bearssl_ec.h */
uint32_t
br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk,
const void *sig, size_t sig_len)
{
/*
* We use a double-sized buffer because a malformed ASN.1 signature
* may trigger a size expansion when converting to "raw" format.
*/
unsigned char rsig[(FIELD_LEN << 2) + 24];
if (sig_len > ((sizeof rsig) >> 1)) {
return 0;
}
memcpy(rsig, sig, sig_len);
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
/* see bearssl_ec.h */
uint32_t
br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
const void *hash, size_t hash_len,
const br_ec_public_key *pk,
const void *sig, size_t sig_len)
{
/*
* IMPORTANT: this code is fit only for curves with a prime
* order. This is needed so that modular reduction of the X
* coordinate of a point can be done with a simple subtraction.
*/
const br_ec_curve_def *cd;
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN];
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
unsigned char eU[POINT_LEN];
size_t nlen, rlen, ulen;
uint32_t n0i, res;
/*
* If the curve is not supported, then report an error.
*/
if (((impl->supported_curves >> pk->curve) & 1) == 0) {
return 0;
}
/*
* Get the curve parameters (generator and order).
*/
switch (pk->curve) {
case BR_EC_secp256r1:
cd = &br_secp256r1;
break;
case BR_EC_secp384r1:
cd = &br_secp384r1;
break;
case BR_EC_secp521r1:
cd = &br_secp521r1;
break;
default:
return 0;
}
/*
* Signature length must be even.
*/
if (sig_len & 1) {
return 0;
}
rlen = sig_len >> 1;
/*
* Public key point must have the proper size for this curve.
*/
if (pk->qlen != cd->generator_len) {
return 0;
}
/*
* Get modulus; then decode the r and s values. They must be
* lower than the modulus, and s must not be null.
*/
nlen = cd->order_len;
br_i31_decode(n, cd->order, nlen);
n0i = br_i31_ninv31(n[1]);
if (!br_i31_decode_mod(r, sig, rlen, n)) {
return 0;
}
if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
return 0;
}
if (br_i31_iszero(s)) {
return 0;
}
/*
* Invert s. We do that with a modular exponentiation; we use
* the fact that for all the curves we support, the least
* significant byte is not 0 or 1, so we can subtract 2 without
* any carry to process.
* We also want 1/s in Montgomery representation, which can be
* done by converting _from_ Montgomery representation before
* the inversion (because (1/s)*R = 1/(s/R)).
*/
br_i31_from_monty(s, n, n0i);
memcpy(tx, cd->order, nlen);
tx[nlen - 1] -= 2;
br_i31_modpow(s, tx, nlen, n, n0i, t1, t2);
/*
* Truncate the hash to the modulus length (in bits) and reduce
* it modulo the curve order. The modular reduction can be done
* with a subtraction since the truncation already reduced the
* value to the modulus bit length.
*/
br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]);
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
/*
* Multiply the (truncated, reduced) hash value with 1/s, result in
* t2, encoded in ty.
*/
br_i31_montymul(t2, t1, s, n, n0i);
br_i31_encode(ty, nlen, t2);
/*
* Multiply r with 1/s, result in t1, encoded in tx.
*/
br_i31_montymul(t1, r, s, n, n0i);
br_i31_encode(tx, nlen, t1);
/*
* Compute the point x*Q + y*G.
*/
ulen = cd->generator_len;
memcpy(eU, pk->q, ulen);
res = impl->muladd(eU, NULL, ulen,
tx, nlen, ty, nlen, cd->curve);
/*
* Get the X coordinate, reduce modulo the curve order, and
* compare with the 'r' value.
*
* The modular reduction can be done with subtractions because
* we work with curves of prime order, so the curve order is
* close to the field order (Hasse's theorem).
*/
br_i31_zero(t1, n[0]);
br_i31_decode(t1, &eU[1], ulen >> 1);
t1[0] = n[0];
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
res &= ~br_i31_sub(t1, r, 1);
res &= br_i31_iszero(t1);
return res;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* Compute ASN.1 encoded length for the provided integer. The ASN.1
* encoding is signed, so its leading bit must have value 0; it must
* also be of minimal length (so leading bytes of value 0 must be
* removed, except if that would contradict the rule about the sign
* bit).
*/
static size_t
asn1_int_length(const unsigned char *x, size_t xlen)
{
while (xlen > 0 && *x == 0) {
x ++;
xlen --;
}
if (xlen == 0 || *x >= 0x80) {
xlen ++;
}
return xlen;
}
/* see bearssl_ec.h */
size_t
br_ecdsa_raw_to_asn1(void *sig, size_t sig_len)
{
/*
* Internal buffer is large enough to accommodate a signature
* such that r and s fit on 125 bytes each (signed encoding),
* meaning a curve order of up to 999 bits. This is the limit
* that ensures "simple" length encodings.
*/
unsigned char *buf;
size_t hlen, rlen, slen, zlen, off;
unsigned char tmp[257];
buf = (unsigned char*)sig;
if ((sig_len & 1) != 0) {
return 0;
}
/*
* Compute lengths for the two integers.
*/
hlen = sig_len >> 1;
rlen = asn1_int_length(buf, hlen);
slen = asn1_int_length(buf + hlen, hlen);
if (rlen > 125 || slen > 125) {
return 0;
}
/*
* SEQUENCE header.
*/
tmp[0] = 0x30;
zlen = rlen + slen + 4;
if (zlen >= 0x80) {
tmp[1] = 0x81;
tmp[2] = zlen;
off = 3;
} else {
tmp[1] = zlen;
off = 2;
}
/*
* First INTEGER (r).
*/
tmp[off ++] = 0x02;
tmp[off ++] = rlen;
if (rlen > hlen) {
tmp[off] = 0x00;
memcpy(tmp + off + 1, buf, hlen);
} else {
memcpy(tmp + off, buf + hlen - rlen, rlen);
}
off += rlen;
/*
* Second INTEGER (s).
*/
tmp[off ++] = 0x02;
tmp[off ++] = slen;
if (slen > hlen) {
tmp[off] = 0x00;
memcpy(tmp + off + 1, buf + hlen, hlen);
} else {
memcpy(tmp + off, buf + sig_len - slen, slen);
}
off += slen;
/*
* Return ASN.1 signature.
*/
memcpy(sig, tmp, off);
return off;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
static const br_config_option config[] = {
{ "BR_64",
#if BR_64
1
#else
0
#endif
},
{ "BR_AES_X86NI",
#if BR_AES_X86NI
1
#else
0
#endif
},
{ "BR_amd64",
#if BR_amd64
1
#else
0
#endif
},
{ "BR_ARMEL_CORTEXM_GCC",
#if BR_ARMEL_CORTEXM_GCC
1
#else
0
#endif
},
{ "BR_BE_UNALIGNED",
#if BR_BE_UNALIGNED
1
#else
0
#endif
},
{ "BR_CLANG",
#if BR_CLANG
1
#else
0
#endif
},
{ "BR_CLANG_3_7",
#if BR_CLANG_3_7
1
#else
0
#endif
},
{ "BR_CLANG_3_8",
#if BR_CLANG_3_8
1
#else
0
#endif
},
{ "BR_CT_MUL15",
#if BR_CT_MUL15
1
#else
0
#endif
},
{ "BR_CT_MUL31",
#if BR_CT_MUL31
1
#else
0
#endif
},
{ "BR_GCC",
#if BR_GCC
1
#else
0
#endif
},
{ "BR_GCC_4_4",
#if BR_GCC_4_4
1
#else
0
#endif
},
{ "BR_GCC_4_5",
#if BR_GCC_4_5
1
#else
0
#endif
},
{ "BR_GCC_4_6",
#if BR_GCC_4_6
1
#else
0
#endif
},
{ "BR_GCC_4_7",
#if BR_GCC_4_7
1
#else
0
#endif
},
{ "BR_GCC_4_8",
#if BR_GCC_4_8
1
#else
0
#endif
},
{ "BR_GCC_4_9",
#if BR_GCC_4_9
1
#else
0
#endif
},
{ "BR_GCC_5_0",
#if BR_GCC_5_0
1
#else
0
#endif
},
{ "BR_i386",
#if BR_i386
1
#else
0
#endif
},
{ "BR_INT128",
#if BR_INT128
1
#else
0
#endif
},
{ "BR_LE_UNALIGNED",
#if BR_LE_UNALIGNED
1
#else
0
#endif
},
{ "BR_LOMUL",
#if BR_LOMUL
1
#else
0
#endif
},
{ "BR_MAX_EC_SIZE", BR_MAX_EC_SIZE },
{ "BR_MAX_RSA_SIZE", BR_MAX_RSA_SIZE },
{ "BR_MAX_RSA_FACTOR", BR_MAX_RSA_FACTOR },
{ "BR_MSC",
#if BR_MSC
1
#else
0
#endif
},
{ "BR_MSC_2005",
#if BR_MSC_2005
1
#else
0
#endif
},
{ "BR_MSC_2008",
#if BR_MSC_2008
1
#else
0
#endif
},
{ "BR_MSC_2010",
#if BR_MSC_2010
1
#else
0
#endif
},
{ "BR_MSC_2012",
#if BR_MSC_2012
1
#else
0
#endif
},
{ "BR_MSC_2013",
#if BR_MSC_2013
1
#else
0
#endif
},
{ "BR_MSC_2015",
#if BR_MSC_2015
1
#else
0
#endif
},
{ "BR_POWER8",
#if BR_POWER8
1
#else
0
#endif
},
{ "BR_RDRAND",
#if BR_RDRAND
1
#else
0
#endif
},
{ "BR_SLOW_MUL",
#if BR_SLOW_MUL
1
#else
0
#endif
},
{ "BR_SLOW_MUL15",
#if BR_SLOW_MUL15
1
#else
0
#endif
},
{ "BR_SSE2",
#if BR_SSE2
1
#else
0
#endif
},
{ "BR_UMUL128",
#if BR_UMUL128
1
#else
0
#endif
},
{ "BR_USE_UNIX_TIME",
#if BR_USE_UNIX_TIME
1
#else
0
#endif
},
{ "BR_USE_WIN32_RAND",
#if BR_USE_WIN32_RAND
1
#else
0
#endif
},
{ "BR_USE_WIN32_TIME",
#if BR_USE_WIN32_TIME
1
#else
0
#endif
},
{ NULL, 0 }
};
/* see bearssl.h */
const br_config_option *
br_get_config(void)
{
return config;
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* This file contains the encoded OID for the standard hash functions.
* Such OID appear in, for instance, the PKCS#1 v1.5 padding for RSA
* signatures.
*/
static const unsigned char md5_OID[] = {
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05
};
static const unsigned char sha1_OID[] = {
0x2B, 0x0E, 0x03, 0x02, 0x1A
};
static const unsigned char sha224_OID[] = {
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04
};
static const unsigned char sha256_OID[] = {
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01
};
static const unsigned char sha384_OID[] = {
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02
};
static const unsigned char sha512_OID[] = {
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03
};
/* see inner.h */
const unsigned char *
br_digest_OID(int digest_id, size_t *len)
{
switch (digest_id) {
case br_md5_ID:
*len = sizeof md5_OID;
return md5_OID;
case br_sha1_ID:
*len = sizeof sha1_OID;
return sha1_OID;
case br_sha224_ID:
*len = sizeof sha224_OID;
return sha224_OID;
case br_sha256_ID:
*len = sizeof sha256_OID;
return sha256_OID;
case br_sha384_ID:
*len = sizeof sha384_OID;
return sha384_OID;
case br_sha512_ID:
*len = sizeof sha512_OID;
return sha512_OID;
default:
*len = 0;
return NULL;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/* see inner.h */
size_t
br_digest_size_by_ID(int digest_id)
{
switch (digest_id) {
case br_md5sha1_ID:
return br_md5_SIZE + br_sha1_SIZE;
case br_md5_ID:
return br_md5_SIZE;
case br_sha1_ID:
return br_sha1_SIZE;
case br_sha224_ID:
return br_sha224_SIZE;
case br_sha256_ID:
return br_sha256_SIZE;
case br_sha384_ID:
return br_sha384_SIZE;
case br_sha512_ID:
return br_sha512_SIZE;
default:
/* abort(); */
return 0;
}
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* We compute "carryless multiplications" through normal integer
* multiplications, masking out enough bits to create "holes" in which
* carries may expand without altering our bits; we really use 8 data
* bits per 32-bit word, spaced every fourth bit. Accumulated carries
* may not exceed 8 in total, which fits in 4 bits.
*
* It would be possible to use a 3-bit spacing, allowing two operands,
* one with 7 non-zero data bits, the other one with 10 or 11 non-zero
* data bits; this asymmetric splitting makes the overall code more
* complex with thresholds and exceptions, and does not appear to be
* worth the effort.
*/
/*
* We cannot really autodetect whether multiplications are "slow" or
* not. A typical example is the ARM Cortex M0+, which exists in two
* versions: one with a 1-cycle multiplication opcode, the other with
* a 32-cycle multiplication opcode. They both use exactly the same
* architecture and ABI, and cannot be distinguished from each other
* at compile-time.
*
* Since most modern CPU (even embedded CPU) still have fast
* multiplications, we use the "fast mul" code by default.
*/
#if BR_SLOW_MUL
/*
* This implementation uses Karatsuba-like reduction to make fewer
* integer multiplications (9 instead of 16), at the expense of extra
* logical operations (XOR, shifts...). On modern x86 CPU that offer
* fast, pipelined multiplications, this code is about twice slower than
* the simpler code with 16 multiplications. This tendency may be
* reversed on low-end platforms with expensive multiplications.
*/
#define MUL32(h, l, x, y) do { \
uint64_t mul32tmp = MUL(x, y); \
(h) = (uint32_t)(mul32tmp >> 32); \
(l) = (uint32_t)mul32tmp; \
} while (0)
static inline void
bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
{
uint32_t x0, x1, x2, x3;
uint32_t y0, y1, y2, y3;
uint32_t a0, a1, a2, a3, a4, a5, a6, a7, a8;
uint32_t b0, b1, b2, b3, b4, b5, b6, b7, b8;
x0 = x & (uint32_t)0x11111111;
x1 = x & (uint32_t)0x22222222;
x2 = x & (uint32_t)0x44444444;
x3 = x & (uint32_t)0x88888888;
y0 = y & (uint32_t)0x11111111;
y1 = y & (uint32_t)0x22222222;
y2 = y & (uint32_t)0x44444444;
y3 = y & (uint32_t)0x88888888;
/*
* (x0+W*x1)*(y0+W*y1) -> a0:b0
* (x2+W*x3)*(y2+W*y3) -> a3:b3
* ((x0+x2)+W*(x1+x3))*((y0+y2)+W*(y1+y3)) -> a6:b6
*/
a0 = x0;
b0 = y0;
a1 = x1 >> 1;
b1 = y1 >> 1;
a2 = a0 ^ a1;
b2 = b0 ^ b1;
a3 = x2 >> 2;
b3 = y2 >> 2;
a4 = x3 >> 3;
b4 = y3 >> 3;
a5 = a3 ^ a4;
b5 = b3 ^ b4;
a6 = a0 ^ a3;
b6 = b0 ^ b3;
a7 = a1 ^ a4;
b7 = b1 ^ b4;
a8 = a6 ^ a7;
b8 = b6 ^ b7;
MUL32(b0, a0, b0, a0);
MUL32(b1, a1, b1, a1);
MUL32(b2, a2, b2, a2);
MUL32(b3, a3, b3, a3);
MUL32(b4, a4, b4, a4);
MUL32(b5, a5, b5, a5);
MUL32(b6, a6, b6, a6);
MUL32(b7, a7, b7, a7);
MUL32(b8, a8, b8, a8);
a0 &= (uint32_t)0x11111111;
a1 &= (uint32_t)0x11111111;
a2 &= (uint32_t)0x11111111;
a3 &= (uint32_t)0x11111111;
a4 &= (uint32_t)0x11111111;
a5 &= (uint32_t)0x11111111;
a6 &= (uint32_t)0x11111111;
a7 &= (uint32_t)0x11111111;
a8 &= (uint32_t)0x11111111;
b0 &= (uint32_t)0x11111111;
b1 &= (uint32_t)0x11111111;
b2 &= (uint32_t)0x11111111;
b3 &= (uint32_t)0x11111111;
b4 &= (uint32_t)0x11111111;
b5 &= (uint32_t)0x11111111;
b6 &= (uint32_t)0x11111111;
b7 &= (uint32_t)0x11111111;
b8 &= (uint32_t)0x11111111;
a2 ^= a0 ^ a1;
b2 ^= b0 ^ b1;
a0 ^= (a2 << 1) ^ (a1 << 2);
b0 ^= (b2 << 1) ^ (b1 << 2);
a5 ^= a3 ^ a4;
b5 ^= b3 ^ b4;
a3 ^= (a5 << 1) ^ (a4 << 2);
b3 ^= (b5 << 1) ^ (b4 << 2);
a8 ^= a6 ^ a7;
b8 ^= b6 ^ b7;
a6 ^= (a8 << 1) ^ (a7 << 2);
b6 ^= (b8 << 1) ^ (b7 << 2);
a6 ^= a0 ^ a3;
b6 ^= b0 ^ b3;
*lo = a0 ^ (a6 << 2) ^ (a3 << 4);
*hi = b0 ^ (b6 << 2) ^ (b3 << 4) ^ (a6 >> 30) ^ (a3 >> 28);
}
#else
/*
* Simple multiplication in GF(2)[X], using 16 integer multiplications.
*/
static inline void
bmul(uint32_t *hi, uint32_t *lo, uint32_t x, uint32_t y)
{
uint32_t x0, x1, x2, x3;
uint32_t y0, y1, y2, y3;
uint64_t z0, z1, z2, z3;
uint64_t z;
x0 = x & (uint32_t)0x11111111;
x1 = x & (uint32_t)0x22222222;
x2 = x & (uint32_t)0x44444444;
x3 = x & (uint32_t)0x88888888;
y0 = y & (uint32_t)0x11111111;
y1 = y & (uint32_t)0x22222222;
y2 = y & (uint32_t)0x44444444;
y3 = y & (uint32_t)0x88888888;
z0 = MUL(x0, y0) ^ MUL(x1, y3) ^ MUL(x2, y2) ^ MUL(x3, y1);
z1 = MUL(x0, y1) ^ MUL(x1, y0) ^ MUL(x2, y3) ^ MUL(x3, y2);
z2 = MUL(x0, y2) ^ MUL(x1, y1) ^ MUL(x2, y0) ^ MUL(x3, y3);
z3 = MUL(x0, y3) ^ MUL(x1, y2) ^ MUL(x2, y1) ^ MUL(x3, y0);
z0 &= (uint64_t)0x1111111111111111;
z1 &= (uint64_t)0x2222222222222222;
z2 &= (uint64_t)0x4444444444444444;
z3 &= (uint64_t)0x8888888888888888;
z = z0 | z1 | z2 | z3;
*lo = (uint32_t)z;
*hi = (uint32_t)(z >> 32);
}
#endif
/* see bearssl_hash.h */
void
br_ghash_ctmul(void *y, const void *h, const void *data, size_t len)
{
const unsigned char *buf, *hb;
unsigned char *yb;
uint32_t yw[4];
uint32_t hw[4];
/*
* Throughout the loop we handle the y and h values as arrays
* of 32-bit words.
*/
buf = (unsigned char*)data;
yb = (unsigned char*)y;
hb = (const unsigned char*)h;
yw[3] = br_dec32be(yb);
yw[2] = br_dec32be(yb + 4);
yw[1] = br_dec32be(yb + 8);
yw[0] = br_dec32be(yb + 12);
hw[3] = br_dec32be(hb);
hw[2] = br_dec32be(hb + 4);
hw[1] = br_dec32be(hb + 8);
hw[0] = br_dec32be(hb + 12);
while (len > 0) {
const unsigned char *src;
unsigned char tmp[16];
int i;
uint32_t a[9], b[9], zw[8];
uint32_t c0, c1, c2, c3, d0, d1, d2, d3, e0, e1, e2, e3;
/*
* Get the next 16-byte block (using zero-padding if
* necessary).
*/
if (len >= 16) {
src = buf;
buf += 16;
len -= 16;
} else {
memcpy(tmp, buf, len);
memset(tmp + len, 0, (sizeof tmp) - len);
src = tmp;
len = 0;
}
/*
* Decode the block. The GHASH standard mandates
* big-endian encoding.
*/
yw[3] ^= br_dec32be(src);
yw[2] ^= br_dec32be(src + 4);
yw[1] ^= br_dec32be(src + 8);
yw[0] ^= br_dec32be(src + 12);
/*
* We multiply two 128-bit field elements. We use
* Karatsuba to turn that into three 64-bit
* multiplications, which are themselves done with a
* total of nine 32-bit multiplications.
*/
/*
* y[0,1]*h[0,1] -> 0..2
* y[2,3]*h[2,3] -> 3..5
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6..8
*/
a[0] = yw[0];
b[0] = hw[0];
a[1] = yw[1];
b[1] = hw[1];
a[2] = a[0] ^ a[1];
b[2] = b[0] ^ b[1];
a[3] = yw[2];
b[3] = hw[2];
a[4] = yw[3];
b[4] = hw[3];
a[5] = a[3] ^ a[4];
b[5] = b[3] ^ b[4];
a[6] = a[0] ^ a[3];
b[6] = b[0] ^ b[3];
a[7] = a[1] ^ a[4];
b[7] = b[1] ^ b[4];
a[8] = a[6] ^ a[7];
b[8] = b[6] ^ b[7];
for (i = 0; i < 9; i ++) {
bmul(&b[i], &a[i], b[i], a[i]);
}
c0 = a[0];
c1 = b[0] ^ a[2] ^ a[0] ^ a[1];
c2 = a[1] ^ b[2] ^ b[0] ^ b[1];
c3 = b[1];
d0 = a[3];
d1 = b[3] ^ a[5] ^ a[3] ^ a[4];
d2 = a[4] ^ b[5] ^ b[3] ^ b[4];
d3 = b[4];
e0 = a[6];
e1 = b[6] ^ a[8] ^ a[6] ^ a[7];
e2 = a[7] ^ b[8] ^ b[6] ^ b[7];
e3 = b[7];
e0 ^= c0 ^ d0;
e1 ^= c1 ^ d1;
e2 ^= c2 ^ d2;
e3 ^= c3 ^ d3;
c2 ^= e0;
c3 ^= e1;
d0 ^= e2;
d1 ^= e3;
/*
* GHASH specification has the bits "reversed" (most
* significant is in fact least significant), which does
* not matter for a carryless multiplication, except that
* the 255-bit result must be shifted by 1 bit.
*/
zw[0] = c0 << 1;
zw[1] = (c1 << 1) | (c0 >> 31);
zw[2] = (c2 << 1) | (c1 >> 31);
zw[3] = (c3 << 1) | (c2 >> 31);
zw[4] = (d0 << 1) | (c3 >> 31);
zw[5] = (d1 << 1) | (d0 >> 31);
zw[6] = (d2 << 1) | (d1 >> 31);
zw[7] = (d3 << 1) | (d2 >> 31);
/*
* We now do the reduction modulo the field polynomial
* to get back to 128 bits.
*/
for (i = 0; i < 4; i ++) {
uint32_t lw;
lw = zw[i];
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
}
memcpy(yw, zw + 4, sizeof yw);
}
/*
* Encode back the result.
*/
br_enc32be(yb, yw[3]);
br_enc32be(yb + 4, yw[2]);
br_enc32be(yb + 8, yw[1]);
br_enc32be(yb + 12, yw[0]);
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* This implementation uses 32-bit multiplications, and only the low
* 32 bits for each multiplication result. This is meant primarily for
* the ARM Cortex M0 and M0+, whose multiplication opcode does not yield
* the upper 32 bits; but it might also be useful on architectures where
* access to the upper 32 bits requires use of specific registers that
* create contention (e.g. on i386, "mul" necessarily outputs the result
* in edx:eax, while "imul" can use any registers but is limited to the
* low 32 bits).
*
* The implementation trick that is used here is bit-reversing (bit 0
* is swapped with bit 31, bit 1 with bit 30, and so on). In GF(2)[X],
* for all values x and y, we have:
* rev32(x) * rev32(y) = rev64(x * y)
* In other words, if we bit-reverse (over 32 bits) the operands, then we
* bit-reverse (over 64 bits) the result.
*/
/*
* Multiplication in GF(2)[X], truncated to its low 32 bits.
*/
static inline uint32_t
bmul32(uint32_t x, uint32_t y)
{
uint32_t x0, x1, x2, x3;
uint32_t y0, y1, y2, y3;
uint32_t z0, z1, z2, z3;
x0 = x & (uint32_t)0x11111111;
x1 = x & (uint32_t)0x22222222;
x2 = x & (uint32_t)0x44444444;
x3 = x & (uint32_t)0x88888888;
y0 = y & (uint32_t)0x11111111;
y1 = y & (uint32_t)0x22222222;
y2 = y & (uint32_t)0x44444444;
y3 = y & (uint32_t)0x88888888;
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
z0 &= (uint32_t)0x11111111;
z1 &= (uint32_t)0x22222222;
z2 &= (uint32_t)0x44444444;
z3 &= (uint32_t)0x88888888;
return z0 | z1 | z2 | z3;
}
/*
* Bit-reverse a 32-bit word.
*/
static uint32_t
rev32(uint32_t x)
{
#define RMS(m, s) do { \
x = ((x & (uint32_t)(m)) << (s)) \
| ((x >> (s)) & (uint32_t)(m)); \
} while (0)
RMS(0x55555555, 1);
RMS(0x33333333, 2);
RMS(0x0F0F0F0F, 4);
RMS(0x00FF00FF, 8);
return (x << 16) | (x >> 16);
#undef RMS
}
/* see bearssl_hash.h */
void
br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len)
{
/*
* This implementation is similar to br_ghash_ctmul() except
* that we have to do the multiplication twice, with the
* "normal" and "bit reversed" operands. Hence we end up with
* eighteen 32-bit multiplications instead of nine.
*/
const unsigned char *buf, *hb;
unsigned char *yb;
uint32_t yw[4];
uint32_t hw[4], hwr[4];
buf = (unsigned char*)data;
yb = (unsigned char*)y;
hb = (const unsigned char*)h;
yw[3] = br_dec32be(yb);
yw[2] = br_dec32be(yb + 4);
yw[1] = br_dec32be(yb + 8);
yw[0] = br_dec32be(yb + 12);
hw[3] = br_dec32be(hb);
hw[2] = br_dec32be(hb + 4);
hw[1] = br_dec32be(hb + 8);
hw[0] = br_dec32be(hb + 12);
hwr[3] = rev32(hw[3]);
hwr[2] = rev32(hw[2]);
hwr[1] = rev32(hw[1]);
hwr[0] = rev32(hw[0]);
while (len > 0) {
const unsigned char *src;
unsigned char tmp[16];
int i;
uint32_t a[18], b[18], c[18];
uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
uint32_t zw[8];
if (len >= 16) {
src = buf;
buf += 16;
len -= 16;
} else {
memcpy(tmp, buf, len);
memset(tmp + len, 0, (sizeof tmp) - len);
src = tmp;
len = 0;
}
yw[3] ^= br_dec32be(src);
yw[2] ^= br_dec32be(src + 4);
yw[1] ^= br_dec32be(src + 8);
yw[0] ^= br_dec32be(src + 12);
/*
* We are using Karatsuba: the 128x128 multiplication is
* reduced to three 64x64 multiplications, hence nine
* 32x32 multiplications. With the bit-reversal trick,
* we have to perform 18 32x32 multiplications.
*/
/*
* y[0,1]*h[0,1] -> 0,1,4
* y[2,3]*h[2,3] -> 2,3,5
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,7,8
*/
a[0] = yw[0];
a[1] = yw[1];
a[2] = yw[2];
a[3] = yw[3];
a[4] = a[0] ^ a[1];
a[5] = a[2] ^ a[3];
a[6] = a[0] ^ a[2];
a[7] = a[1] ^ a[3];
a[8] = a[6] ^ a[7];
a[ 9] = rev32(yw[0]);
a[10] = rev32(yw[1]);
a[11] = rev32(yw[2]);
a[12] = rev32(yw[3]);
a[13] = a[ 9] ^ a[10];
a[14] = a[11] ^ a[12];
a[15] = a[ 9] ^ a[11];
a[16] = a[10] ^ a[12];
a[17] = a[15] ^ a[16];
b[0] = hw[0];
b[1] = hw[1];
b[2] = hw[2];
b[3] = hw[3];
b[4] = b[0] ^ b[1];
b[5] = b[2] ^ b[3];
b[6] = b[0] ^ b[2];
b[7] = b[1] ^ b[3];
b[8] = b[6] ^ b[7];
b[ 9] = hwr[0];
b[10] = hwr[1];
b[11] = hwr[2];
b[12] = hwr[3];
b[13] = b[ 9] ^ b[10];
b[14] = b[11] ^ b[12];
b[15] = b[ 9] ^ b[11];
b[16] = b[10] ^ b[12];
b[17] = b[15] ^ b[16];
for (i = 0; i < 18; i ++) {
c[i] = bmul32(a[i], b[i]);
}
c[4] ^= c[0] ^ c[1];
c[5] ^= c[2] ^ c[3];
c[8] ^= c[6] ^ c[7];
c[13] ^= c[ 9] ^ c[10];
c[14] ^= c[11] ^ c[12];
c[17] ^= c[15] ^ c[16];
/*
* y[0,1]*h[0,1] -> 0,9^4,1^13,10
* y[2,3]*h[2,3] -> 2,11^5,3^14,12
* (y[0,1]+y[2,3])*(h[0,1]+h[2,3]) -> 6,15^8,7^17,16
*/
d0 = c[0];
d1 = c[4] ^ (rev32(c[9]) >> 1);
d2 = c[1] ^ c[0] ^ c[2] ^ c[6] ^ (rev32(c[13]) >> 1);
d3 = c[4] ^ c[5] ^ c[8]
^ (rev32(c[10] ^ c[9] ^ c[11] ^ c[15]) >> 1);
d4 = c[2] ^ c[1] ^ c[3] ^ c[7]
^ (rev32(c[13] ^ c[14] ^ c[17]) >> 1);
d5 = c[5] ^ (rev32(c[11] ^ c[10] ^ c[12] ^ c[16]) >> 1);
d6 = c[3] ^ (rev32(c[14]) >> 1);
d7 = rev32(c[12]) >> 1;
zw[0] = d0 << 1;
zw[1] = (d1 << 1) | (d0 >> 31);
zw[2] = (d2 << 1) | (d1 >> 31);
zw[3] = (d3 << 1) | (d2 >> 31);
zw[4] = (d4 << 1) | (d3 >> 31);
zw[5] = (d5 << 1) | (d4 >> 31);
zw[6] = (d6 << 1) | (d5 >> 31);
zw[7] = (d7 << 1) | (d6 >> 31);
for (i = 0; i < 4; i ++) {
uint32_t lw;
lw = zw[i];
zw[i + 4] ^= lw ^ (lw >> 1) ^ (lw >> 2) ^ (lw >> 7);
zw[i + 3] ^= (lw << 31) ^ (lw << 30) ^ (lw << 25);
}
memcpy(yw, zw + 4, sizeof yw);
}
br_enc32be(yb, yw[3]);
br_enc32be(yb + 4, yw[2]);
br_enc32be(yb + 8, yw[1]);
br_enc32be(yb + 12, yw[0]);
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2016 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* This is the 64-bit variant of br_ghash_ctmul32(), with 64-bit operands
* and bit reversal of 64-bit words.
*/
static inline uint64_t
bmul64(uint64_t x, uint64_t y)
{
uint64_t x0, x1, x2, x3;
uint64_t y0, y1, y2, y3;
uint64_t z0, z1, z2, z3;
x0 = x & (uint64_t)0x1111111111111111;
x1 = x & (uint64_t)0x2222222222222222;
x2 = x & (uint64_t)0x4444444444444444;
x3 = x & (uint64_t)0x8888888888888888;
y0 = y & (uint64_t)0x1111111111111111;
y1 = y & (uint64_t)0x2222222222222222;
y2 = y & (uint64_t)0x4444444444444444;
y3 = y & (uint64_t)0x8888888888888888;
z0 = (x0 * y0) ^ (x1 * y3) ^ (x2 * y2) ^ (x3 * y1);
z1 = (x0 * y1) ^ (x1 * y0) ^ (x2 * y3) ^ (x3 * y2);
z2 = (x0 * y2) ^ (x1 * y1) ^ (x2 * y0) ^ (x3 * y3);
z3 = (x0 * y3) ^ (x1 * y2) ^ (x2 * y1) ^ (x3 * y0);
z0 &= (uint64_t)0x1111111111111111;
z1 &= (uint64_t)0x2222222222222222;
z2 &= (uint64_t)0x4444444444444444;
z3 &= (uint64_t)0x8888888888888888;
return z0 | z1 | z2 | z3;
}
static uint64_t
rev64(uint64_t x)
{
#define RMS(m, s) do { \
x = ((x & (uint64_t)(m)) << (s)) \
| ((x >> (s)) & (uint64_t)(m)); \
} while (0)
RMS(0x5555555555555555, 1);
RMS(0x3333333333333333, 2);
RMS(0x0F0F0F0F0F0F0F0F, 4);
RMS(0x00FF00FF00FF00FF, 8);
RMS(0x0000FFFF0000FFFF, 16);
return (x << 32) | (x >> 32);
#undef RMS
}
/* see bearssl_ghash.h */
void
br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len)
{
const unsigned char *buf, *hb;
unsigned char *yb;
uint64_t y0, y1;
uint64_t h0, h1, h2, h0r, h1r, h2r;
buf = (unsigned char*)data;
yb = (unsigned char*)y;
hb = (const unsigned char*)h;
y1 = br_dec64be(yb);
y0 = br_dec64be(yb + 8);
h1 = br_dec64be(hb);
h0 = br_dec64be(hb + 8);
h0r = rev64(h0);
h1r = rev64(h1);
h2 = h0 ^ h1;
h2r = h0r ^ h1r;
while (len > 0) {
const unsigned char *src;
unsigned char tmp[16];
uint64_t y0r, y1r, y2, y2r;
uint64_t z0, z1, z2, z0h, z1h, z2h;
uint64_t v0, v1, v2, v3;
if (len >= 16) {
src = buf;
buf += 16;
len -= 16;
} else {
memcpy(tmp, buf, len);
memset(tmp + len, 0, (sizeof tmp) - len);
src = tmp;
len = 0;
}
y1 ^= br_dec64be(src);
y0 ^= br_dec64be(src + 8);
y0r = rev64(y0);
y1r = rev64(y1);
y2 = y0 ^ y1;
y2r = y0r ^ y1r;
z0 = bmul64(y0, h0);
z1 = bmul64(y1, h1);
z2 = bmul64(y2, h2);
z0h = bmul64(y0r, h0r);
z1h = bmul64(y1r, h1r);
z2h = bmul64(y2r, h2r);
z2 ^= z0 ^ z1;
z2h ^= z0h ^ z1h;
z0h = rev64(z0h) >> 1;
z1h = rev64(z1h) >> 1;
z2h = rev64(z2h) >> 1;
v0 = z0;
v1 = z0h ^ z2;
v2 = z1 ^ z2h;
v3 = z1h;
v3 = (v3 << 1) | (v2 >> 63);
v2 = (v2 << 1) | (v1 >> 63);
v1 = (v1 << 1) | (v0 >> 63);
v0 = (v0 << 1);
v2 ^= v0 ^ (v0 >> 1) ^ (v0 >> 2) ^ (v0 >> 7);
v1 ^= (v0 << 63) ^ (v0 << 62) ^ (v0 << 57);
v3 ^= v1 ^ (v1 >> 1) ^ (v1 >> 2) ^ (v1 >> 7);
v2 ^= (v1 << 63) ^ (v1 << 62) ^ (v1 << 57);
y0 = v2;
y1 = v3;
}
br_enc64be(yb, y1);
br_enc64be(yb + 8, y0);
}
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#define BR_ENABLE_INTRINSICS 1
/*
* This is the GHASH implementation that leverages the pclmulqdq opcode
* (from the AES-NI instructions).
*/
#if BR_AES_X86NI
/*
* Test CPU support for PCLMULQDQ.
*/
static inline int
pclmul_supported(void)
{
/*
* Bit mask for features in ECX:
* 1 PCLMULQDQ support
*/
return br_cpuid(0, 0, 0x00000002, 0);
}
/* see bearssl_hash.h */
br_ghash
br_ghash_pclmul_get(void)
{
return pclmul_supported() ? &br_ghash_pclmul : 0;
}
BR_TARGETS_X86_UP
/*
* GHASH is defined over elements of GF(2^128) with "full little-endian"
* representation: leftmost byte is least significant, and, within each
* byte, leftmost _bit_ is least significant. The natural ordering in
* x86 is "mixed little-endian": bytes are ordered from least to most
* significant, but bits within a byte are in most-to-least significant
* order. Going to full little-endian representation would require
* reversing bits within each byte, which is doable but expensive.
*
* Instead, we go to full big-endian representation, by swapping bytes
* around, which is done with a single _mm_shuffle_epi8() opcode (it
* comes with SSSE3; all CPU that offer pclmulqdq also have SSSE3). We
* can use a full big-endian representation because in a carryless
* multiplication, we have a nice bit reversal property:
*
* rev_128(x) * rev_128(y) = rev_255(x * y)
*
* So by using full big-endian, we still get the right result, except
* that it is right-shifted by 1 bit. The left-shift is relatively
* inexpensive, and it can be mutualised.
*
*
* Since SSE2 opcodes do not have facilities for shitfting full 128-bit
* values with bit precision, we have to break down values into 64-bit
* chunks. We number chunks from 0 to 3 in left to right order.
*/
/*
* Byte-swap a complete 128-bit value. This normally uses
* _mm_shuffle_epi8(), which gets translated to pshufb (an SSSE3 opcode).
* However, this crashes old Clang versions, so, for Clang before 3.8,
* we use an alternate (and less efficient) version.
*/
#if BR_CLANG && !BR_CLANG_3_8
#define BYTESWAP_DECL
#define BYTESWAP_PREP (void)0
#define BYTESWAP(x) do { \
__m128i _src_hash_ghash_pclmul_cbyteswap1, _src_hash_ghash_pclmul_cbyteswap2; \
_src_hash_ghash_pclmul_cbyteswap1 = (x); \
_src_hash_ghash_pclmul_cbyteswap2 = _mm_srli_epi16(_src_hash_ghash_pclmul_cbyteswap1, 8); \
_src_hash_ghash_pclmul_cbyteswap1 = _mm_slli_epi16(_src_hash_ghash_pclmul_cbyteswap1, 8); \
_src_hash_ghash_pclmul_cbyteswap1 = _mm_or_si128(_src_hash_ghash_pclmul_cbyteswap1, _src_hash_ghash_pclmul_cbyteswap2); \
_src_hash_ghash_pclmul_cbyteswap1 = _mm_shufflelo_epi16(_src_hash_ghash_pclmul_cbyteswap1, 0x1B); \
_src_hash_ghash_pclmul_cbyteswap1 = _mm_shufflehi_epi16(_src_hash_ghash_pclmul_cbyteswap1, 0x1B); \
(x) = _mm_shuffle_epi32(_src_hash_ghash_pclmul_cbyteswap1, 0x4E); \
} while (0)
#else
#define BYTESWAP_DECL __m128i _src_hash_ghash_pclmul_cbyteswap_index;
#define BYTESWAP_PREP do { \
_src_hash_ghash_pclmul_cbyteswap_index = _mm_set_epi8( \
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); \
} while (0)
#define BYTESWAP(x) do { \
(x) = _mm_shuffle_epi8((x), _src_hash_ghash_pclmul_cbyteswap_index); \
} while (0)
#endif
/*
* Call pclmulqdq. Clang appears to have trouble with the intrinsic, so,
* for that compiler, we use inline assembly. Inline assembly is
* potentially a bit slower because the compiler does not understand
* what the opcode does, and thus cannot optimize instruction
* scheduling.
*
* We use a target of "sse2" only, so that Clang may still handle the
* '__m128i' type and allocate SSE2 registers.
*/
#if BR_CLANG
BR_TARGET("sse2")
static inline __m128i
pclmulqdq00(__m128i x, __m128i y)
{
__asm__ ("pclmulqdq $0x00, %1, %0" : "+x" (x) : "x" (y));
return x;
}
BR_TARGET("sse2")
static inline __m128i
pclmulqdq11(__m128i x, __m128i y)
{
__asm__ ("pclmulqdq $0x11, %1, %0" : "+x" (x) : "x" (y));
return x;
}
#else
#define pclmulqdq00(x, y) _mm_clmulepi64_si128(x, y, 0x00)
#define pclmulqdq11(x, y) _mm_clmulepi64_si128(x, y, 0x11)
#endif
/*
* From a 128-bit value kw, compute kx as the XOR of the two 64-bit
* halves of kw (into the right half of kx; left half is unspecified).
*/
#define BK(kw, kx) do { \
kx = _mm_xor_si128(kw, _mm_shuffle_epi32(kw, 0x0E)); \
} while (0)
/*
* Combine two 64-bit values (k0:k1) into a 128-bit (kw) value and
* the XOR of the two values (kx).
*/
#define PBK(k0, k1, kw, kx) do { \
kw = _mm_unpacklo_epi64(k1, k0); \
kx = _mm_xor_si128(k0, k1); \
} while (0)
/*
* Left-shift by 1 bit a 256-bit value (in four 64-bit words).
*/
#define SL_256(x0, x1, x2, x3) do { \
x0 = _mm_or_si128( \
_mm_slli_epi64(x0, 1), \
_mm_srli_epi64(x1, 63)); \
x1 = _mm_or_si128( \
_mm_slli_epi64(x1, 1), \
_mm_srli_epi64(x2, 63)); \
x2 = _mm_or_si128( \
_mm_slli_epi64(x2, 1), \
_mm_srli_epi64(x3, 63)); \
x3 = _mm_slli_epi64(x3, 1); \
} while (0)
/*
* Perform reduction in GF(2^128). The 256-bit value is in x0..x3;
* result is written in x0..x1.
*/
#define REDUCE_F128(x0, x1, x2, x3) do { \
x1 = _mm_xor_si128( \
x1, \
_mm_xor_si128( \
_mm_xor_si128( \
x3, \
_mm_srli_epi64(x3, 1)), \
_mm_xor_si128( \
_mm_srli_epi64(x3, 2), \
_mm_srli_epi64(x3, 7)))); \
x2 = _mm_xor_si128( \
_mm_xor_si128( \
x2, \
_mm_slli_epi64(x3, 63)), \
_mm_xor_si128( \
_mm_slli_epi64(x3, 62), \
_mm_slli_epi64(x3, 57))); \
x0 = _mm_xor_si128( \
x0, \
_mm_xor_si128( \
_mm_xor_si128( \
x2, \
_mm_srli_epi64(x2, 1)), \
_mm_xor_si128( \
_mm_srli_epi64(x2, 2), \
_mm_srli_epi64(x2, 7)))); \
x1 = _mm_xor_si128( \
_mm_xor_si128( \
x1, \
_mm_slli_epi64(x2, 63)), \
_mm_xor_si128( \
_mm_slli_epi64(x2, 62), \
_mm_slli_epi64(x2, 57))); \
} while (0)
/*
* Square value kw into (dw,dx).
*/
#define SQUARE_F128(kw, dw, dx) do { \
__m128i z0, z1, z2, z3; \
z1 = pclmulqdq11(kw, kw); \
z3 = pclmulqdq00(kw, kw); \
z0 = _mm_shuffle_epi32(z1, 0x0E); \
z2 = _mm_shuffle_epi32(z3, 0x0E); \
SL_256(z0, z1, z2, z3); \
REDUCE_F128(z0, z1, z2, z3); \
PBK(z0, z1, dw, dx); \
} while (0)
/* see bearssl_hash.h */
BR_TARGET("ssse3,pclmul")
void
br_ghash_pclmul(void *y, const void *h, const void *data, size_t len)
{
const unsigned char *buf1, *buf2;
unsigned char tmp[64];
size_t num4, num1;
__m128i yw, h1w, h1x;
BYTESWAP_DECL
/*
* We split data into two chunks. First chunk starts at buf1
* and contains num4 blocks of 64-byte values. Second chunk
* starts at buf2 and contains num1 blocks of 16-byte values.
* We want the first chunk to be as large as possible.
*/
buf1 = (unsigned char*)data;
num4 = len >> 6;
len &= 63;
buf2 = buf1 + (num4 << 6);
num1 = (len + 15) >> 4;
if ((len & 15) != 0) {
memcpy(tmp, buf2, len);
memset(tmp + len, 0, (num1 << 4) - len);
buf2 = tmp;
}
/*
* Preparatory step for endian conversions.
*/
BYTESWAP_PREP;
/*
* Load y and h.
*/
yw = _mm_loadu_si128((const __m128i_u*)y);
h1w = _mm_loadu_si128((const __m128i_u*)h);
BYTESWAP(yw);
BYTESWAP(h1w);
BK(h1w, h1x);
if (num4 > 0) {
__m128i h2w, h2x, h3w, h3x, h4w, h4x;
__m128i t0, t1, t2, t3;
/*
* Compute h2 = h^2.
*/
SQUARE_F128(h1w, h2w, h2x);
/*
* Compute h3 = h^3 = h*(h^2).
*/
t1 = pclmulqdq11(h1w, h2w);
t3 = pclmulqdq00(h1w, h2w);
t2 = _mm_xor_si128(pclmulqdq00(h1x, h2x),
_mm_xor_si128(t1, t3));
t0 = _mm_shuffle_epi32(t1, 0x0E);
t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
SL_256(t0, t1, t2, t3);
REDUCE_F128(t0, t1, t2, t3);
PBK(t0, t1, h3w, h3x);
/*
* Compute h4 = h^4 = (h^2)^2.
*/
SQUARE_F128(h2w, h4w, h4x);
while (num4 -- > 0) {
__m128i aw0, aw1, aw2, aw3;
__m128i ax0, ax1, ax2, ax3;
aw0 = _mm_loadu_si128((const __m128i_u*)(buf1 + 0));
aw1 = _mm_loadu_si128((const __m128i_u*)(buf1 + 16));
aw2 = _mm_loadu_si128((const __m128i_u*)(buf1 + 32));
aw3 = _mm_loadu_si128((const __m128i_u*)(buf1 + 48));
BYTESWAP(aw0);
BYTESWAP(aw1);
BYTESWAP(aw2);
BYTESWAP(aw3);
buf1 += 64;
aw0 = _mm_xor_si128(aw0, yw);
BK(aw1, ax1);
BK(aw2, ax2);
BK(aw3, ax3);
BK(aw0, ax0);
t1 = _mm_xor_si128(
_mm_xor_si128(
pclmulqdq11(aw0, h4w),
pclmulqdq11(aw1, h3w)),
_mm_xor_si128(
pclmulqdq11(aw2, h2w),
pclmulqdq11(aw3, h1w)));
t3 = _mm_xor_si128(
_mm_xor_si128(
pclmulqdq00(aw0, h4w),
pclmulqdq00(aw1, h3w)),
_mm_xor_si128(
pclmulqdq00(aw2, h2w),
pclmulqdq00(aw3, h1w)));
t2 = _mm_xor_si128(
_mm_xor_si128(
pclmulqdq00(ax0, h4x),
pclmulqdq00(ax1, h3x)),
_mm_xor_si128(
pclmulqdq00(ax2, h2x),
pclmulqdq00(ax3, h1x)));
t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3));
t0 = _mm_shuffle_epi32(t1, 0x0E);
t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
SL_256(t0, t1, t2, t3);
REDUCE_F128(t0, t1, t2, t3);
yw = _mm_unpacklo_epi64(t1, t0);
}
}
while (num1 -- > 0) {
__m128i aw, ax;
__m128i t0, t1, t2, t3;
aw = _mm_loadu_si128((const __m128i_u*)buf2);
BYTESWAP(aw);
buf2 += 16;
aw = _mm_xor_si128(aw, yw);
BK(aw, ax);
t1 = pclmulqdq11(aw, h1w);
t3 = pclmulqdq00(aw, h1w);
t2 = pclmulqdq00(ax, h1x);
t2 = _mm_xor_si128(t2, _mm_xor_si128(t1, t3));
t0 = _mm_shuffle_epi32(t1, 0x0E);
t1 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
t2 = _mm_xor_si128(t2, _mm_shuffle_epi32(t3, 0x0E));
SL_256(t0, t1, t2, t3);
REDUCE_F128(t0, t1, t2, t3);
yw = _mm_unpacklo_epi64(t1, t0);
}
BYTESWAP(yw);
_mm_storeu_si128((__m128i_u*)y, yw);
}
BR_TARGETS_X86_DOWN
#else
/* see bearssl_hash.h */
br_ghash
br_ghash_pclmul_get(void)
{
return 0;
}
#endif
//silver_chain_scope_start
//mannaged by silver chain
//silver_chain_scope_end
/*
* Copyright (c) 2017 Thomas Pornin
* [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) * * The vtable offers functions called `init()`, `update()`, `out()`, * `set()` and `set_state()`, which are in fact the functions from * the procedural API. That vtable also contains two informative fields: * * - `context_size` * * The size of the context structure (`br_xxx_context`), in bytes. * This can be used by generic implementations to perform dynamic * context allocation. * * - `desc` * * A "descriptor" field that encodes some information on the hash * function: symbolic identifier, output size, state size, * internal block size, details on the padding. * * Users of this object-oriented API (in particular generic HMAC * implementations) may make the following assumptions: * * - Hash output size is no more than 64 bytes. * - Hash internal state size is no more than 64 bytes. * - Internal block size is a power of two, no less than 16 and no more * than 256. * * * ## Implemented Hash Functions * * Implemented hash functions are: * * | Function | Name | Output length | State length | * | :-------- | :------ | :-----------: | :----------: | * | MD5 | md5 | 16 | 16 | * | SHA-1 | sha1 | 20 | 20 | * | SHA-224 | sha224 | 28 | 32 | * | SHA-256 | sha256 | 32 | 32 | * | SHA-384 | sha384 | 48 | 64 | * | SHA-512 | sha512 | 64 | 64 | * | MD5+SHA-1 | md5sha1 | 36 | 36 | * * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the * same input; in the implementation, the internal data buffer is * shared, thus making it more memory-efficient than separate MD5 and * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS * 1.1.) * * * ## Multi-Hasher * * An aggregate hasher is provided, that can compute several standard * hash functions in parallel. It uses `br_multihash_context` and a * procedural API. It is configured with the implementations (the vtables) * that it should use; it will then compute all these hash functions in * parallel, on the same input. It is meant to be used in cases when the * hash of an object will be used, but the exact hash function is not * known yet (typically, streamed processing on X.509 certificates). * * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 * and SHA-512) are supported by the multi-hasher. * * * ## GHASH * * GHASH is not a generic hash function; it is a _universal_ hash function, * which, as the name does not say, means that it CANNOT be used in most * places where a hash function is needed. GHASH is used within the GCM * encryption mode, to provide the checked integrity functionality. * * A GHASH implementation is basically a function that uses the type defined * in this file under the name `br_ghash`: * * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); * * The `y` pointer refers to a 16-byte value which is used as input, and * receives the output of the GHASH invocation. `h` is a 16-byte secret * value (that serves as key). `data` and `len` define the input data. * * Three GHASH implementations are provided, all constant-time, based on * the use of integer multiplications with appropriate masking to cancel * carry propagation. */ /** * \brief Class type for hash function implementations. * * A `br_hash_class` instance references the methods implementing a hash * function. Constant instances of this structure are defined for each * implemented hash function. Such instances are also called "vtables". * * Vtables are used to support object-oriented programming, as * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). */ typedef struct br_hash_class_ br_hash_class; struct br_hash_class_ { /** * \brief Size (in bytes) of the context structure appropriate for * computing this hash function. */ size_t context_size; /** * \brief Descriptor word that contains information about the hash * function. * * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` * and `BR_HASHDESC_xxx_MASK` to access the specific value, as * follows: * * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK * * The defined elements are: * * - `ID`: the symbolic identifier for the function, as defined * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) * (MD5 = 1, SHA-1 = 2,...). * * - `OUT`: hash output size, in bytes. * * - `STATE`: internal running state size, in bytes. * * - `LBLEN`: base-2 logarithm for the internal block size, as * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 * and SHA-256, since these functions use 64-byte blocks; for * SHA-384 and SHA-512, this is 7, corresponding to their * 128-byte blocks). * * The descriptor may contain a few other flags. */ uint32_t desc; /** * \brief Initialisation method. * * This method takes as parameter a pointer to a context area, * that it initialises. The first field of the context is set * to this vtable; other elements are initialised for a new hash * computation. * * \param ctx pointer to (the first field of) the context. */ void (*init)(const br_hash_class **ctx); /** * \brief Data injection method. * * The `len` bytes starting at address `data` are injected into * the running hash computation incarnated by the specified * context. The context is updated accordingly. It is allowed * to have `len == 0`, in which case `data` is ignored (and could * be `NULL`), and nothing happens. * on the input data. * * \param ctx pointer to (the first field of) the context. * \param data pointer to the first data byte to inject. * \param len number of bytes to inject. */ void (*update)(const br_hash_class **ctx, const void *data, size_t len); /** * \brief Produce hash output. * * The hash output corresponding to all data bytes injected in the * context since the last `init()` call is computed, and written * in the buffer pointed to by `dst`. The hash output size depends * on the implemented hash function (e.g. 16 bytes for MD5). * The context is _not_ modified by this call, so further bytes * may be afterwards injected to continue the current computation. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the hash output. */ void (*out)(const br_hash_class *const *ctx, void *dst); /** * \brief Get running state. * * This method saves the current running state into the `dst` * buffer. What constitutes the "running state" depends on the * hash function; for Merkle-Damgård hash functions (like * MD5 or SHA-1), this is the output obtained after processing * each block. The number of bytes injected so far is returned. * The context is not modified by this call. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the state. * \return the injected total byte length. */ uint64_t (*state)(const br_hash_class *const *ctx, void *dst); /** * \brief Set running state. * * This methods replaces the running state for the function. * * \param ctx pointer to (the first field of) the context. * \param stb source buffer for the state. * \param count injected total byte length. */ void (*set_state)(const br_hash_class **ctx, const void *stb, uint64_t count); }; #ifndef BR_DOXYGEN_IGNORE #define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) #define BR_HASHDESC_ID_OFF 0 #define BR_HASHDESC_ID_MASK 0xFF #define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) #define BR_HASHDESC_OUT_OFF 8 #define BR_HASHDESC_OUT_MASK 0x7F #define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) #define BR_HASHDESC_STATE_OFF 15 #define BR_HASHDESC_STATE_MASK 0xFF #define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) #define BR_HASHDESC_LBLEN_OFF 23 #define BR_HASHDESC_LBLEN_MASK 0x0F #define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) #define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) #define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) #endif /* * Specific hash functions. * * Rules for contexts: * -- No interior pointer. * -- No pointer to external dynamically allocated resources. * -- First field is called 'vtable' and is a pointer to a * const-qualified br_hash_class instance (pointer is set by init()). * -- SHA-224 and SHA-256 contexts are identical. * -- SHA-384 and SHA-512 contexts are identical. * * Thus, contexts can be moved and cloned to capture the hash function * current state; and there is no need for any explicit "release" function. */ /** * \brief Symbolic identifier for MD5. */ #define br_md5_ID 1 /** * \brief MD5 output size (in bytes). */ #define br_md5_SIZE 16 /** * \brief Constant vtable for MD5. */ extern const br_hash_class br_md5_vtable; /** * \brief MD5 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[4]; #endif } br_md5_context; /** * \brief MD5 context initialisation. * * This function initialises or resets a context for a new MD5 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5_init(br_md5_context *ctx); /** * \brief Inject some data bytes in a running MD5 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5_update(br_md5_context *ctx, const void *data, size_t len); /** * \brief Compute MD5 output. * * The MD5 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5_out(const br_md5_context *ctx, void *out); /** * \brief Save MD5 running state. * * The running state for MD5 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5_state(const br_md5_context *ctx, void *out); /** * \brief Restore MD5 running state. * * The running state for MD5 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-1. */ #define br_sha1_ID 2 /** * \brief SHA-1 output size (in bytes). */ #define br_sha1_SIZE 20 /** * \brief Constant vtable for SHA-1. */ extern const br_hash_class br_sha1_vtable; /** * \brief SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[5]; #endif } br_sha1_context; /** * \brief SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-1 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha1_init(br_sha1_context *ctx); /** * \brief Inject some data bytes in a running SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-1 output. * * The SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha1_out(const br_sha1_context *ctx, void *out); /** * \brief Save SHA-1 running state. * * The running state for SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); /** * \brief Restore SHA-1 running state. * * The running state for SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-224. */ #define br_sha224_ID 3 /** * \brief SHA-224 output size (in bytes). */ #define br_sha224_SIZE 28 /** * \brief Constant vtable for SHA-224. */ extern const br_hash_class br_sha224_vtable; /** * \brief SHA-224 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[8]; #endif } br_sha224_context; /** * \brief SHA-224 context initialisation. * * This function initialises or resets a context for a new SHA-224 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha224_init(br_sha224_context *ctx); /** * \brief Inject some data bytes in a running SHA-224 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-224 output. * * The SHA-224 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha224_out(const br_sha224_context *ctx, void *out); /** * \brief Save SHA-224 running state. * * The running state for SHA-224 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); /** * \brief Restore SHA-224 running state. * * The running state for SHA-224 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha224_set_state(br_sha224_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-256. */ #define br_sha256_ID 4 /** * \brief SHA-256 output size (in bytes). */ #define br_sha256_SIZE 32 /** * \brief Constant vtable for SHA-256. */ extern const br_hash_class br_sha256_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-256 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha256_context; #else typedef br_sha224_context br_sha256_context; #endif /** * \brief SHA-256 context initialisation. * * This function initialises or resets a context for a new SHA-256 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha256_init(br_sha256_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-256 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); #else #define br_sha256_update br_sha224_update #endif /** * \brief Compute SHA-256 output. * * The SHA-256 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha256_out(const br_sha256_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-256 running state. * * The running state for SHA-256 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); #else #define br_sha256_state br_sha224_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-256 running state. * * The running state for SHA-256 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha256_set_state(br_sha256_context *ctx, const void *stb, uint64_t count); #else #define br_sha256_set_state br_sha224_set_state #endif /** * \brief Symbolic identifier for SHA-384. */ #define br_sha384_ID 5 /** * \brief SHA-384 output size (in bytes). */ #define br_sha384_SIZE 48 /** * \brief Constant vtable for SHA-384. */ extern const br_hash_class br_sha384_vtable; /** * \brief SHA-384 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint64_t val[8]; #endif } br_sha384_context; /** * \brief SHA-384 context initialisation. * * This function initialises or resets a context for a new SHA-384 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha384_init(br_sha384_context *ctx); /** * \brief Inject some data bytes in a running SHA-384 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-384 output. * * The SHA-384 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha384_out(const br_sha384_context *ctx, void *out); /** * \brief Save SHA-384 running state. * * The running state for SHA-384 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); /** * \brief Restore SHA-384 running state. * * The running state for SHA-384 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha384_set_state(br_sha384_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-512. */ #define br_sha512_ID 6 /** * \brief SHA-512 output size (in bytes). */ #define br_sha512_SIZE 64 /** * \brief Constant vtable for SHA-512. */ extern const br_hash_class br_sha512_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-512 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha512_context; #else typedef br_sha384_context br_sha512_context; #endif /** * \brief SHA-512 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha512_init(br_sha512_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-512 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); #else #define br_sha512_update br_sha384_update #endif /** * \brief Compute SHA-512 output. * * The SHA-512 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha512_out(const br_sha512_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-512 running state. * * The running state for SHA-512 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); #else #define br_sha512_state br_sha384_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-512 running state. * * The running state for SHA-512 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha512_set_state(br_sha512_context *ctx, const void *stb, uint64_t count); #else #define br_sha512_set_state br_sha384_set_state #endif /* * "md5sha1" is a special hash function that computes both MD5 and SHA-1 * on the same input, and produces a 36-byte output (MD5 and SHA-1 * concatenation, in that order). State size is also 36 bytes. */ /** * \brief Symbolic identifier for MD5+SHA-1. * * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the * same input. It is not one of the functions identified in TLS, so * we give it a symbolic identifier of value 0. */ #define br_md5sha1_ID 0 /** * \brief MD5+SHA-1 output size (in bytes). */ #define br_md5sha1_SIZE 36 /** * \brief Constant vtable for MD5+SHA-1. */ extern const br_hash_class br_md5sha1_vtable; /** * \brief MD5+SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val_md5[4]; uint32_t val_sha1[5]; #endif } br_md5sha1_context; /** * \brief MD5+SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5sha1_init(br_md5sha1_context *ctx); /** * \brief Inject some data bytes in a running MD5+SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); /** * \brief Compute MD5+SHA-1 output. * * The MD5+SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); /** * \brief Save MD5+SHA-1 running state. * * The running state for MD5+SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); /** * \brief Restore MD5+SHA-1 running state. * * The running state for MD5+SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5sha1_set_state(br_md5sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Aggregate context for configurable hash function support. * * The `br_hash_compat_context` type is a type which is large enough to * serve as context for all standard hash functions defined above. */ typedef union { const br_hash_class *vtable; br_md5_context md5; br_sha1_context sha1; br_sha224_context sha224; br_sha256_context sha256; br_sha384_context sha384; br_sha512_context sha512; br_md5sha1_context md5sha1; } br_hash_compat_context; /* * The multi-hasher is a construct that handles hashing of the same input * data with several hash functions, with a single shared input buffer. * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 * simultaneously, though which functions are activated depends on * the set implementation pointers. */ /** * \brief Multi-hasher context structure. * * The multi-hasher runs up to six hash functions in the standard TLS list * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over * the same input. * * The multi-hasher does _not_ follow the OOP structure with a vtable. * Instead, it is configured with the vtables of the hash functions it * should run. Structure fields are not supposed to be accessed directly. */ typedef struct { #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint32_t val_32[25]; uint64_t val_64[16]; const br_hash_class *impl[6]; #endif } br_multihash_context; /** * \brief Clear a multi-hasher context. * * This should always be called once on a given context, _before_ setting * the implementation pointers. * * \param ctx the multi-hasher context. */ void br_multihash_zero(br_multihash_context *ctx); /** * \brief Set a hash function implementation. * * Implementations shall be set _after_ clearing the context (with * `br_multihash_zero()`) but _before_ initialising the computation * (with `br_multihash_init()`). The hash function implementation * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove * an implementation from the multi-hasher. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \param impl the hash function vtable, or `NULL`. */ static inline void br_multihash_setimpl(br_multihash_context *ctx, int id, const br_hash_class *impl) { /* * This code relies on hash functions ID being values 1 to 6, * in the MD5 to SHA-512 order. */ ctx->impl[id - 1] = impl; } /** * \brief Get a hash function implementation. * * This function returns the currently configured vtable for a given * hash function (by symbolic ID). If no such function was configured in * the provided multi-hasher context, then this function returns `NULL`. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \return the hash function vtable, or `NULL`. */ static inline const br_hash_class * br_multihash_getimpl(const br_multihash_context *ctx, int id) { return ctx->impl[id - 1]; } /** * \brief Reset a multi-hasher context. * * This function prepares the context for a new hashing computation, * for all implementations configured at that point. * * \param ctx the multi-hasher context. */ void br_multihash_init(br_multihash_context *ctx); /** * \brief Inject some data bytes in a running multi-hashing computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_multihash_update(br_multihash_context *ctx, const void *data, size_t len); /** * \brief Compute a hash output from a multi-hasher. * * The hash output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `dst`. The hash * function to use is identified by `id` and must be one of the standard * hash functions. If that hash function was indeed configured in the * multi-hasher context, the corresponding hash value is written in * `dst` and its length (in bytes) is returned. If the hash function * was _not_ configured, then nothing is written in `dst` and 0 is * returned. * * The context itself is not modified, so extra bytes may be injected * afterwards to continue the hash computations. * * \param ctx pointer to the context structure. * \param id the hash function symbolic identifier. * \param dst destination buffer for the hash output. * \return the hash output length (in bytes), or 0. */ size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); /** * \brief Type for a GHASH implementation. * * GHASH is a sort of keyed hash meant to be used to implement GCM in * combination with a block cipher (with 16-byte blocks). * * The `y` array has length 16 bytes and is used for input and output; in * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte * value that serves as key (it is derived from the encryption key in GCM, * using the block cipher). The data length (`len`) is expressed in bytes. * The `y` array is updated. * * If the data length is not a multiple of 16, then the data is implicitly * padded with zeros up to the next multiple of 16. Thus, when using GHASH * in GCM, this method may be called twice, for the associated data and * for the ciphertext, respectively; the zero-padding implements exactly * the GCM rules. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (mixed 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (strict 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, * but it is expected to be faster on architectures for which the * 32-bit multiplication opcode does not yield the upper 32 bits of the * product. It is constant-time (if multiplications are constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (64-bit). * * This implementation uses multiplications of 64-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). It is substantially faster than `br_ghash_ctmul()` * and `br_ghash_ctmul32()` on most 64-bit architectures. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using the `pclmulqdq` opcode (part of the * AES-NI instructions). * * This implementation is available only on x86 platforms where the * compiler supports the relevant intrinsic functions. Even if the * compiler supports these functions, the local CPU might not support * the `pclmulqdq` opcode, meaning that a call will fail with an * illegal instruction exception. To safely obtain a pointer to this * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pclmul` GHASH implementation, if available. * * If the `pclmul` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pclmul()` function. Otherwise, it will return `0`. * * \return the `pclmul` GHASH implementation, or `0`. */ br_ghash br_ghash_pclmul_get(void); /** * \brief GHASH implementation using the POWER8 opcodes. * * This implementation is available only on POWER8 platforms (and later). * To safely obtain a pointer to this function when supported (or 0 * otherwise), use `br_ghash_pwr8_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pwr8` GHASH implementation, if available. * * If the `pwr8` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pwr8()` function. Otherwise, it will return `0`. * * \return the `pwr8` GHASH implementation, or `0`. */ br_ghash br_ghash_pwr8_get(void); #ifdef __cplusplus } #endif #endif /* * Copyright (c) 2016 Thomas Pornin
* [https://www.bearssl.org/oop.html](https://www.bearssl.org/oop.html) * * The vtable offers functions called `init()`, `update()`, `out()`, * `set()` and `set_state()`, which are in fact the functions from * the procedural API. That vtable also contains two informative fields: * * - `context_size` * * The size of the context structure (`br_xxx_context`), in bytes. * This can be used by generic implementations to perform dynamic * context allocation. * * - `desc` * * A "descriptor" field that encodes some information on the hash * function: symbolic identifier, output size, state size, * internal block size, details on the padding. * * Users of this object-oriented API (in particular generic HMAC * implementations) may make the following assumptions: * * - Hash output size is no more than 64 bytes. * - Hash internal state size is no more than 64 bytes. * - Internal block size is a power of two, no less than 16 and no more * than 256. * * * ## Implemented Hash Functions * * Implemented hash functions are: * * | Function | Name | Output length | State length | * | :-------- | :------ | :-----------: | :----------: | * | MD5 | md5 | 16 | 16 | * | SHA-1 | sha1 | 20 | 20 | * | SHA-224 | sha224 | 28 | 32 | * | SHA-256 | sha256 | 32 | 32 | * | SHA-384 | sha384 | 48 | 64 | * | SHA-512 | sha512 | 64 | 64 | * | MD5+SHA-1 | md5sha1 | 36 | 36 | * * (MD5+SHA-1 is the concatenation of MD5 and SHA-1 computed over the * same input; in the implementation, the internal data buffer is * shared, thus making it more memory-efficient than separate MD5 and * SHA-1. It can be useful in implementing SSL 3.0, TLS 1.0 and TLS * 1.1.) * * * ## Multi-Hasher * * An aggregate hasher is provided, that can compute several standard * hash functions in parallel. It uses `br_multihash_context` and a * procedural API. It is configured with the implementations (the vtables) * that it should use; it will then compute all these hash functions in * parallel, on the same input. It is meant to be used in cases when the * hash of an object will be used, but the exact hash function is not * known yet (typically, streamed processing on X.509 certificates). * * Only the standard hash functions (MD5, SHA-1, SHA-224, SHA-256, SHA-384 * and SHA-512) are supported by the multi-hasher. * * * ## GHASH * * GHASH is not a generic hash function; it is a _universal_ hash function, * which, as the name does not say, means that it CANNOT be used in most * places where a hash function is needed. GHASH is used within the GCM * encryption mode, to provide the checked integrity functionality. * * A GHASH implementation is basically a function that uses the type defined * in this file under the name `br_ghash`: * * typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); * * The `y` pointer refers to a 16-byte value which is used as input, and * receives the output of the GHASH invocation. `h` is a 16-byte secret * value (that serves as key). `data` and `len` define the input data. * * Three GHASH implementations are provided, all constant-time, based on * the use of integer multiplications with appropriate masking to cancel * carry propagation. */ /** * \brief Class type for hash function implementations. * * A `br_hash_class` instance references the methods implementing a hash * function. Constant instances of this structure are defined for each * implemented hash function. Such instances are also called "vtables". * * Vtables are used to support object-oriented programming, as * described on [the BearSSL Web site](https://www.bearssl.org/oop.html). */ typedef struct br_hash_class_ br_hash_class; struct br_hash_class_ { /** * \brief Size (in bytes) of the context structure appropriate for * computing this hash function. */ size_t context_size; /** * \brief Descriptor word that contains information about the hash * function. * * For each word `xxx` described below, use `BR_HASHDESC_xxx_OFF` * and `BR_HASHDESC_xxx_MASK` to access the specific value, as * follows: * * (hf->desc >> BR_HASHDESC_xxx_OFF) & BR_HASHDESC_xxx_MASK * * The defined elements are: * * - `ID`: the symbolic identifier for the function, as defined * in [TLS](https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1) * (MD5 = 1, SHA-1 = 2,...). * * - `OUT`: hash output size, in bytes. * * - `STATE`: internal running state size, in bytes. * * - `LBLEN`: base-2 logarithm for the internal block size, as * defined for HMAC processing (this is 6 for MD5, SHA-1, SHA-224 * and SHA-256, since these functions use 64-byte blocks; for * SHA-384 and SHA-512, this is 7, corresponding to their * 128-byte blocks). * * The descriptor may contain a few other flags. */ uint32_t desc; /** * \brief Initialisation method. * * This method takes as parameter a pointer to a context area, * that it initialises. The first field of the context is set * to this vtable; other elements are initialised for a new hash * computation. * * \param ctx pointer to (the first field of) the context. */ void (*init)(const br_hash_class **ctx); /** * \brief Data injection method. * * The `len` bytes starting at address `data` are injected into * the running hash computation incarnated by the specified * context. The context is updated accordingly. It is allowed * to have `len == 0`, in which case `data` is ignored (and could * be `NULL`), and nothing happens. * on the input data. * * \param ctx pointer to (the first field of) the context. * \param data pointer to the first data byte to inject. * \param len number of bytes to inject. */ void (*update)(const br_hash_class **ctx, const void *data, size_t len); /** * \brief Produce hash output. * * The hash output corresponding to all data bytes injected in the * context since the last `init()` call is computed, and written * in the buffer pointed to by `dst`. The hash output size depends * on the implemented hash function (e.g. 16 bytes for MD5). * The context is _not_ modified by this call, so further bytes * may be afterwards injected to continue the current computation. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the hash output. */ void (*out)(const br_hash_class *const *ctx, void *dst); /** * \brief Get running state. * * This method saves the current running state into the `dst` * buffer. What constitutes the "running state" depends on the * hash function; for Merkle-Damgård hash functions (like * MD5 or SHA-1), this is the output obtained after processing * each block. The number of bytes injected so far is returned. * The context is not modified by this call. * * \param ctx pointer to (the first field of) the context. * \param dst destination buffer for the state. * \return the injected total byte length. */ uint64_t (*state)(const br_hash_class *const *ctx, void *dst); /** * \brief Set running state. * * This methods replaces the running state for the function. * * \param ctx pointer to (the first field of) the context. * \param stb source buffer for the state. * \param count injected total byte length. */ void (*set_state)(const br_hash_class **ctx, const void *stb, uint64_t count); }; #ifndef BR_DOXYGEN_IGNORE #define BR_HASHDESC_ID(id) ((uint32_t)(id) << BR_HASHDESC_ID_OFF) #define BR_HASHDESC_ID_OFF 0 #define BR_HASHDESC_ID_MASK 0xFF #define BR_HASHDESC_OUT(size) ((uint32_t)(size) << BR_HASHDESC_OUT_OFF) #define BR_HASHDESC_OUT_OFF 8 #define BR_HASHDESC_OUT_MASK 0x7F #define BR_HASHDESC_STATE(size) ((uint32_t)(size) << BR_HASHDESC_STATE_OFF) #define BR_HASHDESC_STATE_OFF 15 #define BR_HASHDESC_STATE_MASK 0xFF #define BR_HASHDESC_LBLEN(ls) ((uint32_t)(ls) << BR_HASHDESC_LBLEN_OFF) #define BR_HASHDESC_LBLEN_OFF 23 #define BR_HASHDESC_LBLEN_MASK 0x0F #define BR_HASHDESC_MD_PADDING ((uint32_t)1 << 28) #define BR_HASHDESC_MD_PADDING_128 ((uint32_t)1 << 29) #define BR_HASHDESC_MD_PADDING_BE ((uint32_t)1 << 30) #endif /* * Specific hash functions. * * Rules for contexts: * -- No interior pointer. * -- No pointer to external dynamically allocated resources. * -- First field is called 'vtable' and is a pointer to a * const-qualified br_hash_class instance (pointer is set by init()). * -- SHA-224 and SHA-256 contexts are identical. * -- SHA-384 and SHA-512 contexts are identical. * * Thus, contexts can be moved and cloned to capture the hash function * current state; and there is no need for any explicit "release" function. */ /** * \brief Symbolic identifier for MD5. */ #define br_md5_ID 1 /** * \brief MD5 output size (in bytes). */ #define br_md5_SIZE 16 /** * \brief Constant vtable for MD5. */ extern const br_hash_class br_md5_vtable; /** * \brief MD5 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[4]; #endif } br_md5_context; /** * \brief MD5 context initialisation. * * This function initialises or resets a context for a new MD5 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5_init(br_md5_context *ctx); /** * \brief Inject some data bytes in a running MD5 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5_update(br_md5_context *ctx, const void *data, size_t len); /** * \brief Compute MD5 output. * * The MD5 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5_out(const br_md5_context *ctx, void *out); /** * \brief Save MD5 running state. * * The running state for MD5 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5_state(const br_md5_context *ctx, void *out); /** * \brief Restore MD5 running state. * * The running state for MD5 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5_set_state(br_md5_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-1. */ #define br_sha1_ID 2 /** * \brief SHA-1 output size (in bytes). */ #define br_sha1_SIZE 20 /** * \brief Constant vtable for SHA-1. */ extern const br_hash_class br_sha1_vtable; /** * \brief SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[5]; #endif } br_sha1_context; /** * \brief SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-1 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha1_init(br_sha1_context *ctx); /** * \brief Inject some data bytes in a running SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha1_update(br_sha1_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-1 output. * * The SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha1_out(const br_sha1_context *ctx, void *out); /** * \brief Save SHA-1 running state. * * The running state for SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha1_state(const br_sha1_context *ctx, void *out); /** * \brief Restore SHA-1 running state. * * The running state for SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha1_set_state(br_sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-224. */ #define br_sha224_ID 3 /** * \brief SHA-224 output size (in bytes). */ #define br_sha224_SIZE 28 /** * \brief Constant vtable for SHA-224. */ extern const br_hash_class br_sha224_vtable; /** * \brief SHA-224 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val[8]; #endif } br_sha224_context; /** * \brief SHA-224 context initialisation. * * This function initialises or resets a context for a new SHA-224 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha224_init(br_sha224_context *ctx); /** * \brief Inject some data bytes in a running SHA-224 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha224_update(br_sha224_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-224 output. * * The SHA-224 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha224_out(const br_sha224_context *ctx, void *out); /** * \brief Save SHA-224 running state. * * The running state for SHA-224 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha224_state(const br_sha224_context *ctx, void *out); /** * \brief Restore SHA-224 running state. * * The running state for SHA-224 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha224_set_state(br_sha224_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-256. */ #define br_sha256_ID 4 /** * \brief SHA-256 output size (in bytes). */ #define br_sha256_SIZE 32 /** * \brief Constant vtable for SHA-256. */ extern const br_hash_class br_sha256_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-256 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha256_context; #else typedef br_sha224_context br_sha256_context; #endif /** * \brief SHA-256 context initialisation. * * This function initialises or resets a context for a new SHA-256 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha256_init(br_sha256_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-256 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha256_update(br_sha256_context *ctx, const void *data, size_t len); #else #define br_sha256_update br_sha224_update #endif /** * \brief Compute SHA-256 output. * * The SHA-256 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha256_out(const br_sha256_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-256 running state. * * The running state for SHA-256 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha256_state(const br_sha256_context *ctx, void *out); #else #define br_sha256_state br_sha224_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-256 running state. * * The running state for SHA-256 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha256_set_state(br_sha256_context *ctx, const void *stb, uint64_t count); #else #define br_sha256_set_state br_sha224_set_state #endif /** * \brief Symbolic identifier for SHA-384. */ #define br_sha384_ID 5 /** * \brief SHA-384 output size (in bytes). */ #define br_sha384_SIZE 48 /** * \brief Constant vtable for SHA-384. */ extern const br_hash_class br_sha384_vtable; /** * \brief SHA-384 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint64_t val[8]; #endif } br_sha384_context; /** * \brief SHA-384 context initialisation. * * This function initialises or resets a context for a new SHA-384 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha384_init(br_sha384_context *ctx); /** * \brief Inject some data bytes in a running SHA-384 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha384_update(br_sha384_context *ctx, const void *data, size_t len); /** * \brief Compute SHA-384 output. * * The SHA-384 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha384_out(const br_sha384_context *ctx, void *out); /** * \brief Save SHA-384 running state. * * The running state for SHA-384 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha384_state(const br_sha384_context *ctx, void *out); /** * \brief Restore SHA-384 running state. * * The running state for SHA-384 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha384_set_state(br_sha384_context *ctx, const void *stb, uint64_t count); /** * \brief Symbolic identifier for SHA-512. */ #define br_sha512_ID 6 /** * \brief SHA-512 output size (in bytes). */ #define br_sha512_SIZE 64 /** * \brief Constant vtable for SHA-512. */ extern const br_hash_class br_sha512_vtable; #ifdef BR_DOXYGEN_IGNORE /** * \brief SHA-512 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; } br_sha512_context; #else typedef br_sha384_context br_sha512_context; #endif /** * \brief SHA-512 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_sha512_init(br_sha512_context *ctx); #ifdef BR_DOXYGEN_IGNORE /** * \brief Inject some data bytes in a running SHA-512 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_sha512_update(br_sha512_context *ctx, const void *data, size_t len); #else #define br_sha512_update br_sha384_update #endif /** * \brief Compute SHA-512 output. * * The SHA-512 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_sha512_out(const br_sha512_context *ctx, void *out); #ifdef BR_DOXYGEN_IGNORE /** * \brief Save SHA-512 running state. * * The running state for SHA-512 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_sha512_state(const br_sha512_context *ctx, void *out); #else #define br_sha512_state br_sha384_state #endif #ifdef BR_DOXYGEN_IGNORE /** * \brief Restore SHA-512 running state. * * The running state for SHA-512 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_sha512_set_state(br_sha512_context *ctx, const void *stb, uint64_t count); #else #define br_sha512_set_state br_sha384_set_state #endif /* * "md5sha1" is a special hash function that computes both MD5 and SHA-1 * on the same input, and produces a 36-byte output (MD5 and SHA-1 * concatenation, in that order). State size is also 36 bytes. */ /** * \brief Symbolic identifier for MD5+SHA-1. * * MD5+SHA-1 is the concatenation of MD5 and SHA-1, computed over the * same input. It is not one of the functions identified in TLS, so * we give it a symbolic identifier of value 0. */ #define br_md5sha1_ID 0 /** * \brief MD5+SHA-1 output size (in bytes). */ #define br_md5sha1_SIZE 36 /** * \brief Constant vtable for MD5+SHA-1. */ extern const br_hash_class br_md5sha1_vtable; /** * \brief MD5+SHA-1 context. * * First field is a pointer to the vtable; it is set by the initialisation * function. Other fields are not supposed to be accessed by user code. */ typedef struct { /** * \brief Pointer to vtable for this context. */ const br_hash_class *vtable; #ifndef BR_DOXYGEN_IGNORE unsigned char buf[64]; uint64_t count; uint32_t val_md5[4]; uint32_t val_sha1[5]; #endif } br_md5sha1_context; /** * \brief MD5+SHA-1 context initialisation. * * This function initialises or resets a context for a new SHA-512 * computation. It also sets the vtable pointer. * * \param ctx pointer to the context structure. */ void br_md5sha1_init(br_md5sha1_context *ctx); /** * \brief Inject some data bytes in a running MD5+SHA-1 computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_md5sha1_update(br_md5sha1_context *ctx, const void *data, size_t len); /** * \brief Compute MD5+SHA-1 output. * * The MD5+SHA-1 output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `out`. The context * itself is not modified, so extra bytes may be injected afterwards * to continue that computation. * * \param ctx pointer to the context structure. * \param out destination buffer for the hash output. */ void br_md5sha1_out(const br_md5sha1_context *ctx, void *out); /** * \brief Save MD5+SHA-1 running state. * * The running state for MD5+SHA-1 (output of the last internal block * processing) is written in the buffer pointed to by `out`. The * number of bytes injected since the last initialisation or reset * call is returned. The context is not modified. * * \param ctx pointer to the context structure. * \param out destination buffer for the running state. * \return the injected total byte length. */ uint64_t br_md5sha1_state(const br_md5sha1_context *ctx, void *out); /** * \brief Restore MD5+SHA-1 running state. * * The running state for MD5+SHA-1 is set to the provided values. * * \param ctx pointer to the context structure. * \param stb source buffer for the running state. * \param count the injected total byte length. */ void br_md5sha1_set_state(br_md5sha1_context *ctx, const void *stb, uint64_t count); /** * \brief Aggregate context for configurable hash function support. * * The `br_hash_compat_context` type is a type which is large enough to * serve as context for all standard hash functions defined above. */ typedef union { const br_hash_class *vtable; br_md5_context md5; br_sha1_context sha1; br_sha224_context sha224; br_sha256_context sha256; br_sha384_context sha384; br_sha512_context sha512; br_md5sha1_context md5sha1; } br_hash_compat_context; /* * The multi-hasher is a construct that handles hashing of the same input * data with several hash functions, with a single shared input buffer. * It can handle MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 * simultaneously, though which functions are activated depends on * the set implementation pointers. */ /** * \brief Multi-hasher context structure. * * The multi-hasher runs up to six hash functions in the standard TLS list * (MD5, SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512) in parallel, over * the same input. * * The multi-hasher does _not_ follow the OOP structure with a vtable. * Instead, it is configured with the vtables of the hash functions it * should run. Structure fields are not supposed to be accessed directly. */ typedef struct { #ifndef BR_DOXYGEN_IGNORE unsigned char buf[128]; uint64_t count; uint32_t val_32[25]; uint64_t val_64[16]; const br_hash_class *impl[6]; #endif } br_multihash_context; /** * \brief Clear a multi-hasher context. * * This should always be called once on a given context, _before_ setting * the implementation pointers. * * \param ctx the multi-hasher context. */ void br_multihash_zero(br_multihash_context *ctx); /** * \brief Set a hash function implementation. * * Implementations shall be set _after_ clearing the context (with * `br_multihash_zero()`) but _before_ initialising the computation * (with `br_multihash_init()`). The hash function implementation * MUST be one of the standard hash functions (MD5, SHA-1, SHA-224, * SHA-256, SHA-384 or SHA-512); it may also be `NULL` to remove * an implementation from the multi-hasher. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \param impl the hash function vtable, or `NULL`. */ static inline void br_multihash_setimpl(br_multihash_context *ctx, int id, const br_hash_class *impl) { /* * This code relies on hash functions ID being values 1 to 6, * in the MD5 to SHA-512 order. */ ctx->impl[id - 1] = impl; } /** * \brief Get a hash function implementation. * * This function returns the currently configured vtable for a given * hash function (by symbolic ID). If no such function was configured in * the provided multi-hasher context, then this function returns `NULL`. * * \param ctx the multi-hasher context. * \param id the hash function symbolic identifier. * \return the hash function vtable, or `NULL`. */ static inline const br_hash_class * br_multihash_getimpl(const br_multihash_context *ctx, int id) { return ctx->impl[id - 1]; } /** * \brief Reset a multi-hasher context. * * This function prepares the context for a new hashing computation, * for all implementations configured at that point. * * \param ctx the multi-hasher context. */ void br_multihash_init(br_multihash_context *ctx); /** * \brief Inject some data bytes in a running multi-hashing computation. * * The provided context is updated with some data bytes. If the number * of bytes (`len`) is zero, then the data pointer (`data`) is ignored * and may be `NULL`, and this function does nothing. * * \param ctx pointer to the context structure. * \param data pointer to the injected data. * \param len injected data length (in bytes). */ void br_multihash_update(br_multihash_context *ctx, const void *data, size_t len); /** * \brief Compute a hash output from a multi-hasher. * * The hash output for the concatenation of all bytes injected in the * provided context since the last initialisation or reset call, is * computed and written in the buffer pointed to by `dst`. The hash * function to use is identified by `id` and must be one of the standard * hash functions. If that hash function was indeed configured in the * multi-hasher context, the corresponding hash value is written in * `dst` and its length (in bytes) is returned. If the hash function * was _not_ configured, then nothing is written in `dst` and 0 is * returned. * * The context itself is not modified, so extra bytes may be injected * afterwards to continue the hash computations. * * \param ctx pointer to the context structure. * \param id the hash function symbolic identifier. * \param dst destination buffer for the hash output. * \return the hash output length (in bytes), or 0. */ size_t br_multihash_out(const br_multihash_context *ctx, int id, void *dst); /** * \brief Type for a GHASH implementation. * * GHASH is a sort of keyed hash meant to be used to implement GCM in * combination with a block cipher (with 16-byte blocks). * * The `y` array has length 16 bytes and is used for input and output; in * a complete GHASH run, it starts with an all-zero value. `h` is a 16-byte * value that serves as key (it is derived from the encryption key in GCM, * using the block cipher). The data length (`len`) is expressed in bytes. * The `y` array is updated. * * If the data length is not a multiple of 16, then the data is implicitly * padded with zeros up to the next multiple of 16. Thus, when using GHASH * in GCM, this method may be called twice, for the associated data and * for the ciphertext, respectively; the zero-padding implements exactly * the GCM rules. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ typedef void (*br_ghash)(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (mixed 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (strict 32-bit). * * This implementation uses multiplications of 32-bit values, with a * 32-bit result. It is usually somewhat slower than `br_ghash_ctmul()`, * but it is expected to be faster on architectures for which the * 32-bit multiplication opcode does not yield the upper 32 bits of the * product. It is constant-time (if multiplications are constant-time). * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul32(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using multiplications (64-bit). * * This implementation uses multiplications of 64-bit values, with a * 64-bit result. It is constant-time (if multiplications are * constant-time). It is substantially faster than `br_ghash_ctmul()` * and `br_ghash_ctmul32()` on most 64-bit architectures. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_ctmul64(void *y, const void *h, const void *data, size_t len); /** * \brief GHASH implementation using the `pclmulqdq` opcode (part of the * AES-NI instructions). * * This implementation is available only on x86 platforms where the * compiler supports the relevant intrinsic functions. Even if the * compiler supports these functions, the local CPU might not support * the `pclmulqdq` opcode, meaning that a call will fail with an * illegal instruction exception. To safely obtain a pointer to this * function when supported (or 0 otherwise), use `br_ghash_pclmul_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pclmul(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pclmul` GHASH implementation, if available. * * If the `pclmul` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pclmul()` function. Otherwise, it will return `0`. * * \return the `pclmul` GHASH implementation, or `0`. */ br_ghash br_ghash_pclmul_get(void); /** * \brief GHASH implementation using the POWER8 opcodes. * * This implementation is available only on POWER8 platforms (and later). * To safely obtain a pointer to this function when supported (or 0 * otherwise), use `br_ghash_pwr8_get()`. * * \param y the array to update. * \param h the GHASH key. * \param data the input data (may be `NULL` if `len` is zero). * \param len the input data length (in bytes). */ void br_ghash_pwr8(void *y, const void *h, const void *data, size_t len); /** * \brief Obtain the `pwr8` GHASH implementation, if available. * * If the `pwr8` implementation was compiled in the library (depending * on the compiler abilities) _and_ the local CPU appears to support the * opcode, then this function will return a pointer to the * `br_ghash_pwr8()` function. Otherwise, it will return `0`. * * \return the `pwr8` GHASH implementation, or `0`. */ br_ghash br_ghash_pwr8_get(void); #ifdef __cplusplus } #endif #endif /* * Copyright (c) 2016 Thomas Pornin